Nodejs 동작원리(이벤트기반, 논블로킹, 싱글스레드)
Nodejs는 이벤트기반, 논블로킹, 싱글스레드 기반입니다.
차례대로 이해해보자!
이벤트 기반
이벤트 기반: 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식(클릭이나 네트워크 요청)
- 이벤트 기반 시스템에는 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해야한다
-> 이벤트리스너에 콜백함수를 등록한다.
function first() {
second();
console.log('첫 번째');
}
function second(){
third();
console.log('두 번째');
}
function third() {
console.log('세 번째');
}
first();
이 코드의 호출 스택은 아래와 같다.
호출 스택에는 먼저 anonumous(전역 콘텍스트) - first() - second() - third() 순서대로 쌓이고
실행은 역순으로 실행됩니다.
콘텍스트 : 함수가 호출되었을 때 생성되는 환경.
function run() {
console.log('3초후 실행');
}
console.log('시작');
setTimeout(run, 3000);
console.log('끝');
결과는 아래와 같다
시작 - 끝 - 3초 후 실행
호출 스택만 알고있다면 위의 코드를 이해하기란 매우 어렵다.
setTimeout 함수의 콜백인 run이 호출 스택에 언제 들어가는지 위의 내용으로는 어렵기 때문이다.
이를 파악하기 위해 이벤트 루프, 태스크 큐, 백그라운드를 알아야한다.
이벤트 루프: 이벤트 발생 시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행 순서를 결정하는 역할을 담당.
노드가 종료될때 까지 이벤트 처리를 위한 작업을 반복하므로 루프라고 부른다.
백그라운드: setTimeout 같은 타이머나 이벤트 리스너들이 대기하는 곳입니다. 여러 작업이 동시에 실행될 수 있다.
태스크 큐: 이벤트 발생 후, 백그라운드에서는 태스크 큐로 타이머나 이벤트 리스너의 콜백 함수로 보낸다. 정해진 순서대로 콜백들이 줄을 서 있으므로 콜백 큐라고도 불린다. 콜백들은 보통 완료된 순서대로 줄을 서 있지만, 특정한 경우 순서가 바뀌기도 한다.
1. 먼저 전역 스택인 anonymous가 호출스택에 들어간다. 그 후 setTimeout이 호출 스택에 들어간다.
2. setTimeout이 실행되고 타이머와 run은 백그라운드로 보내진다.
3. setTimeout과 anonymous가 호출스택에서 빠진다.
4. 백그라운드에서 3초를 센 후 run함수를 태스크 큐로 보낸다.(백그라운드 작업완료)
5. 호출 스택 실행이 끝나 비워지면 이벤트루프가 태스크 큐의 콜백을 호출 스택으로 올린다.
6. run이 호출스택으로 올려지고 run이 실행지고 호출스택에서 제거된다.
7. 이벤트 루프는 태스크 큐에 콜백이 들어올 때까지 대기한다.
- 만약 호출 스택에 함수가 너무 많이 들어있으면 3초가 지난후에도 run 함수가 실행되지 않을 수 있다.
논블로킹 I/O
논블로킹 - 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행하는 것.
블로킹 - 이전 작업이 끝나야만 다음 작업을 수행하는 것
* 논블로킹과 동시는 같은 의미가 아니다
- 동시성은 동시 처리가 가능한 작업을 논블로킹 처리해야 얻을 수 있는 것.
싱글 스레드
프로세스 - 운영체제에서 할당하는 작업의 단위.( 노드나 웹 브라우저 같은 프로그램은 개별적인 프로세스, 프로세스 간에는 메모리 등의 자원을 공유하지 않는다.)
스레드 - 프로세스 내에서 실행되는 흐름의 단위.( 프로세스는 스레드를 여러개 생성해 작업을 동시에 처리할 수 있다. 스레드들은 부모 프로세스의 자원을 공유한다. 같은 주소의 메모리에 접근 가능하므로 데이터를 공유할 수 있다.)
흔히 노드는 싱글 스레드라고 많이 들었다.
하지만 노드는 싱글 스레드처럼 보이는것이다!
즉, 싱글 스레드로 동작하지 않는다.
노드실행 - 프로세스 하나 생성 - 내부적으로 여러 개의 스레드 생성 -
=> 이 스레드 중에서 직접 제어할 수 있는 스레드는 하나 뿐.(흔히 노드가 싱글 스레드라고 여겨지는 이유)
- 노드가 싱글 스레드로 동작하지 않는 두가지 경우
1.스레드 풀
- 노드가 특정 동작을 수행할 때 스스로 멀티 스레드를 사용한다. 대표적인 예로 암호화, 파일 입출력, 압축 등이 있다.
2.워커 스레드
- 노드12 버전에서 안정화된 기능, 직접 다수의 스레드를 다룰 수 있으며 CPU작업이 많은 경우 워커 스레드를 사용한다.
노드는 싱글스레드 논블로킹 방식.
작업이 들어오면 백그라운드에 넘기고 다음 작업을 처리.
노드의 장점: 서버에는 기본적으로 I/O 요청이 많이발생. 노드는 I/O 처리를 잘 한다.(채팅 어플리케이션, 주식차트, JSON 데이터를 제공하는 API서버 적합)
자바스크립트 사용! 개발 생산성을 획기적으로 높였다.
노드의 단점: CPU 부하가 큰 작업에는 적합하지 않는다. 멀티 스레드 기능이 생겼지만 다른 언어에 비해 속도가 많이 느리고 난이도가 매우 높다.