6주차: GusLift가 실시간으로 라이드 매칭하는 방법

발행: (2026년 3월 15일 오후 10:41 GMT+9)
5 분 소요
원문: Dev.to

Source: Dev.to

매칭 룸 추상화

우리는 전역 풀을 운영하지 않습니다. 위치, 요일, 출발 시간별로 파티션을 나눕니다. 룸 키는 다음과 같은 형태입니다:

Westie:mon:08:00

이 문자열은 Cloudflare Durable Object (DO) 의 정체성이 되며, 해당 슬롯에 대한 실시간 상태를 모두 소유하는 메모리 내 프로세스입니다. 월요일 오전 8시 에 Westie에서 출발하는 모든 사람은 하나의 룸을 공유합니다. 10시 30분에 떠나요? 완전히 다른 룸이 됩니다. 이렇게 하면 각 인스턴스가 작고 집중된 상태를 유지할 수 있습니다. 매칭 룸은 다른 출발 창에 대해 알지도, 신경 쓰지도 않습니다.

올바른 룸으로 들어가기

사용자가 앱을 열면 Cloudflare Worker 가 요청을 처리합니다. 인증을 수행하고, 사용자의 스케줄을 해석한 뒤 슬롯 키를 생성하고, WebSocket 연결을 해당 DO 로 전달합니다. Worker는 상태를 갖지 않는 순수 라우터이며, 모든 흥미로운 상태는 가리키는 객체에 존재합니다.

DO가 추적하는 내용

DO는 네 가지 상태를 유지합니다:

  • drivers — 운전자 ID → 남은 좌석 수 매핑
  • riders_waiting — 라이드 요청 중인 승객들의 FIFO 큐
  • pending_matches — 운전자가 선택했지만 아직 승인이 되지 않은 승객들
  • connections — 사용자당 하나씩 존재하는 실시간 WebSocket 핸들

상태가 변할 때마다 모든 연결된 클라이언트에게 브로드캐스트됩니다. 프론트엔드는 DO가 보유한 그대로를 그대로 반영하며, 그 외의 내용은 없습니다.

흐름

  1. 운전자가 온라인 상태가 됨driver_online 과 좌석 수를 전송 → 룸에 등록되고 모두에게 브로드캐스트됩니다.
  2. 승객이 좌석을 요청rider_request 를 전송 → 큐에 추가됩니다.
  3. 운전자가 승객을 선택 → 해당 승객이 riders_waiting 에서 pending_matches 로 이동하고, 소켓을 통해 match_request 를 받습니다.
  4. 승객은 30초 안에 수락해야 합니다.
    • 응답 없음 → 승객이 다시 큐로 돌아갑니다.
    • 수락 → 좌석 수가 감소하고, 라이드가 Postgres에 기록되며, 룸이 모두에게 업데이트됩니다.

동시 이벤트—예를 들어 두 운전자가 동시에 같은 승객을 선택하는 경우—는 DO가 단일 스레드 모델에서 메시지를 하나씩 처리하기 때문에 명시적인 락이 필요 없이 부드럽게 처리됩니다.

왜 Durable Objects인가

서버리스 플랫폼과 WebSocket은 기본적으로 맞지 않습니다: 서버리스 함수는 무상태이며 짧은 수명을 가지고, WebSocket은 지속적인 상태를 요구합니다. DO는 이벤트 간에 살아남는 지속적인 단일 스레드 프로세스와 메모리 내 상태를 제공하여 이 문제를 해결합니다. 로드가 아침 20분 창에 집중되는 캠퍼스 앱의 경우, 필요할 때 룸이 생성되고 유휴 시에는 대기 상태로 전환되어 유휴 인프라와 연결 핸드오프 문제를 없앱니다.

남은 과제

아직 해결되지 않은 열린 문제들:

  • 매치가 수락된 뒤 운전자가 취소하는 경우.
  • 출발 창이 지나도 정리되지 않는 룸.
  • 소켓 이벤트에 대한 속도 제한.

이러한 과제들은 원칙적으로는 간단하지만, 초기 구현에 포함되지 않았을 뿐입니다.

0 조회
Back to Blog

관련 글

더 보기 »

트라비고

Gemini와 함께 말하는 속도만큼 빠르게 여행하세요! 라이브 에이전트가 몰입형 스토리텔링 및 3D 내비게이션과 만나는 곳. 이 프로젝트는 Gemini Live Ag...에 진입하기 위해 만들어졌습니다.