[선착순 티켓팅] 1. 기능 설계

소포카·2022년 11월 24일
2

FanUP

목록 보기
2/4
post-thumbnail

FanUP은 비대면 팬미팅 플랫폼입니다.
해당 시리즈는 프로젝트를 진행하며 겪은 설계 고민, 트러블 슈팅 과정에 대해 다룹니다.

Github: https://github.com/boostcampwm-2022/web03-FanUP

배경

프로젝트를 진행하며 FanUP 서비스의 가장 핵심이 되는 선착순 티켓팅 기능을 구현하게 되었습니다.
기획 단계부터 해당 기능에 대해 자세히 다뤄보고 싶었기에 그 과정을 글로 남겨보고자 합니다.

티켓팅 기능에 관한 글은 3부작으로 작성할 예정입니다.

  1. 티켓팅 기능 설계
  2. 기능 구현과 부하 테스트
  3. 성능 개선을 위한 캐시 도입기

티켓팅 기능 설계

우리가 영화를 보기 위해 영화관 좌석을 예매하듯, 티켓팅 기능은 팬미팅에 참여하기 위해 입장권을 구매하는 과정입니다. 프로젝트의 핵심 로직이다보니 다른 기능과도 연결된 부분이 많아 설계 과정에서부터 많은 고민을 했습니다.

유저 시나리오

티켓팅을 진행하기 위한 선행 조건으로는 팬미팅 이벤트가 생성되어야 합니다.(=티켓 개설)
팬미팅의 경우 아티스트가 이벤트를 등록 및 수정할 수 있으며 이벤트를 등록할 때, 다음과 같은 정보들을 지정하게 됩니다.

  • 팬미팅 시작 시간
  • 티켓팅 시작 시간
  • 최대 참여 인원

위 내용을 바탕으로 설계한 유저()가 팬미팅에 참가하기까지의 시나리오는 다음과 같습니다.
(보라색으로 표시된 부분이 이 참여하는 시나리오입니다.)

  1. 현재 구매 가능한(혹은 판매 예정) 티켓 목록을 조회한다.
  2. 원하는 티켓을 선택한다.
  3. 티켓팅을 진행한다.
  4. 티켓팅 성공 시, 팬미팅 참여 링크를 발급받는다.
  5. 팬미팅 시작 시간이 되면 팬미팅을 진행한다.

티켓팅 기능 플로우

전체적인 흐름을 살펴봤으니 이제 티켓팅 기능에 대해 집중적으로 살펴보겠습니다.
티켓팅 기능은 스파이크성 대량 트래픽이 유입되는 상황을 가정하였기에 처리 속도를 줄이기 위해 로직을 최대한 분리하였습니다. 따라서 티켓팅 기능에서는 오로지 유저의 티켓 구매 여부만을 판단합니다.

요구사항

  1. 티켓팅 시작 시간부터 팬미팅 시작 시간 전까지 티켓 구매가 가능하다.
  2. 티켓팅 성공 인원 수는 팬미팅 등록 시 정해진 최대 참여 인원을 초과해서는 안된다.
  3. 동일 티켓은 1인당 1장만 구매가 가능하다. (중복 구매 불가)

위 요구사항을 토대로 정의한 기능 플로우는 다음과 같습니다.

  1. 유저가 구매하려는 티켓의 유효성 확인
  2. 요구사항 만족 여부 확인
  3. 티켓 구매에 성공했다면 DB에 ticket id, user id 저장

사실 티켓팅 성공 이후에 팬미팅 참여 링크를 발급하는 로직과 해당 로직을 어느 시점에서 실행해야 하는지에 대한 논의도 오래 진행했지만 해당 글의 주제에 부합하지 않는거 같아 제외했습니다. 해당 부분은 나중에 기회가 된다면 따로 작성해보겠습니다.
(혼란했던 논의 과정이 궁금하시다면..)

API 명세

요청

precondition: login 한 유저

POST /ticket-user
body {
	ticketId: number
}

현 프로젝트는 MSAAPI Gateway Pattern을 도입하였기에 티켓팅 기능을 구현하는 티켓 서비스로 전달되는 요청은 모두 유효한 user라는 것이 보장됩니다. 또한 gateway에서 각 마이크로 서비스를 호출하는 경우 user id를 파라미터로 함께 보내주기 때문에 요청에는 해당 내용이 포함되지 않습니다.

FanUPMSA 도입기가 궁금하시다면 이 글을 참고해주세요.

응답

  • 티켓팅 성공
{
	statusCode: 201,
  	message: "Ticketing success"
}
  • 티켓팅 실패
{
	statusCode: 400,
    message: "All tickets are sold out"
}

유저가 티켓을 구매하는 시나리오 중, 가장 첫 단계는 현재 구매 가능한 티켓 리스트를 조회하는 것입니다. 여기서 구매 가능한 티켓이란 티켓의 잔여 수량이 남아있으며 현재 시간이 해당 티켓에 대한 팬미팅 시작 시간보다 30분 이전인 경우를 뜻합니다.

따라서 티켓의 잔여 수량이 없어 티켓팅을 실패하는 경우 파라미터로 전달되는 ticketId가 유효하지 않다고 판단해 400 에러를 반환하도록 했습니다.

ERD 설계

티켓팅 기능을 담당하는 티켓 서비스의 ERD입니다.
각 테이블 및 컬럼에 대한 설명은 다음과 같습니다.

  • Ticket: 팬미팅에 참가하기 위한 티켓 정보를 저장

    칼럼명설명
    id티켓 고유 id
    title티켓 이름
    content티켓 설명
    artistId해당 티켓을 발행한 아티스트의 id
    salesTime티켓 판매 시작 시간
    startTime팬미팅 시작 시간
    totalAmount티켓 총 수량
    numberTeam한 팀 당 최대 인원
    timeTeam한 팀 당 팬미팅 진행 시간
    price티켓 가격
  • UserTicket: 티켓팅을 성공한 유저의 정보를 저장

    칼럼명설명
    id고유 id
    userId해당 티켓을 구매한 user의 id
    ticketId해당 티켓의 id
    fanupId팬미팅에 참여하기 위한 방의 id
  • Artist: 아티스트의 정보를 저장

    칼럼명설명
    id고유 id
    name아티스트의 이름
    profileUrl프로필 사진의 url

마무리

티켓팅 기능만 놓고 보면 비교적 간단한 플로우를 가지고 있습니다.
하지만 우리는 해당 기능이 스파이크성 대량 트래픽을 감당해야하는 예상 시나리오를 세웠습니다.

다음 편에서는 기능 구현 과정에서 기능이 안정적으로 동작하는지 확인하기 위해 부하 테스트를 진행하며 단일 서버 + RDB 기준 최대 throughput과 응답시간을 살펴볼 예정입니다.

profile
https://github.com/sophoca

0개의 댓글