42강
시스템 설계 면접 6단계 방법
백지 앞에서 얼어붙지 않는 법 — 무엇을 어떤 순서로 물을 것인가
먼저 보면 좋은 강의: 웹 요청의 해부, 지연 시간과 처리량
단계별로 보기
스페이스바로 재생/정지, 좌우 화살표로 단계 이동, R로 처음으로 돌아갑니다.
대기 중1 / 4 단계 — 1·2단계 — 무엇을, 얼마나
아직 아무것도 그리지 않았습니다. 먼저 묻습니다. 무엇을 만듭니까. 긴 주소를 짧게 만들고, 짧은 주소를 누르면 원래대로 보낸다. 통계와 계정은 범위 밖. 그리고 숫자를 셉니다. 쓰기 초당 12건, 읽기 초당 1200건. 읽기가 쓰기의 100배. 이 비율 하나가 앞으로의 모든 결정을 지배합니다. 숫자를 세지 않고 부품을 고르면, 그건 설계가 아니라 취향입니다.
이 강의를 마치면
- 설계 문제를 6단계의 정해진 순서로 분해해서 접근한다.
- 설계를 시작하기 전에 반드시 범위를 좁히고 숫자를 세워야 하는 이유를 설명한다.
- '정답'이 아니라 '근거 있는 선택과 그 대가'를 말하는 것이 설계임을 설명한다.
- URL 단축 서비스 예제에 6단계를 처음부터 끝까지 적용한다.
백지의 공포
"트위터를 설계해 보세요."
이 말을 들으면 대부분 두 가지 중 하나를 합니다. 얼어붙거나, 아니면 곧바로 "일단 로드밸런서를 두고 서버를 여러 대…"라고 부품 이름을 나열하기 시작합니다.
둘 다 실패합니다. 후자가 더 나빠 보이지 않지만 사실 더 나쁩니다. 무엇을 만드는지도 모르면서 부품부터 고르고 있기 때문입니다.
설계는 재능이 아니라 순서입니다. 이 강의는 그 순서를 드립니다. 이 순서는 면접장에서만 쓰는 게 아닙니다. 실제로 새 시스템을 만들 때 쓰는 순서와 같습니다.
1. 요구사항 명확화 — 무엇을 만드는가
2. 규모 추정 — 얼마나 크게 만드는가
3. API와 데이터 모델 — 겉과 속의 계약
4. 상위 설계 — 큰 그림
5. 병목 심화 — 가장 먼저 무너질 곳
6. 트레이드오프 — 무엇을 포기했는가---
1단계 — 요구사항 명확화
절대로 바로 그리지 마세요. 먼저 물어야 합니다.
"트위터를 설계하라"는 요구는 사실 요구가 아닙니다. 트위터에는 타임라인, 검색, DM, 알림, 광고, 추천이 다 있습니다. 이걸 다 하면 아무것도 못 합니다.
물어야 할 것은 세 가지입니다.
- 무엇을 하는가 (기능) — 이 중 어디까지가 범위입니까? 글쓰기와 피드 읽기만
할까요?
- 어때야 하는가 (품질) — 얼마나 빨라야 합니까? 얼마나 안 죽어야 합니까?
데이터가 잠깐 안 맞아도 괜찮습니까?
- 무엇을 안 하는가 (범위 밖) — 이번엔 검색과 광고는 다루지 않겠습니다.
마지막 항목이 특히 중요합니다. 범위를 명시적으로 잘라내지 않으면 나중에 반드시 "그럼 검색은요?"라는 질문에 무너집니다. 미리 "이번 범위 밖입니다"라고 말해두면 그 질문 자체가 사라집니다.
이 단계에서 가장 흔한 실수: 물어보지 않는 것. 묻지 않고 시작하면, 상대가 생각한 것과 다른 걸 30분간 설계하게 됩니다.
2단계 — 규모 추정
이제 숫자를 셉니다. 이 단계가 없으면 나머지 전부가 취향 문제로 전락합니다.
"캐시를 두겠습니다"라는 말은 숫자가 없으면 그냥 유행어입니다. "읽기가 초당 150건인데 데이터베이스는 30건뿐이라 캐시가 필요합니다"는 근거입니다.
세는 방법은 단순합니다. 사용자 수에서 시작해 초당 몇 건인지까지 내려갑니다.
숫자는 정확할 필요가 전혀 없습니다. 자릿수만 맞으면 됩니다. 초당 100건과 초당 10만 건은 완전히 다른 설계지만, 초당 100건과 초당 130건은 같은 설계입니다.
꼭 세야 할 것은 세 가지입니다.
- 초당 요청 수 — 그리고 읽기와 쓰기를 반드시 나눠서. 이 비율이
설계의 절반을 결정합니다.
- 최대치 — 평균의 2~5배로 잡습니다. 시스템은 평균이 아니라 최대치에서
무너집니다.
- 저장 용량 — 하루에 얼마나 쌓이고, 몇 년을 보관해야 하는가.
3단계 — API와 데이터 모델
큰 그림을 그리기 전에 계약을 정합니다.
API는 바깥과의 계약입니다. 무엇을 받아서 무엇을 돌려주는가. 두세 줄이면 충분합니다.
POST /urls {긴 주소} → {짧은 주소}
GET /{짧은코드} → 원래 주소로 이동데이터 모델은 안쪽의 계약입니다. 무엇을 어떤 모양으로 저장하는가.
이 단계를 건너뛰는 사람이 많은데, 여기서 나오는 정보가 결정적입니다. 위 API를 보면 읽기(GET)가 쓰기(POST)보다 압도적으로 많을 것임이 바로 드러납니다. 짧은 주소는 한 번 만들고 수천 번 눌리니까요. 이 사실 하나가 4단계의 구조를 거의 결정합니다.
4단계 — 상위 설계
이제야 그림을 그립니다. 앞의 세 단계가 있어야 이 그림의 모든 선에 이유가 생깁니다.
요령은 가장 단순한 것부터 그리고, 숫자가 강제할 때만 부품을 더하는 것입니다.
사용자 → 서버 → 데이터베이스여기서 시작합니다. 그리고 2단계의 숫자를 하나씩 대봅니다.
- "초당 150건인데 서버 하나가 40건이네" → 로드밸런서 + 서버 여러 대
- "데이터베이스는 30건뿐인데 읽기가 150건이네" → 앞에 캐시
- "이 작업은 사용자를 기다리게 할 이유가 없네" → 큐 + 워커로 뒤로 뺀다
부품마다 그것을 강제한 숫자를 말할 수 있어야 합니다. 말할 수 없는 부품은 빼세요. 그건 장식입니다.
5단계 — 병목 심화
그림이 나왔습니다. 이제 가장 먼저 무너질 곳 하나를 골라 깊이 팝니다.
전부를 깊게 파려 하면 아무것도 못 팝니다. 하나를 고르세요.
고르는 기준은 "가장 어려운 곳"이 아니라 "제일 먼저 터질 곳"입니다. 보통은 이 셋 중 하나입니다.
- 가장 느린 부품 — 대개 데이터베이스
- 혼자뿐인 부품 — 죽으면 전체가 죽는 곳
- 가장 불공평한 곳 — 특정 데이터에만 요청이 몰리는 곳 (인기 게시물,
유명 사용자)
세 번째가 실무에서 가장 자주 사람을 잡습니다. 평균으로 계산하면 여유가 넘치는데, 실제로는 1%의 데이터에 90%의 요청이 몰려서 무너집니다.
6단계 — 트레이드오프
마지막이자, 좋은 설계자와 부품 나열자를 가르는 단계입니다.
모든 선택에는 대가가 있습니다. 그것을 말하지 않으면 선택한 게 아니라 그냥 주워온 것입니다.
- 캐시를 뒀다 → 오래된 값이 잠깐 보일 수 있다. 얼마나 잠깐? 그게 괜찮은
데이터인가?
- 큐로 뒤로 뺐다 → 결과가 즉시 반영되지 않는다. 사용자에게 뭐라고 보여줄
것인가?
- 복제본을 뒀다 → 방금 쓴 걸 못 읽을 수 있다.
이 단계에서 해야 할 말은 이런 모양입니다.
"캐시를 60초 두겠습니다. 그러면 링크가 삭제된 뒤에도 최대 60초는 열립니다. 이 서비스에서는 그 정도는 허용된다고 봅니다. 만약 삭제가 즉시 반영돼야 한다면, 삭제 시 캐시를 지우는 경로를 추가하고 그만큼 복잡도를 받겠습니다."
이렇게 말할 수 있으면 설계자입니다. "캐시를 두면 빨라집니다"만 말하면 부품 나열자입니다.
---
처음부터 끝까지 — URL 단축 서비스
6단계를 실제로 돌려 봅시다.
1. 요구사항 명확화
- 기능: 긴 주소를 짧은 주소로 만든다. 짧은 주소를 누르면 원래 주소로 보낸다.
- 품질: 이동은 200밀리초 안에. 거의 안 죽어야 한다. 짧은 주소는 절대 다른
곳으로 가면 안 된다.
- 범위 밖: 클릭 통계, 사용자 계정, 커스텀 주소. 이번엔 안 합니다.
2. 규모 추정
- 하루 새 링크 100만 개 → 초당 약 12건 (쓰기)
- 링크 하나당 평균 100번 눌림 → 하루 1억 번 → 초당 약 1,200건 (읽기)
- 읽기:쓰기 = 100:1
이 비율 하나가 모든 것을 말해줍니다. 이건 읽기 시스템입니다. 쓰기 최적화에 시간을 쓰면 안 됩니다.
- 5년 보관 → 링크 18억 개 → 하나에 500바이트면 약 1TB. 한 대에 들어갑니다.
샤딩은 필요 없습니다. (숫자를 안 셌으면 괜히 샤딩을 넣었을 것입니다.)
3. API와 데이터 모델
POST /urls {longUrl} → {shortCode}
GET /{shortCode} → 301/302 리다이렉트urls: shortCode(키) → longUrl, createdAt키 하나로 값 하나를 꺼내는 것뿐입니다. 조인도, 검색도, 범위 질의도 없습니다. 이렇게 단순한 접근 패턴은 캐시가 완벽하게 먹힙니다.
4. 상위 설계
가장 단순하게 시작합니다: 사용자 → 서버 → DB. 이제 숫자를 댑니다.
- 읽기 초당 1,200건, 서버 하나가 40건 → 로드밸런서 + 서버 여러 대
- DB는 초당 30건 → 1,200건을 절대 못 받습니다. 캐시가 필수입니다.
사용자 → 로드밸런서 → 서버 여러 대 → 캐시 → 데이터베이스선 하나하나에 숫자가 붙어 있습니다.
5. 병목 심화 — 인기 링크
DB가 초당 30건인데 읽기는 1,200건입니다. 캐시가 이걸 흡수해야 합니다. 흡수할 수 있을까요?
여기서 불공평함이 등장합니다. 링크가 18억 개지만 요청은 극소수의 인기 링크에 몰립니다. 방금 SNS에 올라간 링크 몇 개가 오늘 클릭의 대부분을 차지합니다.
이건 나쁜 소식처럼 들리지만 사실 최고의 소식입니다. 인기 링크 몇천 개만 캐시에 있으면 요청의 95% 이상이 캐시에서 끝납니다. 캐시에 18억 개를 다 넣을 필요가 없습니다.
- 캐시 적중률 95% → DB로 가는 건 초당 60건
- 아직 30건보다 많군요 → 적중률을 98%로 올리거나, 읽기 복제본을 하나 둡니다
이게 병목 심화입니다. 숫자를 대고, 안 맞으면 부품을 더하고, 다시 셉니다.
6. 트레이드오프
- 캐시 유효시간 60초 → 링크를 지워도 최대 60초는 열립니다. 스팸 링크를
즉시 차단해야 한다면 삭제 시 캐시를 지우는 경로가 필요합니다. 이번 범위에서는 60초를 받아들입니다.
- 짧은 코드 생성 → 무작위로 만들면 충돌을 확인해야 하고, 순번으로 만들면
다음 코드를 남이 추측할 수 있습니다. 이 서비스는 비밀 링크가 아니므로 순번 방식의 단순함을 택하겠습니다.
- 샤딩 안 함 → 1TB는 한 대에 들어갑니다. 나중에 10배가 되면 그때
shortCode 기준으로 나눌 수 있습니다. 지금 넣지 않는 것이 옳습니다.
---
마지막 조언
이 6단계에서 사람들이 가장 많이 건너뛰는 것은 2단계(규모 추정)입니다. 그리고 그것이 나머지를 전부 망칩니다. 숫자가 없으면 4단계의 부품들이 "있으면 좋을 것 같아서" 놓인 장식이 되고, 5단계에서 무엇이 병목인지 말할 수 없고, 6단계에서 무엇을 포기했는지도 말할 수 없습니다.
그리고 기억할 것 하나.
설계에 정답은 없습니다. 근거 없는 선택이 오답일 뿐입니다.
다음 두 강의에서 이 6단계를 직접 적용해 볼 것입니다. 먼저 URL 단축 서비스, 그다음 뉴스 피드입니다.
이 강의가 단순화한 것
교육용 모형은 언제나 무언가를 생략합니다. 무엇을 생략했는지 아는 것도 학습의 일부입니다.
전제한 것
- 이 6단계는 널리 쓰이는 관행을 정리한 것이지 표준 규격이 아니다. 조직과 문제에 따라 순서와 비중이 달라진다.
- 본문의 URL 단축 서비스 숫자는 설명을 위해 고른 예시이며 특정 서비스의 실제 지표가 아니다.
- 캔버스의 그림은 4단계의 결과물 예시일 뿐이며, 이 구조가 모든 문제의 정답은 아니다.
- 규모 추정은 자릿수만 맞추는 것을 목표로 한다. 정밀한 용량 산정은 별도의 작업이다.
다루지 않은 것
- 비용 산정과 예산 제약
- 팀 구조와 조직이 아키텍처에 미치는 영향(콘웨이의 법칙)
- 보안, 규제 준수, 데이터 주권 요구사항
- 기존 시스템에서 점진적으로 옮겨가는 마이그레이션 전략
더 읽을거리: System Design Interview — 6-step framework · Google SRE Book — Handling Overload
이 강의에 물어보기
하루 5번이 강의 본문만 근거로 답합니다. 강의에 없는 내용은 지어내지 않습니다.