🎁 지금 가입하면 온라인 AI를 최대 30분 무료로 사용할 수 있습니다. 신용카드는 필요하지 않습니다.

Node.js 면접 질문과 답변: 이벤트 루프, 비동기, API, 확장

September 3, 2026
이벤트 루프, 비동기 패턴, Express, 스트림, 메모리 누수, 보안, 확장에 대한 답변과 코드가 포함된 Node.js 면접 질문.
Node.js 면접 질문과 답변: 이벤트 루프, 비동기, API, 확장
node js interview questions
nodejs interview questions and answers
node event loop interview
express interview questions

Node.js 면접은 이벤트 루프와 비동기 코드에서 시작해 API, 에러 처리, 스트림, 성능, 보안으로 이어집니다. 지원자가 가장 자주 발목을 잡히는 지점은 이벤트 루프를 마법처럼 설명하는 것입니다. 무엇이 어디서 실행되고 무엇이 블로킹되는지를 명확히 설명하는지가 면접관이 듣고자 하는 핵심입니다.

아래는 답변과 함께 정리한 24개의 질문입니다. 코드 예제는 기억만으로 타이핑할 수 있도록 짧게 구성했습니다.

이벤트 루프와 비동기

1. Node.js란 무엇인가요?

Chrome의 V8 엔진 위에서 동작하며 브라우저 밖에서 실행되는 JavaScript 런타임입니다. JavaScript는 단일 스레드 이벤트 루프로 실행하고 I/O는 논블로킹 방식으로 처리하기 때문에, 대부분의 시간을 대기하는 데 쓰는 다수의 연결을 잘 다룹니다.

2. 이벤트 루프는 어떻게 동작하나요?

JavaScript 코드는 하나의 스레드에서 실행됩니다. 파일 읽기나 요청 전송 같은 I/O 작업을 시작하면 Node는 그 작업을 시스템이나 스레드 풀에 넘기고 계속 진행합니다. 작업이 끝나면 콜백이 큐에 들어가고, 콜 스택이 비었을 때 이벤트 루프가 이를 실행합니다. 루프는 타이머, 대기 중인 콜백, 폴(I/O), 체크(setImmediate), 종료 콜백 단계를 거칩니다.

3. process.nextTick, Promise, setTimeout, setImmediate의 실행 순서는 어떻게 되나요?

console.log('1 sync');
setTimeout(() => console.log('4 timeout'), 0);
setImmediate(() => console.log('5 immediate'));
Promise.resolve().then(() => console.log('3 promise'));
process.nextTick(() => console.log('2 nextTick'));

동기 코드가 먼저 실행됩니다. 그다음 process.nextTick 콜백, 그다음 프로미스 마이크로태스크, 그다음 루프 단계가 실행됩니다. 메인 모듈에서는 setTimeout(0)과 setImmediate의 순서가 달라질 수 있지만, I/O 콜백 안에서는 setImmediate가 항상 먼저 실행됩니다. 단순히 외우지 말고 설명할 수 있어야 합니다.

4. "이벤트 루프를 블로킹한다"는 무슨 뜻이며, 어떻게 피하나요?

거대한 JSON 파싱, 큰 루프, 요청 핸들러에서의 fs.readFileSync 같은 긴 동기 작업은 그것이 끝날 때까지 다른 모든 요청을 멈춥니다. 비동기 API를 사용하거나, 작업을 여러 청크로 나누거나, CPU를 많이 쓰는 작업을 워커 스레드나 다른 프로세스로 옮겨서 피할 수 있습니다.

5. 콜백, 프로미스, async/await의 차이는 무엇인가요?

콜백은 원래 방식이며 깊게 중첩될 수 있습니다. 프로미스는 미래의 값을 나타내고 then으로 체이닝합니다. async/await는 프로미스 위에 얹은 문법으로 동기 코드처럼 읽히고 try/catch와 함께 사용할 수 있습니다.

6. 비동기 작업을 병렬로 실행하려면 어떻게 하나요?

const [user, orders] = await Promise.all([getUser(id), getOrders(id)]);

Promise.all은 하나라도 실패하면 거부됩니다. Promise.allSettled는 모두 기다린 뒤 각 결과를 알려줍니다. Promise.race는 가장 먼저 완료된 것을 반환합니다. 호출이 서로 독립적일 때는 루프 안에서 await를 쓰지 마세요.

7. 워커 스레드, 자식 프로세스, 클러스터의 차이는 무엇인가요?

워커 스레드는 한 프로세스 안의 별도 스레드에서 JavaScript를 실행하며 메모리를 공유할 수 있어 CPU를 많이 쓰는 작업에 적합합니다. 자식 프로세스는 별도의 프로그램을 시작합니다. 클러스터 모듈은 앱의 복사본을 코어 수만큼 포크하고 포트를 공유하므로, 요청 처리에 모든 CPU를 활용할 수 있습니다.

모듈과 도구

8. CommonJS와 ES 모듈의 차이는 무엇인가요?

CommonJS는 require와 module.exports를 사용하고 동기적으로 로드합니다. ES 모듈은 import와 export를 사용하며 JavaScript의 표준이고 최상위 await를 지원합니다. Node는 둘 다 지원하며, 파일 확장자나 package.json의 type 필드로 선택합니다.

9. package.json에는 무엇이 들어가며, dependencies와 devDependencies의 차이는 무엇인가요?

메타데이터, 스크립트, 의존성이 들어갑니다. dependencies는 런타임에 필요하고, devDependencies는 개발과 테스트에만 필요합니다. lock 파일은 정확한 버전을 기록해 설치를 재현 가능하게 만듭니다.

10. 환경 설정은 어떻게 관리하나요?

환경 변수를 사용하고 process.env를 통해 읽되, 검증된 설정 모듈을 거칩니다. 시크릿은 저장소에 두지 말고, 프로덕션에서는 시크릿 매니저를 사용하세요.

API와 Express

11. Express에서 미들웨어란 무엇인가요?

요청, 응답, next에 접근할 수 있는 함수입니다. 미들웨어는 순서대로 실행되며 요청을 수정하거나, 응답을 끝내거나, 제어를 넘길 수 있습니다. 로깅, 본문 파싱, 인증, 에러 처리에 주로 사용합니다.

app.use((req, res, next) => {
  console.log(req.method, req.url);
  next();
});

12. Express 앱에서 에러는 어떻게 처리하나요?

비동기 핸들러에서 에러를 잡아 next(err)로 넘기고, 네 개의 인자 (err, req, res, next)를 받는 에러 처리 미들웨어로 일관된 응답을 보냅니다. Express 5에서는 핸들러에서 거부된 프로미스가 자동으로 전달됩니다. 잡히지 않은 예외와 처리되지 않은 거부에 대해서는 알 수 없는 상태로 계속 실행하지 말고 로그를 남기고 프로세스를 재시작하세요.

13. 주문을 생성하는 REST API 엔드포인트를 어떻게 설계하시겠어요?

입력을 검증하고, 사용자를 인증하고, 권한을 확인하고, 데이터베이스 트랜잭션 안에서 주문을 생성하고, 새 리소스와 그 위치와 함께 201을 반환하고, 멱등성 키로 중복을 처리하고, 적절한 상태 코드와 함께 명확한 에러를 반환합니다.

14. 사용자 인증은 어떻게 하나요?

쿠키를 사용하는 세션, 또는 JWT 같은 토큰을 사용합니다. 비밀번호는 bcrypt나 argon2 같은 느린 알고리즘으로 해시합니다. JWT를 쓸 때는 만료를 짧게 유지하고, 리프레시 토큰을 신중히 사용하며, 토큰에 민감한 데이터를 저장하지 마세요.

스트림, 파일, 성능

15. 스트림이란 무엇이며, 왜 사용하나요?

스트림은 데이터를 한꺼번에 메모리에 올리는 대신 청크 단위로 처리합니다. 종류로는 읽기 가능(readable), 쓰기 가능(writable), 듀플렉스(duplex), 변환(transform)이 있습니다. 대용량 파일, 업로드, 다운로드에 사용하세요.

const fs = require('node:fs');
const { pipeline } = require('node:stream/promises');
const zlib = require('node:zlib');
await pipeline(fs.createReadStream('in.log'), zlib.createGzip(), fs.createWriteStream('in.log.gz'));

16. 배압(backpressure)이란 무엇인가요?

쓰기 가능한 스트림이 읽기 가능한 스트림의 속도를 따라가지 못할 때, 소스에 속도를 늦추라고 신호를 보냅니다. pipeline과 pipe가 이를 대신 처리해 줍니다. 직접 작성한다면 write()의 반환값을 확인하고 drain 이벤트를 기다리세요.

17. 메모리 누수는 어떻게 찾나요?

시간에 따른 메모리를 관찰하고, 힙 스냅샷을 찍어(Chrome DevTools 또는 --inspect) 서로 비교해 어떤 객체가 계속 늘어나는지 확인하세요. 흔한 원인은 만료되지 않는 전역 캐시, 제거되지 않은 이벤트 리스너, 큰 객체를 붙잡고 있는 클로저입니다.

18. Node.js 애플리케이션은 어떻게 확장하나요?

cluster 모듈이나 프로세스 매니저로 여러 프로세스를 실행하고, 로드 밸런서 뒤에 배치하며, 세션을 Redis나 데이터베이스로 옮겨 앱을 무상태(stateless)로 유지하고, 캐싱을 활용하며, 컨테이너로 스케일 아웃하세요. CPU를 많이 쓰는 작업은 워커나 별도 서비스로 옮기세요.

19. 느린 엔드포인트는 어떻게 프로파일링하나요?

먼저 로그와 타이밍으로 측정한 뒤, --prof나 --cpu-prof, 또는 플레임 그래프 도구를 사용해 핫 함수를 찾으세요. 데이터베이스 쿼리도 확인하세요. 느린 원인은 JavaScript보다 그쪽에 있는 경우가 더 많습니다.

보안과 안정성

20. 흔한 Node.js 보안 문제는 무엇인가요?

인젝션(SQL, NoSQL, 명령), 크로스 사이트 스크립팅, 취약한 인증, 취약한 의존성, 코드 내 시크릿, 누락된 속도 제한, 안전하지 않은 역직렬화 등이 있습니다. 입력 검증, 파라미터화된 쿼리, helmet, 의존성 감사(npm audit), 최소 권한 원칙으로 완화하세요.

21. 우아하게 종료하려면 어떻게 하나요?

SIGTERM을 받으면 새 연결 수락을 중단하고, 처리 중인 요청이 끝나게 한 뒤, 데이터베이스 연결을 닫고 종료하되, 대비책으로 타임아웃을 두세요.

process.on('SIGTERM', () => {
  server.close(() => process.exit(0));
});

22. Node.js 코드는 어떻게 테스트하나요?

내장 node:test, Jest, Vitest 같은 러너로 외부 호출을 모킹하며 단위 테스트를 작성하세요. 테스트 데이터베이스를 사용한 통합 테스트와 Supertest 같은 도구로 HTTP 수준 테스트를 하세요. 테스트는 빠르고 독립적으로 유지하세요.

설계와 시나리오

23. 부하가 걸리면 API가 느려집니다. 어떻게 조사하나요?

지연 시간과 CPU 지표를 확인하세요. 한 코어에서 CPU가 높다면 블로킹 코드나 과도한 JSON 작업을 찾으세요. CPU는 낮은데 지연 시간이 높다면 데이터베이스나 다른 서비스를 기다리는 부분을 살펴보세요. 그런 다음 캐싱, 인덱스, 커넥션 풀링, 배칭을 추가하고 부하 상태에서 다시 테스트하세요.

24. 대용량 파일을 위한 파일 업로드 엔드포인트는 어떻게 만드나요?

메모리에 버퍼링하는 대신 업로드를 스토리지로 바로 스트리밍하세요. 예를 들어 사전 서명된 URL(pre-signed URL)을 사용하는 객체 스토리지가 좋습니다. 크기 제한을 설정하고, 타입을 검증하고, 필요하면 스캔한 뒤, 이후 백그라운드 작업으로 처리하세요.

준비 방법

인증, 데이터베이스, 업로드 라우트가 있는 작은 API를 작성한 뒤, 부하 도구로 프로파일링하고 문제 하나를 해결하세요. 이벤트 루프를 그려 보고 위와 같은 작은 스크립트의 출력을 설명하는 연습을 하세요. 성능이나 안정성 문제를 디버깅한 실제 경험 하나를 준비하세요. 코딩 라운드는 코딩 인터뷰 어시스턴트 가이드를, 설계는 시스템 디자인 가이드를 참고하세요.

답변을 소리 내어 말하고, 용어를 설명 없이 사용한 부분이 있는지 녹취록을 읽어 보세요. 실시간 인터뷰에서는 AI 도구에 관한 고용주의 규칙을 따르세요.

YesToTheOffer로 Node.js 면접 답변을 연습하세요

모의 기술 면접을 진행하고, 이벤트 루프를 소리 내어 설명하고, 이후 녹취록을 검토하세요. 30분 무료, 구독 없음.

iOS & Android — 출시 예정
요금 보기