Node.js는 Chrome V8 Javascript 엔진으로 빌드된 JavaScript 런타입니다.
런타임: 특정 언어로 만든 프로그램들을 실행할 수 있는 환경
JavaScript는 웹애플리케이션을 개발할 때 사용하는데, 이때 모든 브라우저는 JavaScript 코드를 해석하기 위해 JavaScript Engine을 내장하고 있다. (Chrome은 V8)
Node.js는 서버에서 JavaScript를 동작할 수 있도록, 서버로서 기능하기 위한 도구를 제공한다.
서버
: 네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 또는 프로그램으로 클라이언트의 요청에 응답한다.
클라이언트
: 요청을 보내는 주체로, 브라우저나 테스크톱 프로그램 그리고 다른 서버에 요청을 보내는 서버일 수도 있다.
웹 사이트를 방문하기 위해 주소창에 사이트 주소를 입력(요청)
-> 브라우저는 주소에 해당하는 위치를 파악
-> 컴퓨터로부터 웹 사이트의 페이지를 받아와 요청자의 브라우저(클라이언트)에 띄운다(응답).
이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식
이벤트 기반 시스템에서는 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해두어야 하는데, 이를 이벤트 리스터(event listener)
에 콜백(callback)
함수를 등록한다고 표현한다.
노드는 이벤트 기반 방식으로 동작하기 때문에 이벤트가 발생하면 이벤트 리스너에 저장해둔 콜백 함수를 호출한다. 발생한 이벤트가 없거나 발생했던 이벤트를 다 처리하면, 다음 이벤트가 발생할 때 까지 대기한다.
여러 이벤트가 동시에 발생했을 때 어떤 순서로 콜백 함수를 호출할지를 이벤트 루프가 판단한다.
이벤트 루프(event loop)
: 이벤트 발생 시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행 순서를 결정하는 역할을 담당. 노드가 종료될 때까지 이벤트 처리를 위한 작업을 반복
백그라운드
: setTimeout 같은 타이머나 이벤트 리스너들이 대기하는 곳
태스크 큐
: 이벤트 발생 후, 백그라운드에서는 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수를 보낸다.
function run(){
console.log('3초 후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');
[결과]
시작
끝
3초 후 실행
이벤트 루프를 잘 활용하면 오래 걸리는 작업(동시에 실행될 수 있는 작업/동시에 실행될 수 없는 작업)을 효율적으로 처리할 수 있다.
자바스크립트 코드는 동시에 실행될 수 없는데, 자바스크립트 상에서 돌아가는 것이 아닌 Input/0utput 작업에서는 동시에 처리될 수 있다. 이러한 작업을 할 때 노드는 논블로킹 방식으로 처리한다.
function longRunningTask(){
// 오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
longRunningTask();
console.log('다음 작업');
[결과]
시작
작업 끝
다음 작업
function longRunningTask(){
// 오래 걸리는 작업
console.log('작업 끝');
}
console.log('시작');
setTimieout(longRunningTask(), 0);
console.log('다음 작업');
[결과]
시작
다음 작업
작업 끝
setTimieout(콜백, 0)은 코드를 논 블로킹으로 만들기 위해 사용하느 기법 중 하나이다.
이벤트 루프로 setTimeout의 콜백 함수인 longRunningTask가 태스크 큐로 보내지므로 순서대로 실행되지 않는다. 다음 작업이 먼저 실행된 후, 오래 걸리는 작업이 완료된다.
프로세스
: 운영체제에서 할당하는 작업의 단위로, 노드나 웹 브라우저 같은 프로그램은 개별 프로세스이다. 프로세스 간에는 메모리 등의 자원을 공유하지 않는다.
스레드
: 프로세스 내에서 실행되는 흐름의 단위로, 프로세스는 스레드를 여러 개 생성해 여러 작업을 동시에 처리할 수 있다. 스레드들은 부모 프로세스 자원을 공유하고, 같은 주소 메모리 접근이 가능해 데이터를 공유할 수 있다.
노드는 싱글스레드이다.
정확히 말하면 노드는 싱글 스레드로 동작하지 않는다. 노드를 실행하면 먼저 프로세스가 하나 생성되고, 그 프로세스에서 스레드를 생성하는데 내부적으로 스레드를 여러 개 생성한다. 그중에서 직접 제어할 수 있는 스레드는 하나뿐이기 때문에 흔히 노드가 싱글 스레드라고 여겨진다.
요청이 많이 들어오면 한 번에 하나씩 요청을 처리한다. 블로킹이 심하게 일어나는 작업을 처리하지만 않으면 스레드는 하나로 충분하다. 블로킹이 발생할 것 같은 경우에 논 블로킹 방법으로 대기 시간을 줄인다.
싱글 스레드, 블로킹
싱글 스레드, 논 블로킹
멀티 스레드, 블로킹
멀티 스레딩 | 멀티 프로세싱 |
---|---|
하나의 프로세스 안에서 여러 개의 스레드 사용 | 여러 개의 프로세스 사용 |
CPU 작업이 많을 때 사용 | I/O 요청이 많을 때 사용 |
프로그래밍이 어려움 | 프로그래밍이 비교적 쉬움 |
I/O 작업을 처리할 때는 멀티 스레딩 보다 멀티 프로세싱이 효율적이므로 노드는 멀티 프로세싱을 많이 한다.
노드는 기본적으로 싱글 스레드, 논 블로킹 모델을 사용하므로 싱글 스레드와 논 블로킹 모델의 장단점과 크게 다르지 않다.
서버에는 기본적으로 I/O 요청이 많이 발생하므로, I/O 처리를 잘하는 노드를 서버로 사용하면 좋다. 노드는 libuv 라이브러리를 사용하여 I/O 작업을 논 블로킹 방식으로 처리한다. 따라서 스레드 하나가 많은 수의 I/O를 혼자서도 감당할 수 있다. 하지만 CPU 부하가 큰 작업에는 적합하지 않다. 작성한 코드는 모두 스레드 하나에서 처리된다.
노드는 이와 같은 특성으로 개수는 많지만 크기는 작은 데이터를 실시간으로 주고받는 데 적합하다. 실시간 채딩 애플리케이션이나 주식 차트 JSON 데이터를 제공하는 API 서버가 노드를 많이 사용한다.
장점 | 단점 |
---|---|
멀티 스레드 방식에 비해 적은 컴퓨터 자원 사용 | 기본적으로 싱글 스레드라서 CPU 코어를 하나만 사용 |
I/O 작업이 많은 서버로 적합 | CPU 작업이 많은 서버로는 부적합 |
멀티 스레드 방식보다 쉬움 | 하나뿐인 스레드가 멈추지 않도록 관리가 필요함 |
웹 서버가 내장되어 있음 | 서버 규모가 커졌을 때 서버를 관리하기 어려움 |
자바스크립트를 사용함 | 어중간한 성능 |
JSON 형식과 쉽게 호환됨 |