kt-event-marketing/design/backend/sequence/inner/participation-참여자목록조회.puml
2025-10-22 15:02:54 +09:00

121 lines
4.5 KiB
Plaintext

@startuml participation-참여자목록조회
!theme mono
title Participation Service - 참여자 목록 조회 내부 시퀀스
actor "사장님" as Owner
participant "API Gateway" as Gateway
participant "ParticipationController" as Controller
participant "ParticipationService" as Service
participant "ParticipantRepository" as Repo
database "Participation DB" as DB
database "Redis Cache<<E>>" as Cache
== UFR-PART-020: 참여자 목록 조회 ==
Owner -> Gateway: GET /api/v1/events/{eventId}/participants\n?entryPath={경로}&isWinner={당첨여부}\n&name={이름}&phone={전화번호}\n&page={페이지}&size={크기}
activate Gateway
Gateway -> Gateway: JWT 토큰 검증\n- 토큰 유효성 확인\n- 사장님 권한 확인
alt JWT 검증 실패
Gateway --> Owner: 401 Unauthorized
deactivate Gateway
else JWT 검증 성공
Gateway -> Controller: GET /participants\n{eventId, filters, pagination}
activate Controller
Controller -> Controller: 요청 파라미터 유효성 검증\n- eventId 필수\n- page >= 0\n- size: 10~100
alt 유효성 검증 실패
Controller --> Gateway: 400 Bad Request
Gateway --> Owner: 400 Bad Request
deactivate Controller
deactivate Gateway
else 유효성 검증 성공
Controller -> Service: getParticipantList(eventId, filters, pageable)
activate Service
Service -> Service: 캐시 키 생성\n- participant_list:{eventId}:{filters}:{page}
Service -> Cache: GET participant_list:{key}
activate Cache
Cache --> Service: 캐시 조회 결과
deactivate Cache
alt 캐시 HIT
Service --> Controller: ParticipantListResponse\n(캐시된 데이터)
note right of Service
캐시된 데이터 반환
- TTL: 10분
- 실시간 정확도 vs 성능 트레이드오프
end note
Controller --> Gateway: 200 OK\n{participants, totalElements, totalPages}
Gateway --> Owner: 200 OK\n참여자 목록 표시
deactivate Service
deactivate Controller
deactivate Gateway
else 캐시 MISS: DB 조회
Service -> Service: 동적 쿼리 생성\n- 참여 경로 필터\n- 당첨 여부 필터\n- 이름/전화번호 검색
Service -> Repo: findParticipants(eventId, filters, pageable)
activate Repo
Repo -> DB: SELECT p.participant_id, p.name,\np.phone_number, p.entry_path,\np.application_number, p.participated_at,\np.is_winner\nFROM participants p\nWHERE p.event_id = ?\n[AND p.entry_path = ?]\n[AND p.is_winner = ?]\n[AND (p.name LIKE ? OR p.phone_number LIKE ?)]\nORDER BY p.participated_at DESC\nLIMIT ? OFFSET ?
activate DB
note right of DB
동적 쿼리 조건:
- entryPath 필터 (선택)
- isWinner 필터 (선택)
- name/phone 검색 (선택)
- 페이지네이션 (필수)
필요 인덱스:
idx_participants_event_filters
(event_id, entry_path, is_winner, participated_at DESC)
end note
DB --> Repo: 참여자 목록 결과셋
deactivate DB
Repo -> DB: SELECT COUNT(*)\nFROM participants\nWHERE event_id = ?\n[필터 조건 동일]
activate DB
DB --> Repo: 전체 건수
deactivate DB
Repo --> Service: Page<Participant>
deactivate Repo
Service -> Service: DTO 변환\n- 전화번호 마스킹 (010-****-1234)\n- 응모번호 형식화\n- 당첨 여부 라벨 변환
Service -> Cache: SET participant_list:{key} = data\nTTL: 10분
activate Cache
note right of Cache
캐시 저장:
- TTL: 10분
- 실시간 참여 반영과 성능 균형
- 이벤트 참여 빈도 고려
end note
Cache --> Service: 캐시 저장 완료
deactivate Cache
Service --> Controller: ParticipantListResponse\n{participants[], totalElements, totalPages, currentPage}
deactivate Service
Controller --> Gateway: 200 OK\n{data, pagination}
deactivate Controller
Gateway --> Owner: 200 OK
deactivate Gateway
Owner -> Owner: 참여자 목록 화면 표시\n- 테이블 형태\n- 페이지네이션\n- 필터/검색 UI
end
end
end
@enduml