이벤트 루프로 이해하는 Node.js 비동기 처리

이벤트 루프란 무엇인가

Node.js는 단일 스레드로 동작하지만, 수많은 요청을 동시에 처리하는 것처럼 보입니다. 그 비밀이 바로 이벤트 루프(Event Loop)입니다. 이벤트 루프는 자바스크립트 엔진이 처리할 작업이 없을 때, 대기 중인 콜백 함수들을 순서에 맞게 실행시켜주는 일종의 ‘작업 관리자’입니다. Node.js는 파일 읽기, 네트워크 요청 같은 시간이 오래 걸리는 작업을 libuv라는 라이브러리에 위임하고, 그 작업이 끝나면 콜백을 이벤트 루프에 등록해 실행하는 구조로 동작합니다.

동작 원리를 식당에 비유해보기

이벤트 루프를 이해하기 좋은 비유는 ‘1인 셰프가 운영하는 식당’입니다. 셰프(메인 스레드)는 한 번에 한 가지 요리만 만들 수 있습니다. 하지만 손님이 주문한 오래 걸리는 요리(예: 오븐에 굽는 요리)는 오븐(백그라운드 스레드풀)에 맡겨두고, 셰프는 곧바로 다음 손님의 주문을 받습니다. 오븐에서 요리가 다 되면 벨이 울리고, 셰프는 그 요리를 마무리해서 내보냅니다.

실제 코드로 보면 다음과 같습니다.

  • console.log('주문 접수') – 즉시 실행되는 동기 코드
  • fs.readFile() – 오래 걸리는 작업이라 백그라운드로 위임
  • 콜백 함수 – 작업이 끝난 뒤 이벤트 루프가 실행

이런 방식 덕분에 셰프(스레드)는 한 손님의 요리가 끝날 때까지 멍하니 기다리지 않고, 계속 다른 일을 처리할 수 있습니다. 이것이 바로 Node.js가 ‘논블로킹(Non-blocking) I/O’를 구현하는 핵심 원리입니다.

실무에서 왜 중요한가

이벤트 루프를 이해하면 왜 Node.js가 대량의 동시 접속을 적은 자원으로 처리할 수 있는지 알 수 있습니다. 예를 들어 웹 서버가 수천 개의 요청을 동시에 받아도, 각 요청이 파일이나 DB 작업을 기다리는 동안 스레드를 점유하지 않기 때문에 효율적으로 확장할 수 있습니다.

반대로 이벤트 루프의 원리를 모르면, CPU 연산이 많은 작업(예: 복잡한 반복문, 대용량 데이터 정렬)을 동기적으로 처리하다가 전체 서버가 멈추는 실수를 하기 쉽습니다. 이벤트 루프는 I/O 대기 시간을 효율적으로 활용할 뿐, CPU 작업 자체를 병렬로 처리해주지는 않기 때문입니다. 그래서 무거운 연산은 별도 워커 스레드나 프로세스로 분리하는 것이 실무에서 흔히 쓰이는 전략입니다.

결국 이벤트 루프는 Node.js의 성능과 한계를 동시에 설명해주는 핵심 개념이며, 비동기 코드를 다룰 때 반드시 짚고 넘어가야 할 기초 지식입니다.

댓글 남기기