WEBBOOK CHAPTER

Next.js 16.3, 서비스로 완성하기: 26장. 예약 도메인을 상태 기계로 설계한다

26장. 예약 도메인을 상태 기계로 설계한다

예약을 boolean confirmed로 만들면 승인 대기, 취소, 만료, 환불을 표현하지 못한다. LocalLoop는 PENDING_PAYMENT → CONFIRMED → ATTENDEDPENDING_PAYMENT → EXPIRED, CONFIRMED → CANCEL_REQUESTED → CANCELLED 전이를 둔다. 각 전이는 누가, 어떤 조건으로, 몇 시에 바꿀 수 있는지 표로 정의한다. DB에는 현재 상태뿐 아니라 transition event와 actor를 남긴다.

좌석은 “조회 뒤 감소” 두 문장이 아니라 하나의 경쟁 조건이다. 트랜잭션 안에서 session row를 잠그거나 조건부 update를 수행하고 영향 행 수가 1일 때만 Booking을 만든다. 마지막 한 좌석에 두 요청을 동시에 보낸 통합 테스트에서 성공 1건·sold out 1건·잔여석 0·중복 0을 주장해야 한다.


update class_session
   set remaining_seats = remaining_seats - 1
 where id = $1 and remaining_seats > 0;

결제·메일처럼 다른 시스템으로 나가는 작업은 같은 DB 트랜잭션에서 outbox row를 만든다. worker는 event id에 unique 제약을 두고 재전송한다. “API가 200을 반환했다”가 아니라 Booking·좌석·outbox·결제 provider 기록이 대사되어야 예약 완료다.