@startuml !theme mono title Participation Service ERD ' 스타일 정의 skinparam linetype ortho skinparam roundcorner 10 skinparam class { BackgroundColor White BorderColor Black ArrowColor Black } ' 참여자 테이블 entity "participants" as participants { **id : BIGSERIAL <>** -- participant_id : VARCHAR(50) <> event_id : VARCHAR(50) <> name : VARCHAR(100) phone_number : VARCHAR(20) email : VARCHAR(100) channel : VARCHAR(50) store_visited : BOOLEAN bonus_entries : INTEGER agree_marketing : BOOLEAN agree_privacy : BOOLEAN is_winner : BOOLEAN winner_rank : INTEGER won_at : TIMESTAMP created_at : TIMESTAMP updated_at : TIMESTAMP -- **Indexes:** idx_participants_event_created idx_participants_event_winner idx_participants_event_store -- **Constraints:** uk_participant_id UNIQUE uk_event_phone UNIQUE (event_id, phone_number) chk_bonus_entries (1 <= bonus_entries <= 3) chk_channel IN ('WEB', 'MOBILE', 'INSTORE') chk_winner_rank (winner_rank IS NULL OR > 0) } ' 추첨 이력 테이블 entity "draw_logs" as draw_logs { **id : BIGSERIAL <>** -- event_id : VARCHAR(50) <> total_participants : INTEGER winner_count : INTEGER apply_store_visit_bonus : BOOLEAN algorithm : VARCHAR(50) drawn_at : TIMESTAMP drawn_by : VARCHAR(100) created_at : TIMESTAMP updated_at : TIMESTAMP -- **Indexes:** idx_draw_logs_event idx_draw_logs_drawn_at -- **Constraints:** uk_draw_event UNIQUE (event_id) chk_winner_count (winner_count > 0) chk_total_participants (total_participants >= winner_count) chk_algorithm IN ('RANDOM', 'WEIGHTED') } ' 관계 정의 participants "N" -- "1" draw_logs : event_id ' 노트 note right of participants **참여자 관리** - 중복 참여 방지 (event_id + phone_number) - 매장 방문 보너스 응모권 관리 - 당첨자 상태 관리 **보너스 응모권 계산** - 기본: 1개 - 매장 방문 시: 3개 (+2 보너스) **participant_id 형식** EVT{eventId}-{YYYYMMDD}-{SEQ} 예시: EVT123-20251029-001 end note note right of draw_logs **추첨 이력 관리** - 이벤트당 1회만 추첨 가능 - 재추첨 방지 - 감사 추적 (drawn_by, drawn_at) **추첨 알고리즘** - RANDOM: 단순 무작위 추첨 - WEIGHTED: 보너스 응모권 적용 추첨 end note ' 캐시 정보 노트 note bottom of participants **Redis 캐시 키 구조** 1. 참여 세션 정보 Key: participation:session:{eventId}:{phoneNumber} TTL: 10분 용도: 중복 참여 방지 2. 추첨 결과 임시 저장 Key: participation:draw:{eventId} TTL: 1시간 용도: 빠른 조회 3. 이벤트별 참여자 카운트 Key: participation:count:{eventId} TTL: 5분 용도: 실시간 집계 end note ' 외부 참조 노트 note top of participants **외부 서비스 참조 (캐시 기반)** - event_id: Event Service 이벤트 ID - 직접 FK 관계 없음 (마이크로서비스 독립성) - Redis 캐시로 이벤트 정보 참조 end note @enduml