- Authors
- Name
- 들어가며
- 1. 요구사항 확인 표현 (Clarifying Requirements)
- 2. 아키텍처 설명 표현 (Describing Architecture)
- 3. 확장성 논의 표현 (Discussing Scalability)
- 4. 트레이드오프 분석 표현 (Analyzing Trade-offs)
- 5. 데이터 모델링 설명 표현 (Data Modeling)
- 6. 실전 대화 시뮬레이션
- 7. 핵심 표현 비교표
- 8. 빈칸 채우기 퀴즈
- 9. 실전 말하기 연습
- 마치며
- 참고자료

들어가며
System Design Interview는 시니어 엔지니어 채용의 핵심 관문입니다. FAANG(Meta, Apple, Amazon, Netflix, Google)을 비롯한 글로벌 테크 기업의 면접에서 이 라운드는 단순히 기술 지식을 측정하는 것이 아니라, 복잡한 시스템을 설계하면서 자신의 사고 과정을 명확하게 전달하는 능력을 평가합니다.
한국인 엔지니어가 System Design Interview에서 겪는 가장 큰 어려움은 기술력 부족이 아닙니다. 대부분 기술적으로는 충분한 역량을 갖추고 있지만, 영어로 자신의 설계 의도를 구조적으로 전달하는 데 어려움을 느낍니다. 예를 들어 "이 부분은 캐시를 쓰면 좋을 것 같은데..."라는 생각을 영어로 "I would introduce a caching layer here to reduce the read latency on our database"처럼 명확하게 표현하는 것이 쉽지 않습니다.
이 글은 System Design Interview의 각 단계에서 사용하는 핵심 영어 표현 패턴을 체계적으로 정리합니다. 단순한 표현 나열이 아니라, 각 표현이 왜 효과적인지, 어떤 상황에서 사용하는지, 그리고 면접관에게 어떤 인상을 주는지까지 함께 다룹니다. 실전 시뮬레이션, 어휘 비교표, 퀴즈를 통해 학습한 표현을 즉시 자기 것으로 만들 수 있도록 구성했습니다.
이 글에서 다루는 핵심 역량은 다음과 같습니다.
- 면접 초반에 요구사항을 체계적으로 확인하는 질문 패턴
- 복잡한 아키텍처를 상위에서 하위로(top-down) 명확하게 설명하는 화법
- 확장성(scalability) 전략을 정량적 근거와 함께 제안하는 표현
- 설계 결정의 장단점을 균형 있게 분석하는 트레이드오프 논의 패턴
- 데이터 모델과 스키마 선택을 논리적으로 정당화하는 표현
1. 요구사항 확인 표현 (Clarifying Requirements)
System Design Interview의 시작은 항상 요구사항 확인입니다. 면접관이 "Design a URL shortener" 또는 "Design a chat system"이라고 말하면, 바로 설계에 들어가는 것은 가장 흔한 실수입니다. 면접관은 지원자가 모호한 문제를 어떻게 구체화하는지, 올바른 질문을 던지는 능력이 있는지를 평가합니다.
면접 시작 시 프레임 설정
면접이 시작되면 먼저 접근 방식을 설명하는 것이 중요합니다. 이렇게 하면 면접관에게 구조적으로 사고하는 사람이라는 인상을 줍니다.
"Before jumping into the design, I'd like to spend a few minutes
clarifying the requirements and understanding the constraints."
(설계에 들어가기 전에, 몇 분간 요구사항을 확인하고 제약 조건을
이해하는 시간을 갖겠습니다.)
"I'll start by asking some clarifying questions, then outline
a high-level design, and iteratively refine it."
(먼저 확인 질문을 드리고, 상위 레벨 설계를 스케치한 다음,
반복적으로 개선해 나가겠습니다.)
"My approach will be to first understand the functional and
non-functional requirements, then work through the system
design top-down."
(제 접근 방식은 먼저 기능적/비기능적 요구사항을 이해한 다음,
시스템 설계를 상위에서 하위로 진행하는 것입니다.)
기능적 요구사항 확인
기능적 요구사항(Functional Requirements)은 시스템이 무엇을 해야 하는지를 정의합니다. 핵심 기능과 범위를 명확히 하는 질문을 던져야 합니다.
"What are the core use cases we need to support?"
(지원해야 하는 핵심 사용 사례는 무엇인가요?)
"Should the system support real-time updates, or is
eventual consistency acceptable?"
(시스템이 실시간 업데이트를 지원해야 하나요, 아니면
최종 일관성도 허용되나요?)
"Do we need to support both mobile and web clients,
or can I focus on one platform initially?"
(모바일과 웹 클라이언트를 모두 지원해야 하나요, 아니면
처음에는 하나의 플랫폼에 집중해도 될까요?)
"Is there a requirement for offline support or
graceful degradation?"
(오프라인 지원이나 우아한 성능 저하에 대한
요구사항이 있나요?)
비기능적 요구사항과 규모 추정
비기능적 요구사항(Non-Functional Requirements)은 시스템의 품질 속성을 정의합니다. 규모 추정(Back-of-the-envelope estimation)을 함께 수행하면 면접관에게 좋은 인상을 줍니다.
"Let me do a quick back-of-the-envelope calculation to
estimate the scale."
(규모를 추정하기 위해 빠른 대략적 계산을 해보겠습니다.)
"If we have 100 million daily active users, and each user
generates an average of 10 requests per day, that gives us
roughly 1 billion requests per day, or about 12,000 QPS."
(일일 활성 사용자가 1억 명이고, 각 사용자가 하루 평균 10개의
요청을 생성한다면, 하루 약 10억 건, 즉 약 12,000 QPS입니다.)
"What's the expected read-to-write ratio? I'm assuming
it's heavily read-biased, maybe 100:1?"
(예상 읽기 대 쓰기 비율은 어떻게 되나요? 읽기 중심이라고
가정하면, 100:1 정도일까요?)
"Are there any specific latency requirements? For example,
should the 99th percentile response time be under
200 milliseconds?"
(특정 지연시간 요구사항이 있나요? 예를 들어, 99번째 백분위
응답 시간이 200밀리초 이하여야 하나요?)
"What's our availability target? Five nines, or is
99.9 percent sufficient?"
(가용성 목표는 어떻게 되나요? 파이브 나인인지, 아니면
99.9 퍼센트로 충분한지?)
범위 한정과 우선순위 설정
제한된 면접 시간(보통 45-60분) 내에서 모든 것을 다룰 수 없으므로, 범위를 적극적으로 한정하는 것이 중요합니다.
"Given the 45-minute time constraint, I'd propose we focus on
the core messaging flow first, and then discuss notification
delivery and media handling if time permits."
(45분의 시간 제약을 고려해, 핵심 메시징 흐름에 먼저 집중하고,
시간이 허락하면 알림 전달과 미디어 처리를 논의하겠습니다.)
"Let me prioritize the requirements. I see the URL shortening
and redirection as P0, analytics as P1, and custom domains
as P2."
(요구사항에 우선순위를 매기겠습니다. URL 단축과 리디렉션을 P0,
분석 기능을 P1, 커스텀 도메인을 P2로 봅니다.)
"I'll table the authentication and authorization aspects for now
and assume we have an existing auth service we can integrate with."
(인증과 인가 부분은 잠시 보류하고, 통합할 수 있는 기존 인증
서비스가 있다고 가정하겠습니다.)
2. 아키텍처 설명 표현 (Describing Architecture)
요구사항이 확인되면 전체 아키텍처를 설명하는 단계로 넘어갑니다. 이 단계의 핵심은 상위에서 하위로(top-down) 접근하면서, 각 컴포넌트의 역할과 상호작용을 명확하게 전달하는 것입니다.
상위 레벨 아키텍처 소개
화이트보드(또는 온라인 다이어그램 도구)에 큰 그림을 그리면서 설명을 시작합니다.
"Let me sketch out the high-level architecture first.
At the topmost level, I see three main layers: the client
layer, the application layer, and the data layer."
(먼저 상위 레벨 아키텍처를 스케치하겠습니다. 가장 높은 수준에서,
클라이언트 레이어, 애플리케이션 레이어, 데이터 레이어의
세 가지 주요 레이어가 보입니다.)
"The system will be composed of several microservices,
each responsible for a single bounded context."
(시스템은 여러 마이크로서비스로 구성되며, 각각은 하나의
바운디드 컨텍스트를 담당합니다.)
"I'm envisioning a distributed architecture with
a load balancer at the entry point, multiple stateless
application servers, and a replicated database cluster."
(진입점에 로드 밸런서가 있고, 여러 상태 비보존
애플리케이션 서버와 복제된 데이터베이스 클러스터로 구성된
분산 아키텍처를 구상하고 있습니다.)
컴포넌트 역할 설명
각 컴포넌트를 설명할 때는 역할(responsibility), 입출력(input/output), 다른 컴포넌트와의 관계를 명확히 합니다.
"The API Gateway serves as the single entry point for all
client requests. It handles authentication, rate limiting,
and request routing to the appropriate backend service."
(API 게이트웨이는 모든 클라이언트 요청의 단일 진입점 역할을 합니다.
인증, 속도 제한, 적절한 백엔드 서비스로의 요청 라우팅을 처리합니다.)
"This service is responsible for generating unique short URLs
and persisting the mapping between the short URL and the
original URL."
(이 서비스는 고유한 단축 URL을 생성하고, 단축 URL과
원본 URL 간의 매핑을 영속화하는 역할을 합니다.)
"The notification service acts as a fan-out component. When
a new message arrives, it distributes push notifications to
all relevant subscribers."
(알림 서비스는 팬아웃 컴포넌트 역할을 합니다. 새 메시지가 도착하면,
관련된 모든 구독자에게 푸시 알림을 분배합니다.)
데이터 흐름 설명 패턴
데이터가 시스템을 통해 흐르는 과정을 단계별로 설명하는 것은 면접관이 매우 좋아하는 패턴입니다. "walk through"라는 표현을 활용합니다.
"Let me walk you through a typical write path. When a user
creates a new post, the request first hits our load balancer."
(일반적인 쓰기 경로를 설명하겠습니다. 사용자가 새 게시물을
생성하면, 요청은 먼저 로드 밸런서에 도달합니다.)
"From there, the load balancer forwards the request to one of
the application servers using a round-robin strategy."
(거기서 로드 밸런서가 라운드 로빈 전략을 사용해 애플리케이션
서버 중 하나로 요청을 전달합니다.)
"The application server validates the input, enriches the data
with metadata, and then writes it to the primary database."
(애플리케이션 서버가 입력을 검증하고, 메타데이터로 데이터를
보강한 다음, 프라이머리 데이터베이스에 씁니다.)
"Simultaneously, a message is published to the event bus,
which triggers the indexing service to update the search index
and the notification service to alert followers."
(동시에 이벤트 버스에 메시지가 발행되고, 이것이 인덱싱 서비스가
검색 인덱스를 업데이트하고 알림 서비스가 팔로워에게 알리도록
트리거합니다.)
기술 선택 근거 설명
단순히 기술을 언급하는 것이 아니라, 왜 그 기술을 선택했는지 근거를 함께 제시해야 합니다.
"I'm choosing Redis as the caching layer because it provides
sub-millisecond latency and supports various data structures
like sorted sets, which are ideal for our leaderboard feature."
(캐싱 레이어로 Redis를 선택합니다. 밀리초 이하의 지연시간을 제공하고,
리더보드 기능에 이상적인 정렬된 집합(sorted set) 같은 다양한
데이터 구조를 지원하기 때문입니다.)
"For the message queue, I'd go with Kafka over RabbitMQ
because we need high throughput, message durability,
and the ability to replay events."
(메시지 큐로는 RabbitMQ 대신 Kafka를 선택하겠습니다.
높은 처리량, 메시지 내구성, 이벤트 재생 기능이
필요하기 때문입니다.)
"I'd recommend using a NoSQL database like DynamoDB here
because our access patterns are well-defined and we need
to scale horizontally without worrying about sharding complexity."
(여기서는 DynamoDB 같은 NoSQL 데이터베이스를 추천합니다.
접근 패턴이 잘 정의되어 있고, 샤딩 복잡성 걱정 없이
수평 확장해야 하기 때문입니다.)
3. 확장성 논의 표현 (Discussing Scalability)
확장성(Scalability)은 System Design Interview의 핵심 주제입니다. 면접관은 시스템이 트래픽 증가에 어떻게 대응하는지, 병목 지점을 어떻게 해결하는지 들고 싶어합니다.
수평 확장 vs 수직 확장
"For the application tier, I'd go with horizontal scaling
rather than vertical scaling. Adding more instances behind
the load balancer is more cost-effective and provides better
fault tolerance than scaling up a single machine."
(애플리케이션 계층에서는 수직 확장보다 수평 확장을 선택하겠습니다.
로드 밸런서 뒤에 인스턴스를 추가하는 것이 단일 머신을
스케일업하는 것보다 비용 효율적이고 내결함성이 더 좋습니다.)
"The beauty of making these services stateless is that we can
scale them out independently based on demand."
(이 서비스들을 상태 비보존으로 만드는 장점은 수요에 따라
독립적으로 스케일아웃할 수 있다는 것입니다.)
"We might start with vertical scaling for the database in
the short term, but we should plan for sharding as we
approach the limits of a single node."
(단기적으로는 데이터베이스의 수직 확장으로 시작하되,
단일 노드의 한계에 가까워지면 샤딩을 계획해야 합니다.)
캐싱 전략 설명
"To handle the high read traffic, I'd introduce a multi-level
caching strategy. First, a CDN for static assets. Second,
an application-level cache using Redis for frequently accessed
data. Third, a local in-memory cache for hot data."
(높은 읽기 트래픽을 처리하기 위해 다단계 캐싱 전략을
도입하겠습니다. 첫째, 정적 자산을 위한 CDN. 둘째,
자주 접근하는 데이터를 위한 Redis 기반 애플리케이션 레벨 캐시.
셋째, 핫 데이터를 위한 로컬 인메모리 캐시입니다.)
"For the caching strategy, I'd use a write-through pattern
for data that needs strong consistency, and a cache-aside
pattern for data where slight staleness is acceptable."
(캐싱 전략으로, 강한 일관성이 필요한 데이터에는 write-through
패턴을, 약간의 오래됨이 허용되는 데이터에는 cache-aside
패턴을 사용하겠습니다.)
"The cache hit ratio is critical here. If we can achieve
a 95 percent cache hit rate, we reduce the database load
by 20x, which would bring our P99 latency well under
the 200-millisecond target."
(캐시 적중률이 여기서 핵심입니다. 95퍼센트 캐시 적중률을
달성하면, 데이터베이스 부하를 20배 줄여 P99 지연시간을
200밀리초 목표 이하로 낮출 수 있습니다.)
데이터베이스 확장과 파티셔닝
"As the data volume grows, we'll need to partition the database.
I'd suggest range-based sharding on the timestamp for time-series
data, or hash-based sharding on the user ID for user-centric data."
(데이터 볼륨이 증가하면 데이터베이스를 파티셔닝해야 합니다.
시계열 데이터에는 타임스탬프 기반 범위 샤딩을, 사용자 중심
데이터에는 사용자 ID 기반 해시 샤딩을 제안합니다.)
"To avoid the hotspot problem with hash-based sharding,
we could use consistent hashing, which minimizes data
redistribution when we add or remove nodes."
(해시 기반 샤딩에서 핫스팟 문제를 피하기 위해, 일관된 해싱을
사용할 수 있습니다. 노드를 추가하거나 제거할 때 데이터
재분배를 최소화합니다.)
"For read scalability, I'd set up read replicas. The primary
handles all writes, and reads are distributed across multiple
replicas. This gives us a read throughput that scales linearly
with the number of replicas."
(읽기 확장성을 위해 읽기 복제본을 설정하겠습니다. 프라이머리가
모든 쓰기를 처리하고, 읽기는 여러 복제본에 분배됩니다. 이렇게
하면 복제본 수에 비례해 읽기 처리량이 선형적으로 확장됩니다.)
병목 지점 식별과 해결
"The bottleneck in this design is the single database write path.
Under peak load, all write operations funnel through one primary
node, which could become saturated."
(이 설계의 병목 지점은 단일 데이터베이스 쓰기 경로입니다.
피크 부하에서 모든 쓰기 작업이 하나의 프라이머리 노드로
집중되어 과부하가 될 수 있습니다.)
"To alleviate this bottleneck, I'd introduce a write-behind
queue. Instead of writing directly to the database, the application
writes to a fast message queue, and a background worker processes
the writes in batches."
(이 병목을 완화하기 위해 write-behind 큐를 도입하겠습니다.
데이터베이스에 직접 쓰는 대신, 애플리케이션이 빠른 메시지 큐에
쓰고, 백그라운드 워커가 배치로 쓰기를 처리합니다.)
"Another potential bottleneck is the fan-out on read. If a user
follows thousands of accounts, assembling their timeline
could be expensive."
(또 다른 잠재적 병목은 읽기 시 팬아웃입니다. 사용자가 수천 개의
계정을 팔로우한다면, 타임라인을 조합하는 것이
비용이 많이 들 수 있습니다.)
4. 트레이드오프 분석 표현 (Analyzing Trade-offs)
트레이드오프 분석은 시니어 엔지니어의 핵심 역량입니다. 면접관은 은탄환(silver bullet)은 없다는 것을 이해하고, 각 설계 결정의 장단점을 균형 있게 분석할 수 있는 지원자를 높이 평가합니다.
트레이드오프 프레임 제시
"There's a fundamental trade-off here between consistency and
availability. Following the CAP theorem, since we're building
a distributed system, we need to decide which one to prioritize
when network partitions occur."
(여기에 일관성과 가용성 사이의 근본적인 트레이드오프가 있습니다.
CAP 정리에 따라, 분산 시스템을 구축하고 있으므로 네트워크
파티션이 발생할 때 어느 쪽을 우선시할지 결정해야 합니다.)
"The trade-off I see here is between system complexity and
performance. We could get a 10x improvement in query latency
by denormalizing the data, but that introduces data
consistency challenges."
(여기서 제가 보는 트레이드오프는 시스템 복잡성과 성능 사이입니다.
데이터를 비정규화하면 쿼리 지연시간을 10배 개선할 수 있지만,
데이터 일관성 문제가 발생합니다.)
"We're essentially trading off development velocity for
operational simplicity. A monolithic approach would be faster
to build initially, but a microservices architecture gives us
better long-term scalability and team autonomy."
(본질적으로 개발 속도와 운영 단순성 사이의 트레이드오프입니다.
모놀리식 접근이 초기에는 더 빠르게 구축할 수 있지만,
마이크로서비스 아키텍처가 장기적 확장성과 팀 자율성에서
더 유리합니다.)
대안 비교 표현
여러 선택지를 비교할 때는 구조적으로 장단점을 나열하는 것이 효과적입니다.
"Let me compare two approaches. Option A is a push-based model,
where we precompute timelines. Option B is a pull-based model,
where we compute timelines on demand."
(두 가지 접근 방식을 비교하겠습니다. 옵션 A는 타임라인을
사전 계산하는 푸시 기반 모델입니다. 옵션 B는 요청 시
타임라인을 계산하는 풀 기반 모델입니다.)
"The advantage of Option A is lower read latency since the
timeline is precomputed. The downside is higher write
amplification and storage cost."
(옵션 A의 장점은 타임라인이 사전 계산되므로 읽기 지연시간이
낮다는 것입니다. 단점은 쓰기 증폭과 저장 비용이
높다는 것입니다.)
"Given our requirement of sub-100-millisecond read latency and
the fact that our system is heavily read-biased, I'd lean toward
Option A, the push-based model, and optimize for the celebrity
problem separately."
(100밀리초 이하의 읽기 지연시간 요구사항과 시스템이 읽기 중심이라는
점을 고려하면, 옵션 A인 푸시 기반 모델을 선호하고, 셀러브리티
문제는 별도로 최적화하겠습니다.)
결정 정당화 패턴
설계 결정을 내린 후에는 왜 그 결정을 했는지 명확하게 정당화해야 합니다.
"I'm going with this approach because it aligns with our primary
requirement of high availability. The slight inconsistency window
of a few seconds is acceptable for our use case."
(이 접근 방식을 선택하는 이유는 고가용성이라는 우리의 주요
요구사항에 부합하기 때문입니다. 몇 초간의 약간의 불일치 구간은
우리 사용 사례에서 허용 가능합니다.)
"The reason I prefer eventual consistency here is that user
experience data shows that users rarely notice a 2-3 second
delay in feed updates, but they absolutely notice downtime."
(여기서 최종 일관성을 선호하는 이유는 사용자 경험 데이터에 따르면
사용자가 피드 업데이트의 2-3초 지연은 거의 인지하지 못하지만,
다운타임은 확실히 인지하기 때문입니다.)
"If I had to revisit this decision, the trigger would be if our
consistency requirements changed, for example, if we needed to
support financial transactions."
(이 결정을 재검토해야 한다면, 일관성 요구사항이 변경될 때가
그 계기일 것입니다. 예를 들어, 금융 거래를 지원해야 하는
경우입니다.)
5. 데이터 모델링 설명 표현 (Data Modeling)
데이터 모델은 시스템의 기초입니다. 면접에서 데이터 모델을 설명할 때는 엔티티 관계, 접근 패턴, 인덱싱 전략을 함께 다뤄야 합니다.
엔티티와 관계 설명
"Let me define the core entities first. We have Users, Posts,
and Comments. A User can create multiple Posts, and each Post
can have multiple Comments. This is a one-to-many relationship
in both cases."
(먼저 핵심 엔티티를 정의하겠습니다. User, Post, Comment가 있습니다.
User는 여러 Post를 생성할 수 있고, 각 Post는 여러 Comment를
가질 수 있습니다. 두 경우 모두 일대다 관계입니다.)
"For the follower relationship, we have a many-to-many
relationship between Users. I'd model this as a separate
adjacency table with follower_id and followee_id."
(팔로워 관계의 경우, User 간의 다대다 관계입니다. 이것을
follower_id와 followee_id를 가진 별도의 인접 테이블로
모델링하겠습니다.)
"I'm intentionally denormalizing the author name into the
Post table to avoid an expensive join on every read operation."
(모든 읽기 작업에서의 비용이 큰 조인을 피하기 위해
의도적으로 작성자 이름을 Post 테이블에 비정규화합니다.)
데이터베이스 선택 근거
"For the main user data, I'd use a relational database like
PostgreSQL because we need ACID transactions for user account
operations and the data has clear relational structure."
(주요 사용자 데이터에는 PostgreSQL 같은 관계형 데이터베이스를
사용하겠습니다. 사용자 계정 작업에 ACID 트랜잭션이 필요하고,
데이터가 명확한 관계형 구조를 가지기 때문입니다.)
"For the message history, I'd choose Cassandra because it excels
at write-heavy workloads and provides linear scalability.
The access pattern is simple: we always query by conversation ID
and sort by timestamp."
(메시지 이력에는 Cassandra를 선택하겠습니다. 쓰기 중심 워크로드에
탁월하고 선형 확장성을 제공합니다. 접근 패턴이 단순합니다:
항상 대화 ID로 쿼리하고 타임스탬프로 정렬합니다.)
"I'd store the media files in an object store like S3,
and only keep the metadata and reference URLs in our
primary database. This separation of concerns keeps the
database lean and the storage cost manageable."
(미디어 파일은 S3 같은 객체 스토어에 저장하고, 프라이머리
데이터베이스에는 메타데이터와 참조 URL만 보관하겠습니다.
이런 관심사의 분리가 데이터베이스를 가볍게 유지하고
저장 비용을 관리 가능하게 합니다.)
인덱싱과 쿼리 최적화
"I'd create a composite index on user_id and created_at
to efficiently support the query pattern of fetching
a user's recent posts."
(사용자의 최근 게시물을 가져오는 쿼리 패턴을 효율적으로
지원하기 위해 user_id와 created_at에 복합 인덱스를
생성하겠습니다.)
"For the search functionality, I'd use an inverted index
powered by Elasticsearch. The primary database serves as
the source of truth, and we asynchronously sync data
to the search index."
(검색 기능에는 Elasticsearch 기반의 역인덱스를 사용하겠습니다.
프라이머리 데이터베이스가 정보의 원천(source of truth) 역할을
하고, 비동기적으로 검색 인덱스에 데이터를 동기화합니다.)
"To avoid full table scans, I'd partition the analytics data
by date range, so queries that filter by time period only
need to scan the relevant partitions."
(전체 테이블 스캔을 피하기 위해, 분석 데이터를 날짜 범위로
파티셔닝하겠습니다. 시간 기간으로 필터링하는 쿼리는
관련 파티션만 스캔하면 됩니다.)
6. 실전 대화 시뮬레이션
실제 System Design Interview가 어떻게 진행되는지 시뮬레이션해 보겠습니다. 면접 주제는 "Design a URL Shortener (like bit.ly)" 입니다.
[면접관] "Let's design a URL shortening service, similar to bit.ly.
How would you approach this?"
[지원자] "Great, that's an interesting problem. Before I start
designing, I'd like to clarify a few requirements.
First, on the functional side: Should the system support
custom aliases, or only auto-generated short URLs? And do we
need analytics, like click tracking and geographic data?"
[면접관] "Let's support both auto-generated and custom aliases.
Yes, basic analytics would be nice."
[지원자] "Got it. Now for scale: what's the expected volume of
URL shortening requests? Are we talking millions per day?"
[면접관] "Assume 100 million new URLs per month, and a 10:1
read-to-write ratio for redirects."
[지원자] "Okay, let me do the math. 100 million writes per month
is roughly 40 writes per second on average. With a 10:1
read ratio, that's about 400 redirects per second. We should
design for peak traffic of maybe 5-10x that, so around
2,000 to 4,000 reads per second.
For storage, if the average URL mapping is about 500 bytes
and we store for 5 years, that's roughly 3 terabytes.
That's manageable with a well-designed database setup.
Now let me outline the high-level architecture. I see three
main components:
First, a URL shortening service that takes a long URL and
returns a short one. It generates a unique key, stores the
mapping, and returns the short URL.
Second, a URL redirection service that receives a short URL,
looks up the original URL, and issues an HTTP 301 or 302
redirect.
Third, an analytics service that tracks each redirect event
for reporting purposes.
For the key generation, I'd use a base62 encoding of a
counter or a hash. With 7 characters in base62, we get
about 3.5 trillion unique URLs, which is more than enough.
For the database, I'd go with a NoSQL key-value store
because our access pattern is simple: given a short key,
return the long URL. This is a perfect fit for something
like DynamoDB or Redis.
The trade-off between 301 and 302 redirects is worth
discussing. A 301 is a permanent redirect, which means
browsers will cache it and bypass our service on subsequent
requests. This reduces our server load but means we lose
analytics data. A 302 is a temporary redirect, so the
browser will always come to us first, giving us accurate
click tracking but at higher server load.
Given that analytics is a requirement, I'd use 302 redirects
by default and offer 301 as an option for users who don't
need analytics.
For scalability, I'd put the redirection service behind
a load balancer with auto-scaling. Since the service is
stateless, scaling horizontally is straightforward.
I'd also add a caching layer with Redis to handle hot URLs
that get millions of clicks."
[면접관] "Good. What about the availability and reliability
of the system?"
[지원자] "For availability, I'd deploy across multiple
availability zones. The key-value store would have
cross-region replication for disaster recovery.
For reliability, I'd implement a circuit breaker pattern
between services. If the analytics service is down,
the redirect should still work. We can buffer analytics
events in a message queue and process them when the
analytics service recovers.
I'd also add monitoring and alerting on key metrics:
redirect latency at the P99 level, error rates, and
cache hit ratios. If the cache hit ratio drops below
90 percent, that's an early warning sign that we might
need to scale the cache layer."
7. 핵심 표현 비교표
System Design Interview에서 같은 의미를 전달하더라도, 표현의 수준에 따라 면접관에게 주는 인상이 크게 달라집니다. 아래 표에서 초급 표현과 고급 표현을 비교해 보세요.
| 상황 | 초급 표현 | 고급 표현 | 한국어 의미 |
|---|---|---|---|
| 확장 필요 설명 | "We need more servers" | "We should scale horizontally by adding more instances behind the load balancer" | 로드 밸런서 뒤에 인스턴스를 추가해 수평 확장해야 합니다 |
| 캐시 도입 제안 | "We can use cache" | "I'd introduce a caching layer to reduce read latency and offload the database" | 읽기 지연시간을 줄이고 데이터베이스 부하를 줄이기 위해 캐싱 레이어를 도입하겠습니다 |
| 트레이드오프 언급 | "This is good and bad" | "The trade-off here is between write amplification and read performance" | 여기서의 트레이드오프는 쓰기 증폭과 읽기 성능 사이에 있습니다 |
| 데이터베이스 선택 | "I'll use SQL database" | "I'd opt for PostgreSQL given our need for ACID compliance and complex querying" | ACID 준수와 복잡한 쿼리 필요성을 고려해 PostgreSQL을 선택하겠습니다 |
| 지연시간 언급 | "It will be fast" | "This should bring our P99 latency well under the 200-millisecond SLA" | P99 지연시간을 200밀리초 SLA 이하로 낮출 수 있을 것입니다 |
| 병목 지점 설명 | "Database is slow" | "The database is the bottleneck in this write path due to lock contention" | 락 경합으로 인해 데이터베이스가 이 쓰기 경로의 병목입니다 |
| 비동기 처리 제안 | "Do it later" | "I'd decouple this using an async message queue for eventual processing" | 비동기 메시지 큐를 사용해 디커플링하고 최종적으로 처리하겠습니다 |
| 기술 선택 이유 | "Kafka is popular" | "Kafka is well-suited here due to its high throughput, durability guarantees, and replay capability" | Kafka는 높은 처리량, 내구성 보장, 재생 기능 덕분에 여기에 적합합니다 |
핵심 어휘 정리
| 영어 용어 | 한국어 의미 | 사용 맥락 |
|---|---|---|
| back-of-the-envelope calculation | 대략적인 추정 계산 | 규모 추정 시 사용 |
| bottleneck | 병목 지점 | 성능 제한 요소 설명 시 |
| fan-out | 팬아웃 (하나의 입력을 여러 출력으로 분배) | 메시지 분배, 타임라인 구성 시 |
| write amplification | 쓰기 증폭 | 하나의 논리적 쓰기가 여러 물리적 쓰기를 유발할 때 |
| hot partition / hotspot | 핫 파티션 / 핫스팟 | 특정 파티션에 트래픽이 집중될 때 |
| sharding | 샤딩 (데이터 수평 분할) | 데이터베이스 확장 논의 시 |
| consistent hashing | 일관된 해싱 | 노드 추가/제거 시 최소 재분배 설명 시 |
| circuit breaker | 서킷 브레이커 (장애 전파 방지 패턴) | 서비스 간 장애 격리 설명 시 |
| eventual consistency | 최종 일관성 | CAP 정리, 분산 시스템 논의 시 |
| idempotent / idempotency | 멱등성 (동일 연산 반복 시 같은 결과) | API 설계, 재시도 논의 시 |
| read replica | 읽기 복제본 | 읽기 확장성 논의 시 |
| denormalization | 비정규화 | 읽기 성능 최적화를 위한 데이터 중복 허용 시 |
| source of truth | 정보의 원천 (신뢰할 수 있는 단일 데이터 소스) | 데이터 일관성 논의 시 |
| SLA (Service Level Agreement) | 서비스 수준 협약 | 성능 요구사항 정의 시 |
| P99 latency | 99번째 백분위 지연시간 | 성능 지표 논의 시 |
8. 빈칸 채우기 퀴즈
다음 문장의 빈칸에 적절한 영어 표현을 넣어보세요. 각 문장은 System Design Interview에서 자주 사용되는 패턴입니다.
Quiz 1. 규모 추정을 시작할 때:
"Let me do a quick __________ calculation to estimate the scale of this system."
정답 확인
back-of-the-envelope
전체 문장: "Let me do a quick back-of-the-envelope calculation to estimate the scale of this system."
의미: 이 시스템의 규모를 추정하기 위해 빠른 대략적 계산을 하겠습니다.
Quiz 2. 수평 확장을 설명할 때:
"We can __________ scale this service by adding more instances behind the load balancer."
정답 확인
horizontally
전체 문장: "We can horizontally scale this service by adding more instances behind the load balancer."
의미: 로드 밸런서 뒤에 인스턴스를 추가함으로써 이 서비스를 수평 확장할 수 있습니다.
Quiz 3. 캐시 적중률을 논의할 때:
"If we can achieve a 95 percent cache ________ rate, we can significantly reduce the database load."
정답 확인
hit
전체 문장: "If we can achieve a 95 percent cache hit rate, we can significantly reduce the database load."
의미: 95퍼센트의 캐시 적중률을 달성하면, 데이터베이스 부하를 크게 줄일 수 있습니다.
Quiz 4. 트레이드오프를 제시할 때:
"The __________ here is between consistency and availability."
정답 확인
trade-off
전체 문장: "The trade-off here is between consistency and availability."
의미: 여기서의 트레이드오프는 일관성과 가용성 사이에 있습니다.
Quiz 5. 데이터 흐름을 설명하기 시작할 때:
"Let me ________ you ________ the data flow for a typical read request."
정답 확인
walk ... through
전체 문장: "Let me walk you through the data flow for a typical read request."
의미: 일반적인 읽기 요청에 대한 데이터 흐름을 설명해 드리겠습니다.
Quiz 6. 기술 선택의 이유를 설명할 때:
"I'd ________ for Kafka because it provides high throughput and message durability."
정답 확인
go (또는 opt)
전체 문장: "I'd go for Kafka because it provides high throughput and message durability."
의미: Kafka를 선택하겠습니다. 높은 처리량과 메시지 내구성을 제공하기 때문입니다.
Quiz 7. 병목 지점을 식별할 때:
"The __________ in this design is the single-threaded write path to the database."
정답 확인
bottleneck
전체 문장: "The bottleneck in this design is the single-threaded write path to the database."
의미: 이 설계의 병목 지점은 데이터베이스로의 단일 스레드 쓰기 경로입니다.
Quiz 8. API의 멱등성을 논의할 때:
"We should make this API __________ so that retries don't create duplicate entries."
정답 확인
idempotent
전체 문장: "We should make this API idempotent so that retries don't create duplicate entries."
의미: 재시도가 중복 항목을 생성하지 않도록 이 API를 멱등으로 만들어야 합니다.
Quiz 9. 가용성 목표를 논의할 때:
"Our availability target is five ________, which translates to less than 5.26 minutes of downtime per year."
정답 확인
nines
전체 문장: "Our availability target is five nines, which translates to less than 5.26 minutes of downtime per year."
의미: 가용성 목표는 파이브 나인(99.999%)이며, 이는 연간 5.26분 미만의 다운타임을 의미합니다.
Quiz 10. 비동기 처리를 제안할 때:
"I'd __________ the image processing from the upload flow by putting it on a message queue."
정답 확인
decouple
전체 문장: "I'd decouple the image processing from the upload flow by putting it on a message queue."
의미: 메시지 큐에 넣어서 이미지 처리를 업로드 흐름에서 분리하겠습니다.
9. 실전 말하기 연습
아래 시나리오를 읽고, 영어로 답변을 구성해 보세요. 가능하면 소리 내어 말하는 연습을 하세요. 각 시나리오에는 예시 답변을 제공합니다.
연습 1: 아키텍처 설명
시나리오: 면접관이 "Design a chat application like Slack"이라고 했습니다. 상위 레벨 아키텍처를 설명하세요.
[예시 답변]
"I'd architect this as a set of microservices. At the top level,
we have the client applications connecting through WebSocket
connections for real-time messaging.
The WebSocket Gateway manages persistent connections with
clients and handles message routing. Behind it, we have
a Message Service that processes incoming messages, persists
them to the database, and publishes events.
For real-time delivery, I'd use a pub-sub system. When a user
sends a message to a channel, the Message Service publishes
it to the channel's topic. The WebSocket Gateway subscribes
to relevant topics and pushes messages to connected clients.
For message persistence, I'd use Cassandra for the message
store, optimized for the write-heavy workload and the access
pattern of fetching messages by channel ID sorted by timestamp.
I'd also have a separate Presence Service that tracks which
users are online, using Redis with TTL-based expiry to manage
user heartbeats."
연습 2: 트레이드오프 분석
시나리오: 면접관이 "Should we use a SQL or NoSQL database for the user profile service?"라고 물었습니다. 트레이드오프를 분석하세요.
[예시 답변]
"This is a great question, and the answer depends on our
specific requirements. Let me analyze the trade-offs.
For a user profile service, a SQL database like PostgreSQL
offers strong consistency, ACID transactions, and flexible
querying with JOINs. This is beneficial if we need complex
queries across related data, like fetching a user's profile
along with their subscription status and billing information.
On the other hand, a NoSQL database like DynamoDB offers
better horizontal scalability and predictable performance at
any scale. If our access pattern is simple, primarily looking
up a profile by user ID, NoSQL gives us single-digit
millisecond latency regardless of the data volume.
Given that user profiles typically have a well-defined schema
and we might need to do complex queries for admin tools and
analytics, I'd lean toward PostgreSQL for the primary
user profile store. However, I'd cache the frequently
accessed profile data in Redis to handle the high read
throughput from the application layer.
The key consideration is that PostgreSQL can handle our
scale if we implement read replicas. If we were at the
scale of billions of users, I'd reconsider and potentially
use DynamoDB with a separate analytics pipeline."
연습 3: 확장성 대응
시나리오: 면접관이 "Your system is handling 10,000 QPS now. How would you handle a 100x increase in traffic?"라고 물었습니다.
[예시 답변]
"A 100x traffic increase from 10,000 to 1 million QPS is
a significant jump, so I'd approach this in multiple phases.
First, the low-hanging fruit: I'd aggressively optimize our
caching strategy. If we can push our cache hit ratio from
80 to 98 percent, that alone reduces the database load by
10x. I'd implement a multi-tier cache with a local in-process
cache, a distributed Redis cluster, and a CDN for static
and semi-static content.
Second, I'd horizontally scale the stateless application
tier. Since our services are containerized, I'd configure
auto-scaling policies based on CPU utilization and request
queue depth.
Third, and this is the hardest part, the database layer.
I'd shard the database using consistent hashing on the
primary access key. For our use case, sharding by user ID
distributes the load evenly. I'd also separate the read
and write paths, with dedicated read replicas in each
region.
Fourth, I'd introduce asynchronous processing wherever
possible. Any operation that doesn't need to be synchronous,
like analytics event recording, notification delivery, or
search index updates, should go through a message queue.
Finally, I'd set up comprehensive monitoring with dashboards
showing QPS per service, latency distributions, error rates,
and resource utilization. This gives us visibility to
proactively identify bottlenecks before they cause user
impact."
연습 4: 장애 대응 설계
시나리오: 면접관이 "How would you handle a scenario where one of your downstream services goes down?"라고 물었습니다.
[예시 답변]
"Resilience to downstream failures is critical. I'd implement
several defense-in-depth strategies.
First, the circuit breaker pattern. If a downstream service
starts returning errors above a threshold, say 50 percent
error rate over 30 seconds, the circuit breaker trips and we
stop sending requests to that service. Instead, we return
a degraded response or fall back to cached data.
Second, I'd implement retry logic with exponential backoff
and jitter. This prevents thundering herd problems when the
downstream service recovers.
Third, for critical paths, I'd design graceful degradation.
For example, if the recommendation service is down, the
application should still serve the core content, just without
personalized recommendations. The user experience degrades
slightly rather than failing completely.
Fourth, I'd use bulkheads to isolate failures. Each
downstream dependency gets its own thread pool and connection
pool, so a slow or failing service doesn't consume all
the resources and cascade failures to other services.
Finally, I'd set up health checks and automated failover.
If a primary instance fails, traffic automatically routes
to a healthy instance within seconds."
마치며
System Design Interview에서 좋은 성과를 내려면 기술 지식과 영어 커뮤니케이션 능력 모두가 필요합니다. 이 글에서 다룬 표현들을 정리하면 다음과 같습니다.
요구사항 확인 단계의 핵심 패턴:
- "Before jumping into the design, I'd like to clarify..." (설계 전 확인)
- "Let me do a back-of-the-envelope calculation..." (규모 추정)
- "Given the time constraint, I'd like to focus on..." (범위 한정)
아키텍처 설명 단계의 핵심 패턴:
- "Let me sketch out the high-level architecture..." (상위 레벨 설명)
- "Let me walk you through the data flow..." (데이터 흐름 설명)
- "I'm choosing X because..." (기술 선택 정당화)
확장성 논의의 핵심 패턴:
- "I'd go with horizontal scaling rather than..." (확장 전략)
- "The bottleneck in this design is..." (병목 식별)
- "To alleviate this, I'd introduce..." (해결책 제안)
트레이드오프 분석의 핵심 패턴:
- "The trade-off here is between X and Y..." (트레이드오프 제시)
- "The advantage of Option A is... The downside is..." (장단점 비교)
- "I'm going with this approach because..." (결정 정당화)
System Design Interview 준비에서 가장 효과적인 연습 방법은 실제로 소리 내어 영어로 설계를 설명하는 것입니다. 혼자서 화이트보드 앞에 서서 45분간 시스템을 설계하면서 영어로 설명하는 연습을 반복하세요. 처음에는 어색하더라도, 이 글의 표현 패턴을 반복 사용하다 보면 자연스러운 기술 영어로 자리 잡을 것입니다.
면접은 결국 커뮤니케이션입니다. 완벽한 설계보다 명확한 설명이 더 중요합니다. 자신의 사고 과정을 투명하게 공유하고, 트레이드오프를 솔직하게 인정하며, 면접관의 피드백에 유연하게 대응하는 것이 System Design Interview 성공의 핵심입니다.
참고자료
- System Design Interview - An insider's guide by Alex Xu - System Design 면접 준비의 바이블로 불리는 도서
- Grokking the System Design Interview - Educative - 인터랙티브 System Design 면접 코스
- Martin Kleppmann - Designing Data-Intensive Applications - 데이터 중심 애플리케이션 설계의 교과서
- Google SRE Book - Site Reliability Engineering - Google의 사이트 신뢰성 엔지니어링 공개 도서
- AWS Well-Architected Framework - AWS의 잘 설계된 아키텍처 프레임워크
- High Scalability Blog - 대규모 시스템 아키텍처 사례 연구 블로그
- ByteByteGo - System Design Newsletter by Alex Xu - System Design 주간 뉴스레터와 시각 자료