Skip to content
On this page

핵심 개념 이해하기

서버

네트워크를 통해 클라이언트로부터 요청이 오면 정보나 서비스를 응답으로 제공하는 컴퓨터 또는 프로그램을 의미합니다.

자바스크립트 런타임

자바스크립트를 실행할 수 있는 환경으로, Node.js는 Chrome V8 Javascript 엔진으로 빌드된 자바스크립트 런타임입니다.

V8과 더불어 libuv라는 라이브러를 사용하여 이벤트 기반, 논블로킹 IO 모델을 구현합니다.

이벤트 기반

이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식으로, 이벤트 리스너에 콜백함수를 등록하여 구현합니다.

여러 이벤트가 발생했을 때 어떤 순서로 콜백함수를 호출할지는 이벤트 루프가 판단합니다.

이벤트 루프는 호출 스택이 비어 있으면 태스크 큐에서 하나씩 함수를 가져와 호출 스택에 넣고 실행합니다.

런타임 구성요소

  • 호출 스택 : 함수를 호출하여 생성되는 환경객체(컨택스트)가 스택구조로 저장되는 메모리 공간으로, 코드가 실행되면 전역 컨택스트가 최초로 push됩니다.
  • 이벤트 루프 : 이벤트 발생 시 호출할 콜백함수들을 관리하고, 호출된 콜백함수의 실행순서를 결정하는 역할을 담당합니다.
  • 백그라운드 : setTimeout 같은 타이머나 이벤트 리스너들이 대기하는 곳입니다.
  • 태스크 큐 : 이벤트 발생 후, 백그라운드에서는 태스크 큐로 타이머나 이벤트 리스너의 콜백함수를 보냅니다.

브라우저 런타임과 거의 동일합니다.

논블로킹 IO

논블로킹(non-blocking)이란 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행하는 것이고 블로킹(blocking)은 이전 작업이 끝나야만 다음 작업을 수행하는 것을 의미합니다.

논블로킹 방식을 적용하려면 작업들이 모두 동시에 처리될 수 있어야 한다는 전제가 있어야 합니다.

파일 시스템 접근(파일 읽기 및 쓰기, 폴더 만들기 등), 네트워크 요청과 응답 등이 IO 작업의 예시인데 node.js에서는 논블로킹 방식으로 처리합니다.

node.js는 필요하면 IO 작업을 백그라운드로 넘겨 동시에 처리하곤 합니다.

WARNING

여기서 논블로킹 방식으로 여러 작업들을 동시에 처리할 수 있지만 이는 병렬적인 것과는 완전히 다른 얘기입니다.

싱글 스레드

프로세스는 운영체제에서 할당하는 작업의 단위로 프로세스 간의 메모리 등의 자원을 공유하지 않습니다.

스레드는 단일 프로세스 내에서 실행되는 흐름의 단위로 스레드를 여러 개 생성하여 다수의 작업들을 동시에 처리할 수 있고 부모 프로세스의 자원을 공유합니다.

node.js를 실행하면 프로세스가 하나 생성되고 내부에 스레드들이 형성되는데 사용자가 제어할 수 있는 스레드는 하나만 있습니다.

스레드 풀과 워커 스레드

위와 같은 이유로 node.js는 싱글 스레드 환경이라고 하지만 여러 개의 스레드들을 사용하는 경우도 있습니다.

  • 스레드 풀 : 암호화, 파일 입출력, 압축 등의 작업을 할 때 스스로 멀티 스레드를 사용합니다.

  • 워커 스레드 : v12 이상부터 안정화된 기능으로 개발자가 직접 다수의 스레드를 다룰 수 있으며 CPU 연산량이 많은 경우 워커 스레드를 적용할 수 있습니다.

node.js는 싱글 스레드 + 논블로킹 모델로 단일 스레드가 처리할 개별 작업들의 완료여부를 확인하지 않고 실행순서대로 처리하는 것으로 이해할 수 있습니다.

멀티 스레드를 적용한다면 병렬적으로 처리할 수 있겠지만 요청의 개수가 많아지는 IO를 처리하는 경우 관리할 스레드들이 많아지므로 그만큼 관리 비용이 늘어납니다(개발도 어려움).

그래서 IO가 빈번한 작업에는 멀티프로세싱, CPU 작업이 많은 작업은 멀티스레딩이 유리합니다.