[설계 3] N회 상품은 왜 예약 한 건이 아닌가

N회 상품을 “다섯 번 예약하는 상품”이라고만 설명하면 첫 방문 뒤에 필요한 업무 사실이 사라집니다. 환자는 일정을 바꿀 수 있고, 예약을 지키지 않을 수도 있고, 한 번의 내원에서 일부 시술만 받을 수도 있습니다. 앞으로 받을 혜택을 바꾸는 일은 커머스의 별도 판단일 수도 있습니다. 확정 슬롯은 예약 한 건을 뜻할 뿐이며, 구매 권리나 실제 진료 완료와 같은 사실이 아닙니다.
환자 A가 5회 상품을 구매했다고 해보겠습니다. 예약 서비스는 적어도 다음 세 가지 질문에 각각 답해야 합니다.
- 커머스 서비스는 몇 회를 판매했는가?
- 임상 기준 데이터 원본이 확인한 완료 근거는 몇 회의 의무를 끝냈는가?
- 아직 이행할 수 있는 의무가 몇 개이고, 그중 다음 제안을 계산할 대상은 무엇인가?
구매 권리 ≠ 확정 예약 ≠ 실제 진료 완료
이 글은 환자 A의 한 회차를 따라간 뒤 다음 회차가 어떻게 계산되는지 보여 줍니다. 모든 서비스가 하나의 카운터를 나눠 갖는 모델을 만들려는 것이 아닙니다. 구매 계약, 예약 계획, 예약, 완료 사실이 일정 변경 뒤에도 각각 설명 가능해야 한다는 것이 핵심입니다.
환자 A는 예약 다섯 건이 아니라 방문 권리 다섯 회를 구매한다
섹션 제목: “환자 A는 예약 다섯 건이 아니라 방문 권리 다섯 회를 구매한다”상품명, 가격, 병원, 개인 정보는 일반화했습니다. 숫자 5는 세 가지 횟수를 눈에 보이게 하는 예시일 뿐이며,
모델은 양의 repeatCount라면 어떤 값에도 적용됩니다.
| 시점 | 환자 A의 행위 또는 이벤트 | 업무 의미 | 예약 서비스가 보존하는 것 |
|---|---|---|---|
| T1 | 5회 상품을 구매한다 | 상품 버전에 따라 다섯 번 이용할 수 있는 계약 | 구매 기준 데이터 원본, 구매 ID, 구매 당시 상품 기준 정보 |
| T2 | 구매 완료 이벤트를 받는다 | 하나의 구매 사실을 실행 가능한 계획으로 해석해야 함 | 기준 데이터 원본이 한정된 구매마다 AppointmentPlan 생성 |
| T3 | 계획을 전개한다 | 달력 슬롯 다섯 개가 아니라 미래 이행 의무 다섯 개가 생김 | PlannedTreatment 1..5, 간격, 의존 관계, 출처 이력 |
| T4 | 첫 방문 희망일을 요청한다 | 고객 선호 또는 제안 입력이지 동의가 아님 | 불변 BookingPreferenceSnapshot |
| T5 | 후보 하나를 제안받고 동의한다 | 한 번의 방문이 예약으로 전환됨 | 합의한 AppointmentItem을 가진 Appointment 하나 |
| T6 | 내원해 시술을 완료한다 | 의무 하나가 이행됨 | 완료 근거, used = 1, remaining = 4 |
첫 구매가 Appointment 다섯 개를 만들지는 않습니다. 하나의 계획 안에 다섯 개의 의무가 생기고, 그중
현재 조건을 만족하며 고객이 동의한 첫 번째 의무만 예약이 됩니다. 나머지 네 개는 첫 방문이 보류되거나
확정된 동안에도 추적 가능한 미래 업무로 남습니다.
여기서 권리는 환자 A가 구매로 확보한 상품 이용 권리입니다. 인증이나 인가 권한을 뜻하지 않습니다. 예약 서비스는 가격이나 환불 가능 여부를 결정하지 않고, 그 권리를 일정으로 해석하는 데 필요한 구매 정보를 보존합니다.
총 횟수·사용 횟수·잔여 이행 의무·예약 슬롯은 서로 다른 사실
섹션 제목: “총 횟수·사용 횟수·잔여 이행 의무·예약 슬롯은 서로 다른 사실”화면에는 “4회 남음”이라고 표시할 수 있지만, 서로 다른 내부 사실을 하나의 숫자로 합치면 안 됩니다. 환자 A가 첫 방문을 완료했고 두 번째 방문은 아직 제안 상태라고 해보겠습니다.
| 측정값 | 방문 1 완료 뒤 예시 | 답하는 질문 | 바꾸는 이벤트 또는 판단 |
|---|---|---|---|
| 총 구매 권리 | 5 | 이 상품 기준 정보로 커머스가 몇 회를 판매했는가? | 새 구매는 새 계획을 만들며, 상품 수정은 이 기준 정보를 다시 쓰지 않음 |
| 사용·완료 횟수 | 1 | 임상 기준 데이터 원본이 확인한 완료 근거가 몇 개의 의무를 이행했는가? | 제안·보류가 아니라 임상 완료 또는 이행 이벤트 |
| 잔여 이행 의무 | 4 | 앞으로 이행할 수 있는 계획 항목이 몇 개인가? | 완료, 미래 항목의 명시적 취소, 기준 데이터 원본이 확인한 업무 이벤트 |
| 예약된 슬롯 | 0 또는 1 | 현재 수용량을 점유하는 예약이 몇 개인가? | PROPOSED, HELD, CONFIRMED, 일정 변경, 만료, 취소 |
미래 방문이 HELD 또는 CONFIRMED가 되면 수용량은 줄어들 수 있지만 used가 줄거나 늘지는 않습니다.
반대로 커머스가 미래 혜택의 취소를 승인하면 실제로 진료받지 않았어도 잔여 이행 의무가 줄 수 있습니다.
노쇼는 내원 사실과 운영 정책의 입력이지, 자동으로 사용 횟수를 차감하는 이벤트가 아닙니다.
실무 규칙은 간단합니다. “잔여 권리”는 계획과 기준 데이터 원본이 확인한 업무 사실에서, “예약된 슬롯”은 예약 사실에서 각각 표시합니다. 달력 행이 만들어졌다는 이유만으로 방문 횟수를 차감하지 않습니다.
한 번의 구매는 하나의 AppointmentPlan, 여러 PlannedTreatment가 된다
섹션 제목: “한 번의 구매는 하나의 AppointmentPlan, 여러 PlannedTreatment가 된다”선택한 모델은 구매 경계와 실제 방문 경계를 분리합니다.
Purchase 1 ──> AppointmentPlan 1 ──> PlannedTreatment 1..N ▲ │ fulfills / attemptsAppointment 1 ──> AppointmentItem 1..N ──────┘ │ └── ResourceAllocation 1..NAppointmentPlan은 기준 데이터 원본이 식별한 구매에 속합니다.
sourcePurchaseAuthority와sourcePurchaseId는 구매 사실의 원천과 원본 식별자를 가리킵니다.catalogSourceAuthority,productId,catalogVersion은 구매 시점에 해석한 상품 기준 데이터를 보존합니다.- 각
PlannedTreatment는 회차, 예상 시간, 필요한 역량, 간격 제약을 유지합니다. - 나중에 추가로 구매하면 기존 계획에 조용히 합치지 않고 **새
AppointmentPlan**을 만듭니다.
sequenceNo는 “1회차”, “5회차”를 표시하고 정렬하는 메타데이터입니다. 달력을 소유하는 하위 aggregate가
아닙니다. 실제 방문은 Appointment가, 그 방문에서 시도한 진료 의무는 AppointmentItem이 나타냅니다.
한 번의 방문에 여러 계획의 항목을 넣을 수는 있지만, 각 항목은 자신이 속한 구매와 PlannedTreatment를
계속 가리켜야 합니다.
환자 A가 나중에 같은 병원에서 또 다른 5회 상품을 구매하는 경우도 마찬가지입니다. 두 상품의 항목이 임상· 운영상 호환되고 환자가 동의하면 한 번의 방문에서 함께 처리할 수 있습니다. 그렇더라도 두 번째 구매에는 두 번째 계획, 두 번째 구매 출처, 별도의 잔여 의무가 있어야 합니다.
구매 시점에 다섯 번의 예약을 모두 확정하지 않는 이유
섹션 제목: “구매 시점에 다섯 번의 예약을 모두 확정하지 않는 이유”상품 기준 정보는 다섯 개의 의무가 있다는 사실을 알려 줍니다. 그러나 구매 순간에 미래의 모든 예약을 알 수는 없습니다.
- 반복 간격은 구매 시각이 아니라 이전 진료가 실제로 완료된 시각부터 계산해야 할 수 있습니다.
- 다음 방문 전에 병원 업무시간, 담당자, 진료실(room), 장비가 바뀔 수 있습니다.
- 환자 A가 다른 날짜를 원할 수 있고, 확정 예약을 바꾸려면 새 제안과 동의가 필요합니다.
WithinDaysAfterPurchase같은 최초 예약 규칙은 첫 제안을 계산할 때만 쓰는 제한된 대체 규칙입니다. 상품 혜택 만료일도 아니고 자동 확정 명령도 아닙니다.- 다섯 슬롯을 모두 확정하면 병원의 미래 수용량을 과장하고, 환자가 아직 검토하지 않은 예약을 만들어 버립니다.
예약의 상태는 이 경계를 드러냅니다.
| 상태 | 환자 A에게 보이는 것 | 수용량 의미 | 상품 권리가 사용되는가 |
|---|---|---|---|
PROPOSED | 검토할 후보 시간·항목·자원 | 확정 예약이 아니며 정책에 따라 다시 계산 가능 | 아니오 |
HELD | 짧은 시간 동안 보류된 후보 | 보류(hold) 만료 전까지 수용량을 점유 | 아니오 |
CONFIRMED | 동의한 한 번의 예약 | 합의한 방문이 수용량을 점유 | 완료 전에는 아니오 |
COMPLETED | 방문 또는 항목이 실제로 이행됨 | 과거 사실이며 미래 슬롯은 점유하지 않음 | 해당 계획 항목은 예 |
앞의 세 상태는 예약에 관한 것이고, 마지막 사실은 진료 완료에 관한 것입니다. UI 카운터나 재시도 처리기가 한 상태에서 다른 상태를 임의로 추론해서는 안 됩니다.

다음 회차는 기존 예약을 고치는 일이 아니라 새 제안이다
섹션 제목: “다음 회차는 기존 예약을 고치는 일이 아니라 새 제안이다”1회차가 완료되면 예약 서비스는 그 완료 사실을 다음 회차의 기준 시점으로 사용합니다. 미리 만들어 둔 “2회차 예약” 항목을 새 날짜로 옮기는 방식이 아닙니다. 애초에 그런 확정 항목이 존재해서는 안 됩니다.
| 순서 | 환자 A의 사실 | 예약 서비스의 해석 | 다음 작업 |
|---|---|---|---|
| 첫 회차 | PlannedTreatment 1이 병원에서 완료됨 | used = 1, 2번 항목은 아직 PLANNED | 실제 완료 시각과 정책으로 후보 계산 |
| 다음 제안 | 간격·자원·병원 운영 조건을 만족하는 날짜가 있음 | 새로운 PROPOSED 또는 HELD 제안 | 동의를 받고 기존 확정 예약은 재사용하지 않음 |
| 일정 변경 | 환자 A가 방문 전 다른 시간을 요청함 | 구매 총량이 아니라 제안·예약이 바뀜 | 제안을 만료·교체하고 이유와 이력 보존 |
| 두 번째 완료 | 2번 항목이 완료됨 | used = 2, 잔여 의무는 3개 | 다음 대상에 대해 같은 주기를 반복 |
진료가 중단된 경우에는 선행 진료의 실제 완료 사실이 더 중요합니다. 월요일에 시작했지만 임상 완료 이벤트가 수요일에 들어왔다면, 다음 간격은 수요일을 기준으로 계산합니다. 구매일이나 폐기된 제안은 임상 다음 회차를 계산하는 기준 시점이 아닙니다.
일정 변경·취소·노쇼는 서로 다른 사실이다
섹션 제목: “일정 변경·취소·노쇼는 서로 다른 사실이다”“환자가 이 달력 항목을 지키지 않았다”만으로는 다음 서비스가 할 일을 정할 수 없습니다. 예약 서비스는 객관적인 방문 사실을 보존하고, 다음 업무 규칙의 소유자에게 전달합니다.
| 상황 | 예약 서비스가 남기는 사실 | 5회 권리에 미치는 영향 | 다음 소유자 또는 작업 |
|---|---|---|---|
| 제안이 만료되거나 거부됨 | 확정 예약으로 전환되지 않은 제안 | 사용되지 않으며 계획 항목은 계속 이용 가능 | 새 제안 계산 또는 환자 연락 |
| 확정 예약을 다시 잡음 | 기존 예약과 새 제안을 모두 이력으로 보존 | 총 구매 횟수와 used는 그대로 | 새 시간·자원 제안과 고객 동의 |
환자가 NO_SHOW가 됨 | 확정 예약에 실제 내원하지 않음 | used를 자동 차감하지 않음 | 승인된 정책 적용과 CRM 상담 handoff |
| 방문이 일부만 완료됨 | 완료 항목과 미완료 항목을 분리 | 임상 기준 데이터 원본이 확인한 완료 항목만 사용 처리 | 미완료 항목을 DEFERRED로 남기고 연결된 시도 생성 |
| 병원 사정이 확정 예약에 영향을 줌 | 영향받은 자원·시간·예약 이력을 보존 | 구매 권리를 조용히 소진하거나 삭제하지 않음 | 새 제안, 설명, 고객 동의 |
노쇼가 반복되면 병원이 다음 예약에 재확인, 보증금, 상담 전화를 요구할 수 있습니다. VIP 고객의 편의를 고려하는 설명 가능한 우선순위 정책도 운영할 수 있습니다. 하지만 이것은 별도의 기준 데이터와 승인 절차를 가지는 운영·커머스·CRM 정책입니다. 예약 서비스 내부에서 횟수를 몰래 차감하는 규칙이 아니며, 이 글에서 현재 기능으로 약속하지도 않습니다.
소진 사실은 예약 서비스가 단독으로 결정하지 않는다
섹션 제목: “소진 사실은 예약 서비스가 단독으로 결정하지 않는다”환자 A에 관한 데이터 흐름을 서비스별 질문으로 나누면 경계가 선명해집니다.
| 업무 영역 | 기준 데이터 원본 | 주고받는 사실 | 예약 서비스의 책임 |
|---|---|---|---|
| 상품 관리·상품 개발 | 버전 상품, BOM, 반복 횟수, 간격, 자원 요구 | 상품 프로젝션 또는 동기화 이벤트 | 구매 시점 예약 해석 기준 정보 검증·보존 |
| 구매·커머스 | 구매 계약, 이용 권리, 환불, 원본 구매 ID | PurchaseCompleted, 환불, 계획 취소 이벤트 | 구매마다 계획을 만들고 외부 권리 판단을 미래 의무에 반영 |
| 예약 서비스 | 계획, 계획 항목, 제안, 보류(hold), 확정, 방문 이력 | 객관적 예약 이벤트와 지속 보존 아웃박스(outbox) | 시간·수용량·예약 상태·감사 이력 소유 |
| 임상·시술 | 실제 시작, 완료, 부분 완료 | 완료·이행 근거 | 계획에 완료를 반영하고 다음 가능 시점을 계산 |
| 고객 상담·CRM | 고객 프로필 정보, 노쇼 상담, 민원, 보상, 서비스 등급 판단 | 지연·노쇼·취소·재예약 사실 | 상담 판단에 필요한 객관적 사실과 handoff 제공 |
| 알림·통계 | 연락 동의, 발송 이력, 프로젝션, 지표 | 예약 이벤트와 스키마 계약 | 채널 발송과 조회 모델을 예약 트랜잭션 밖에 둠 |
이 계약에서 sourceAuthority는 사실을 소유한 기준 데이터 원본을 가리킵니다. 사용자 역할, 권한, 다른
서비스의 데이터를 수정할 수 있다는 주장이 아닙니다. 그래서 달력에 등록된 예약은 예약 서비스가 보고할 수 있지만,
진료 완료는 임상 서비스가, 이용 권리와 환불 판단은 커머스가 설명해야 합니다.
현재 구현·승인 설계·운영 대기·로드맵
섹션 제목: “현재 구현·승인 설계·운영 대기·로드맵”| 사실성 표지 | 이번 글에서 말하는 범위 | 독자가 확인할 질문 |
|---|---|---|
| 현재 구현 | 버전형 상품 프로젝션, 구매 하나당 계획 식별자, 반복 PlannedTreatment 전개, 희망 일정 기준 정보, 계획·항목 상태 | 관찰한 원본과 테스트에서 이 계약을 확인할 수 있는가 |
| 승인된 설계 | 회차별 후보, PROPOSED · HELD · CONFIRMED, 실제 완료 기준 후속 계산, 명시적 예외 흐름 | 설계 문서를 이미 배포된 API처럼 설명하고 있지 않은가 |
| 운영 대기 | 브로커 전달, 임상·커머스 이벤트 연동, 알림 아웃박스(outbox) 카나리, 운영 백필/운영 준비 상태 | 전달·재생·복구를 실제 환경에서 검증했는가 |
| 로드맵 | 환자용 후속 제안 동의 채널, 구체적인 노쇼 페널티, 설명 가능한 VIP 우선순위 정책 | 아직 결정되지 않은 정책을 현재 기능으로 약속하고 있지 않은가 |
현재 기반 구현이 계획과 계획 항목을 만든다고 해서 모든 병원이 구매 직후 5회 예약을 모두 확정한다는 뜻은 아닙니다. 승인된 설계는 앞으로 후보·수용량·동의·운영 차질 기능이 지켜야 할 경계를 정의합니다. 이 표지를 유지하는 것이 기술 계약의 일부입니다.
다음 글에서 다룰 것
섹션 제목: “다음 글에서 다룰 것”N회 상품은 같은 종류의 진료를 반복합니다. 다음 글에서는 패키지 상품으로 범위를 넓혀, 서로 다른 소요 시간과 의존 관계를 가진 상품 BOM이 여러 진료로 이루어진 그래프와 가능한 방문으로 전개되는 과정을 살펴보겠습니다. 그래프를 하나의 예약이나 하나의 잔여 카운터로 납작하게 만들지 않는 것이 목표입니다.
시각 자료로 다시 보기
섹션 제목: “시각 자료로 다시 보기”아래 보조 자료는 원본 설계와 clinic-appointment 저장소를 대신하지 않고, 이번 글의 경계를 보조합니다.
근거 링크
섹션 제목: “근거 링크”- clinic-appointment 저장소
- 상품 카탈로그 정의
- AppointmentPlan 모델
- AppointmentPlan 리비전 모델
- 예약 희망 기준 정보
- 구매 완료 이벤트 처리
- 상품·구매·예약 데이터 흐름
- 진료 계획·예약·수용량 설계
- 예약 설계
댓글
GitHub 계정으로 의견을 남기거나 reaction을 남길 수 있습니다.