이미지 출처: https://docs.libuv.org/en/v1.x/index.html
도움: chatgpt, stackoverflow 등. chatgpt는 부정확한 내용이 조금 있어서 구글링 도움을 많이 받음.
노드는 비동기 + 이벤트 기반 모델을 기반으로 작동한다. 일반적으로 single thread, non-blocking I/O, event loop를 노드의 특징으로 설명하는데, 이러한 핵심 동작 원리는 내부적으로 C언어 기반으로 작성된 libuv가 수행한다.
libuv
libuv는 Node.js의 이벤트 기반 비동기 I/O 모델을 지원하기 위해 작성된 크로스 플랫폼 라이브러리로, 노드는 내부적으로 시간이 오래 걸리는 작업(File I/O, DNS 연산 등)을 libuv에 위임하여 처리한다. 해당 작업 중 일부는 libuv 내부 정의된 스레드풀을 이용하여 처리하고, 일부는 운영체제에게 위임한다.
내부적으로 들어가면 파일 I/O나 네트워킹이나 운영체제의 시스템 콜 호출에 의해 처리되지만, 파일 I/O의 경우 크로스 플랫폼에서 동작하는 비동기 디스크 API가 마땅치 않아서 스레드 풀에서 blocking I/O 방식으로 처리한다고 한다.
node의 핵심 동작 구조인 이벤트 루프 역시 libuv에 의해 지원된다. 이벤트 루프 동작 단계는 다음과 같다.
- 이벤트 루프가 시작될 때 "현재(now)" 시간 개념을 초기화한다. libuv의 어떤 작업이나 이벤트는 현재 시간과 비교하여 언제 실행될지 결정되는데, 이를 위해 초기 시간을 지정하는 부분이다. ( 초기 시간 설정 )
ex) 타이머 작업은 현재 시간 + 시간 간격이 되는 시점에 실행되어야 하므로, 초기 시간을 알 필요가 있다. - 루프가 UV_RUN_DEFAULT로 동작하면 Due timer이 동작한다. due timer은 libuv에서 제공하는 타이머 기능 중 하나로, 특정 시간이 지난 후 작업을 예약하고 실행할 수 있도록 도와주며, 특정 간격 이후 작업을 실행하도록 계획하는 데 사용된다. ( 타이머 실행 )
- 루프가 활성 상태(loop alive)라면 루프를 반복, 아니면 종료한다. 루프는 active / ref'd 핸들, active request 또는 close handle이 활성 상태인 경우 지속된다.
- Pending Callback을 호출한다. I/O 콜백은 일반적으로 I/O 풀링 직후에 실행되지만, 이벤트 루프 반복을 위해 연기되기도 한다. 이렇듯 이전 루프에서 I/O 콜백 실행이 연기된 경우 현재 루프의 Pending Callback 단계에서 처리된다.
- Idle Handle이 호출된다. 이름(idle = 유휴)과는 달리 루프가 반복될 때마다 콜백을 호출하며, I/O blocking 대신 zero timeout pool을 수행하는 점이 perpare handle과 다른 점이라고 한다.
- Prepare Handle이 호출된다. 이 핸들은 I/O 블로킹 전에 콜백을 호출한다.
- 폴링 제한 시간이 계산된다. 계산된 시간은 I/O polling에 사용된다. ( 자세한 규칙은 공식 문서 참고 )
- I/O 작업을 위해 루프가 블록된다. 이전 단계에서 계산된 폴링 제한 시간 만큼 지속되며, read/write 작업 I/O 관련 핸들은 이 시점에 콜백을 호출한다.
- Check Handle이 호출된다. I/O 작업에 의해 루프가 블록되자마자 자신의 콜백을 호출하며, 근본적으로 Prepare Handle과 반대 위치에 있다고 한다.
- Close Callback이 호출된다. 핸들이 uv_close( ) 에 의해 닫히면 close callback을 호출한다.
- 루프의 "현재(now)" 시간 개념이 업데이트된다.
- Due timer이 동작한다. 루프의 현재 시간은 다음 이벤트 루프 시작 전까지 갱신되지 않으므로, 루프 동작 도중에 타이머가 만료되더라도 다음 이벤트 루프 시작 전까지는 실행되지 않는다.
- 반복이 종료된다.
※ 파일 I/O는 스레드 풀에 의해 병렬 처리될 수 있지만 네트워크 I/O는 항상 단일 스레드, 즉 이벤트 루프에서 처리된다( 시스템 API 기반). Node.js에서 스레드 풀에서 처리되도록 정의된 것은 DNS lookup, fs, crypto, zlib 라이브러리 정도.
'javascript > nodejs' 카테고리의 다른 글
[nodejs] thread pool (0) | 2023.08.16 |
---|---|
[nodejs] esbuild 전체 폴더 감시하기 (0) | 2023.05.30 |
[nodejs] express-session typescript와 사용하기 (0) | 2023.03.21 |
[nodejs] prisma ORM 라이브러리 (0) | 2023.02.22 |
[nodejs] mysql2 라이브러리 (0) | 2023.02.14 |