MongoDB 시니어 CS 기초 기술면접
새 면접Q. MongoDB가 내부적으로 사용하는 B-Tree와 LSM-Tree의 차이점을 설명하고, MongoDB의 WiredTiger 스토리지 엔진이 B-Tree를 선택한 이유와 트레이드오프를 분석해주세요.
읽기 성능과 쓰기 성능, 그리고 공간 증폭(space amplification) 측면에서 비교해보세요.
B-Tree는 제자리 업데이트(in-place update) 방식으로 읽기 성능이 우수하며 O(log n)의 일관된 조회 성능을 제공합니다. 반면 LSM-Tree는 순차 쓰기 기반으로 쓰기 성능이 뛰어나지만 읽기 시 여러 레벨을 탐색해야 하는 읽기 증폭(read amplification) 문제가 있습니다. WiredTiger는 OLTP 워크로드에서 읽기 성능과 범위 쿼리 성능이 중요하다고 판단하여 B-Tree를 선택했습니다. 대신 쓰기 성능을 보완하기 위해 체크포인트 기반의 MVCC와 압축 기법을 활용합니다. 트레이드오프로는 쓰기 증폭(write amplification)이 LSM-Tree보다 높고, 랜덤 I/O가 발생하여 SSD에서 상대적으로 불리할 수 있습니다.
- • B-Tree는 읽기 최적화, LSM-Tree는 쓰기 최적화 구조
- • WiredTiger는 OLTP 워크로드의 읽기/범위 쿼리 성능을 우선시
- • 쓰기 증폭과 읽기 증폭 간의 트레이드오프 이해
수백만 건의 문서를 관리하는 시스템에서 인덱스 구조 선택은 쿼리 패턴에 따라 전체 시스템 성능을 좌우합니다.
대용량 로그 데이터 저장 시스템에서는 LSM-Tree가 더 적합할 수 있는데, MongoDB 대신 Cassandra나 RocksDB를 선택해야 하는 상황은 어떤 경우일까요?
Q. MongoDB 레플리카셋 환경에서 클라이언트가 Primary 노드에 쓰기 요청을 보냈는데 네트워크 파티션으로 인해 응답을 받지 못했습니다. 이때 발생할 수 있는 Split-brain 문제와 MongoDB가 이를 방지하기 위해 사용하는 메커니즘을 TCP/IP 계층 관점에서 설명해주세요.
Majority Write Concern과 Election 프로토콜, 그리고 Heartbeat 메커니즘을 고려해보세요.
Split-brain은 네트워크 파티션으로 클러스터가 분리되어 각각 독립적으로 쓰기를 수행하는 상황입니다. MongoDB는 Raft 기반의 Election 프로토콜을 사용하여 과반수(majority) 투표로만 Primary를 선출하므로, 파티션된 소수 그룹은 Primary가 될 수 없습니다. Write Concern을 majority로 설정하면 과반수 노드에 복제가 완료되어야 쓰기가 성공하므로, 네트워크 복구 후 데이터 일관성이 보장됩니다. TCP 계층에서는 keepalive와 MongoDB의 Heartbeat(기본 2초)를 통해 노드 상태를 모니터링하며, electionTimeoutMillis 내에 응답이 없으면 재선출을 시작합니다. 클라이언트는 retryWrites 옵션으로 멱등성을 보장하며 재시도를 처리합니다.
- • 과반수 기반 Election으로 Split-brain 방지
- • Write Concern majority로 데이터 일관성 보장
- • Heartbeat와 TCP keepalive로 네트워크 장애 감지
멀티 리전 배포 시 네트워크 지연과 파티션을 고려한 레플리카셋 토폴로지 설계가 가용성을 결정합니다.
5개 노드 레플리카셋에서 3개 노드가 있는 데이터센터와 2개 노드가 있는 DR 센터 간 네트워크가 단절되면 어느 쪽이 Primary를 유지하게 되나요? Arbiter를 어디에 배치해야 할까요?
Q. MongoDB 프로덕션 환경에서 메모리 부족으로 OOM Killer가 mongod 프로세스를 종료시키는 상황이 발생했습니다. Linux 메모리 관리 관점에서 WiredTiger 캐시와 페이지 캐시의 관계, 그리고 이를 방지하기 위한 메모리 설정 전략을 설명해주세요.
가상 메모리, RSS, WiredTiger 내부 캐시, 그리고 OS 페이지 캐시 간의 관계를 고려하세요.
WiredTiger는 기본적으로 전체 메모리의 50% 또는 RAM-1GB 중 큰 값을 내부 캐시로 사용하며, 이는 프로세스의 RSS(Resident Set Size)에 포함됩니다. 하지만 MongoDB는 mmap 기반 파일 접근도 사용하므로 OS 페이지 캐시도 추가로 소비하여 전체 메모리 사용량이 WiredTiger 캐시보다 훨씬 클 수 있습니다. Linux는 메모리 압박 시 페이지 캐시를 먼저 회수하지만, overcommit 설정에 따라 OOM Killer가 메모리를 많이 사용하는 mongod를 종료할 수 있습니다. 방지 전략으로는 WiredTiger 캐시를 전체 메모리의 40-50%로 제한하고, vm.swappiness를 1로 설정하며, oom_score_adj로 mongod의 우선순위를 조정하고, 충분한 swap 공간을 확보해야 합니다. 또한 메모리 모니터링으로 FTDC 데이터와 serverStatus의 메모리 메트릭을 주기적으로 확인해야 합니다.
- • WiredTiger 캐시와 OS 페이지 캐시가 별도로 메모리를 소비
- • OOM Killer는 메모리 부족 시 프로세스를 강제 종료
- • 캐시 크기 제한과 OS 파라미터 튜닝으로 예방
대용량 데이터를 처리하는 MongoDB 서버에서 메모리 설정 실수는 서비스 장애로 직결됩니다.
Transparent Huge Pages(THP)가 MongoDB 성능에 부정적인 영향을 미치는 이유는 무엇이며, 이를 비활성화해야 하는 이유를 설명해주세요.
Q. MongoDB의 aggregation pipeline에서 $lookup 연산이 nested loop join을 사용한다고 할 때, 조인되는 컬렉션의 크기가 각각 N과 M일 때 시간 복잡도를 분석하고, 이를 최적화하기 위한 인덱스 전략과 알고리즘적 접근 방법을 설명해주세요.
인덱스가 있을 때와 없을 때의 복잡도 차이, 그리고 hash join과의 비교를 생각해보세요.
인덱스가 없는 경우 nested loop join의 시간 복잡도는 O(N*M)으로, 외부 컬렉션의 각 문서마다 내부 컬렉션 전체를 스캔합니다. 조인 필드에 인덱스가 있으면 내부 조회가 O(log M)이 되어 전체 복잡도는 O(N*log M)으로 개선됩니다. 최적화 전략으로는 첫째, $lookup의 localField와 foreignField에 대한 인덱스를 생성하고, 둘째, $match로 파이프라인 초반에 데이터를 필터링하여 N을 줄이며, 셋째, $lookup 전에 $project로 필요한 필드만 선택해 메모리 사용을 줄입니다. MongoDB 5.0 이상에서는 특정 조건에서 hash join을 사용하여 O(N+M)의 성능을 낼 수 있지만, 메모리 사용량이 증가하는 트레이드오프가 있습니다.
- • 인덱스 없이는 O(N*M), 인덱스 사용 시 O(N*log M)
- • 조인 필드 인덱스와 초기 필터링으로 최적화
- • Hash join은 메모리를 더 사용하지만 시간 복잡도 개선
대규모 데이터 분석 쿼리에서 조인 최적화 여부가 응답 시간을 초 단위에서 분 단위로 바꿀 수 있습니다.
수백만 건의 문서를 조인해야 하는 상황에서 $lookup 대신 애플리케이션 레벨에서 조인하는 것이 더 나은 경우는 언제인가요?
Q. ACID 트랜잭션의 Isolation Level 중 Read Committed와 Snapshot Isolation의 차이를 설명하고, MongoDB의 다중 문서 트랜잭션이 어떤 수준을 제공하는지, 그리고 이것이 Phantom Read를 방지할 수 있는지 분석해주세요.
MVCC 구조와 트랜잭션 시작 시점의 스냅샷 개념을 고려하세요.
Read Committed는 커밋된 데이터만 읽지만 트랜잭션 중 같은 쿼리를 반복하면 다른 결과를 볼 수 있는 Non-repeatable Read가 발생합니다. Snapshot Isolation은 트랜잭션 시작 시점의 일관된 스냅샷을 보장하여 Repeatable Read를 제공하지만, 여전히 Phantom Read가 발생할 수 있습니다. MongoDB는 WiredTiger의 MVCC를 기반으로 Snapshot Isolation을 제공하며, 기본적으로 snapshot read concern을 사용하면 트랜잭션 시작 시점의 데이터를 일관되게 읽습니다. Phantom Read 방지를 위해서는 read concern을 snapshot으로, write concern을 majority로 설정해야 하며, 이는 사실상 Serializable에 가까운 격리 수준을 제공합니다. 다만 성능 트레이드오프로 인해 트랜잭션 처리량이 감소하고 충돌 시 재시도가 필요할 수 있습니다.
- • Snapshot Isolation은 트랜잭션 시작 시점의 일관된 뷰 제공
- • MongoDB는 MVCC 기반 Snapshot Isolation 지원
- • read concern snapshot + write concern majority로 Phantom Read 방지
금융 거래나 재고 관리 시스템에서 트랜잭션 격리 수준 설정이 데이터 정합성과 동시성 성능을 결정합니다.
MongoDB 트랜잭션에서 TransientTransactionError가 발생하는 주요 원인과 이를 처리하기 위한 재시도 전략을 설명해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!