mirror of
https://github.com/ktds-dg0501/kt-event-marketing.git
synced 2025-12-06 11:26:26 +00:00
25 KiB
25 KiB
KT Event Marketing - Clean Architecture Package Structure
프로젝트 구조 개요
kt-event-marketing/
├── common/ # 공통 모듈
├── user-service/ # 사용자 서비스
├── event-service/ # 이벤트 서비스
├── ai-service/ # AI 서비스
├── content-service/ # 콘텐츠 서비스
├── distribution-service/ # 배포 서비스
├── participation-service/ # 참여 서비스
├── analytics-service/ # 분석 서비스
├── settings.gradle
└── build.gradle
Common 모듈 패키지 구조
common/
└── src/main/java/com/kt/event/common/
├── dto/
│ ├── ApiResponse.java # 공통 API 응답 래퍼
│ ├── PageResponse.java # 페이지네이션 응답
│ └── ErrorResponse.java # 에러 응답
├── exception/
│ ├── ErrorCode.java # 에러 코드 enum
│ ├── BusinessException.java # 비즈니스 예외
│ ├── InfraException.java # 인프라 예외
│ └── GlobalExceptionHandler.java # 전역 예외 핸들러
├── util/
│ ├── DateTimeUtil.java # 날짜/시간 유틸
│ ├── StringUtil.java # 문자열 유틸
│ ├── ValidationUtil.java # 유효성 검증 유틸
│ └── EncryptionUtil.java # 암호화 유틸
├── security/
│ ├── UserPrincipal.java # 인증된 사용자 정보
│ ├── JwtTokenProvider.java # JWT 토큰 제공자
│ └── JwtAuthenticationFilter.java # JWT 인증 필터
└── entity/
└── BaseTimeEntity.java # 생성/수정 시간 base entity
User Service 패키지 구조 (Clean Architecture)
user-service/
└── src/main/java/com/kt/event/user/
├── biz/ # Business Layer
│ ├── domain/ # 도메인 모델
│ │ ├── User.java
│ │ ├── Store.java
│ │ └── BusinessVerification.java
│ ├── usecase/ # Use Case 인터페이스
│ │ ├── in/ # Inbound Port (비즈니스 로직 진입점)
│ │ │ ├── RegisterUserUseCase.java
│ │ │ ├── LoginUserUseCase.java
│ │ │ ├── LogoutUserUseCase.java
│ │ │ ├── GetUserProfileUseCase.java
│ │ │ ├── UpdateUserProfileUseCase.java
│ │ │ ├── ChangePasswordUseCase.java
│ │ │ └── GetStoreInfoUseCase.java
│ │ └── out/ # Outbound Port (외부 의존성 인터페이스)
│ │ ├── UserReader.java
│ │ ├── UserWriter.java
│ │ ├── StoreReader.java
│ │ ├── StoreWriter.java
│ │ ├── RedisSessionWriter.java
│ │ └── BusinessVerifier.java
│ ├── service/ # Use Case 구현체
│ │ ├── UserService.java
│ │ ├── AuthenticationService.java
│ │ └── ProfileService.java
│ └── dto/ # 비즈니스 DTO
│ ├── UserCommand.java
│ ├── UserInfo.java
│ └── StoreInfo.java
└── infra/ # Infrastructure Layer
├── UserApplication.java # Spring Boot Main
├── controller/ # REST API Controller (Inbound Adapter)
│ ├── UserController.java
│ └── AuthController.java
├── dto/ # API Request/Response DTO
│ ├── request/
│ │ ├── UserRegisterRequest.java
│ │ ├── UserLoginRequest.java
│ │ ├── UserProfileUpdateRequest.java
│ │ └── ChangePasswordRequest.java
│ └── response/
│ ├── UserProfileResponse.java
│ ├── StoreInfoResponse.java
│ └── LoginResponse.java
├── gateway/ # Outbound Adapter
│ ├── entity/ # JPA Entity
│ │ ├── UserEntity.java
│ │ └── StoreEntity.java
│ ├── repository/ # JPA Repository
│ │ ├── UserJpaRepository.java
│ │ └── StoreJpaRepository.java
│ ├── UserGateway.java # User Reader/Writer 구현
│ ├── StoreGateway.java # Store Reader/Writer 구현
│ ├── RedisSessionGateway.java # Redis Session 구현
│ └── BusinessVerifierGateway.java # 사업자번호 검증 구현
└── config/ # 설정
├── SecurityConfig.java
├── RedisConfig.java
├── SwaggerConfig.java
└── DataLoader.java
Event Service 패키지 구조 (Clean Architecture)
event-service/
└── src/main/java/com/kt/event/event/
├── biz/
│ ├── domain/
│ │ ├── Event.java
│ │ ├── EventObjective.java
│ │ ├── EventStatus.java
│ │ ├── AIRecommendation.java
│ │ ├── Image.java
│ │ ├── DistributionChannel.java
│ │ └── Job.java
│ ├── usecase/
│ │ ├── in/
│ │ │ ├── CreateEventObjectiveUseCase.java
│ │ │ ├── RequestAIRecommendationUseCase.java
│ │ │ ├── SelectAIRecommendationUseCase.java
│ │ │ ├── RequestImageGenerationUseCase.java
│ │ │ ├── SelectImageUseCase.java
│ │ │ ├── EditImageUseCase.java
│ │ │ ├── SelectDistributionChannelsUseCase.java
│ │ │ ├── PublishEventUseCase.java
│ │ │ ├── GetEventListUseCase.java
│ │ │ ├── GetEventDetailUseCase.java
│ │ │ ├── UpdateEventUseCase.java
│ │ │ ├── DeleteEventUseCase.java
│ │ │ ├── EndEventUseCase.java
│ │ │ └── GetJobStatusUseCase.java
│ │ └── out/
│ │ ├── EventReader.java
│ │ ├── EventWriter.java
│ │ ├── JobReader.java
│ │ ├── JobWriter.java
│ │ ├── KafkaJobPublisher.java
│ │ ├── KafkaEventPublisher.java
│ │ ├── RedisAIDataReader.java
│ │ ├── RedisImageDataReader.java
│ │ └── DistributionServiceCaller.java
│ ├── service/
│ │ ├── EventCreationService.java
│ │ ├── EventManagementService.java
│ │ ├── AIRecommendationService.java
│ │ ├── ImageGenerationService.java
│ │ ├── DistributionService.java
│ │ └── JobStatusService.java
│ └── dto/
│ ├── EventCommand.java
│ ├── EventInfo.java
│ ├── AIRecommendationInfo.java
│ ├── ImageInfo.java
│ ├── ChannelInfo.java
│ └── JobInfo.java
└── infra/
├── EventApplication.java
├── controller/
│ ├── EventController.java
│ ├── EventCreationController.java
│ └── JobController.java
├── dto/
│ ├── request/
│ │ ├── EventObjectiveRequest.java
│ │ ├── AIRecommendationSelectionRequest.java
│ │ ├── ImageSelectionRequest.java
│ │ ├── ImageEditRequest.java
│ │ ├── ChannelSelectionRequest.java
│ │ └── EventUpdateRequest.java
│ └── response/
│ ├── EventResponse.java
│ ├── EventListResponse.java
│ ├── JobStatusResponse.java
│ └── PublishResponse.java
├── gateway/
│ ├── entity/
│ │ ├── EventEntity.java
│ │ ├── AIRecommendationEntity.java
│ │ ├── ImageEntity.java
│ │ ├── DistributionChannelEntity.java
│ │ └── JobEntity.java
│ ├── repository/
│ │ ├── EventJpaRepository.java
│ │ ├── AIRecommendationJpaRepository.java
│ │ ├── ImageJpaRepository.java
│ │ ├── DistributionChannelJpaRepository.java
│ │ └── JobJpaRepository.java
│ ├── EventGateway.java
│ ├── JobGateway.java
│ ├── KafkaProducerGateway.java
│ ├── RedisGateway.java
│ └── DistributionServiceGateway.java
└── config/
├── SecurityConfig.java
├── KafkaProducerConfig.java
├── RedisConfig.java
├── SwaggerConfig.java
└── FeignConfig.java
AI Service 패키지 구조 (Clean Architecture)
ai-service/
└── src/main/java/com/kt/event/ai/
├── biz/
│ ├── domain/
│ │ ├── AIRecommendation.java
│ │ ├── TrendAnalysis.java
│ │ ├── EventRecommendation.java
│ │ └── Job.java
│ ├── usecase/
│ │ ├── in/
│ │ │ ├── GenerateAIRecommendationUseCase.java
│ │ │ ├── GetJobStatusUseCase.java
│ │ │ └── GetRecommendationResultUseCase.java
│ │ └── out/
│ │ ├── JobReader.java
│ │ ├── JobWriter.java
│ │ ├── RedisResultWriter.java
│ │ ├── RedisResultReader.java
│ │ ├── TrendAnalyzer.java
│ │ └── AIModelCaller.java
│ ├── service/
│ │ ├── AIRecommendationService.java
│ │ ├── TrendAnalysisService.java
│ │ └── JobManagementService.java
│ └── dto/
│ ├── AICommand.java
│ ├── AIResult.java
│ ├── TrendInfo.java
│ └── JobInfo.java
└── infra/
├── AIApplication.java
├── controller/
│ └── InternalAIController.java
├── dto/
│ ├── request/
│ │ └── AIRequestDto.java
│ └── response/
│ ├── AIRecommendationResponse.java
│ ├── JobStatusResponse.java
│ └── TrendAnalysisResponse.java
├── gateway/
│ ├── entity/
│ │ └── JobEntity.java
│ ├── repository/
│ │ └── JobJpaRepository.java
│ ├── JobGateway.java
│ ├── RedisGateway.java
│ ├── TrendAnalyzerGateway.java
│ └── ClaudeAPIGateway.java
├── consumer/
│ └── AIJobConsumer.java
└── config/
├── SecurityConfig.java
├── KafkaConsumerConfig.java
├── RedisConfig.java
├── SwaggerConfig.java
└── ClaudeAPIConfig.java
Content Service 패키지 구조 (Clean Architecture)
content-service/
└── src/main/java/com/kt/event/content/
├── biz/
│ ├── domain/
│ │ ├── Content.java
│ │ ├── GeneratedImage.java
│ │ ├── ImageStyle.java
│ │ ├── Platform.java
│ │ └── Job.java
│ ├── usecase/
│ │ ├── in/
│ │ │ ├── GenerateImagesUseCase.java
│ │ │ ├── GetJobStatusUseCase.java
│ │ │ ├── GetEventContentUseCase.java
│ │ │ ├── GetImageListUseCase.java
│ │ │ ├── GetImageDetailUseCase.java
│ │ │ └── RegenerateImageUseCase.java
│ │ └── out/
│ │ ├── ContentReader.java
│ │ ├── ContentWriter.java
│ │ ├── JobReader.java
│ │ ├── JobWriter.java
│ │ ├── RedisAIDataReader.java
│ │ ├── RedisImageWriter.java
│ │ ├── ImageGeneratorCaller.java
│ │ └── CDNUploader.java
│ ├── service/
│ │ ├── ImageGenerationService.java
│ │ ├── ContentManagementService.java
│ │ └── JobManagementService.java
│ └── dto/
│ ├── ContentCommand.java
│ ├── ContentInfo.java
│ ├── ImageInfo.java
│ └── JobInfo.java
└── infra/
├── ContentApplication.java
├── controller/
│ └── ContentController.java
├── dto/
│ ├── request/
│ │ ├── ImageGenerationRequest.java
│ │ └── RegenerateRequest.java
│ └── response/
│ ├── ContentResponse.java
│ ├── ImageResponse.java
│ └── JobStatusResponse.java
├── gateway/
│ ├── entity/
│ │ ├── ContentEntity.java
│ │ ├── GeneratedImageEntity.java
│ │ └── JobEntity.java
│ ├── repository/
│ │ ├── ContentJpaRepository.java
│ │ ├── GeneratedImageJpaRepository.java
│ │ └── JobJpaRepository.java
│ ├── ContentGateway.java
│ ├── JobGateway.java
│ ├── RedisGateway.java
│ ├── StableDiffusionGateway.java
│ └── AzureBlobStorageGateway.java
├── consumer/
│ └── ImageGenerationJobConsumer.java
└── config/
├── SecurityConfig.java
├── KafkaConsumerConfig.java
├── RedisConfig.java
├── SwaggerConfig.java
└── AzureStorageConfig.java
Distribution Service 패키지 구조 (Clean Architecture)
distribution-service/
└── src/main/java/com/kt/event/distribution/
├── biz/
│ ├── domain/
│ │ ├── Distribution.java
│ │ ├── DistributionChannel.java
│ │ ├── ChannelResult.java
│ │ └── DistributionStatus.java
│ ├── usecase/
│ │ ├── in/
│ │ │ ├── DistributeToChannelsUseCase.java
│ │ │ └── GetDistributionStatusUseCase.java
│ │ └── out/
│ │ ├── DistributionReader.java
│ │ ├── DistributionWriter.java
│ │ ├── ChannelDistributor.java
│ │ └── KafkaEventPublisher.java
│ ├── service/
│ │ ├── DistributionService.java
│ │ └── ChannelService.java
│ └── dto/
│ ├── DistributionCommand.java
│ ├── DistributionInfo.java
│ └── ChannelInfo.java
└── infra/
├── DistributionApplication.java
├── controller/
│ └── DistributionController.java
├── dto/
│ ├── request/
│ │ └── DistributionRequest.java
│ └── response/
│ ├── DistributionResponse.java
│ └── DistributionStatusResponse.java
├── gateway/
│ ├── entity/
│ │ ├── DistributionEntity.java
│ │ └── ChannelResultEntity.java
│ ├── repository/
│ │ ├── DistributionJpaRepository.java
│ │ └── ChannelResultJpaRepository.java
│ ├── DistributionGateway.java
│ ├── KafkaProducerGateway.java
│ └── channel/
│ ├── UriDongneTVGateway.java
│ ├── RingoBizGateway.java
│ ├── GenieTVGateway.java
│ ├── InstagramGateway.java
│ ├── NaverBlogGateway.java
│ └── KakaoChannelGateway.java
└── config/
├── SecurityConfig.java
├── KafkaProducerConfig.java
├── SwaggerConfig.java
├── ResilienceConfig.java
└── FeignConfig.java
Participation Service 패키지 구조 (Clean Architecture)
participation-service/
└── src/main/java/com/kt/event/participation/
├── biz/
│ ├── domain/
│ │ ├── Participant.java
│ │ ├── Winner.java
│ │ ├── DrawResult.java
│ │ └── Consent.java
│ ├── usecase/
│ │ ├── in/
│ │ │ ├── ParticipateEventUseCase.java
│ │ │ ├── GetParticipantListUseCase.java
│ │ │ ├── GetParticipantDetailUseCase.java
│ │ │ ├── DrawWinnersUseCase.java
│ │ │ └── GetWinnerListUseCase.java
│ │ └── out/
│ │ ├── ParticipantReader.java
│ │ ├── ParticipantWriter.java
│ │ ├── WinnerReader.java
│ │ ├── WinnerWriter.java
│ │ ├── DrawExecutor.java
│ │ └── KafkaEventPublisher.java
│ ├── service/
│ │ ├── ParticipationService.java
│ │ └── WinnerDrawService.java
│ └── dto/
│ ├── ParticipationCommand.java
│ ├── ParticipantInfo.java
│ ├── WinnerInfo.java
│ └── DrawCommand.java
└── infra/
├── ParticipationApplication.java
├── controller/
│ └── ParticipationController.java
├── dto/
│ ├── request/
│ │ ├── ParticipationRequest.java
│ │ └── WinnerDrawRequest.java
│ └── response/
│ ├── ParticipationResponse.java
│ ├── ParticipantListResponse.java
│ └── WinnerResponse.java
├── gateway/
│ ├── entity/
│ │ ├── ParticipantEntity.java
│ │ └── WinnerEntity.java
│ ├── repository/
│ │ ├── ParticipantJpaRepository.java
│ │ └── WinnerJpaRepository.java
│ ├── ParticipantGateway.java
│ ├── WinnerGateway.java
│ ├── DrawExecutorGateway.java
│ └── KafkaProducerGateway.java
└── config/
├── SecurityConfig.java
├── KafkaProducerConfig.java
└── SwaggerConfig.java
Analytics Service 패키지 구조 (Clean Architecture)
analytics-service/
└── src/main/java/com/kt/event/analytics/
├── biz/
│ ├── domain/
│ │ ├── EventAnalytics.java
│ │ ├── ChannelPerformance.java
│ │ ├── TimelineData.java
│ │ ├── RoiDetail.java
│ │ └── ParticipantProfile.java
│ ├── usecase/
│ │ ├── in/
│ │ │ ├── GetAnalyticsDashboardUseCase.java
│ │ │ ├── GetChannelPerformanceUseCase.java
│ │ │ ├── GetTimelineDataUseCase.java
│ │ │ └── GetRoiDetailUseCase.java
│ │ └── out/
│ │ ├── AnalyticsReader.java
│ │ ├── AnalyticsWriter.java
│ │ ├── ExternalAPIDataCollector.java
│ │ └── RedisAnalyticsCache.java
│ ├── service/
│ │ ├── AnalyticsDashboardService.java
│ │ ├── PerformanceAnalysisService.java
│ │ └── RoiCalculationService.java
│ └── dto/
│ ├── AnalyticsCommand.java
│ ├── AnalyticsInfo.java
│ ├── PerformanceInfo.java
│ └── RoiInfo.java
└── infra/
├── AnalyticsApplication.java
├── controller/
│ └── AnalyticsController.java
├── dto/
│ └── response/
│ ├── AnalyticsDashboardResponse.java
│ ├── ChannelPerformanceResponse.java
│ ├── TimelineDataResponse.java
│ └── RoiDetailResponse.java
├── gateway/
│ ├── entity/
│ │ ├── EventAnalyticsEntity.java
│ │ ├── ChannelPerformanceEntity.java
│ │ └── TimelineDataEntity.java
│ ├── repository/
│ │ ├── EventAnalyticsJpaRepository.java
│ │ ├── ChannelPerformanceJpaRepository.java
│ │ └── TimelineDataJpaRepository.java
│ ├── AnalyticsGateway.java
│ ├── RedisGateway.java
│ └── external/
│ ├── UriDongneTVAPIGateway.java
│ ├── GenieTVAPIGateway.java
│ ├── InstagramAPIGateway.java
│ ├── NaverAPIGateway.java
│ └── KakaoAPIGateway.java
├── consumer/
│ └── AnalyticsEventConsumer.java
└── config/
├── SecurityConfig.java
├── KafkaConsumerConfig.java
├── RedisConfig.java
├── SwaggerConfig.java
├── ResilienceConfig.java
└── FeignConfig.java
아키텍처 설명
Clean Architecture 레이어 구조
-
biz (Business Layer) - 비즈니스 로직
domain/: 핵심 도메인 모델 (순수 Java 객체, 외부 의존성 없음)usecase/in/: Inbound Port (비즈니스 로직 진입점 인터페이스)usecase/out/: Outbound Port (외부 의존성 인터페이스)service/: Use Case 구현체 (비즈니스 로직 실행)dto/: 비즈니스 레이어 내부 DTO
-
infra (Infrastructure Layer) - 외부 세계와의 통신
controller/: REST API Controller (Inbound Adapter)dto/request/,dto/response/: API 계약 DTOgateway/: Outbound Adapter (DB, 외부 API, Kafka, Redis 등)gateway/entity/: JPA Entitygateway/repository/: JPA Repositoryconsumer/: Kafka Consumerconfig/: 설정 클래스
의존성 규칙
- biz → infra: ❌ 불가능 (비즈니스 로직은 인프라에 의존하지 않음)
- infra → biz: ✅ 가능 (인프라는 비즈니스 인터페이스를 구현)
- domain → 외부: ❌ 불가능 (순수 비즈니스 로직만 포함)
네이밍 규칙
- UseCase 인터페이스:
{동작}{대상}UseCase(예:RegisterUserUseCase) - Service 구현체:
{대상}Service(예:UserService) - Gateway 구현체:
{대상}Gateway(예:UserGateway) - Port 인터페이스:
{대상}{동작}(예:UserReader,UserWriter)
기술 스택 정리
| 레이어 | 기술 |
|---|---|
| Framework | Spring Boot 3.3.0, Java 21 |
| Database | PostgreSQL (각 서비스별 독립 DB) |
| Cache | Redis (공통) |
| Message Queue | Kafka (비동기 Job 처리, Event 발행) |
| Security | JWT, Spring Security |
| API Documentation | Swagger UI (SpringDoc OpenAPI) |
| Persistence | Spring Data JPA |
| Build Tool | Gradle 8.x |
작성일: 2025-10-23 작성자: Backend Developer (리액트킹)