대기열 구현 (1) - 기획 및 설계

오형상·2025년 1월 20일
0

Ficket

목록 보기
26/27

1. 프로젝트 소개

Ficket은 얼굴 인식 기반의 티켓팅 서비스입니다. 이벤트마다 사용자가 몰리는 상황에서도 안정적이고 공정한 티켓팅을 제공하기 위해 대기열 시스템을 설계했습니다. 이번 글에서는 Ficket의 대기열 설계를 어떻게 했고, 그 설계를 구현하기 위해 어떤 기술 스택을 선택했는지, 그리고 왜 그런 선택을 했는지를 공유해 보겠습니다.


2. 대기열 방식의 종류

대기열 시스템은 크게 두 가지 방식으로 나뉩니다: 놀이공원 방식은행 창구 방식입니다. 두 방식은 처리 순서와 구조가 다르며, 각각의 장단점이 존재합니다.

놀이공원 방식

놀이공원 방식은 특정 그룹의 사용자들이 한 번에 입장하는 것이 아니라, 정해진 간격으로 새로운 사용자들이 계속해서 입장하는 구조입니다. 놀이공원의 인기 놀이기구에 사람들이 줄을 서고, 일정 간격으로 새로운 사람들이 입장하고, 일정 시간이 지나면 자동으로 나가는 방식과 유사합니다.

핵심 원리

  • n: 일정 간격마다 입장할 수 있는 최대 인원 수.
  • t: 새로운 사람들이 입장하는 간격(시간).
  • m: 입장한 사람이 자동으로 나가는 시간.

처리 로직
1. 일정 간격(t)마다 최대 n명이 입장합니다.
2. 입장한 사람들은 m 시간이 지나면 자동으로 나갑니다.

예시

  • 1분(t=1)마다 최대 20명이 입장(n=20), 10분(m=10) 후 자동으로 나감.
  • 오전 9시에 20명이 입장하면, 9:01에 다시 20명이 입장, 9:02에도 20명이 추가로 입장.
  • 9:10이 되면 9:00에 입장한 20명이 자동으로 나갑니다.

장점

  • 일정 간격마다 꾸준히 요청을 처리하므로 처리량이 예측 가능합니다.
  • 간단한 구조로 대규모 요청에서 관리하기 쉽습니다.

단점

  • 요청 순서가 공정하게 유지되지만, 특정 요청의 처리 시간이 길어질 경우 전체 시스템 처리 속도에 영향을 줄 수 있습니다.
  • 일정한 시간(tm)으로 입장/퇴장이 이루어지므로 유동성이 떨어질 수 있습니다.

은행 창구 방식

은행 창구 방식은 여러 개의 창구가 독립적으로 운영되며, 요청이 가용한 창구로 배정되는 구조입니다. 창구에서 자리가 비면 대기열에서 바로 다음 요청을 처리합니다.

핵심 원리

  • n: 현재 작업 중인 사람 수.
  • m: 대기 중인 사람 수.

처리 로직
1. 작업 공간에서 한 명이 처리 완료되면(n--), 대기열에서 한 명이 작업 공간으로 이동합니다(m--, n++).
2. 처리 공간과 대기열이 실시간으로 연결되어 자리가 비는 즉시 다음 요청을 처리합니다.

예시

  • 현재 작업 공간에 5명(n=5), 대기 중인 사람이 10명(m=10)일 때, 한 명이 작업을 마치면(n=4), 대기열에서 한 명이 들어와 다시 5명(n=5)이 됩니다.

장점

  • 병렬 처리로 전체 처리 속도가 빠릅니다.
  • 처리 시간이 긴 요청이 있더라도 다른 요청에 영향을 주지 않습니다.

단점

  • 처리 순서를 보장하기 위해 상태 관리가 복잡할 수 있습니다.
  • 특정 요청이 늦어지는 경우, 순서 보장을 위해 별도의 정렬 로직이 필요합니다.

3. 왜 은행 창구 방식을 선택했는가?

Ficket에서는 대기열 시스템을 설계할 때 은행 창구 방식을 선택했습니다. 이 방식을 선택한 이유는 아래와 같습니다:


1. 먼저 들어온 사람의 권익을 보장하기 위해

은행 창구 방식에서는 보통 n초마다 사람이 들어오고 빈 좌석에 대해 경쟁적으로 처리합니다.

하지만 Ficket에서는 먼저 대기열에 들어온 사람이 다음 순서로 반드시 처리되도록 설계했습니다.
경쟁 방식이 아닌 FIFO(First In, First Out) 원칙을 따름으로써,
먼저 들어온 사람의 권리를 보장할 수 있었습니다.

2. 티켓팅의 특성

티켓팅은 보통 1~2분 내에 완료되는 작업입니다.

  • 놀이공원 방식처럼 일정 시간이 지나야만 대기열이 갱신되는 방식은 티켓팅 특성에 맞지 않았습니다.
  • 은행 창구 방식은 작업이 끝난 즉시 대기열에서 다음 요청을 가져오기 때문에 빠른 순환 구조를 제공합니다.

3. 작업 공간의 크기 제한 가능

은행 창구 방식은 작업 공간의 크기를 유동적으로 설정할 수 있다는 장점이 있습니다.

  • 예를 들어, 우리 서버가 감당할 수 있는 최대 인원을 설정해 과부하를 방지할 수 있습니다.
  • 작업 공간에 들어가는 요청 수를 제한함으로써, 시스템이 안정적으로 동작하도록 설계할 수 있었습니다.
  • 이를 통해 확장성안정성을 모두 확보할 수 있었습니다.

4. 작업 시간 제한으로 자리 점유 방지

티켓팅 시스템에서는 특정 사용자가 작업 공간을 과도하게 점유하면, 대기열이 불필요하게 길어지는 문제가 발생할 수 있습니다.

  • 은행 창구 방식에서는 작업 공간에서 일정 시간이 지나면 자동으로 사용자를 내보내는 로직을 추가해 이런 문제를 해결했습니다.
  • 작업 공간에 새로운 요청이 빠르게 들어올 수 있도록 설계해 시스템이 원활하게 운영될 수 있었습니다.

단점: 실시간 상태 관리의 복잡성

은행 창구 방식은 요청의 처리 순서를 보장하려면 실시간 상태를 확인하는 로직이 필요합니다.

  • 작업 공간에서 누가 나갔는지, 대기열에서 누가 들어와야 하는지 등을 정확히 트래킹해야 하므로 구현이 다소 복잡합니다.

4. 선택한 기술 스택

Why Kafka?

  • Kafka는 병렬 처리가 가능하도록 설계되었습니다.
    파티션을 활용하면 여러 작업을 동시에 처리할 수 있어 대기열의 효율성을 높일 수 있습니다.
  • 이벤트별로 병렬성과 순서를 조정하는 데 유연한 옵션을 제공합니다.

Why Redis?

  • Redis는 빠른 읽기/쓰기 성능을 제공합니다. 대기열 상태를 실시간으로 캐싱하고 조회하기에 적합합니다.
  • ZSet(정렬된 집합)을 활용하면 요청을 정렬하고 순서를 유지할 수 있습니다.
    예를 들어, Kafka 메시지에 포함된 currentTime 값을 Redis ZSet의 score로 사용해 대기열 순서를 보장했습니다.
  • Pub/Sub 기능을 통해 실시간 상태 동기화에도 활용할 수 있었습니다.

Why WebSocket + WebFlux?

  • WebSocket은 실시간 업데이트에 특화된 기술입니다. 사용자에게 대기열 상태를 실시간으로 알리기 위해 도입했습니다.
  • WebFlux는 비동기 논블로킹 방식으로 동작하여, 많은 WebSocket 연결을 효율적으로 처리할 수 있었습니다.

Why Locust?

  • Locust는 대규모 트래픽 시뮬레이션을 쉽게 할 수 있는 도구입니다.
    "우리 시스템이 얼마나 많은 트래픽을 감당할 수 있을까?"라는 질문에 대한 답을 찾는 데 유용했습니다.
  • 병목 지점을 확인하고 개선하기 위해 활용했습니다.

마무리하며

이번 글에서는 Ficket 대기열 시스템의 설계와 선택한 기술 스택에 대해 공유해 보았습니다.
다음 글에서는 Kafka와 Redis를 이용한 대기열 구현 과정을 다뤄볼 예정입니다.

0개의 댓글