////
Search
🏒

7장. 호텔 예약 시스템

메리어트 인터내셔널같은 호텔 체인의 예약 시스템을 설계할 것이다.
이 장에서 다루는 내용은 다른 면접 문제에 활용될 수 있을만큼 범용성있는 것도 있다.
에어비앤비 시스템 설계
항공권 예약 시스템 설계
영화 티켓 예매 시스템 설계

1단계: 문제 이해 및 설계 범위 확정

요구사항 가정
시스템 규모는 5000개 호텔에 100만 개 객실을 갖춘 호텔 체인
대금은 예약 시 지불한다고 가정
호텔 웹사이트나 앱에서만 예약이 가능하며 취소도 가능
10% 초과 예약이 가능해야 한다. 실제 객실 수보다 더 많은 객실을 판매할 수 있어야 함
객실 가격은 유동적, 가격은 객실의 여유도에 따라 달라짐

비기능 요구사항

높은 수준의 동시성 지원
성수기, 대규모 이벤트 기간에는 일부 인기 호텔의 특정 객실을 예약하려는 고객이 몰릴 수 있다.
적절한 지연 시간
사용자가 예약을 할 때는 응답 시간이 빠르면 이상적이겠으나 예약 요청 처리에 몇 초 정도가 소요되는 것은 괜찮다.

개략적 규모 추정

총 5,000개 호텔에 100만 개의 객실
평균적으로 객실의 70%가 사용 중이고 평균 투숙 기간은 3일이라고 가정
일일 예상 예약 건수는 100만 * 0.7 / 3이므로 대략 240,000
초당 예약 건수는 240,000 / 100,000 대략 3이므로 초당 예약 트랜잭션 수는 그렇게 크지 않음
시스템 내 모든 페이지의 QPS는 다음과 같다. 각 단계별로 대략 90%는 이탈한다고 가정해보자.
호텔/객실 상세 페이지 300
예약 상세 페이지 30
객실 예약 페이지 3

2단계: 개략적 설계안 제시 및 동의 구하기

API 설계

호텔 관련 API
호텔 상세 정보 반환, 신규 호텔 추가, 호텔 정보 갱신, 호텔 정보 삭제
객실 관련 API
객실 상세 정보 반환, 신규 객실 추가, 객실 정보 갱신, 객실 정보 삭제
예약 관련 API
예약 이력 반환, 특정 예약 상세 정보 반환, 신규 예약, 예약 취소

데이터 모델

호텔 예약 시스템은 다음 질의를 지원해야 한다.
호텔 상세 정보 확인
지정된 날짜 범위에 사용 가능한 객실 유형 확인
예약 정보 기록
예약 내역 또는 과거 예약 이력 정보 조회
본 설계안에서는 관계형 데이터베이스를 선택했는데 그 이유는 다음과 같다.
읽기 빈도가 쓰기 빈도 대비 높은 작업 흐름을 잘 지원한다.
관계형 데이터베이스는 ACID 속성을 보장한다. 이는 예약 시스템을 만들 때 중요하다.
관계형 데이터베이스를 사용하면 데이터를 쉽게 모델링할 수 있다.

개략적 설계안

이 호텔 예약 시스템은 MSA를 사용한다. 공개 API 게이트웨이가 각 서비스에 대한 요청으로 분기시켜줄 것이다.

3단계: 상세 설계

동시성 문제

같은 사용자가 예약 버튼을 여러 번 누를 수 있다.
클라이언트 측 구현
클라이언트가 요청을 전송하고 난 후, 예약 버튼을 회색으로 표시하거나 비활성화하는 것이다.
멱등 API
예약 API 요청에 멱등 키를 추가하는 방안이다. 예약의 ID를 멱등 키로 사용하여 방지하는 것이다.
예약화면에 들어오는 경우, ID를 발급하여 해당 ID를 토대로 중복이 발생하지 않도록하는 것이다.
여러 사용자가 같은 객실을 동시에 예약하려 한다.
비관적 락
특정 트랜잭션이 특정 레코드를 변경하려할 때, 해당 레코드에 락을 걸어 접근을 방지하는 것이다.
구현이 쉽고 모든 갱신 연산을 직렬화하여 충돌을 막는데, 이는 여러 레코드에 락을 거는 경우 교착 상태가 발생할 우려가 있어
낙관적 락
일반적으로 버전 번호와 타임스탬프 두 방법으로 구현되는 락이다. 보통은 시간 흐름에 영향을 받는 타임스탬프 대신 버전 번호를 더 자주 쓴다.
데이터를 읽을 때, 버전 번호를 같이 읽고 갱신 시 읽었던 버전 번호와 다르면 갱신 요청이 실패하는 방식의 동작 방식이다.
이 방법은 데이터에 대한 경쟁이 치열한 경우의 성능 저하를 제외하고서는 꽤 괜찮은 성능을 보인다.
데이터베이스 제약 조건
데이터베이스 내부의 제약 조건을 사용해 데이터 갱신 시, 해당 제약 조건을 검사하는 방식이다.
데이터베이스의 타입에 영향을 많이 받으며 데이터에 대한 경쟁이 심한 경우, 실패하는 경우가 잦아 좋지 않은 사용자 경험을 제공할 수 있다.

시스템 규모 확장

호텔 예약 시스템에 대한 부하는 일반적으로 높지 않으나 야놀자, 여기어때와 같이 유명한 예약 애플리케이션과 연동되어야 할때, 평균 QPS가 증가할 수 있다.
먼저 모든 서비스는 무상태 서비스이므로 서버를 추가하는 것으로 성능 문제를 해결할 수는 있으나 데이터베이스는 단순히 서버를 늘리는 것만으로는 문제를 해결할 수 없다.
먼저 샤딩을 고민해볼 수 있다. 샤딩을 하려면 데이터를 어떻게 분배할지 정해야 하는데, hotelId가 좋은 후보가 되어줄 수 있다.
그리고 캐시를 고려해볼 수 있다. 잔여 객실 데이터의 경우, 과거의 정보는 필요하지 않다. 따라서 캐시를 적용해 잔여 객실을 빠르게 제공해줄 수 있다.

4단계: 마무리

비관적, 낙관적 락 등을 이용한 경쟁 조건 시나리오의 해결법을 알아보며 예약 시스템을 설계했다.
추가적으로 마이크로서비스 아키텍처에서 발생할 가능성이 높은 데이터 일관성 이슈를 더 살펴보면 좋을 것이다.