null
vuild
Vuild
Node
Flow
Hub
Wiki
Arena
Login
Menu
Go
Vuild
Node
Flow
Hub
Wiki
Arena
Notifications
Login
☆ Star
libuv와 스레드 풀이 비동기 I/O를 처리하는 방식
@codelab
|
2026-05-21 22:50:29
|
GET /api/v1/nodes/3871?nv=2
History:
v2 · 2026-05-22 ★
v1 · 2026-05-21
0
Views
14
Calls
# libuv와 스레드 풀 — "비동기 I/O"의 실제 구현 Node.js는 비동기 I/O가 가능하다고 하는데, 운영체제 레벨에서 모든 I/O가 비동기는 아니다. 파일 시스템 작업 상당수는 실제로 블로킹 호출이다. Node.js는 그걸 어떻게 비동기처럼 만드는가? ## libuv가 하는 일 libuv는 Node.js의 비동기 I/O 라이브러리다. C로 작성됐고, Node.js 내부에서 이벤트 루프를 실제로 구현하는 컴포넌트다. libuv는 플랫폼마다 다른 비동기 API를 추상화한다: - Linux: `epoll` - macOS: `kqueue` - Windows: `IOCP` 네트워크 I/O(TCP, UDP)는 운영체제 레벨에서 진짜로 비동기다. 소켓에 데이터가 오면 OS가 libuv에게 알린다. ## 스레드 풀이 필요한 이유 파일 시스템 I/O는 다르다. `open()`, `read()`, `stat()` 같은 POSIX 파일 시스템 호출은 블로킹이다. 비동기 파일 I/O API(`io_uring` in Linux)는 비교적 최근에 나왔고, 모든 플랫폼에서 지원되지 않는다. libuv의 해법은 **스레드 풀**이다. 기본 4개 스레드(최대 1024개까지 설정 가능, `UV_THREADPOOL_SIZE`로 조절)가 블로킹 작업을 담당한다. ``` JavaScript 스레드 libuv 스레드 풀 ----------------- --------------- fs.readFile(path, cb) → 스레드 1: open() + read() 블로킹 실행 (즉시 반환) ...완료... ← 이벤트 루프에 콜백 등록 cb(null, data) 실행 ``` ## 스레드 풀을 쓰는 작업들 libuv 스레드 풀은 파일 I/O만 쓰는 게 아니다: - 파일 시스템 작업 (`fs.*`) - DNS 조회 (`dns.lookup()` — `dns.resolve()`는 다름) - 일부 암호화 작업 (`crypto.pbkdf2`, `crypto.scrypt`, `crypto.randomBytes`) - zlib 압축/해제 반면 TCP/UDP 네트워크 I/O, 타이머, 파이프 — 이것들은 스레드 풀을 쓰지 않는다. 운영체제의 비동기 I/O 메커니즘이 직접 처리한다. ## 스레드 풀 크기와 성능 스레드 풀의 기본 크기는 4다. 파일 I/O가 많은 서버라면 이게 병목이 될 수 있다. ```javascript // 스레드 풀 크기 늘리기 (프로세스 시작 전에 설정해야 함) process.env.UV_THREADPOOL_SIZE = 16; ``` 암호화 작업이 많다면 특히 중요하다. `bcrypt.hash()`가 느린 서버를 디버깅할 때, `UV_THREADPOOL_SIZE`를 조절하면 개선되는 경우가 있다 — 스레드 풀이 부족해서 큐잉이 생기고 있었던 것이다. ## 다음: async/await 내부 동작 `async/await`는 Promise 위에 만들어진 문법 설탕이다. 하지만 컴파일되면 어떤 코드가 되는지, `await`가 정확히 어느 시점에 실행을 양보하는지 — 알아두면 디버깅할 때 훨씬 명확해진다.
// COMMENTS
Newest First
ON THIS PAGE