시스템 디자인 면접 질문
시스템 디자인 면접은 모호한 문제의 범위를 정하고 규모에 따른 트레이드오프를 추론하는 능력을 평가합니다. 정답은 하나가 아닙니다 — 면접관은 명확하고 구조화된 접근 방식을 원합니다.
시스템 디자인 면접에서 다루는 내용
요구사항 및 범위
무언가를 설계하기 전에 기능적 요구사항과 비기능적 요구사항을 명확히 합니다.
추정
의사 결정을 정당화하기 위한 트래픽, 저장소, 대역폭의 대략적인 수치.
상위 수준 설계
API, 데이터 모델, 핵심 컴포넌트 및 그들 간의 데이터 흐름.
확장 및 트레이드오프
캐싱, 샤딩, 복제, 큐, 일관성 vs 가용성, 병목 지점.
샘플 시스템 디자인 면접 질문
- bit.ly와 같은 URL 단축기를 설계하세요.좋은 답변이 다루는 것
- Base62 인코딩 또는 해시 기반 ID 생성
- 충돌 해결 전략 (예: 고유 ID 생성기 사용)
- 301 vs 302 리디렉션 (영구 vs 임시)
- 데이터베이스 샤딩 및 캐싱 (예: Redis)
- 분석 데이터 수집 (클릭 카운트, 지리적 분포)
샘플 답변 보기
URL 단축기 설계의 핵심은 긴 URL을 짧은 고유 문자열로 매핑하는 것입니다. 먼저, URL ID를 생성하는 방법을 결정해야 합니다. 일반적으로 Base62 인코딩(0-9, a-z, A-Z)을 사용하여 짧은 문자열을 만들거나, MD5 등 해시 함수의 처음 몇 바이트를 사용할 수 있습니다. 충돌을 방지하기 위해 고유 ID 생성기(예: Snowflake)를 사용하거나, 데이터베이스의 auto-increment ID를 Base62로 변환하는 방법이 있습니다. 리디렉션은 HTTP 301(영구) 또는 302(임시)를 사용하며, 301은 브라우저 캐싱으로 인해 분석이 어려울 수 있으므로 302가 선호되기도 합니다. 저장소로는 수평 확장이 용이한 관계형 데이터베이스(예: PostgreSQL)를 샤딩하여 사용하고, 읽기 부하를 줄이기 위해 Redis 같은 캐시 계층을 둡니다. 또한, 클릭 카운트, 사용자 IP, 타임스탬프 등의 분석 데이터를 별도로 수집하여 비동기적으로 처리합니다. 요청이 증가하면 데이터베이스 샤딩과 캐시 확장을 통해 대응합니다.
- 뉴스 피드(예: Twitter/Instagram 타임라인)를 설계하세요.좋은 답변이 다루는 것
- 팬아웃 전략: 쓰기 시 팬아웃 vs 읽기 시 팬아웃
- 타임라인 생성 (개인화된 피드 혼합)
- 캐싱 계층 (예: Redis로 최근 피드)
- 데이터 저장: 관계형 DB와 NoSQL 혼합 (사용자, 게시물, 관계)
- 랭킹 및 필터링 알고리즘 (시간, 관련성)
샘플 답변 보기
뉴스 피드 시스템은 사용자에게 최신 게시물을 효율적으로 보여주는 것이 목표입니다. 주요 설계 결정은 팬아웃 방식입니다. '쓰기 시 팬아웃'은 게시물 작성 시 모든 팔로워에게 바로 전달하여 읽기 부하를 분산하지만, 핫한 사용자(예: 유명인)의 경우 쓰기 부하가 급증합니다. '읽기 시 팬아웃'은 읽을 때 타임라인을 생성하므로 쓰기 부하는 없지만 읽기 지연이 발생합니다. 실제로는 하이브리드 방식: 일반 사용자는 쓰기 시 팬아웃, 핫 사용자는 읽기 시 팬아웃을 적용합니다. 타임라인은 각 사용자별로 Redis 리스트로 관리하고, 새로운 게시물을 추가합니다. 데이터 저장은 사용자 정보는 관계형 DB, 게시물은 NoSQL(예: Cassandra)로 처리하고, 팔로우 관계는 그래프 DB(Neo4j)나 키-값 저장소를 사용할 수 있습니다. 피드 랭킹은 시간순 외에도 사용자 관심사나 상호작용 등을 고려한 머신러닝 모델을 적용할 수 있습니다. 확장을 위해 CDN으로 정적 이미지/비디오를 캐싱하고, 데이터베이스 샤딩과 리드 레플리카를 도입합니다.
- 공개 API를 위한 속도 제한기를 설계하세요.좋은 답변이 다루는 것
- 레이어 7 (애플리케이션 레벨) 속도 제한
- 알고리즘: 토큰 버킷, 슬라이딩 윈도우, 누출 버킷
- 분산 환경에서의 정확성 (Redis 원자 연산, Lua 스크립트)
- 응답 헤더: X-RateLimit-* 설정
- 사용자별 또는 IP별 제한, 비동기 처리
샘플 답변 보기
속도 제한기는 API 남용을 방지하고 서비스 품질을 유지합니다. 설계 시 사용자 인증 토큰, API 키, IP 주소 등 식별자를 기준으로 제한을 적용할 수 있습니다. 일반적인 알고리즘으로 토큰 버킷(Token Bucket)이 간단하고 유연하며, 슬라이딩 윈도우(Sliding Window)는 시간 기반의 정확한 제한을 제공합니다. 분산 환경에서는 Redis의 INCR 또는 Lua 스크립트를 사용하여 원자적으로 카운터를 관리하며, 레이스 컨디션을 방지합니다. 응답 헤더에 X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset을 포함시켜 클라이언트가 남은 한도를 알 수 있도록 합니다. 제한 초과 시 HTTP 429 Too Many Requests를 반환하고, Retry-After 헤더를 설정합니다. 또한, 요청을 버퍼링하여 비동기적으로 처리하는 방법도 고려할 수 있습니다. 확장 시에는 Redis 클러스터를 사용하고, 일관된 해싱으로 각 식별자의 카운터를 특정 노드에 분산합니다.
- 그룹 메시징과 읽음 확인을 지원하는 채팅 시스템을 설계하세요.좋은 답변이 다루는 것
- 메시지 순서 보장 및 그룹 관리
- 읽음 확인 구현 (각 사용자의 마지막 읽은 메시지 ID)
- 웹소켓 vs 롱폴링 (실시간 전달)
- 데이터베이스 스키마: 메시지, 그룹 멤버십, 읽음 상태
- 확장성: 메시지 파티셔닝 (그룹 ID 기준), 캐싱
샘플 답변 보기
채팅 시스템은 실시간 메시지 전달, 그룹 관리, 읽음 확인 등의 기능을 제공해야 합니다. 전송 계층으로 WebSocket을 사용하면 양방향 통신이 가능하고 지연이 낮습니다. 메시지 순서는 그룹 내에서 각 메시지에 서버에서 생성한 전역 일련번호(Sequence ID)를 부여하여 보장합니다. 읽음 확인은 각 사용자별로 마지막으로 읽은 메시지 ID를 저장하고, 사용자가 채팅방을 열 때마다 업데이트합니다. 데이터베이스 스키마는 메시지 테이블(메시지 ID, 그룹 ID, 발신자, 내용, 타임스탬프), 그룹 멤버십 테이블(사용자 ID, 그룹 ID, 마지막 읽은 메시지 ID)로 구성됩니다. 확장을 위해 메시지는 그룹 ID를 기준으로 파티셔닝(샤딩)하고, 최근 메시지는 Redis에 캐싱합니다. 또한, WebSocket 연결을 위한 연결 관리자(Connection Manager)를 별도 서비스로 분리하여 수평 확장합니다.
- 서비스를 1,000명에서 1,000만 명으로 확장하려면 어떻게 하시겠습니까?좋은 답변이 다루는 것
- 로드 밸런서 (L4/L7)와 수평 확장 (오토 스케일링)
- 데이터베이스 샤딩 및 읽기 복제본
- 캐싱 전략 (CDN, Redis/Memcached)
- 마이크로서비스 아키텍처로 분리
- 비동기 처리 (메시지 큐: Kafka, RabbitMQ)
샘플 답변 보기
1,000명에서 1,000만 명으로 확장하려면 점진적인 아키텍처 변화가 필요합니다. 초기(1,000명)에는 단일 서버, 단일 데이터베이스로 충분합니다. 1만 명 규모에서는 로드 밸런서를 도입하고 애플리케이션 서버를 여러 대로 확장합니다. 데이터베이스는 읽기 복제본을 추가하고, 캐싱 계층(Redis)을 도입하여 읽기 부하를 줄입니다. 10만 명 규모에서는 데이터베이스 샤딩(수평 분할)을 적용하고, 정적 파일은 CDN으로 오프로드합니다. 100만 명 이상에서는 마이크로서비스 아키텍처로 전환하여 기능별로 서비스를 분리하고, 각 서비스는 독립적으로 확장합니다. 비동기 처리를 위해 메시지 큐(Kafka)를 도입하여 이메일, 알림 등의 작업을 분리합니다. 오토 스케일링 그룹을 구성하여 트래픽에 따라 서버 수를 동적으로 조절합니다. 데이터베이스는 NoSQL(Cassandra)을 도입하여 쓰기 성능을 높이고, 검색은 Elasticsearch를 사용할 수 있습니다. 지속적인 모니터링과 성능 프로파일링으로 병목을 식별하고 개선합니다.
- 고가용성을 갖춘 분산 키-값 저장소를 설계하세요.좋은 답변이 다루는 것
- 일관된 해싱 (Consistent Hashing)으로 키 분배
- 복제와 가용성: 일관성 수준 (QUORUM, ONE 등)
- CAP 이론 트레이드오프 (가용성 vs 일관성)
- 버전 관리: 벡터 클록 또는 타임스탬프 (충돌 해결)
- 가십 프로토콜 (장애 감지 및 멤버십 관리)
샘플 답변 보기
분산 키-값 저장소는 가용성과 확장성을 보장하면서 데이터 일관성을 유지해야 합니다. 핵심은 일관된 해싱(Consistent Hashing)으로 키를 노드에 분배하여 노드 추가/제거 시 재분배되는 키의 양을 최소화합니다. 데이터 복제는 가용성을 위해 여러 노드에 저장하며, 쓰기 시 N개의 복제본 중 W개의 승인(Write Quorum), 읽기 시 R개의 승인(Read Quorum)을 받는 Quorum 방식을 사용하여 일관성을 조정합니다 (W+R > N). CAP 이론에 따라 네트워크 파티션 발생 시 가용성을 선택할지 일관성을 선택할지 결정해야 합니다. 일반적인 구현은 Dynamo 스타일로 '최종적 일관성(Eventual Consistency)'을 채택하고, 충돌 해결을 위해 벡터 클록(Vector Clock)이나 타임스탬프를 사용합니다. 장애 감지는 가십 프로토콜(Gossip Protocol)을 통해 노드 간 상태를 주기적으로 교환하여 비정상 노드를 감지하고, 멤버십 변경을 전파합니다. 확장 시에는 가상 노드(Virtual Node)를 사용하여 부하 분산을 개선하고, 필요에 따라 자동으로 데이터를 재분배합니다.
준비 방법
- 항상 요구사항과 제약 조건을 명확히 하는 것으로 시작하세요 — 해결책으로 바로 뛰어들지 마세요.
- 반복 가능한 프레임워크를 사용하세요: 요구사항 → 추정 → API → 데이터 모델 → 확장 → 트레이드오프.
- 트레이드오프를 명시적으로 언급하세요(예: 일관성 vs 가용성); 정답은 거의 없습니다.
- 대화를 주도하고 시간을 관리하세요 — 먼저 폭을 다루고, 요청받은 곳에서 깊게 들어가세요.
자주 묻는 질문
시스템 디자인 면접을 어떻게 준비하나요?
반복 가능한 프레임워크를 익히고, 몇 가지 표준 설계(피드, 채팅, URL 단축기, 속도 제한기)를 공부하며, 트레이드오프를 소리 내어 설명하는 연습을 하세요.
특정 기술을 알고 있어야 하나요?
구성 요소(로드 밸런서, 캐시, 큐, SQL vs NoSQL, 샤딩)와 그 장단점을 알아두세요. 특정 제품을 아는 것보다 추론 능력이 더 중요합니다.
가장 흔한 실수는 무엇인가요?
요구사항을 명확히 하거나 추정하지 않고 바로 설계로 뛰어들거나 트레이드오프를 언급하지 않는 것입니다.
시스템 디자인은 시니어 역할만 해당되나요?
중급 및 시니어 레벨에서 가장 흔하지만, 주니어 후보자는 단일 컴포넌트에 초점을 맞춘 가벼운 버전을 받을 수 있습니다.
즉각적인 AI 피드백으로 시스템 디자인 질문 연습하기
이력서를 업로드하고 맞춤형 모의 면접을 받아 무엇을 개선해야 할지 정확히 확인하세요 — 무료로 시작하세요.