Node.js
- Chrome V8 Javascript 엔진으로 빌드된 JavaScript 런타임
- 서버 사이드 플랫폼
Node.js®는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다. Node.js는 이벤트 기반, 논 블로킹 I/O 모델을 사용해 가볍고 효율적입니다. Node.js의 패키지 생태계인 npm은 세계에서 가장 큰 오픈 소스 라이브러리이기도 합니다.
(출처: https://nodejs.org/ko/)
주요 특징
- 비동기 I/O
- 이벤트 위주
- 빠른 속도
- single thread
- 뛰어난 확장성
- no buffering
- license
핵심 개념 정리
1. 서버
- 네트워크를 통해 클라이언트에 정보나 서비스를 제공하는 컴퓨터 or 프로그램
클라이언트
- 요청을 보내는 주체
- 브라우저, 하나의 프로그램, 모바일 앱, 또 다른 서버 등이 될 수 있음
2. 자바스크립트 런타임
런타임
- 특정 언어로 만든 프로그램들을 실행할 수 있는 환경
기존에는 자바스크립트 프로그램을 웹 브라우저 위에서만 실행할 수 있었다.
(브라우저에 자바스크립트 런타임을 내장하고 있기에)
노드 내부 구조
- V8과 함께 libuv 라이브러리 사용
- C, C++로 구현되어 있음
- libuv 라이브러리
- 노드의 특성인 이벤트 기반, 논 블로킹 I/O 모델 구현
3. 이벤트 기반
- 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식
- 이벤트 리스너에 콜백 함수를 등록하여 구현
호출 스택
- 호출할 함수를 호출 스택에 쌓음
- anonymous: 처음 실행 시의 전역 컨텍스트
- 컨텍스트: 함수가 호출되었을 때 생성되는 환경
이벤트 루프
- 이벤트 발생 시 호출할 콜백 함수 관리
- 호출된 콜백 함수의 실행 순서 결정
- 호출 스택이 비어 있을 때, 태스크 큐의 콜백 함수를 호출 스택으로 올림
- 호출 스택이 비어 있지 않으면, 태스크 큐의 함수를 가져오지 않는다.
-> setTimeout의 시간이 정확하지 않은 이유
백그라운드
- setTimout과 같은 타이머나 이벤트 리스너들이 대기하는 곳
- JS가 아닌 다른 언어로 작성된 프로그램
- 여러 작업을 동시에 실행할 수 있다.
태스트 큐(콜백 큐)
- 백그라운드에서 보내온 이벤트 리스너의 콜백함수 대기열
- 실제로는 여러 개의 큐로 이루어져 있다.
타이머 함수가 사용되는 경우
function run() {
console.log('3초 후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');
4. 논 블로킹 I/O
- 노드는 I/O 작업을 백그라운드로 넘겨 동시에 처리 -> 시간 절약
- 자바스크립트 코드는 동시에 실행될 수 없지만, I/O 같은 작업은 동시에 처리될 수 있다.
- I/O (Input/Output)작업: 파일 시스템 접근, 네트워크를 통한 요청 등
논 블로킹
- 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행하는 방법
-> 동시 처리 가능
- <-> 블로킹
- 동시와 같은 의미는 아니다.
예제
function longRunningTask() {
console.log('작업 끝');
}
console.log('시작');
longRunningTask();
console.log('다음 작업');
function longRunningTask() {
console.log('작업 끝');
}
console.log('시작');
setTimeout(longRunningTask,0);
console.log('다음 작업');
코드를 논 블로킹으로 만드는 기법
- setTimeout(콜백, 0);
- 0 밀리초로 설정했으나, 기본적인 지연시간이 존재하므로 논 블로킹 가능
- setImmediate
자바스크립트 코드는 동시에 실행 될 수 없기에 오래 걸리는 작업과 간단한 작업의 실행 순서를 바꿈으로써 간단한 작업이 대기하느느 상황을 막을 수 있다.
5. 싱글 스레드
프로세스
- 운영체제에서 할당하는 작업의 단위
- 프로세스 간에는 자원 공유 X
스레드
- 프로세스 내에서 실행되는 흐름의 단위
- 한 프로세스 내에서 여러 개의 스레드를 생성하여 여러 작업을 동시에 처리 가능
- 부모 프로세스의 자원 공유
노드는 싱글 스레드?
- 실제로는 싱글 스레드로 동작하지 않는다.
- 내부적으로 여러 스레드를 생성하지만, 사용자가 제어할 수 있는 스레드가 하나뿐이다.
-> 노드가 싱글 스레드라고 여겨지는 이유
-> 자바스크립트 코드가 동시에 실행될 수 없는 이유
노드가 싱글 스레드로 동작하지 않는 경우
- 스레드풀
- 노드가 특정 동작을 수행할 때, 스스로 멀티 스레드 사용
- ex. 암호화, 파일 입출력, 압축 등
- 워커 스레드
- 노드 12 버전부터 멀티 스레드 사용 가능
멀티 스레딩 vs 멀티 프로세싱
멀티 스레딩 | 멀티 프로세싱 |
---|
하나의 프로세스 내에서 여러 개의 스레드 사용 | 여러 개의 프로세스 사용 |
CPU 작업이 많을 때 | I/O 요청이 많을 때 |
프로그래밍 어려움 | 프로그래밍 비교적 쉬움 |
서버로서의 노드
장점
- 싱글 스레드, 논 블로킹 모델 사용
- JS 언어의 특성이기도 하다.
- 서버는 기본적으로 I/O 요청이 많이 발생하므로 적합하다.
- libuv 라이브러리를 사용하여 I/O 작업을 논 블로킹으로 처리
-> 개수는 많지만 크기는 작은 데이터를 실시간으로 주고받는 경우에 적합
- 웹 서버 내장
- 노드 이외의 서버는 별도의 웹 서버(Apache, nginx, IIS 등) 설치 필요
- 서버 규모가 커지면 웹 서버 연결해야 한다.
- 자바스크립트 사용
- 웹 브라우저와 서버가 모두 하나의 언어로 개발하여 생산성을 높일 수 있다.
- JS 형식인 JSON을 사용하여 데이터 주고받는데 유용
단점
- 싱글 스레드 이므로 CPU 부하가 큰 작업에는 적합하지 않음
- 멀티 스레드를 지원하지만, CPU를 많이 사용하는 작업을 위한 서버로는 권장 하지 않는다.
- 멀티 스레드 프로그래밍을 하는 것은 싱글 스레드에 비해 어렵다.
- 하더라도, C, C++, Rust, Go 언어에 비해 속도가 느리다.
- 하나뿐인 스레드가 멈추지 않도록 관리가 필요하다.
서버 외의 노드
-
웹, 모바일, 데스크톱 애플리케이션 개발에도 사용되고 있음
-
웹 프레임워크
- Angular
- React
- Vue
-
모바일
- React Native
-
데스크톱
- Electron(Atom, Slack, Discord, VScode 등을 만들었다.)