본문 바로가기

카테고리 없음

Node js의 동작원리와 핵심기술

Node.js란?

Node.js는 자바스크립트를 브라우저 밖, 즉 서버에서도 실행할 수 있게 해주는 런타임입니다. 프론트엔드 개발자가 백엔드 영역까지 확장할 수 있게 해주었고, 빠른 비동기 처리를 기반으로 대규모 실시간 시스템에서 자주 활용됩니다.

정리하자면, Node.js는 Chrome V8 JavaScript 엔진 위에서 동작하는 JavaScript 런타임입니다.

(쉽게 말하면, 브라우저 없이도 JavaScript 코드를 실행할 수 있게 해주는 환경입니다.)

  • 최초 릴리즈: 2009년
  • 개발자: Ryan Dahl
  • 주요 특징:
    • 이벤트 기반
    • 논블로킹 I/O
    • 싱글 스레드 처리

 

Node.js의 동작 원리

1. V8 엔진

Node.js는 Google Chrome의 V8 엔진 위에서 동작합니다. 이 엔진은 JavaScript 코드를 기계어로 바로 컴파일하여 빠르게 실행합니다.

  • JavaScript → V8 → 머신코드 → 실행
  • 고성능 처리를 위한 핵심 요소 중 하나

 

2. 이벤트 기반 처리

Node.js는 I/O 작업을 처리할 때 이벤트 기반(Event-driven) 구조를 채택합니다.

 

fs.readFile('test.txt', (err, data) => { 
	if (err) throw err; 
    console.log(data.toString());
}); console.log('파일 읽기 요청 완료');

readFile은 파일을 읽는 동안 블로킹하지 않고, 바로 다음 줄을 실행한 뒤 완료되면 콜백을 호출합니다.

 

3. 싱글 스레드 + 논블로킹 I/O

Node.js는 싱글 스레드로 작동하지만, I/O 작업은 내부적으로 스레드 풀(libuv)을 사용해 처리합니다.

(코드는 한 줄씩 순차적으로 실행되지만, I/O 작업은 병렬로 처리돼 결과만 콜백으로 받아옴)

 

 

 

 

이벤트 루프(Event Loop)

Node.js가 싱글 스레드임에도 동시성을 구현하는 핵심 기술은 이벤트 루프입니다.

이벤트 루프는 아래처럼 동작합니다.

  1. 호출 스택(Call Stack)
  2. 백그라운드(파일 시스템, 네트워크 등)
  3. 태스크 큐(Callback Queue)
  4. 이벤트 루프가 태스크 큐를 확인하고 스택이 비면 콜백 실행

 

 

추가적으로 핵심기술에 대해 조금 더 디테일하게 알아보겠습니다.

 

V8 JavaScript Engine – 초고속 JS 실행의 비결

V8은 Google이 개발한 오픈소스 JavaScript 엔진으로, Chrome과 Node.js에서 모두 사용됩니다.

특징:

  • Just-In-Time (JIT) 컴파일: JS 코드를 실행 중에 기계어로 변환하여 속도 향상
  • 메모리 관리: 가비지 컬렉션과 힙 관리를 통해 안정적인 실행
  • 빠른 실행: JS를 바이트코드가 아닌, 바로 네이티브 코드로 실행

-> V8은 JavaScript를 해석하지 않고, 바로 실행 가능한 네이티브 코드로 바꿔 빠르게 처리

 

libuv – Node.js의 I/O 마스터

Node.js의 비동기성과 이벤트 기반 I/O는 libuv라는 C 기반 라이브러리 덕분입니다.

libuv의 역할:

  • 비동기 파일 시스템 접근
  • 네트워크 소켓 처리 (TCP/UDP)
  • 스레드 풀 (Thread Pool) 관리
  • 이벤트 루프와 통신하여 작업 완료 통지

구조 요약:

  • I/O 요청이 들어오면 libuv가 OS 레벨 비동기 API 또는 스레드 풀을 통해 처리
  • 작업 완료 시 Node.js로 콜백 알림

Ex) fs.readFile()을 호출하면, 실제로는 libuv가 백그라운드에서 처리한 후 콜백을 호출해주는 구조

 

싱글 스레드지만 멀티태스킹 – 이벤트 루프의 위엄

Node.js는 JavaScript 실행 자체는 싱글 스레드입니다. 하지만 동시에 수천 개의 요청을 처리할 수 있습니다. 비밀은 바로 이벤트 루프(Event Loop) 입니다.

이벤트 루프 구조:

  1. Call Stack: JS 코드가 실행되는 공간 (순차적 실행)
  2. Task Queue: 완료된 비동기 작업의 콜백이 쌓이는 큐
  3. Event Loop: Call Stack이 비면 Task Queue의 콜백을 가져와 실행
  4. libuv: 타이머, I/O, OS 작업들을 Event Loop와 연결
예시

console.log("Start"); 
setTimeout(() => { 
	console.log("Timer Done"); 
}, 1000); 

console.log("End"); 

// 출력 결과: // Start // End // Timer Done

-> setTimeout의 콜백은 libuv의 타이머에서 대기하다 이벤트 루프에 의해 실행됨

 

비동기 처리 방식 – Non-blocking I/O

Node.js는 논블로킹이라는 I/O 모델을 사용합니다. 이는 하나의 요청이 끝날 때까지 기다리지 않고, 그 사이 다른 요청을 처리할 수 있게 합니다.

 
예시

const fs = require('fs'); 
fs.readFile('file.txt', 'utf8', (err, data) => 
	{ console.log(data); 
}); 
console.log("파일 읽는 중...");


파일이 완전히 읽히기 전에 "파일 읽는 중..."이 먼저 출력됨

 

중요한 이유

  • 동시 사용자 수가 많은 서버에 유리
  • 블로킹 없이 네트워크, DB, 파일 등을 효율적으로 처리 가능