Node.js 미드레벨 CS 기초 기술면접

Node.js 미드레벨 (3~7년) CS 기초 5문항 조회수 35 · 2026-07-14 (화) 11:10:59
1 자료구조
Medium

Q. Node.js에서 대용량 로그 데이터를 처리할 때 Array와 Linked List 중 어떤 자료구조가 더 적합한지 설명하고, JavaScript에서 Linked List를 직접 구현해야 하는 이유와 메모리 관리 측면에서의 장단점을 비교해주세요.

A. 모범답안

대용량 로그 데이터의 경우 중간 삽입/삭제가 빈번하다면 Linked List가 O(1) 시간복잡도로 유리하지만, JavaScript는 네이티브 Linked List를 제공하지 않아 직접 구현해야 합니다. Array는 연속된 메모리 할당으로 캐시 지역성이 좋고 인덱스 접근이 O(1)이지만, 중간 삽입/삭제 시 O(n)의 비용이 발생합니다. Linked List는 노드마다 포인터를 저장해야 하므로 메모리 오버헤드가 크고, V8의 최적화를 받기 어려워 실제로는 Array가 더 빠른 경우가 많습니다. 따라서 실무에서는 순차 처리가 주된 경우 Array를, 빈번한 중간 조작이 필요하면 적절한 자료구조 라이브러리 사용을 고려해야 합니다.

핵심 포인트
  • • Array는 연속 메모리로 캐시 효율성이 높지만 중간 삽입/삭제가 O(n)
  • • Linked List는 삽입/삭제가 O(1)이지만 JavaScript는 직접 구현 필요
  • • 실무에서는 V8 최적화를 받는 Array가 대부분의 경우 더 효율적
  • • 메모리 오버헤드와 접근 패턴을 고려한 선택 필요
Follow-up 질문

만약 로그 데이터를 시간순으로 정렬하면서 특정 시간 범위의 데이터만 자주 조회해야 한다면 어떤 자료구조를 사용하는 것이 좋을까요?

2 네트워크
Medium

Q. Node.js 서버에서 HTTP/1.1과 HTTP/2의 차이점을 설명하고, HTTP/2의 멀티플렉싱이 어떻게 동작하는지, 그리고 Node.js에서 HTTP/2를 사용할 때 성능상 이점과 주의해야 할 점을 설명해주세요.

A. 모범답안

HTTP/1.1은 하나의 TCP 연결에서 요청-응답이 순차적으로 처리되어 Head-of-Line Blocking이 발생하지만, HTTP/2는 바이너리 프레이밍 계층을 통해 하나의 연결에서 여러 스트림을 동시에 처리하는 멀티플렉싱을 지원합니다. 각 요청은 고유한 스트림 ID를 가진 프레임으로 분할되어 인터리빙 방식으로 전송되므로 연결 수를 줄이고 레이턴시를 개선할 수 있습니다. Node.js에서는 http2 모듈을 사용하며, 서버 푸시와 헤더 압축(HPACK)으로 추가 성능 향상이 가능합니다. 다만 HTTPS가 필수이고, 레거시 클라이언트 호환성 문제와 단일 TCP 연결의 패킷 손실 시 전체 스트림이 영향받는 점을 고려해야 합니다.

핵심 포인트
  • • HTTP/2는 바이너리 프레이밍과 멀티플렉싱으로 단일 연결에서 다중 스트림 처리
  • • Head-of-Line Blocking 해결 및 헤더 압축으로 성능 개선
  • • 서버 푸시 기능으로 클라이언트 요청 전 리소스 전송 가능
  • • HTTPS 필수 및 TCP 레벨 패킷 손실 시 전체 영향
Follow-up 질문

HTTP/2에서도 TCP 레벨의 Head-of-Line Blocking은 여전히 존재합니다. HTTP/3에서는 이 문제를 어떻게 해결하나요?

3 운영체제
Hard

Q. Node.js 애플리케이션에서 파일 I/O 작업이 Event Loop를 블로킹하지 않는 이유를 libuv의 Thread Pool 관점에서 설명하고, fs.readFile()과 fs.readFileSync()의 내부 동작 차이, 그리고 Thread Pool 크기(UV_THREADPOOL_SIZE)를 조정해야 하는 상황을 설명해주세요.

A. 모범답안

Node.js는 libuv 라이브러리를 통해 파일 I/O 같은 블로킹 작업을 별도의 Thread Pool(기본 4개)에서 처리하여 메인 Event Loop가 블로킹되지 않도록 합니다. fs.readFile()은 작업을 Thread Pool에 위임하고 콜백을 등록한 뒤 즉시 반환하여 Event Loop가 계속 실행되지만, fs.readFileSync()는 메인 스레드에서 직접 시스템 콜을 실행하여 완료될 때까지 블로킹됩니다. 대량의 파일 I/O, 암호화 작업, DNS 조회가 동시에 발생하면 Thread Pool이 고갈되어 다른 비동기 작업까지 지연될 수 있으므로, UV_THREADPOOL_SIZE 환경변수로 크기를 조정해야 합니다. 다만 너무 크게 설정하면 컨텍스트 스위칭 오버헤드가 증가하므로 CPU 코어 수와 작업 특성을 고려해야 합니다.

핵심 포인트
  • • libuv의 Thread Pool이 블로킹 I/O를 처리하여 Event Loop 보호
  • • fs.readFile()은 Thread Pool 사용, fs.readFileSync()는 메인 스레드 블로킹
  • • Thread Pool 고갈 시 모든 비동기 작업이 지연됨
  • • UV_THREADPOOL_SIZE 조정 시 컨텍스트 스위칭 비용 고려 필요
Follow-up 질문

네트워크 I/O는 Thread Pool을 사용하지 않는데, 파일 I/O와 어떻게 다르게 처리되나요?

4 데이터베이스
Medium

Q. Node.js에서 데이터베이스 인덱스의 동작 원리를 B-Tree 구조 관점에서 설명하고, 인덱스를 과도하게 생성했을 때 발생할 수 있는 문제점과 Covering Index가 무엇인지, 그리고 실제로 인덱스가 사용되는지 확인하는 방법을 설명해주세요.

A. 모범답안

데이터베이스 인덱스는 대부분 B-Tree 구조로 구현되어 O(log n) 시간에 검색이 가능하며, 리프 노드에 실제 데이터의 포인터를 저장합니다. 인덱스를 과도하게 생성하면 INSERT/UPDATE/DELETE 시 모든 인덱스를 갱신해야 하므로 쓰기 성능이 저하되고, 추가 저장공간이 필요하며, 옵티마이저가 잘못된 인덱스를 선택할 수 있습니다. Covering Index는 쿼리에 필요한 모든 컬럼을 인덱스가 포함하고 있어 테이블 접근 없이 인덱스만으로 결과를 반환할 수 있는 경우입니다. MySQL에서는 EXPLAIN 명령어로 실행 계획을 확인하여 type이 index나 range인지, key 컬럼에 사용된 인덱스가 표시되는지 확인할 수 있습니다.

핵심 포인트
  • • B-Tree 구조로 O(log n) 검색 성능 제공
  • • 과도한 인덱스는 쓰기 성능 저하 및 저장공간 낭비 유발
  • • Covering Index는 테이블 접근 없이 인덱스만으로 쿼리 처리
  • • EXPLAIN으로 실행 계획 분석하여 인덱스 사용 여부 확인
Follow-up 질문

복합 인덱스(Composite Index)를 생성할 때 컬럼 순서가 중요한 이유는 무엇인가요?

5 알고리즘
Medium

Q. Node.js 애플리케이션에서 LRU(Least Recently Used) 캐시를 구현해야 합니다. LRU 캐시의 동작 원리와 효율적인 구현을 위해 어떤 자료구조 조합을 사용해야 하는지 설명하고, get과 put 연산의 시간복잡도를 O(1)로 만들기 위한 전략을 설명해주세요.

A. 모범답안

LRU 캐시는 용량이 가득 찼을 때 가장 오래 사용되지 않은 항목을 제거하는 캐시 정책입니다. O(1) 시간복잡도를 달성하려면 Hash Map과 Doubly Linked List를 함께 사용해야 하며, Hash Map은 키로 빠른 접근을 제공하고 Doubly Linked List는 사용 순서를 유지합니다. get 연산 시 Hash Map으로 노드를 찾아 리스트의 맨 앞으로 이동시키고, put 연산 시 새 노드를 맨 앞에 추가하며 용량 초과 시 리스트 맨 뒤 노드를 제거합니다. JavaScript에서는 Map 객체와 직접 구현한 Doubly Linked List를 사용하거나, ES2015의 Map이 삽입 순서를 보장하는 특성을 활용할 수 있지만 중간 이동이 필요하므로 완전한 LRU 구현을 위해서는 커스텀 구조가 필요합니다.

핵심 포인트
  • • Hash Map으로 O(1) 접근, Doubly Linked List로 순서 관리
  • • get/put 모두 O(1) 시간복잡도 달성 가능
  • • 최근 사용 항목은 리스트 앞으로, 제거는 리스트 뒤에서 수행
  • • JavaScript Map은 삽입 순서 보장하나 중간 이동이 제한적
Follow-up 질문

LRU 대신 LFU(Least Frequently Used) 캐시를 구현한다면 어떤 자료구조를 사용해야 하고, LRU와 비교했을 때 어떤 상황에서 더 유리한가요?

댓글 0

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

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