시스템 설계 예상문제 (중급)

시스템 설계 예상문제 (중급)

Backend Engineering · Intermediate Practice

시스템 설계 예상문제 · 중급 정답

중급 시스템 설계 문제에 대한 하나의 답변 예시입니다. 정답을 암기하기보다 가정, 판단 근거, 대안과 실제 경험을 자신의 언어로 설명하는 데 활용하세요.

답변 활용 안내 · 아래 답변은 유일한 정답이 아닙니다. 현재 규모와 제약에서 선택한 이유를 확인하고, 실제 면접에서는 본인이 경험한 문제·행동·결과를 덧붙여 답변하세요.

한정 수량 공동구매 서비스

상황

커머스 서비스 ‘DealBox’가 매주 금요일 한정 수량 공동구매를 엽니다. 평소에는 초당 300건 정도지만 인기 상품이 공개되면 10분 동안 초당 2만 건의 조회와 주문 요청이 몰립니다. 지난 행사에서는 상품 페이지가 느려지고, 같은 상품이 재고보다 37개 더 판매되었습니다.[요청] “사용자가 페이지를 빠르게 보고 주문할 수 있어야 하지만, 재고보다 많이 판매해서는 안 됩니다. 결제 실패로 확보된 재고가 계속 묶이는 문제도 해결해 주세요.”

조건

규모와 시스템 구성

  • 회원 500만 명, 행사 동시 접속 20만 명
  • 상품별 수량 1천~1만 개
  • Spring Boot, MySQL, Redis 구성

현재 문제와 제약

  • Traffic행사 시작 시 조회·주문 집중
  • Stock동시 주문으로 초과 판매
  • Timeout결제 실패 후 재고 미반환

꼬리 질문

1

조회 요청과 주문 요청을 구분해 어디부터 확장하겠습니까? 캐시, 서버 증설, DB 튜닝의 우선순위와 그 이유를 설명해 주세요.

답변 예시 보기

진단과 접근

조회와 주문은 병목의 성격이 다릅니다. 상품 설명처럼 자주 바뀌지 않는 조회는 캐시와 CDN으로 흡수하고, 주문은 재고 정합성을 지켜야 하므로 처리량을 제한하며 DB까지 도달하는 요청 수를 관리하는 것이 먼저입니다.

설계와 운영

  • 상품 상세·이미지는 CDN과 Redis에 캐시하고 TTL에 지터를 주어 행사 시작 시 동시 만료를 줄입니다.
  • 주문 API는 별도 서버 풀과 커넥션 풀을 사용하고 대기열 또는 rate limit으로 DB 처리량 이상의 요청을 받지 않습니다.
  • 캐시 적중률, DB 커넥션 사용률, 주문 p95, 오류율을 함께 보고 병목이 실제로 이동했는지 확인합니다.

서버만 늘리면 조회 처리량은 늘어도 하나의 재고 행에 대한 경쟁은 해결되지 않습니다. 먼저 부하 테스트로 조회와 주문의 최대 처리량을 따로 측정하고, 가장 먼저 포화되는 자원부터 개선하는 순서가 안전합니다.

경험 연결 포인트 · 트래픽 급증 시 캐시·서버·DB 중 어디가 먼저 포화됐는지 관측하고 개선한 경험을 수치와 함께 설명합니다.
2

여러 사용자가 마지막 한 개를 동시에 주문할 때 초과 판매를 막는 방법을 제시해 주세요. DB 조건부 갱신과 Redis 재고 관리 중 무엇을 선택할지도 설명해 주세요.

답변 예시 보기

진단과 접근

핵심 불변식은 성공한 주문 수가 재고를 넘지 않는 것입니다. DB를 기준 원장으로 사용한다면 재고 조회와 차감을 분리하지 말고 조건부 갱신 한 번으로 처리해 경쟁 조건을 막을 수 있습니다.

설계와 운영

  • 예를 들어 UPDATE 상품 SET stock=stock-1 WHERE id=? AND stock>0의 영향 행 수가 1일 때만 예약을 성공시킵니다.
  • Redis를 사용한다면 Lua로 확인과 차감을 원자적으로 처리하고, reservationId와 멱등키를 함께 기록합니다.
  • DB unique constraint와 주문별 idempotency key를 마지막 안전장치로 두어 재시도가 두 번 차감하지 않게 합니다.

DB 조건부 갱신은 단순하고 신뢰하기 쉽지만 인기 상품 한 행에 쓰기가 집중됩니다. Redis는 처리량이 높지만 DB 반영·장애 복구가 추가되므로 현재 규모와 팀 운영 역량을 근거로 선택합니다.

경험 연결 포인트 · 동시 수정, 낙관적 잠금, unique constraint 또는 Redis 원자 연산을 적용했던 사례를 연결합니다.
3

주문 후 10분 안에 결제하지 않으면 재고를 반환해야 합니다. 예약 상태와 만료 작업을 어떻게 설계하고, 중복 실행이나 서버 장애에 어떻게 대응하겠습니까?

답변 예시 보기

진단과 접근

재고 확보와 판매 완료를 하나의 상태로 표현하면 만료 작업과 결제 완료가 충돌합니다. 주문을 RESERVED, PAID, EXPIRED 같은 상태로 관리하고 허용된 상태 전이만 조건부로 수행해야 합니다.

설계와 운영

  • 예약 시 expiresAt을 저장하고 지연 큐나 주기 작업이 만료 후보를 찾습니다.
  • 만료 처리는 WHERE status=RESERVED AND expiresAt<=now 조건으로 EXPIRED 전환에 성공한 경우에만 재고를 반환합니다.
  • 결제 완료도 RESERVED 상태에서만 PAID로 전환하며 같은 주문번호 재호출은 기존 결과를 반환합니다.

지연 큐 하나에만 의존하면 메시지 유실 시 좌석이 남을 수 있으므로 DB의 만료 상태를 다시 훑는 보정 배치를 함께 두는 것이 좋습니다. 만료 지연 건수와 오래된 RESERVED 수를 알림 지표로 둡니다.

경험 연결 포인트 · TTL, 예약 만료, 보상 작업 또는 상태 머신을 운영한 경험과 중복 실행을 막은 방법을 설명합니다.