# Participation Service 클래스 설계 결과 ## 📋 개요 **Backend Developer (최수연 "아키텍처")** Participation Service의 클래스 설계를 완료했습니다. Layered Architecture 패턴을 적용하여 이벤트 참여와 당첨자 추첨 기능을 담당하는 서비스를 설계했습니다. ## 🎯 설계 원칙 준수 ### 1. 아키텍처 패턴 - ✅ **Layered Architecture** 적용 - Presentation Layer (Controller) - Application Layer (Service, DTO) - Domain Layer (Entity, Repository) - Infrastructure Layer (Kafka, Config) ### 2. 공통 컴포넌트 참조 - ✅ BaseTimeEntity 상속 (Participant, DrawLog) - ✅ ApiResponse 사용 (모든 API 응답) - ✅ PageResponse 사용 (페이징 응답) - ✅ BusinessException 상속 (ParticipationException) - ✅ ErrorCode 인터페이스 사용 ### 3. 유저스토리 및 API 매핑 - ✅ API 설계서와 일관성 유지 - ✅ Controller 메소드와 API 경로 매핑 완료 ## 📦 패키지 구조 ``` com.kt.event.participation/ ├── presentation/ │ └── controller/ │ ├── ParticipationController.java # 이벤트 참여 API │ ├── WinnerController.java # 당첨자 추첨 API │ └── DebugController.java # 디버그 API │ ├── application/ │ ├── service/ │ │ ├── ParticipationService.java # 참여 비즈니스 로직 │ │ └── WinnerDrawService.java # 추첨 비즈니스 로직 │ └── dto/ │ ├── ParticipationRequest.java # 참여 요청 DTO │ ├── ParticipationResponse.java # 참여 응답 DTO │ ├── DrawWinnersRequest.java # 추첨 요청 DTO │ └── DrawWinnersResponse.java # 추첨 응답 DTO │ ├── domain/ │ ├── participant/ │ │ ├── Participant.java # 참여자 엔티티 │ │ └── ParticipantRepository.java # 참여자 레포지토리 │ └── draw/ │ ├── DrawLog.java # 추첨 로그 엔티티 │ └── DrawLogRepository.java # 추첨 로그 레포지토리 │ ├── exception/ │ └── ParticipationException.java # 참여 관련 예외 (7개 서브 클래스) │ └── infrastructure/ ├── kafka/ │ ├── KafkaProducerService.java # Kafka 프로듀서 │ └── event/ │ └── ParticipantRegisteredEvent.java # 참여자 등록 이벤트 └── config/ └── SecurityConfig.java # 보안 설정 ``` ## 🏗️ 주요 컴포넌트 ### Presentation Layer #### ParticipationController - **POST** `/events/{eventId}/participate` - 이벤트 참여 - **GET** `/events/{eventId}/participants` - 참여자 목록 조회 - **GET** `/events/{eventId}/participants/{participantId}` - 참여자 상세 조회 #### WinnerController - **POST** `/events/{eventId}/draw-winners` - 당첨자 추첨 - **GET** `/events/{eventId}/winners` - 당첨자 목록 조회 ### Application Layer #### ParticipationService **핵심 비즈니스 로직:** - 이벤트 참여 처리 - 중복 참여 체크 (eventId + phoneNumber) - 참여자 ID 자동 생성 (prt_YYYYMMDD_XXX) - Kafka 이벤트 발행 - 참여자 목록/상세 조회 #### WinnerDrawService **핵심 비즈니스 로직:** - 당첨자 추첨 실행 - 가중치 추첨 풀 생성 (매장 방문 5배 보너스) - 추첨 로그 저장 (재추첨 방지) - 당첨자 목록 조회 ### Domain Layer #### Participant 엔티티 - 참여자 정보 관리 - 중복 방지 (UK: event_id + phone_number) - 매장 방문 보너스 (5배 응모권) - 당첨자 상태 관리 (isWinner, winnerRank, wonAt) - 도메인 로직: - `generateParticipantId()` - 참여자 ID 생성 - `calculateBonusEntries()` - 보너스 응모권 계산 - `markAsWinner()` - 당첨자 설정 #### DrawLog 엔티티 - 추첨 이력 관리 - 재추첨 방지 (eventId당 1회만 추첨) - 추첨 알고리즘 기록 (WEIGHTED_RANDOM) - 추첨 메타데이터 (총 참여자, 당첨자 수, 보너스 적용 여부) ### Infrastructure Layer #### KafkaProducerService - **Topic**: `participant-registered-events` - 참여자 등록 이벤트 발행 - 비동기 처리로 메인 로직 영향 최소화 ## 🔍 예외 처리 ### ParticipationException 계층 1. **DuplicateParticipationException** - 중복 참여 2. **EventNotFoundException** - 이벤트 없음 3. **EventNotActiveException** - 이벤트 비활성 4. **ParticipantNotFoundException** - 참여자 없음 5. **AlreadyDrawnException** - 이미 추첨 완료 6. **InsufficientParticipantsException** - 참여자 부족 7. **NoWinnersYetException** - 당첨자 미추첨 ## 🔗 관계 설계 ### 상속 관계 ``` BaseTimeEntity ├── Participant (domain.participant) └── DrawLog (domain.draw) BusinessException └── ParticipationException ├── DuplicateParticipationException ├── EventNotFoundException ├── EventNotActiveException ├── ParticipantNotFoundException ├── AlreadyDrawnException ├── InsufficientParticipantsException └── NoWinnersYetException ``` ### 의존 관계 ``` ParticipationController → ParticipationService WinnerController → WinnerDrawService ParticipationService → ParticipantRepository ParticipationService → KafkaProducerService WinnerDrawService → ParticipantRepository WinnerDrawService → DrawLogRepository KafkaProducerService → ParticipantRegisteredEvent ``` ## 📊 데이터 처리 흐름 ### 이벤트 참여 흐름 ``` 1. 클라이언트 → POST /events/{eventId}/participate 2. ParticipationController → ParticipationService.participate() 3. 중복 참여 체크 (existsByEventIdAndPhoneNumber) 4. 참여자 ID 생성 (findMaxSequenceByDatePrefix) 5. Participant 엔티티 생성 및 저장 6. Kafka 이벤트 발행 (ParticipantRegisteredEvent) 7. ParticipationResponse 반환 ``` ### 당첨자 추첨 흐름 ``` 1. 클라이언트 → POST /events/{eventId}/draw-winners 2. WinnerController → WinnerDrawService.drawWinners() 3. 추첨 완료 여부 확인 (existsByEventId) 4. 참여자 목록 조회 (findByEventIdAndIsWinnerFalse) 5. 가중치 추첨 풀 생성 (createDrawPool) 6. 무작위 셔플 및 당첨자 선정 7. 당첨자 상태 업데이트 (markAsWinner) 8. DrawLog 저장 9. DrawWinnersResponse 반환 ``` ## ✅ 검증 결과 ### PlantUML 문법 검사 ``` ✓ participation-service.puml - No syntax errors ✓ participation-service-simple.puml - No syntax errors ``` ### 설계 검증 항목 - ✅ 유저스토리와 매칭 - ✅ API 설계서와 일관성 - ✅ 내부 시퀀스 설계서와 일관성 - ✅ Layered Architecture 패턴 적용 - ✅ 공통 컴포넌트 참조 - ✅ 클래스 프로퍼티/메소드 명시 - ✅ 클래스 간 관계 표현 - ✅ API-Controller 메소드 매핑 ## 📁 산출물 ### 생성된 파일 1. **design/backend/class/participation-service.puml** - 상세 클래스 다이어그램 - 모든 프로퍼티와 메소드 포함 - 관계 및 의존성 상세 표현 2. **design/backend/class/participation-service-simple.puml** - 요약 클래스 다이어그램 - 패키지 구조 중심 - API 매핑 정보 포함 ## 🎯 특징 및 강점 ### 1. 데이터 중심 설계 - 중복 참여 방지 (DB 제약조건) - 참여자 ID 자동 생성 - 추첨 이력 관리 ### 2. 단순한 비즈니스 로직 - 복잡한 외부 의존성 없음 - 자체 완결적인 도메인 로직 - 명확한 책임 분리 ### 3. 이벤트 기반 통합 - Kafka를 통한 느슨한 결합 - 비동기 이벤트 발행 - 서비스 장애 격리 ### 4. 가중치 추첨 알고리즘 - 매장 방문 보너스 (5배 응모권) - 공정한 무작위 추첨 - 추첨 이력 관리 ## 🔄 다음 단계 1. ✅ **클래스 설계 완료** 2. 🔜 **데이터베이스 설계** - ERD 작성 필요 3. 🔜 **백엔드 개발** - 실제 코드 구현 4. 🔜 **단위 테스트** - 테스트 코드 작성 --- **작성자**: Backend Developer (최수연 "아키텍처") **작성일**: 2025-10-29 **설계 패턴**: Layered Architecture **검증 상태**: ✅ 완료