Node.js 시니어 CS 기초 면접
새 면접Q. B-Tree와 B+Tree의 구조적 차이를 설명하고, 왜 대부분의 데이터베이스 인덱스가 B+Tree를 채택하는지 설명해주세요. 특히 Node.js에서 MongoDB와 PostgreSQL을 사용할 때 각 DB의 인덱스 구조 차이가 쿼리 성능에 미치는 영향과, 복합 인덱스 설계 시 필드 순서가 중요한 이유를 함께 설명해주세요.
B-Tree는 모든 노드에 데이터를 저장하지만, B+Tree는 리프 노드에만 데이터를 저장하고 내부 노드는 키만 가집니다. B+Tree는 리프 노드가 연결 리스트로 연결되어 범위 검색에 유리하며, 내부 노드가 더 많은 키를 저장할 수 있어 트리 높이가 낮아 디스크 I/O가 감소합니다. MongoDB는 B-Tree를, PostgreSQL은 B+Tree를 사용하는데, 범위 쿼리가 많은 경우 PostgreSQL이 더 효율적입니다. 복합 인덱스는 첫 번째 필드부터 순차적으로 사용되므로, 쿼리 패턴에 따라 카디널리티가 높은 필드를 앞에 배치하거나 WHERE 절에서 자주 사용되는 필드 순서로 설계해야 합니다.
- • B+Tree는 리프 노드에만 데이터 저장, 범위 검색 최적화
- • 내부 노드의 팬아웃이 커서 트리 높이 감소, 디스크 I/O 최소화
- • 복합 인덱스는 왼쪽 접두사 규칙을 따르므로 필드 순서가 쿼리 성능에 결정적
- • MongoDB의 WiredTiger는 B-Tree, PostgreSQL은 B+Tree 사용
인덱스 스캔 방식 중 Index Scan, Index Only Scan, Bitmap Index Scan의 차이와 각각이 선택되는 조건을 설명해주세요. Node.js에서 쿼리 실행 계획을 분석하는 방법도 함께 설명해주세요.
Q. HTTP/1.1, HTTP/2, HTTP/3의 주요 차이점을 멀티플렉싱, HOL(Head-of-Line) 블로킹, 전송 프로토콜 관점에서 설명해주세요. Node.js 서버에서 HTTP/2를 활성화할 때 성능 이점과 함께 Server Push 기능의 실제 활용 사례 및 주의사항을 설명해주세요.
HTTP/1.1은 하나의 TCP 연결에서 요청을 순차 처리하여 HOL 블로킹이 발생합니다. HTTP/2는 바이너리 프레이밍과 멀티플렉싱으로 하나의 TCP 연결에서 여러 스트림을 동시 처리하지만 TCP 레벨 HOL 블로킹은 여전히 존재합니다. HTTP/3는 UDP 기반 QUIC 프로토콜을 사용하여 스트림 독립성을 보장하고 연결 수립 시간을 단축합니다. Node.js에서 HTTP/2의 Server Push는 클라이언트 요청 전에 리소스를 미리 전송할 수 있지만, 클라이언트 캐시 상태를 모르면 불필요한 대역폭 낭비가 발생할 수 있어 신중하게 사용해야 합니다.
- • HTTP/2는 멀티플렉싱으로 애플리케이션 레벨 HOL 블로킹 해결, TCP 레벨은 여전히 존재
- • HTTP/3는 QUIC으로 패킷 손실 시 스트림 독립성 보장, 0-RTT 연결 재개 지원
- • Server Push는 CSS, JS 등 필수 리소스 전송에 유용하나 캐시 중복 전송 위험
- • Node.js의 http2 모듈 사용 시 헤더 압축(HPACK)으로 오버헤드 감소
대규모 트래픽 환경에서 Keep-Alive 타임아웃 설정이 서버 리소스와 성능에 미치는 영향을 설명하고, Node.js에서 최적의 타임아웃 값을 결정하는 기준을 제시해주세요.
Q. 프로세스 스케줄링 알고리즘 중 Completely Fair Scheduler(CFS)의 동작 원리를 vruntime 개념을 중심으로 설명하고, Node.js 애플리케이션이 멀티코어 환경에서 실행될 때 CPU 친화성(CPU Affinity)과 컨텍스트 스위칭이 성능에 미치는 영향을 설명해주세요. 또한 클러스터 모드에서 워커 프로세스 배치 전략을 어떻게 수립하시겠습니까?
CFS는 각 프로세스의 가상 실행 시간(vruntime)을 추적하여 가장 작은 vruntime을 가진 프로세스에 CPU를 할당하는 방식으로 공정성을 보장합니다. Red-Black Tree로 프로세스를 관리하여 O(log n) 시간에 다음 실행 프로세스를 선택합니다. Node.js 워커 프로세스가 코어 간 이동하면 캐시 무효화로 성능이 저하되므로, CPU 친화성을 설정하여 특정 코어에 고정할 수 있습니다. 클러스터 모드에서는 NUMA 아키텍처를 고려하여 같은 소켓의 코어에 워커를 배치하고, taskset이나 cluster 모듈의 schedulingPolicy를 활용하여 워커당 전용 코어를 할당하는 전략이 효과적입니다.
- • CFS는 vruntime 기반 공정 스케줄링, Red-Black Tree로 O(log n) 선택
- • 컨텍스트 스위칭 시 L1/L2 캐시 무효화로 성능 저하 발생
- • CPU Affinity 설정으로 캐시 지역성 향상, 특히 CPU 집약 작업에 효과적
- • NUMA 인식 스케줄링으로 메모리 접근 지연 최소화
Node.js 애플리케이션에서 CPU 사용률이 높지 않은데도 응답 시간이 느린 경우, I/O wait과 시스템 콜 오버헤드를 진단하고 최적화하는 방법을 설명해주세요.
Q. 데이터베이스의 MVCC(Multi-Version Concurrency Control) 메커니즘을 설명하고, PostgreSQL과 MySQL(InnoDB)의 MVCC 구현 방식 차이를 Vacuum과 Purge 관점에서 비교해주세요. Node.js에서 장기 실행 트랜잭션이 MVCC 시스템에 미치는 영향과 트랜잭션 타임아웃 설정 전략도 함께 설명해주세요.
MVCC는 읽기와 쓰기가 서로 블로킹하지 않도록 데이터의 여러 버전을 유지하는 동시성 제어 방식입니다. PostgreSQL은 새 버전을 같은 테이블에 저장하고 VACUUM으로 오래된 버전을 정리하며, MySQL InnoDB는 Undo 로그에 이전 버전을 저장하고 Purge 스레드가 백그라운드에서 정리합니다. PostgreSQL은 VACUUM 부담이 크고 테이블 블로트가 발생할 수 있으며, InnoDB는 Undo 로그 크기가 증가할 수 있습니다. Node.js에서 장기 트랜잭션은 오래된 버전을 유지시켜 스토리지와 성능에 악영향을 주므로, statement_timeout과 idle_in_transaction_session_timeout을 설정하여 좀비 트랜잭션을 방지해야 합니다.
- • MVCC는 스냅샷 격리로 읽기-쓰기 충돌 방지, 동시성 향상
- • PostgreSQL은 테이블 내 버전 관리로 VACUUM 필요, InnoDB는 Undo 로그 분리
- • 장기 트랜잭션은 버전 정리를 방해하여 디스크 공간 증가 및 성능 저하 유발
- • 트랜잭션 타임아웃 설정으로 리소스 누수 방지 필수
PostgreSQL에서 트랜잭션 ID 랩어라운드(wraparound) 문제가 발생하는 원인과 이를 예방하기 위한 VACUUM 전략을 설명하고, Node.js 애플리케이션에서 이를 모니터링하는 방법을 제시해주세요.
Q. 분산 시스템에서 일관된 해싱(Consistent Hashing)의 동작 원리와 가상 노드(Virtual Node)의 역할을 설명해주세요. Node.js 기반 분산 캐시 시스템에서 노드 추가/제거 시 데이터 재분배를 최소화하면서도 부하를 균등하게 분산하기 위한 구현 전략과, Jump Consistent Hash 같은 대안 알고리즘과의 비교도 함께 설명해주세요.
일관된 해싱은 해시 링에 노드와 키를 매핑하여 노드 변경 시 K/N개의 키만 재분배되도록 하는 알고리즘입니다(K는 전체 키 수, N은 노드 수). 가상 노드는 하나의 물리 노드를 링에 여러 번 배치하여 부하 불균형을 해소하고 노드 추가/제거 시 영향을 분산시킵니다. Node.js에서는 가상 노드 수를 100~200개로 설정하고 SHA-256 같은 균등 분포 해시 함수를 사용하며, 노드 가중치를 반영할 수 있습니다. Jump Consistent Hash는 메모리 효율적이지만 노드 순서가 고정되어야 하고 가중치 적용이 어려워, 동적 노드 관리가 필요한 경우 일관된 해싱이 더 적합합니다.
- • 일관된 해싱은 노드 변경 시 최소한의 키만 이동하여 캐시 무효화 최소화
- • 가상 노드로 부하 균등 분산 및 노드별 가중치 적용 가능
- • Node.js에서 Map 또는 Red-Black Tree로 해시 링 구현, 이진 탐색으로 O(log n) 노드 찾기
- • Jump Consistent Hash는 O(1) 공간, O(log n) 시간이지만 동적 환경에서 제약
Redis Cluster의 해시 슬롯 방식과 일관된 해싱의 차이를 설명하고, Node.js에서 Redis Cluster를 사용할 때 멀티 키 연산의 제약사항과 해결 방법을 제시해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!