완벽한 다음 행보는 없다.

Node.js란 - 특징, 비동기 작업처리, 멀티스레드, 장단점 본문

Node.js

Node.js란 - 특징, 비동기 작업처리, 멀티스레드, 장단점

We On Fire 2023. 8. 19. 14:42

Node.js는 V8 JavaScript 엔진에 기반한 오픈 소스 서버 사이드 런타임 환경입니다. 주로 웹 개발에 사용되는 자바스크립트 언어로 서버 사이드 개발을 할 수 있게 해줍니다. Non-blocking I/O와 단일 스레드 이벤트 루프를 통한 높은 처리 성능을 가지고 있는 것이 특징입니다

이전까지 Server-Client 웹사이트를 만들 때 웹에서 표시되는 부분은 JavaScript 를 사용하여 만들어야만 했으며, 서버는 Reby, Java 등 다른 언어를 써서 만들었어야 했는데 마침내 한 가지 언어로 전체 웹 페이지를 만들 수 있게 되었다는 점에서 의미가 크다.

특징

이벤트 기반

이벤트 기반(Event-driven)이란 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식을 의미합니다. 즉, 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해두고, 이를 이벤트 리스너에 콜백함수를 등록합니다. 이후 이벤트가 발생하면 리스너에 등록해둔 콜백함수를 호출하며, 이벤트가 끝난 후 노드는 다음 이벤트가 발생할 때까지 대기합니다.

비동기 프로그래밍

비동기 I/O를 제공하며 이를 통해 많은 클라이언트들의 요청을 동시에 처리하고 블로킹을 최소화할 수 있습니다. 이를 통해 확장 가능하고 높은 성능을 가진 애플리케이션을 개발할 수 있습니다.

단일쓰레드 모델

Node.js는 단일쓰레드 이벤트 루프 모델을 기반으로 작동합니다. 그러나 ‘Node.js가 하나의 쓰레드만 사용한다’는 것은 아닙니다. 밑에서 좀 더 다루도록 하겠습니다.

패키지 매니저

Node.js는 npm(Node Package Manager)이라는 패키지 매니저를 포함하고 있습니다. 개발자들은 이를 통해 쉽게 다양한 외부 라이브러리와 모듈을 설치하고 관리할 수 있습니다.

웹 서버 개발

Node.js를 사용하여 웹 서버를 개발할 수 있습니다. Express.js와 같은 웹 프레임워크를 함께 사용하여 웹 애플리케이션을 더욱 편리하게 구축할 수 있습니다. 웹 서버에서 아파치 등의 별도 소프트웨어 없이 동작하는 것이 가능합니다

실시간 데이터 처리

웹 소켓과 같은 기술을 통해 실시간 데이터 통신을 구현할 수 있어 실시간 채팅, 실시간 게임 등에 유용합니다.

비동기 작업 처리 과정

기본적으로 Node.js의 메인 쓰레드는 하나의 코어(core)만 사용합니다. 메인 쓰레드는 동기적인 작업을 처리하다가 비동기 작업이 발생하면 해당 작업을 이벤트 루프로 보내고, 이벤트 루프가 비동기 작업을 관리하고 완료 시에 콜백을 실행하여 처리합니다. 이 과정은 Node.js의 비동기 프로그래밍 모델의 핵심입니다.

여기서 일반적인 비동기 작업의 흐름은 다음과 같습니다

  1. 비동기 작업이 등록: 비동기 작업(예: 파일 읽기, 네트워크 요청)이 시작되면, 해당 작업의 완료 콜백을 정의하고 등록합니다.
  2. 작업이 백그라운드에서 실행: 메인 쓰레드는 비동기 작업을 백그라운드에서 실행하며, 작업이 완료되면 이벤트 큐(콜백 큐)에 완료된 작업에 대한 이벤트(완료 콜백)를 추가합니다.
  3. 비동기 작업 완료 시 콜백 실행: 이벤트 루프가 이벤트 큐에 있는 작업을 처리할 때, 비동기 작업의 완료 콜백을 실행하여 작업 결과를 처리합니다.

이와 같은 방식으로 메인 쓰레드는 동기적인 작업을 처리하다가 비동기 작업이 등장하면 그 작업을 백그라운드에서 실행하고, 작업 완료 시에 해당 작업의 콜백을 이벤트 루프를 통해 실행하여 비동기성을 유지합니다.

Node.js 내부구현 - 멀티스레드와 멀티프로세싱

libuv - 비동기 작업 처리

메인 쓰레드가 비동기 작업을 만나면 해당 작업을 이벤트 루프로 넘기고, 이벤트 루프는 libuv를 통해 해당 작업을 처리합니다.

libuv는 내부적으로 멀티스레딩 및 멀티프로세싱을 사용하여 비동기 작업을 처리합니다. 이로 인해 여러 개의 코어를 사용하여 작업을 동시에 처리할 수 있습니다. 예를 들어, 파일 I/O 작업과 네트워크 I/O 작업은 별도의 스레드 또는 프로세스에서 동작하며, 이를 통해 다중 코어 시스템에서 성능을 향상시킵니다.

Worker Threads - 멀티스레드

Node.js 10부터는 worker_threads 모듈을 통해 멀티스레딩을 지원합니다. Worker Threads 모듈은 별도의 스레드에서 작업을 병렬로 처리하는 데 사용됩니다. 이를 통해 CPU 집약적인 작업을 여러 개의 스레드에서 동시에 실행하여 다중 코어를 활용할 수 있습니다.

Worker Threads를 사용하는 대표적인 상황은 다음과 같습니다.

  1. 계산 작업: 복잡한 계산, 수치 해석, 알고리즘 등의 작업은 CPU를 많이 사용하므로 Worker Threads를 활용하여 병렬로 처리할 수 있습니다.
  2. 데이터 처리: 대용량 데이터 처리, 데이터 분석, 변환 작업 등도 Worker Threads를 통해 병렬 처리하면 처리 시간을 단축할 수 있습니다.
  3. 이미지/비디오 처리: 이미지나 비디오의 변환, 필터링, 압축 등의 작업은 CPU를 많이 사용하므로 Worker Threads를 사용하여 효율적으로 처리할 수 있습니다.
  4. 암호화/해시 작업: 암호화나 해시 함수 등의 작업은 CPU 연산이 많이 필요하며, 이를 병렬 처리하여 성능을 향상시킬 수 있습니다.

클러스터링 - 멀티 프로세스

Node.js의 cluster 모듈을 사용하면 다중 프로세스를 사용할 수 있다. 다수의 프로세스 생성하여 각 프로세스가 하나의 CPU 코어를 사용하게 할 수 있습니다. 이를 통해 병렬성을 향상시켜 성능을 향상시킬 수 있습니다.

워커 스레드는 주로 CPU 집약적인 작업의 병렬 처리에 사용되며, 클러스터링은 I/O 집약적인 작업과 다중 코어 활용, 안정성 유지에 활용됩니다.

장점

단일스레드 - 가볍다

기본적으로 싱글 스레드 기반이라 다른 프레임워크에 비해 사용하는 메모리의 양이 적습니다.

비동기처리와 Non-blocking I/O

Node.js는 Non-blocking I/O를 처리하는 데 최적화된 플랫폼입니다. 한번에 여러 요청이 들어와도 event loop에 의해 비동기적으로 처리되기 때문에 Blocking되는 시간을 최소화 할 수 있습니다.

다른 언어에서도 이런 형태로 구현은 가능하지만 코드가 너무 지저분해지고 구현이 어려운 단점이 있었는데 Node.js에서는 비동기식 함수를 통해 코드 상에서 이 작업을 구현하기에 굉장히 간편하게 만들어줍니다,

라이브러리 생태계

npm을 통해서 다양한 패키지와 라이브러리를 손쉽게 사용 가능합니다.

단점

단일스레드

Node는 모든 요청을 하나의 쓰레드로 처리할 수 있습니다. 즉 여러 개의 요청을 동시에 처리할 수 있는 프레임워크(Java spring)와 비교하면 노드는 한번에 하나의 요청만 처리할 수 있습니다. 이는 예를 들어 처리에 5초가 걸리는 무거운 요청이 왔을 때 스프링의 경우 새로운 스레드를 생성해서 바로 다른 요청을 처리해준다면, 노드는 기존의 요청이 처리되기를 기다려야 합니다. 이러한 문제를 Node.Js + MSA, k8s 로 해결해나가는 블로그를 출처에 적어놓았습니다.

Type safe하지 못하다

이는 자바스크립트 언어의 특징이기도 합니다. 변수의 타입이 실행 시에 결정되므로 유연한 프로그래밍이 가능하지만 타입 관련 오류를 런타임에 발견할 수 있습니다. 이러한 문제는 코드 스타일이나 Typescript로 해결할 수 있습니다.

비동기처리에 대한 숙련도

비동기 프로그래밍과 이벤트 루프의 개념을 알고 활용할 수 있어야 합니다. 그렇지 않다면 의도치 않은 프로그램의 흐름을 발생시키거나 코드가 복잡해지는 문제가 발생합니다. 예를 들어 비동기처리 완료 된 후 실행되어야 하는 코드들이 비동기처리 결과 없이 실행되다가 문제를 일으키거나 할 수 있습니다.

잘 어울리는 서비스

  • 입출력이 자주 발생하는 서비스 - 웹, 알림, 채팅 등
  • 경량화된 API 서버
  • 가벼운 요청이 자주 빠르게 일어나는 서비스

참조

https://cdragon.tistory.com/m/66

https://hanamon.kr/nodejs-개념-이해하기/

https://medium.com/naverfinancial/node-js-vs-java-spring-c4699565918e

Comments