대기열 시스템 동작 흐름 및 추후 개선점

박태현·2025년 7월 26일

대기열 시스템 최종 요청/응답 흐름


대기열 등록 요청 흐름

  1. 클라이언트가 대기열 등록을 요청하면 서버는 요청에 포함된 대기열 구분값인 queueType과 사용자 ID인 userId를 전달받고, 요청이 들어온 시점을 timestamp로 기록합니다.

    또한, 서버는 해당 클라이언트와 SSE 연결을 생성해 Sink 스트림을 반환하며, 이후 클라이언트는 이 스트림을 통해 서버가 push하는 이벤트를 실시간으로 수신받게 됩니다.

  2. 대기열 등록 요청 시 서버는 Redis의 queueType 이름을 가진 ZSet에 userId를 key로, 요청 시각인 timestamp를 score로 저장하여 score에 따라 사용자를 자동 정렬합니다.

  3. 이후 서버는 사용자의 대기열 상태 정보를 DB에 저장하고, Transactional Outbox Pattern에 따라 Outbox 테이블에 변경 기록을 추가하며 MySQL Debezium Connector는 이러한 Outbox 테이블의 변화를 감지하여, 해당 레코드 중 queueType 값을 Kafka로 Produce합니다.

  4. Kafka Consumer가 Sink 스트림으로 queueType 값을 발행하면, 서버는 해당 SSE 스트림을 통해 해당 대기열에 속한 사용자들에게 실시간 상태를 전달합니다.

    사용자가 대기열에 있다면 현재 순위를 전송하고, 허용열에 진입한 경우에는 confirm 이벤트를 보내 클라이언트가 타겟 페이지로 이동할 수 있도록 합니다.

  5. 이와 같은 흐름을 통해 대기열의 등록·삭제 등 상태 변화가 발생할 때마다, 해당 대기열에 연결된 모든 사용자는 자신의 상태를 실시간 SSE 이벤트로 전달받게 됩니다.

추후 개선점


  1. 현재 대기열 시스템은 사용자 상태 관리를 위해 DB를 사용하고 있지만, 이는 필수적인 요소가 아니며 비동기 애플리케이션에서 동기적 처리를 유발해 전체 성능을 저하시키고 시스템의 일관된 비동기 처리 흐름을 깨뜨리는 문제를 발생시키고 있습니다.

    이에 따라 DB 의존성을 제거하고, 대기열 등록 요청을 애플리케이션에서 직접 Kafka로 전달하는 이벤트 기반 구조로 전환하고자 합니다.

  1. 현재 시스템은 단일 서버 환경에서 운영되고 있어 장애 발생 시 서비스 중단 가능성이 존재하며, 트래픽 증가 시 확장성에도 한계가 있습니다. 이를 해결하기 위해 분산 환경으로의 확장하여 고가용성을 확보하고 서버 부하를 분산시키려 합니다.

  2. 기존에는 Java 기반의 WebFlux를 사용하여 리액티브 체인 구조로 개발되어 있으나, 이 구조는 복잡성과 가독성 문제를 초래합니다.

    이를 개선하기 위해 Kotlin 기반으로 전환하고, 코루틴을 도입하여 리액티브 체인을 동기 코드 스타일로 단순화함으로써 유지보수성과 가독성을 높일 계획입니다.

  1. 인프라 측면에서는 Docker 기반의 컨테이너 환경으로 전환하고, Redis 및 Kafka 역시 단일 구조에서 클러스터 형태로 확장하여 고가용성과 확장성을 보완할 예정입니다.
profile
꾸준하게

0개의 댓글