diff --git a/design/backend/sequence/inner/participation-당첨자추첨.puml b/design/backend/sequence/inner/participation-당첨자추첨.puml index c0de56c..8d09789 100644 --- a/design/backend/sequence/inner/participation-당첨자추첨.puml +++ b/design/backend/sequence/inner/participation-당첨자추첨.puml @@ -40,16 +40,36 @@ else JWT 검증 성공 Controller -> Service: drawWinners(eventId, winnerCount, visitBonus) activate Service - Service -> Repo: findAllByEventIdAndIsWinner(eventId, false) - activate Repo - Repo -> DB: SELECT * FROM participants\nWHERE event_id = ?\nAND is_winner = false\nORDER BY participated_at ASC - activate DB - DB --> Repo: 전체 참여자 목록 - deactivate DB - Repo --> Service: List - deactivate Repo + Service -> Service: 이벤트 상태 확인\n- 이벤트 종료 여부\n- 이미 추첨 완료 여부 - alt 참여자 수 부족 + Service -> LogRepo: findByEventId(eventId) + activate LogRepo + LogRepo -> DB: SELECT * FROM draw_logs\nWHERE event_id = ? + activate DB + DB --> LogRepo: 추첨 로그 조회 + deactivate DB + LogRepo --> Service: Optional + deactivate LogRepo + + alt 이미 추첨 완료 + Service --> Controller: AlreadyDrawnException + Controller --> Gateway: 409 Conflict\n{message: "이미 추첨이 완료된 이벤트입니다"} + Gateway --> Owner: 409 Conflict + deactivate Service + deactivate Controller + deactivate Gateway + else 추첨 가능 상태 + + Service -> Repo: findAllByEventIdAndIsWinner(eventId, false) + activate Repo + Repo -> DB: SELECT * FROM participants\nWHERE event_id = ?\nAND is_winner = false\nORDER BY participated_at ASC + activate DB + DB --> Repo: 전체 참여자 목록 + deactivate DB + Repo --> Service: List + deactivate Repo + + alt 참여자 수 부족 Service --> Controller: InsufficientParticipantsException Controller --> Gateway: 400 Bad Request\n{message: "참여자 수가 부족합니다"} Gateway --> Owner: 400 Bad Request @@ -58,22 +78,14 @@ else JWT 검증 성공 deactivate Gateway else 추첨 진행 - Service -> Service: 이벤트 상태 확인\n- 이벤트 종료 여부\n- 이미 추첨 완료 여부 - - alt 이벤트가 아직 진행 중 - Service --> Controller: EventNotEndedException - Controller --> Gateway: 400 Bad Request\n{message: "이벤트가 아직 진행 중입니다"} - Gateway --> Owner: 400 Bad Request - deactivate Service - deactivate Controller - deactivate Gateway - else 추첨 가능 상태 - Service -> Lottery: executeLottery(participants, winnerCount, visitBonus) activate Lottery note right of Lottery 추첨 알고리즘: + 시간 복잡도: O(n log n) + 공간 복잡도: O(n) + 1. 난수 생성 (Crypto.randomBytes) 2. 매장 방문 가산점 적용 (옵션) - 방문 고객: 가중치 2배 @@ -97,6 +109,15 @@ else JWT 검증 성공 Service -> Service: DB 트랜잭션 시작 + alt DB 저장 실패 시 + note right of Service + 트랜잭션 롤백 처리: + - 당첨자 업데이트 취소 + - 추첨 로그 저장 취소 + - 재시도 가능 상태 유지 + end note + end + Service -> Repo: updateWinners(winnerIds) activate Repo Repo -> DB: UPDATE participants\nSET is_winner = true,\nwon_at = NOW()\nWHERE participant_id IN (?) @@ -155,7 +176,7 @@ else JWT 검증 성공 deactivate Gateway Owner -> Owner: 당첨자 목록 화면 표시\n- 당첨자 정보 테이블\n- 재추첨 버튼\n- 추첨 완료 메시지 - end + end end end end diff --git a/design/backend/sequence/inner/participation-이벤트참여.puml b/design/backend/sequence/inner/participation-이벤트참여.puml index 01cccac..f8d8506 100644 --- a/design/backend/sequence/inner/participation-이벤트참여.puml +++ b/design/backend/sequence/inner/participation-이벤트참여.puml @@ -17,7 +17,10 @@ database "Redis Cache<>" as Cache Customer -> Gateway: POST /api/v1/participations\n{name, phone, eventId, entryPath, consent} activate Gateway -Gateway -> Gateway: JWT 토큰 검증\n(선택사항, 비회원 참여 가능) +note right of Gateway + 비회원 참여 가능 + JWT 검증 불필요 +end note Gateway -> Controller: POST /participations/register\n{name, phone, eventId, entryPath, consent} activate Controller diff --git a/design/backend/sequence/inner/participation-참여자목록조회.puml b/design/backend/sequence/inner/participation-참여자목록조회.puml index 42f4b60..2a5d86f 100644 --- a/design/backend/sequence/inner/participation-참여자목록조회.puml +++ b/design/backend/sequence/inner/participation-참여자목록조회.puml @@ -49,7 +49,7 @@ else JWT 검증 성공 Service --> Controller: ParticipantListResponse\n(캐시된 데이터) note right of Service 캐시된 데이터 반환 - - TTL: 5분 + - TTL: 10분 - 실시간 정확도 vs 성능 트레이드오프 end note Controller --> Gateway: 200 OK\n{participants, totalElements, totalPages} @@ -73,6 +73,10 @@ else JWT 검증 성공 - isWinner 필터 (선택) - name/phone 검색 (선택) - 페이지네이션 (필수) + + 필요 인덱스: + idx_participants_event_filters + (event_id, entry_path, is_winner, participated_at DESC) end note DB --> Repo: 참여자 목록 결과셋 @@ -88,12 +92,13 @@ else JWT 검증 성공 Service -> Service: DTO 변환\n- 전화번호 마스킹 (010-****-1234)\n- 응모번호 형식화\n- 당첨 여부 라벨 변환 - Service -> Cache: SET participant_list:{key} = data\nTTL: 5분 + Service -> Cache: SET participant_list:{key} = data\nTTL: 10분 activate Cache note right of Cache 캐시 저장: - - 짧은 TTL (5분) - - 실시간 참여 반영을 위해 + - TTL: 10분 + - 실시간 참여 반영과 성능 균형 + - 이벤트 참여 빈도 고려 end note Cache --> Service: 캐시 저장 완료 deactivate Cache