@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<>" 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: 5분 - 실시간 정확도 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 검색 (선택) - 페이지네이션 (필수) 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 deactivate Repo Service -> Service: DTO 변환\n- 전화번호 마스킹 (010-****-1234)\n- 응모번호 형식화\n- 당첨 여부 라벨 변환 Service -> Cache: SET participant_list:{key} = data\nTTL: 5분 activate Cache note right of Cache 캐시 저장: - 짧은 TTL (5분) - 실시간 참여 반영을 위해 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