Node.js의 싱글 스레드 비동기 처리 방식에 대해 설명하겠습니다. 이 개념을 이해하기 위해서는 **이벤트 루프(Event Loop)**와 비동기 I/O에 대해 알아야 합니다.
🔥 1. Node.js는 왜 싱글 스레드인가?
• 싱글 스레드: Node.js는 **단일 스레드(메인 스레드)**로 동작합니다.
• 하지만 **비동기 작업(파일 입출력, 네트워크 요청, 타이머 등)**은 백그라운드 스레드 (Node.js 내부에 있는 libuv 스레드 풀)에서 처리합니다.
• 이를 통해 메인 스레드는 멈추지 않고 계속해서 다음 작업을 처리할 수 있습니다.
🔥 2. 이벤트 루프(Event Loop)란?
• 이벤트 루프는 싱글 스레드의 핵심 메커니즘으로, 대기 중인 작업을 관리하고, 작업이 완료되었을 때 콜백을 실행하는 구조입니다.
• Node.js는 이벤트 루프를 통해 **비동기 작업(파일 입출력, 네트워크 요청 등)**이 완료되었을 때 콜백 함수를 실행합니다.
• 이벤트 루프는 아래의 6단계로 구성됩니다.
🔥 3. 이벤트 루프의 6단계 (단계별 이해)
1. Timers (타이머)
• setTimeout과 setInterval의 콜백이 실행됩니다.
2. I/O Callbacks
• 대부분의 **비동기 I/O 작업(파일 입출력, 네트워크 요청 등)**이 완료되었을 때, 콜백이 실행됩니다.
3. Idle, Prepare
• 내부적으로 libuv의 준비 작업이 이루어지는 단계로, 보통 사용자 코드와 관련이 없습니다.
4. Poll (폴링)
• 새로운 I/O 이벤트가 있는지 확인합니다.
• 주요 작업 단계로, 파일 입출력 콜백은 주로 여기서 실행됩니다.
5. Check
• setImmediate의 콜백이 실행됩니다.
6. Close Callbacks
• 소켓 연결과 같은 리소스를 닫는 작업이 실행됩니다.
🔥 4. 이벤트 루프가 요청을 처리하는 과정
이제 여러 요청이 연속으로 들어오는 상황에서 Node.js의 동작 방식을 단계별로 설명하겠습니다.
1️⃣ 요청 1, 요청 2, 요청 3이 들어옵니다.
2️⃣ Node.js의 메인 스레드는 각 요청에 대한 콜백을 이벤트 큐에 등록합니다.
3️⃣ **비동기 작업 (파일 입출력, 네트워크 요청 등)**은 백그라운드 스레드(pool)에서 실행됩니다.
4️⃣ 작업이 완료되면, 완료 신호가 이벤트 큐로 전달되고, 이벤트 루프가 대기 중인 콜백을 실행합니다.
5️⃣ 요청이 많아도, 메인 스레드는 절대 멈추지 않고 큐의 콜백을 순서대로 처리합니다.
🔥 5. 여러 요청이 동시에 처리되는지?
Node.js는 요청을 동시에 처리하지 않습니다.
대신, 비동기 I/O 작업이 동시에 실행될 수 있습니다.
자세한 설명
• 메인 스레드는 단일 스레드이므로 한 번에 하나의 자바스크립트 코드만 실행할 수 있습니다.
• 그러나, **백그라운드 스레드(libuv의 스레드 풀)**은 동시에 여러 비동기 작업을 실행할 수 있습니다.
• 예를 들어, 파일 읽기, API 호출, 데이터베이스 조회와 같은 비동기 작업은 동시에 실행됩니다.
• 메인 스레드는 대기 중인 콜백을 순차적으로 실행합니다.
🔥 6. 예시 코드로 이해하기
const fs = require('fs');
console.log('🚀 프로그램 시작');
// 비동기 파일 읽기 (이 작업은 libuv 스레드에서 수행됨)
fs.readFile('file1.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log('📄 file1.txt 읽기 완료');
});
// 비동기 파일 읽기 (동시에 스레드에서 처리됨)
fs.readFile('file2.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log('📄 file2.txt 읽기 완료');
});
console.log('🔄 메인 스레드의 다른 작업 수행');
🔥 7. 실행 순서 분석
1. console.log('🚀 프로그램 시작') 실행 (메인 스레드)
2. fs.readFile('file1.txt')을 백그라운드 스레드 풀에 위임
3. fs.readFile('file2.txt')을 백그라운드 스레드 풀에 위임
4. console.log('🔄 메인 스레드의 다른 작업 수행') 실행 (메인 스레드)
5. 백그라운드 스레드가 file1.txt와 file2.txt를 동시에 읽음
6. 작업이 완료되면 콜백 큐에 추가되며, 메인 스레드가 콜백을 실행합니다.
🔥 8. 동시성(Concurrency)과 병렬성(Parallelism)의 차이
• Node.js는 동시성(concurrency)을 제공합니다.
• 한 번에 하나의 작업만 처리하지만, 작업을 멈추지 않고 다른 작업을 진행합니다.
• 메인 스레드는 쉬지 않고 돌아가며 대기 중인 작업을 실행합니다.
• **병렬성(parallelism)**은 여러 스레드에서 작업이 동시에 실행되는 것을 의미합니다.
• Node.js의 libuv 스레드 풀 덕분에 파일 입출력, 네트워크 요청과 같은 비동기 작업은 병렬로 처리됩니다.
🔥 9. 중요한 개념 요약
용어 의미
싱글 스레드 메인 스레드는 하나뿐입니다.
이벤트 루프 대기 중인 작업을 관리하고, 완료되면 콜백을 실행합니다.
비동기 작업 파일 I/O, 네트워크 요청 등은 백그라운드 스레드에서 처리됩니다.
백그라운드 스레드 libuv 스레드 풀에 의해 실행됩니다.
콜백 큐 작업 완료 후 실행할 콜백이 여기에 들어옵니다.
동시성 여러 작업이 대기 없이 진행되는 것 (병렬은 아님)
병렬성 여러 스레드에서 작업을 동시에 실행하는 것 (libuv 스레드 풀에서 발생)
🔥 10. 그림으로 이해하기 (단순화)
[ Main Thread ] → 이벤트 루프 → 콜백 실행
↓
[ 백그라운드 스레드 ] → 비동기 작업(파일 I/O, 네트워크 요청 등)
🔥 11. 요약
• Node.js는 싱글 스레드지만, libuv 스레드 풀 덕분에 비동기 I/O 작업이 병렬로 실행됩니다.
• 이벤트 루프는 콜백을 대기 중에 추가하고, 하나씩 실행합니다.
• 여러 요청이 들어오면 비동기 I/O는 동시에 진행되지만, 메인 스레드는 콜백을 순차적으로 처리합니다.
• 즉, Node.js는 비동기와 병렬성을 통해 높은 동시성 처리 능력을 갖추고 있습니다.
'Programming > Node.js' 카테고리의 다른 글
Node.js의 성능을 극대화 하기위한 블로킹 작업 피하기 (1) | 2024.12.21 |
---|---|
[.nvmrc]를 활용한 Node.js 버전 관리 (0) | 2024.08.06 |
Node.js의 Event Loop (0) | 2024.05.27 |
Node.js의 동기와 비동기 (0) | 2023.05.14 |