Node.js 미드레벨 기술면접

Node.js 미드레벨 (3~7년) 코딩 · 알고리즘 5문항 조회수 61 · 2026-06-01 (월) 03:10:52
1 비동기 프로그래밍
Medium

Q. Node.js에서 async/await를 사용할 때 여러 개의 독립적인 비동기 작업을 순차적으로 실행하는 것과 병렬로 실행하는 것의 성능 차이를 설명하고, Promise.all(), Promise.allSettled(), Promise.race()의 차이점과 각각의 적절한 사용 사례를 설명해주세요.

A. 모범답안

순차 실행(await를 연속으로 사용)은 각 작업이 완료될 때까지 기다리므로 전체 실행 시간이 모든 작업 시간의 합이 됩니다. 병렬 실행(Promise.all 등)은 동시에 시작하므로 가장 긴 작업 시간만큼만 걸립니다. Promise.all()은 모든 Promise가 성공해야 하며 하나라도 실패하면 즉시 reject됩니다. Promise.allSettled()는 모든 Promise의 성공/실패 여부와 관계없이 모든 결과를 반환합니다. Promise.race()는 가장 먼저 완료되는 Promise의 결과를 반환하며, 타임아웃 구현이나 fallback 전략에 유용합니다.

핵심 포인트
  • • 독립적인 비동기 작업은 병렬 실행으로 성능 향상 가능
  • • Promise.all()은 모두 성공해야 하는 경우, allSettled()는 부분 실패 허용
  • • Promise.race()는 가장 빠른 응답 선택 시 사용
Follow-up 질문

Promise.allSettled()를 사용하여 여러 외부 API 호출 결과를 처리할 때, 일부 API가 실패한 경우 어떻게 핸들링하는 것이 좋을까요?

2 보안
Hard

Q. Node.js 애플리케이션에서 SQL Injection과 NoSQL Injection의 차이점을 설명하고, 각각의 공격 원리와 방어 방법을 구체적으로 설명해주세요. 특히 MongoDB를 사용할 때 query selector injection을 막는 방법을 포함해주세요.

A. 모범답안

SQL Injection은 SQL 쿼리 문자열에 악의적인 SQL 구문을 삽입하는 공격이며, Prepared Statement나 Parameterized Query로 방어합니다. NoSQL Injection은 JSON 객체 형태로 전달되는 쿼리에 $where, $gt 같은 연산자를 삽입하여 인증을 우회하거나 데이터를 탈취하는 공격입니다. MongoDB에서는 사용자 입력을 직접 쿼리에 사용하지 않고, 입력 값의 타입을 검증하며, $where 연산자 사용을 피하고, mongo-sanitize 같은 라이브러리로 쿼리 연산자를 제거해야 합니다. ORM/ODM(Sequelize, Mongoose)을 사용하면 기본적인 방어가 가능하지만, 동적 쿼리 생성 시에는 여전히 주의가 필요합니다.

핵심 포인트
  • • SQL Injection은 문자열 기반, NoSQL Injection은 객체 기반 공격
  • • Parameterized Query와 입력 타입 검증이 핵심 방어책
  • • MongoDB에서 $where, $regex 등 연산자 주입 방지 필요
Follow-up 질문

사용자 입력을 받아서 MongoDB의 정규표현식 검색을 구현해야 할 때, ReDoS(Regular Expression Denial of Service) 공격을 어떻게 방어할 수 있을까요?

3 성능 최적화
Medium

Q. Node.js 애플리케이션에서 require() 또는 import의 모듈 로딩 성능을 최적화하는 방법을 설명하고, Dynamic Import를 사용하여 초기 로딩 시간을 개선하는 전략과 주의사항을 설명해주세요.

A. 모범답안

require()는 동기적으로 모듈을 로드하고 캐싱하므로, 애플리케이션 시작 시 모든 모듈이 한 번에 로드되어 초기 구동 시간이 길어질 수 있습니다. Dynamic Import(import())를 사용하면 필요한 시점에 비동기적으로 모듈을 로드할 수 있어, 초기 로딩 시간을 단축하고 메모리 사용을 최적화할 수 있습니다. 특히 조건부로 사용되는 무거운 라이브러리나 특정 라우트에서만 필요한 모듈은 Dynamic Import로 지연 로딩하는 것이 효과적입니다. 다만 런타임에 모듈을 로드하므로 첫 사용 시 지연이 발생할 수 있고, 에러 핸들링을 반드시 구현해야 합니다.

핵심 포인트
  • • require()는 동기, import()는 비동기 모듈 로딩
  • • 조건부 사용 모듈과 무거운 라이브러리는 Dynamic Import로 지연 로딩
  • • 첫 사용 시 로딩 지연과 에러 핸들링 고려 필요
Follow-up 질문

Webpack이나 번들러를 사용하는 환경에서 Dynamic Import를 사용할 때 코드 스플리팅은 어떻게 동작하나요?

4 데이터베이스
Hard

Q. Node.js에서 트랜잭션을 구현할 때 발생할 수 있는 Deadlock 상황을 설명하고, 이를 방지하거나 해결하기 위한 전략을 데이터베이스 레벨과 애플리케이션 레벨로 나누어 설명해주세요. 특히 Sequelize나 TypeORM 같은 ORM을 사용할 때의 주의사항도 포함해주세요.

A. 모범답안

Deadlock은 두 개 이상의 트랜잭션이 서로가 점유한 리소스를 기다리며 무한 대기 상태에 빠지는 현상입니다. 데이터베이스 레벨에서는 트랜잭션 타임아웃 설정, 데드락 감지 및 자동 롤백 기능을 활용하고, 인덱스를 최적화하여 락 범위를 최소화해야 합니다. 애플리케이션 레벨에서는 모든 트랜잭션에서 테이블 접근 순서를 일관되게 유지하고, 트랜잭션 범위를 최소화하며, 낙관적 락(Optimistic Locking)을 활용할 수 있습니다. ORM 사용 시에는 자동 생성되는 쿼리의 실행 순서를 파악하고, 명시적으로 락 레벨(FOR UPDATE)을 지정하며, 트랜잭션 격리 수준을 적절히 설정해야 합니다.

핵심 포인트
  • • Deadlock은 상호 대기로 인한 무한 대기 상태
  • • 테이블 접근 순서 일관성 유지와 트랜잭션 범위 최소화
  • • ORM 사용 시 자동 생성 쿼리의 실행 순서 파악 필요
Follow-up 질문

READ COMMITTED와 REPEATABLE READ 격리 수준에서 Deadlock 발생 가능성은 어떻게 다르며, 각각 어떤 상황에 적합한가요?

5 아키텍처
Medium

Q. Node.js 마이크로서비스 아키텍처에서 서비스 간 통신 방식으로 REST API, gRPC, Message Queue의 장단점을 비교하고, 각각 어떤 상황에서 선택해야 하는지 설명해주세요. 특히 트랜잭션 일관성과 장애 처리 측면에서의 차이점을 포함해주세요.

A. 모범답안

REST API는 구현이 간단하고 디버깅이 쉬우나 동기 통신으로 서비스 간 강한 결합이 발생하며, 호출 체인이 길어지면 지연이 누적됩니다. gRPC는 Protocol Buffers로 높은 성능과 타입 안정성을 제공하지만 학습 곡선이 있고, 브라우저 직접 호출이 어렵습니다. Message Queue는 비동기 통신으로 서비스 간 느슨한 결합과 높은 확장성을 제공하며, 장애 시 메시지가 유실되지 않지만 최종 일관성(Eventual Consistency)만 보장되고 구현이 복잡합니다. 실시간 동기 응답이 필요하면 REST나 gRPC, 비동기 처리와 장애 복원력이 중요하면 Message Queue를 선택하며, 트랜잭션 일관성이 필요하면 Saga 패턴이나 2PC를 함께 고려해야 합니다.

핵심 포인트
  • • REST는 간단하나 동기 통신으로 결합도 높음, gRPC는 고성능 동기 통신
  • • Message Queue는 비동기로 느슨한 결합과 장애 복원력 제공
  • • 트랜잭션 일관성은 Saga 패턴 등 별도 전략 필요
Follow-up 질문

Message Queue를 사용할 때 메시지 중복 처리 문제를 어떻게 해결할 수 있으며, 멱등성(Idempotency)을 보장하는 방법은 무엇인가요?

댓글 0

로그인 후 댓글을 작성할 수 있습니다.

아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!