Express 미드레벨 CS 기초 면접
새 면접Q. 해시 테이블의 충돌(Collision) 해결 방법 중 Chaining과 Open Addressing의 차이점을 설명하고, 각각 어떤 상황에서 유리한지 말씀해주세요.
메모리 사용 패턴과 데이터 밀도에 따른 성능 차이를 생각해보세요.
Chaining은 같은 해시값을 가진 데이터를 연결 리스트로 관리하는 방식이고, Open Addressing은 충돌 시 다른 빈 버킷을 찾아 저장하는 방식입니다. Chaining은 추가 메모리를 사용하지만 해시 테이블이 가득 차도 성능이 안정적이며, 데이터 삭제가 간단합니다. Open Addressing은 캐시 지역성이 좋고 메모리 오버헤드가 적지만, 테이블이 가득 찰수록 성능이 급격히 저하됩니다. 데이터 개수를 예측하기 어렵거나 삭제가 빈번한 경우 Chaining이, 메모리가 제한적이고 데이터 크기를 예측 가능한 경우 Open Addressing이 유리합니다.
- • Chaining은 연결 리스트 기반, Open Addressing은 탐사 기반
- • 메모리 사용과 캐시 지역성의 트레이드오프
- • 데이터 밀도에 따른 성능 차이
Express의 세션 저장소나 캐시 시스템에서 해시 테이블 기반 자료구조를 선택할 때 메모리와 성능을 고려해야 합니다.
Open Addressing의 탐사 방법 중 Linear Probing과 Quadratic Probing의 차이점은 무엇인가요?
Q. TCP의 3-way handshake와 4-way handshake 과정을 설명하고, TIME_WAIT 상태가 왜 필요한지 말씀해주세요.
연결 수립과 종료 시 패킷의 순서와 지연된 패킷이 미치는 영향을 고려해보세요.
3-way handshake는 SYN, SYN-ACK, ACK 순서로 연결을 수립하며, 양측이 시퀀스 번호를 교환하고 통신 준비를 확인합니다. 4-way handshake는 FIN, ACK, FIN, ACK 순서로 연결을 종료하며, 양방향 연결을 각각 종료합니다. TIME_WAIT 상태는 연결을 종료한 쪽이 일정 시간(2MSL) 동안 유지하는 상태로, 지연된 패킷이 새 연결에 영향을 주는 것을 방지하고 마지막 ACK가 손실되었을 때 재전송을 처리하기 위해 필요합니다. TIME_WAIT이 없으면 이전 연결의 패킷이 새 연결에서 잘못 처리될 수 있습니다.
- • 3-way handshake로 연결 수립, 4-way handshake로 종료
- • TIME_WAIT은 2MSL 동안 유지
- • 지연 패킷 처리와 마지막 ACK 재전송 보장
Express 서버가 많은 클라이언트 연결을 처리할 때 TIME_WAIT 소켓이 포트를 고갈시켜 새 연결을 받지 못하는 문제가 발생할 수 있습니다.
TIME_WAIT 상태가 많이 쌓이면 어떤 문제가 발생하고, 이를 어떻게 해결할 수 있나요?
Q. 퀵소트와 머지소트의 시간 복잡도와 공간 복잡도를 비교하고, 각각의 장단점과 어떤 상황에서 어느 알고리즘을 선택해야 하는지 설명해주세요.
최악의 경우 성능과 메모리 사용, 그리고 데이터 접근 패턴을 고려해보세요.
퀵소트는 평균 O(n log n), 최악 O(n²) 시간 복잡도를 가지며 공간 복잡도는 O(log n)입니다. 머지소트는 항상 O(n log n) 시간 복잡도를 보장하지만 O(n)의 추가 메모리가 필요합니다. 퀵소트는 in-place 정렬로 메모리 효율적이고 캐시 지역성이 좋아 평균적으로 빠르지만, 피벗 선택에 따라 성능이 불안정합니다. 머지소트는 안정 정렬이고 최악의 경우에도 성능이 보장되지만 추가 메모리가 필요합니다. 메모리가 제한적이고 평균 성능이 중요한 경우 퀵소트를, 최악 성능 보장이 필요하거나 안정 정렬이 필요한 경우 머지소트를 선택합니다.
- • 퀵소트는 평균 빠르지만 최악 O(n²), 머지소트는 항상 O(n log n)
- • 퀵소트는 in-place, 머지소트는 O(n) 추가 메모리
- • 안정성과 성능 보장의 트레이드오프
Express API에서 대량의 데이터를 정렬하여 응답할 때 메모리 제약과 성능 요구사항에 따라 적절한 정렬 알고리즘을 선택해야 합니다.
퀵소트에서 최악의 경우를 피하기 위한 피벗 선택 전략에는 어떤 것들이 있나요?
Q. 데이터베이스 인덱스의 B-Tree와 B+Tree 구조의 차이점을 설명하고, 왜 대부분의 RDBMS가 B+Tree를 사용하는지 말씀해주세요.
범위 검색과 데이터 저장 위치의 차이를 생각해보세요.
B-Tree는 모든 노드에 키와 데이터를 저장하지만, B+Tree는 리프 노드에만 데이터를 저장하고 내부 노드는 키만 가집니다. B+Tree는 리프 노드가 연결 리스트로 연결되어 있어 범위 검색과 순차 접근이 효율적입니다. 내부 노드에 더 많은 키를 저장할 수 있어 트리의 높이가 낮아지고, 이는 디스크 I/O 횟수를 줄입니다. 모든 데이터가 리프 노드에 있어 검색 성능이 일정하고, 풀 스캔이 필요할 때도 리프 노드만 순회하면 됩니다. 이러한 이유로 범위 검색이 빈번하고 순차 접근이 중요한 RDBMS에서 B+Tree를 선호합니다.
- • B+Tree는 리프 노드에만 데이터 저장
- • 리프 노드 연결로 범위 검색 효율적
- • 더 낮은 트리 높이로 디스크 I/O 감소
Express 애플리케이션에서 날짜 범위나 가격 범위로 데이터를 조회할 때 B+Tree 인덱스가 성능을 크게 향상시킵니다.
클러스터드 인덱스와 논클러스터드 인덱스의 차이는 무엇이고, 각각 언제 사용하나요?
Q. 프로세스와 스레드의 차이를 메모리 구조 관점에서 설명하고, 멀티프로세스와 멀티스레드의 장단점을 비교해주세요.
컨텍스트 스위칭 비용과 자원 공유 방식의 차이를 고려해보세요.
프로세스는 독립적인 메모리 공간(코드, 데이터, 힙, 스택)을 가지며, 스레드는 같은 프로세스 내에서 코드, 데이터, 힙을 공유하고 스택만 독립적으로 가집니다. 멀티프로세스는 독립적인 메모리로 안정성이 높고 한 프로세스의 오류가 다른 프로세스에 영향을 주지 않지만, 컨텍스트 스위칭 비용이 크고 프로세스 간 통신(IPC)이 복잡합니다. 멀티스레드는 메모리를 공유하여 자원 효율적이고 통신이 빠르지만, 동기화 문제가 발생할 수 있고 한 스레드의 오류가 전체 프로세스에 영향을 줍니다. Node.js는 기본적으로 싱글 스레드지만 Worker Threads로 멀티스레드를 지원합니다.
- • 프로세스는 독립 메모리, 스레드는 메모리 공유
- • 멀티프로세스는 안정적이지만 비용이 큼
- • 멀티스레드는 효율적이지만 동기화 필요
Express 서버에서 CPU 집약적인 작업을 처리할 때 Worker Threads나 클러스터 모드를 사용하여 성능을 향상시킬 수 있습니다.
데드락이 발생하는 4가지 조건과 이를 예방하는 방법은 무엇인가요?
Q. HTTP/1.1, HTTP/2, HTTP/3의 주요 차이점을 설명하고, 각 버전에서 해결하고자 한 성능 문제와 그 해결 방법을 말씀해주세요.
HOL Blocking, 멀티플렉싱, 전송 프로토콜의 변화를 중심으로 생각해보세요.
HTTP/1.1은 Keep-Alive로 연결 재사용이 가능하지만 파이프라이닝에서 HOL Blocking 문제가 있습니다. HTTP/2는 바이너리 프레이밍과 멀티플렉싱으로 하나의 TCP 연결에서 여러 요청을 동시에 처리하여 HOL Blocking을 해결했지만, TCP 레벨의 패킷 손실 시 여전히 전체 스트림이 대기하는 문제가 있습니다. HTTP/3는 TCP 대신 QUIC(UDP 기반)을 사용하여 스트림별 독립적인 손실 복구가 가능하고, 연결 수립이 빠르며(0-RTT), 네트워크 전환 시에도 연결을 유지할 수 있습니다. 각 버전은 레이턴시 감소와 동시성 향상을 목표로 발전했습니다.
- • HTTP/2는 멀티플렉싱으로 애플리케이션 레벨 HOL Blocking 해결
- • HTTP/3는 QUIC으로 TCP 레벨 HOL Blocking까지 해결
- • 0-RTT와 연결 마이그레이션으로 성능 향상
모바일 네트워크 환경에서 패킷 손실이 빈번한 경우 HTTP/3를 사용하면 사용자 경험을 크게 개선할 수 있습니다.
Express 서버에서 HTTP/2를 활성화할 때 고려해야 할 점은 무엇인가요?
Q. 데이터베이스 트랜잭션의 격리 수준 4단계를 설명하고, 각 수준에서 발생할 수 있는 문제(Dirty Read, Non-Repeatable Read, Phantom Read)와 실무에서 격리 수준을 선택하는 기준을 말씀해주세요.
동시성과 일관성의 트레이드오프, 그리고 성능에 미치는 영향을 고려해보세요.
Read Uncommitted는 커밋되지 않은 데이터를 읽을 수 있어 Dirty Read가 발생합니다. Read Committed는 커밋된 데이터만 읽지만 같은 트랜잭션 내에서 반복 읽기 시 다른 값이 나올 수 있는 Non-Repeatable Read가 발생합니다. Repeatable Read는 트랜잭션 시작 시점의 스냅샷을 유지하여 반복 읽기를 보장하지만, 범위 검색 시 새로운 행이 추가되는 Phantom Read가 발생할 수 있습니다. Serializable은 완전한 격리를 보장하지만 성능이 가장 낮습니다. 실무에서는 대부분 Read Committed나 Repeatable Read를 사용하며, 금융 거래처럼 강한 일관성이 필요한 경우 Serializable을, 높은 동시성이 필요한 경우 낮은 격리 수준을 선택합니다.
- • 격리 수준이 높을수록 일관성은 강하지만 동시성은 낮음
- • 각 수준에서 발생 가능한 읽기 이상 현상 이해
- • 비즈니스 요구사항에 따른 적절한 격리 수준 선택
Express API에서 재고 관리나 결제 처리 시 적절한 격리 수준을 설정하지 않으면 동시 요청으로 인한 데이터 불일치가 발생할 수 있습니다.
MySQL의 Repeatable Read에서 Phantom Read가 발생하지 않는 이유는 무엇인가요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!