요구사항부터 잘못 잡으면 40분이 사라진다
"채팅 시스템을 설계하세요"는 질문이 아니라 대화의 시작이다
이 한 문장만 던지고 면접관이 팔짱을 낀 채 기다리는 걸 본 적이 있습니다. 그 침묵을 못 견디고 바로 아키텍처를 그리기 시작하는 지원자가 많습니다. 저라면 그러지 않습니다. 이 문장은 요구사항이 아니라 요구사항을 알아내라는 지시입니다.
물어야 할 것은 대략 이렇습니다. 1:1 채팅만인가, 그룹 채팅도 포함인가. 메시지는 영구 보관인가, 아니면 일정 기간 후 삭제되는가. 읽음 확인이나 타이핑 인디케이터 같은 기능도 범위에 들어가는가. 이 질문들에 답이 다르면 설계가 통째로 달라집니다. 그룹 채팅에 읽음 확인까지 있다면 팬아웃(fan-out) 비용이 완전히 다른 차원의 문제가 됩니다.
여기서 흔한 실수 하나. 질문을 너무 많이, 너무 오래 합니다. 5분이면 충분한 요구사항 정리에 15분을 쓰면 정작 설계할 시간이 없습니다. 저는 핵심 기능 34개와 비기능 요구사항 12개로 범위를 스스로 확정하고, "이렇게 가정하고 진행하겠습니다"라고 선언한 뒤 넘어가는 쪽을 권합니다. 면접관이 다른 의견이 있으면 그때 말해줍니다.
기능 요구사항과 비기능 요구사항은 다른 무게를 가진다
기능 요구사항은 "무엇을 할 수 있어야 하는가"입니다. 비기능 요구사항은 "얼마나 잘해야 하는가"입니다. 이 구분이 왜 중요하냐면, 시스템 디자인 인터뷰에서 진짜 어려운 결정은 대부분 비기능 요구사항에서 나오기 때문입니다. "메시지를 보낼 수 있다"는 누구나 만족시킵니다. "메시지가 순서대로, 100ms 이내에, 유실 없이 도착해야 한다"는 순서 보장·지연시간·안정성 사이에서 진짜 트레이드오프를 만듭니다.
| 항목 | 질문 | 설계에 미치는 영향 |
|---|---|---|
| 일관성 | 최신 데이터가 즉시 보여야 하는가 | 강한 일관성이면 쓰기 지연 증가 |
| 가용성 | 일부 장애 시에도 응답해야 하는가 | 복제·페일오버 구조 필요 |
| 지연시간 | 응답이 몇 ms 안에 와야 하는가 | 캐시·CDN·지리적 분산 필요 여부 |
| 읽기/쓰기 비율 | 읽기가 많은가 쓰기가 많은가 | 캐싱 전략과 인덱스 설계 방향 |
이 표를 면접에서 그대로 그릴 필요는 없습니다. 다만 이 네 가지 축을 머릿속에 갖고 있으면, 면접관이 "그럼 A와 B 중에 뭘 고를 겁니까"라고 물었을 때 감으로 답하지 않고 근거를 댈 수 있습니다.
Back-of-envelope 추정, 정밀함이 아니라 자릿수가 목적이다
추정 계산은 소수점까지 맞히라는 게 아닙니다. 목적은 자릿수를 맞히는 겁니다. 초당 요청이 100건인지 10만 건인지에 따라 단일 서버로 될지, 샤딩이 필요할지가 갈립니다. 100건과 150건의 차이는 설계를 바꾸지 않습니다.
# 예시: DAU 1000만, 1인당 하루 평균 메시지 20건인 채팅 서비스
DAU = 10_000_000
MESSAGES_PER_USER_PER_DAY = 20
daily_messages = DAU * MESSAGES_PER_USER_PER_DAY # 2억 건/일
avg_qps = daily_messages / (24 * 60 * 60) # 약 2,314 QPS
peak_qps = avg_qps * 3 # 피크는 평균의 2~3배로 가정
avg_message_size_bytes = 100 # 텍스트 메시지 평균 크기 가정
daily_storage_gb = (daily_messages * avg_message_size_bytes) / (1024 ** 3)
print(f"평균 QPS: {avg_qps:.0f}, 피크 QPS: {peak_qps:.0f}")
print(f"일일 저장량: {daily_storage_gb:.2f} GB")이 계산 결과(평균 QPS 약 2,300, 피크 약 7,000, 하루 저장량 약 18GB)가 이후 모든 결정의 기준점이 됩니다. QPS가 수천 단위라면 단일 데이터베이스로도 상당 기간 버틸 수 있다는 뜻이고, 하루 18GB면 1년치 데이터가 6~7TB 수준이니 콜드 스토리지 분리를 언제쯤 고려해야 할지 감이 잡힙니다. 반대로 이 숫자를 계산도 안 하고 "당연히 샤딩이 필요합니다"라고 말하면, 면접관 입장에선 근거 없는 오버엔지니어링으로 보입니다.
자주 쓰는 지연시간 감각도 외워두면 유용합니다. 메모리 읽기는 수백 나노초, SSD 읽기는 수십~수백 마이크로초, 같은 리전 내 네트워크 왕복은 0.5ms 안팎, 대륙을 건너는 왕복은 100ms를 넘습니다. 이 숫자를 정확히 외울 필요는 없지만 "메모리 접근이 디스크보다 얼마나 빠른지" 같은 상대적 크기 감각은 캐싱을 왜 쓰는지 설명할 때 그대로 근거가 됩니다.
추정값은 뒤에서 계속 참조된다
이 단계를 대충 하고 넘어가면 안 되는 진짜 이유는, 뒤에서 캐시 크기나 샤드 개수를 정할 때 근거로 다시 꺼내 쓰기 때문입니다. "Redis 캐시를 얼마나 크게 잡을까요"라는 질문에 이 챕터에서 계산한 저장량과 접근 패턴 없이 답하면 그냥 감으로 숫자를 부르는 것밖에 안 됩니다. 요구사항과 추정은 화려하지 않지만, 이 책 후반부의 사례 문제 네 개를 풀 때마다 계속 되돌아오는 기반입니다.