Node 주특기 주차 입문 강의에서 Node의 특징 3가지: single thread, non-blocking I/O, event driven에 대한 설명을 들었는데도 와닿지 않아 따로 문서를 찾아보며 정리해보았다.
Node
추천 참고 자료: https://yjp9603.tistory.com/3
추천 유튭: https://youtu.be/wB9tIg209-8 - non-blocking I/O, https://youtu.be/8aGhZQkoFbQ?t=1105 - event loop
Node.js® is an open-source, cross-platform JavaScript runtime environment.
노드가 등장하기 전의 자바스크립트는 브라우저 안에서만 동작하였지만, 구글에서 2008년에 크롬 브라우저를 출시하면서 V8 engine을 개발하여 JS의 실행속도가 대폭 증가하였다.
Node.js의 구조
- JS V8 엔진 외에 libuv라는 라이브러리가 있는데 그 라이브러리가 event-driven과 non-blocking I/O를 구현한다.
- V8 engine과 libuv는 C와 C++로 구현되어 있다.
Node.js의 특징
- Single Thread = 하나의 call stack
- thread = 일꾼
- 사실, 내부적으로는 node process/browser가 스레드를 여러 개 생성하긴 한다 . 그러나, 우리가 직접 제어할 수있는 것은 메인 하나 이기 때문에 싱글 스레드라고 한다.
- Non-blocking I/O
일단, request의 종류 = CPU-based request + I/O-based request
Non-blocking I/O는 노드 서버가 I/O-based request를 처리하는 방법이다.
- blocking
- I/O 작업이 완료될 때까지 다음 I/O 작업이 기다린다.
- A 함수가 B 함수를 호출하면 A가 B에게 제어권을 넘겨주는데 이떄 A는 함수 실행을 멈춘다. B 실행이 끝나면 다시 제어권을 A로 넘겨주고 A는 재개한다.
- non-blocking
- I/O작업이 완료됐는지 여부와 상관없이 다음 I/O 작업을 진행한다.
- A 함수가 B 함수를 호출해도 제어권은 A가 그대로 가지고 있으면서 (실행도 당연히 된다) B도 실행된다.
- Sync & Async랑 뭐가 다름?
- Blocking & Non-blocking은 제어의 관점
- 상사가 보고서를 읽을 때까지 사원이 기다리는 것 -> 블로킹
- 서류를 상사에게 전달하고 서류 읽는 동안 사원은 돌아가서 할 일 하는 것 -> 논 블로킹
- Sync & Async는 순서와 결과 처리의 관점
- 상사가 서류를 읽는 동안 사원은 할 일 하면서 계속 다 읽었냐 물어보는 것 -> 동기
- 상사가 서류를 읽고 결과를 메일로 보내면 사원은 읽든지 말든지 관심 없고 나중에 처리하는 것 -> 비동기
- Event Driven
- event loop를 통해 비동기 작업을 관리하는 것
- 이벤트 (클릭이나 네트워크 요청 등의 I/O) 발생 시 호출할 콜백 함수들을 관리, 호출된 콜백 함수의 실행 순서를 결정
- Node.js가 실행 종료될 때까지 loop를 계속 돌린다.
따라서, 노드는 하나의 스레드로 동작하지만 I/O 작업이 발생한 경우 non-blocking 방식을 이용하여 이를 비동기적으로 처리할 수 있다.
그래서 자바스크립트 런타임, 즉 Node는 어떻게 동작하는가: call stack, web API, task queue, and event loop에 대하여
-
call stack: 함수들이 순차적으로 쌓이고 처리된다
-
web API: 브라우저에서 제공하는 API로 비동기 작업들을 수행한다
-
task queue: web API에서 넘겨받은 callback 함수를 임시 저장한다
-
event loop: call stack이 비어있다면 task queue의 작업을 call stack으로 옮긴다
-
동작 방식
1. 상황: JS는 싱글 스레드이기 떄문에 (즉, call stack이 하나) 시간이 오래 걸리는 작업이 call stack에 들어가게 되면 다른 코드들이 수행되지 못하고 blocking이 되는 상황이 발생
2. 해결:
1. 이벤트 (DOM, AJAX 등)와 같은 I/O request는 Web APIs를 통해 main thread을 blocking하지 않고 비동기적으로 수행된다.
2. 이런 이벤트들은 백그라운드에서 이벤트 처리가 끝난 후, callback/task queue에 순차적으로 쌓이게 된다
3. 이렇게 쌓이게 된 이벤트들은 이벤트 루프에 의해 call stack이 비어있을 때 큐에서 나와 call stack에 쌓이게 된다.
-
싱글 스레드의 장/단점
- 장점:
- 새로운 스레드를 생성하거나 멀티 스레드를 관리하는 데 필요한 작업들을 하지 않아도 되어 적은 overhead (오버 헤드는 특정 기능을 수행하는데 드는 간접적인 시간, 메모리 등 자원을 말한다)를 가지고 있다.
* 실제로 멀티 쓰레드로 구현된 서비스에서는 이 동시성 문제에 대해 정말많은 신경을 쓴다. 하지만 자바스크립트는 단일 쓰레드로 실행되므로 인해 교착 상태와 같은 다중 쓰레드 환경에서 발생할 수 있는 복잡한 시나리오를 신경 쓸 필요가 없으며 비동기 처리를 통해 쉽게 여러 요청을 처리할 수 있다.
- I/O 작업이 많은 서버로 적합하다
- 단점: CPU intensive한 작업에는 적합하지 않다