Skip to content

feat(subscribe): 구독 서비스 생성#17

Open
lian2945 wants to merge 178 commits intomainfrom
feat/49
Open

feat(subscribe): 구독 서비스 생성#17
lian2945 wants to merge 178 commits intomainfrom
feat/49

Conversation

@lian2945
Copy link
Copy Markdown
Collaborator

@lian2945 lian2945 commented Apr 8, 2026

📌 관련 이슈

  • close #49

📝 변경 사항 요약

작업 유형

  • ✨ feat: 새로운 기능 추가 (기능 단위 완료 후 PR)
  • 🐛 fix: 버그 수정 (버그 1개 = PR 1개)
  • ♻️ refactor: 코드 리팩토링 (작업 단위 완료 후 PR)
  • ✅ test: 테스트 코드 추가/수정 (작업 단위 완료 후 PR)

변경 내용

  • creator 서비스에 IsCreatorAndSubscriberSamePerson gRPC 계약/서버를 추가했습니다.
  • subscribe 서비스에 도메인/애플리케이션/어댑터/예외/보안/설정 계층을 구성했습니다.
  • subscribe REST/gRPC 엔드포인트를 추가했습니다.
  • subscribe에서 creator gRPC를 호출해 creator와 subscriber 동일인물 여부를 검사하고, 자기 구독을 차단하도록 반영했습니다.
  • creator gRPC 호출 경로에 CircuitBreaker(creatorService)와 fallback(503)을 적용했습니다.
  • Kafka 이벤트(user-banned, user-withdrawn, creator-revoked) 수신 시 구독 정리 로직을 추가했습니다.
  • 구독 상태 예외를 반영했습니다.
    • 이미 구독: AlreadySubscribedException (409)
    • 미구독 취소: SubscriptionNotFoundException (404)
    • 자기 구독 시도: SelfSubscriptionNotAllowedException (400)

변경 이유

  • subscribe 서비스를 실사용 가능한 구조로 완성하고, 정책상 금지된 자기 구독을 서버에서 일관되게 차단하기 위해 변경했습니다.
  • creator 식별 검증을 creator 서비스 책임으로 분리해 도메인 경계를 명확히 유지하기 위해 gRPC 연동을 추가했습니다.

✅ 테스트 체크리스트

  • 단위 테스트 작성 및 통과
  • 통합 테스트 통과
  • 기존 기능 정상 동작 확인 (Regression)
  • API 응답값 확인
  • 예외 케이스 처리 확인
  • 로컬 환경에서 직접 테스트 완료

📸 스크린샷 / 로그

펼쳐보기

🔄 동작 플로우 (Mermaid)

 flowchart TD
     A[구독 요청 수신] --> B[Security Filter에서 X-User-Id 추출]
     B --> C[SubscribeService 진입]
     C --> D[creator gRPC: IsCreatorAndSubscriberSamePerson 호출]
     D -->|same_person=true| E[SelfSubscriptionNotAllowedException]
     D -->|same_person=false| F[중복 구독 여부 조회]
     F -->|이미 구독| G[AlreadySubscribedException]
     F -->|미구독| H[구독 저장]
     H --> I[응답 반환]

     J[Kafka user-banned/user-withdrawn] --> K[subscriber 기준 구독 일괄 삭제]
     L[Kafka creator-revoked] --> M[creator 기준 구독 일괄 삭제]
Loading

💬 리뷰어에게

  • creator↔subscribe gRPC 계약(IsCreatorAndSubscriberSamePerson)과 네이밍/응답 필드(same_person)가 의도대로 반영됐는지 확인 부탁드립니다.
  • subscribe의 자기 구독 차단 순서(동일인물 검사 → 중복 검사)와 fallback 503 처리(creatorService CircuitBreaker) 검토 부탁드립니다.
  • 이벤트 정리 로직(user/creator revoked)이 기존 구독 상태 정책과 충돌 없는지 확인 부탁드립니다

lian2945 and others added 30 commits April 3, 2026 08:09
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ponse로 정리

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
lian2945 and others added 21 commits April 8, 2026 12:00
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 8, 2026 03:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR introduces a production-ready subscribe service (REST + gRPC), adds a creator ↔ subscribe gRPC contract to prevent self-subscription, and expands supporting infrastructure across creator/auth/user services (DTO layering, Kafka consumers, security filters, exception handling, CI Sonar compilation).

Changes:

  • Add subscribe service layers, endpoints, domain model, exception handling, security filter, Kafka revoke listeners, and gRPC services/protos.
  • Add creator service gRPC server/protos and new creator domain/application layers (certification workflow, profile APIs, events), plus shared infra (Kafka retry/DLT, security, exception handling).
  • Refactor auth/user DTO packages to command/query/result, add auth Kafka revoke handling, and update SonarCloud workflow to compile Java classes + set sonar.java.binaries.

Reviewed changes

Copilot reviewed 243 out of 336 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
services/user/src/main/java/kr/magicbox/user/application/port/in/LoadUserCredentialUseCase.java Update DTO package imports
services/user/src/main/java/kr/magicbox/user/application/port/in/GetUserNicknameUseCase.java Add new use case interface
services/user/src/main/java/kr/magicbox/user/application/port/in/CheckUserActiveUseCase.java Switch param to Query DTO
services/user/src/main/java/kr/magicbox/user/application/port/in/BanUserUseCase.java Add admin ban use case
services/user/src/main/java/kr/magicbox/user/application/dto/result/UserReviewResult.java Move to result package
services/user/src/main/java/kr/magicbox/user/application/dto/result/LoadUserCredentialResult.java Move to result package
services/user/src/main/java/kr/magicbox/user/application/dto/result/GetUserProfileResult.java Move to result package
services/user/src/main/java/kr/magicbox/user/application/dto/query/GetUserProfileQuery.java Add profile query record
services/user/src/main/java/kr/magicbox/user/application/dto/query/CheckUserActiveQuery.java Add active-check query record
services/user/src/main/java/kr/magicbox/user/application/dto/command/WithdrawUserCommand.java Add withdraw command record
services/user/src/main/java/kr/magicbox/user/application/dto/command/UpdateUserProfileCommand.java Add update-profile command record
services/user/src/main/java/kr/magicbox/user/application/dto/command/UnbanUserCommand.java Add admin unban command
services/user/src/main/java/kr/magicbox/user/application/dto/command/StartSessionCommand.java Add session start command
services/user/src/main/java/kr/magicbox/user/application/dto/command/LoadUserCredentialCommand.java Move to command package
services/user/src/main/java/kr/magicbox/user/application/dto/command/EndSessionCommand.java Add session end command
services/user/src/main/java/kr/magicbox/user/application/dto/command/BanUserCommand.java Add admin ban command
services/user/src/main/java/kr/magicbox/user/application/dto/UpdateUserProfileCommand.java Remove old command record
services/user/src/main/java/kr/magicbox/user/adapter/in/web/exception/handler/GlobalExceptionHandler.java Add optimistic-lock handler
services/user/src/main/java/kr/magicbox/user/adapter/in/web/exception/handler/ErrorResponse.java Add builder-based response
services/user/src/main/java/kr/magicbox/user/adapter/in/web/dto/response/GetUserProfileResponse.java Add response record (new pkg)
services/user/src/main/java/kr/magicbox/user/adapter/in/web/dto/request/UpdateUserProfileRequest.java Move request + update mapping
services/user/src/main/java/kr/magicbox/user/adapter/in/web/dto/GetUserProfileResponse.java Remove old response mapper
services/user/src/main/java/kr/magicbox/user/adapter/in/web/UserQueryController.java Rename controller + query DTO
services/user/src/main/java/kr/magicbox/user/adapter/in/web/UserProfileCommandController.java Remove old command controller
services/user/src/main/java/kr/magicbox/user/adapter/in/web/UserCommandController.java Add update/withdraw endpoints
services/user/src/main/java/kr/magicbox/user/adapter/in/web/AdminUserCommandController.java Add admin ban/unban endpoints
services/user/src/main/java/kr/magicbox/user/adapter/in/kafka/AuthEventKafkaListener.java Wrap session events in commands
services/user/src/main/java/kr/magicbox/user/adapter/in/grpc/UserGrpcService.java Add nickname RPC + query DTO
services/subscribe/src/main/resources/application-prod.yml Add prod config (grpc/kafka/db)
services/subscribe/src/main/resources/application-local.yml Expand local config (grpc/kafka/db)
services/subscribe/src/main/resources/application-dev.yml Add dev config (grpc/kafka/db)
services/subscribe/src/main/proto/subscribe.proto Add subscribe gRPC contract
services/subscribe/src/main/proto/creator.proto Add creator gRPC client contract
services/subscribe/src/main/java/kr/magicbox/subscribe/global/exception/SystemError.java Add 5xx exception type
services/subscribe/src/main/java/kr/magicbox/subscribe/global/exception/BusinessException.java Add 4xx exception type
services/subscribe/src/main/java/kr/magicbox/subscribe/global/exception/BaseException.java Add base exception with status
services/subscribe/src/main/java/kr/magicbox/subscribe/global/configuration/PropertiesConfiguration.java Enable @ConfigurationPropertiesScan
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/vo/UserId.java Add validated VO
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/vo/SubscriptionId.java Add validated VO
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/vo/SubscriberId.java Add validated VO
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/vo/CreatorId.java Add validated VO
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/exception/SubscriptionNotFoundException.java Add domain exception (404)
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/exception/SelfSubscriptionNotAllowedException.java Add domain exception (400)
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/exception/InvalidFieldException.java Add domain exception (400)
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/exception/AlreadySubscribedException.java Add domain exception (409)
services/subscribe/src/main/java/kr/magicbox/subscribe/domain/aggregate/Subscription.java Add subscription aggregate
services/subscribe/src/main/java/kr/magicbox/subscribe/application/service/UnsubscribeService.java Add unsubscribe use case impl
services/subscribe/src/main/java/kr/magicbox/subscribe/application/service/SubscribeService.java Add subscribe + self-check
services/subscribe/src/main/java/kr/magicbox/subscribe/application/service/IsSubscribedService.java Add subscription query use case
services/subscribe/src/main/java/kr/magicbox/subscribe/application/service/HandleUserRevokedService.java Add user-revoked cleanup
services/subscribe/src/main/java/kr/magicbox/subscribe/application/service/HandleCreatorRevokedService.java Add creator-revoked cleanup
services/subscribe/src/main/java/kr/magicbox/subscribe/application/service/GetSubscriberCountService.java Add subscriber count query
services/subscribe/src/main/java/kr/magicbox/subscribe/application/port/in/UnsubscribeUseCase.java Add unsubscribe port
services/subscribe/src/main/java/kr/magicbox/subscribe/application/port/in/SubscribeUseCase.java Add subscribe port
services/subscribe/src/main/java/kr/magicbox/subscribe/application/port/in/IsSubscribedUseCase.java Add is-subscribed port
services/subscribe/src/main/java/kr/magicbox/subscribe/application/port/in/HandleUserRevokedUseCase.java Add revoked handler port
services/subscribe/src/main/java/kr/magicbox/subscribe/application/port/in/HandleCreatorRevokedUseCase.java Add revoked handler port
services/subscribe/src/main/java/kr/magicbox/subscribe/application/port/in/GetSubscriberCountUseCase.java Add count query port
services/subscribe/src/main/java/kr/magicbox/subscribe/application/dto/query/IsSubscribedQuery.java Add query record
services/subscribe/src/main/java/kr/magicbox/subscribe/application/dto/query/GetSubscriberCountQuery.java Add query record
services/subscribe/src/main/java/kr/magicbox/subscribe/application/dto/command/UnsubscribeCommand.java Add command record
services/subscribe/src/main/java/kr/magicbox/subscribe/application/dto/command/SubscribeCommand.java Add command record
services/subscribe/src/main/java/kr/magicbox/subscribe/application/dto/command/HandleUserRevokedCommand.java Add command record
services/subscribe/src/main/java/kr/magicbox/subscribe/application/dto/command/HandleCreatorRevokedCommand.java Add command record
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/web/exception/handler/GlobalExceptionHandler.java Add REST exception handler
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/web/exception/handler/ErrorResponse.java Add REST error response
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/web/SubscribeCommandController.java Add subscribe REST endpoints
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/security/properties/TrustedIpProperties.java Add trusted IP config props
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/security/filter/UserInfoExtractFilter.java Add X-User-Id principal filter
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/security/configuration/SecurityConfiguration.java Add stateless security chain
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/properties/KafkaRetryProperties.java Add retry properties binding
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/event/UserWithdrawnEvent.java Add withdrawn event DTO
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/event/UserBannedEvent.java Add banned event DTO
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/event/CreatorRevokedEvent.java Add creator revoked event DTO
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/UserEventKafkaListener.java Add user revoke listeners
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/KafkaConfiguration.java Add DLT + retry handler
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/kafka/CreatorEventKafkaListener.java Add creator revoke listener
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/grpc/SubscribeGrpcService.java Add subscribe gRPC server
services/subscribe/src/main/java/kr/magicbox/subscribe/adapter/in/grpc/GrpcExceptionInterceptor.java Add gRPC exception mapping
services/subscribe/build.gradle Add protobuf + service deps
services/creator/src/main/resources/application-prod.yml Add prod config (grpc/kafka/db)
services/creator/src/main/resources/application-local.yml Expand local config (grpc/kafka/db)
services/creator/src/main/resources/application-dev.yml Add dev config (grpc/kafka/db)
services/creator/src/main/proto/user.proto Add user nickname gRPC contract
services/creator/src/main/proto/subscribe.proto Add subscribe gRPC contract
services/creator/src/main/proto/shortform.proto Add shortform gRPC contract
services/creator/src/main/proto/review.proto Add review rating gRPC contract
services/creator/src/main/proto/release.proto Add release gRPC contract
services/creator/src/main/proto/creator.proto Add creator identity gRPC contract
services/creator/src/main/java/kr/magicbox/creator/global/exception/SystemError.java Add 5xx exception type
services/creator/src/main/java/kr/magicbox/creator/global/exception/BusinessException.java Add 4xx exception type
services/creator/src/main/java/kr/magicbox/creator/global/exception/BaseException.java Add base exception with status
services/creator/src/main/java/kr/magicbox/creator/global/configuration/PropertiesConfiguration.java Enable @ConfigurationPropertiesScan
services/creator/src/main/java/kr/magicbox/creator/domain/vo/UserId.java Add validated VO
services/creator/src/main/java/kr/magicbox/creator/domain/vo/Nickname.java Add validated VO + trim
services/creator/src/main/java/kr/magicbox/creator/domain/vo/CreatorId.java Add validated VO
services/creator/src/main/java/kr/magicbox/creator/domain/vo/CreatorCertificationResult.java Add certification result VO
services/creator/src/main/java/kr/magicbox/creator/domain/vo/CreatorCertificationRequest.java Add certification request VO
services/creator/src/main/java/kr/magicbox/creator/domain/vo/CreatorCertificationId.java Add validated VO
services/creator/src/main/java/kr/magicbox/creator/domain/exception/InvalidReviewRatingException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/InvalidFieldException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/InvalidCreatorCertificationReviewStatusException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/CreatorNotFoundException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/CreatorNotBannedException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/CreatorCertificationPendingAlreadyExistsException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/CreatorCertificationNotFoundException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/CreatorCertificationAlreadyReviewedException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/exception/CreatorAlreadyExistsException.java Add domain exception
services/creator/src/main/java/kr/magicbox/creator/domain/event/CreatorUnbannedEvent.java Add domain event
services/creator/src/main/java/kr/magicbox/creator/domain/event/CreatorRevokedEvent.java Add domain event
services/creator/src/main/java/kr/magicbox/creator/domain/event/CreatorDomainEventType.java Add event type enum
services/creator/src/main/java/kr/magicbox/creator/domain/event/CreatorDomainEvent.java Add event interface
services/creator/src/main/java/kr/magicbox/creator/domain/event/CreatorCertificationRejectedEvent.java Add domain event
services/creator/src/main/java/kr/magicbox/creator/domain/event/CreatorCertificationApprovedEvent.java Add domain event
services/creator/src/main/java/kr/magicbox/creator/domain/enums/MagicGenre.java Add genre enum
services/creator/src/main/java/kr/magicbox/creator/domain/enums/CreatorStatus.java Add status enum
services/creator/src/main/java/kr/magicbox/creator/domain/enums/CreatorCertificationStatus.java Add certification status enum
services/creator/src/main/java/kr/magicbox/creator/domain/constants/CreatorPolicyConstants.java Add creator policy constants
services/creator/src/main/java/kr/magicbox/creator/domain/aggregate/CreatorCertification.java Add certification aggregate
services/creator/src/main/java/kr/magicbox/creator/domain/aggregate/Creator.java Add creator aggregate
services/creator/src/main/java/kr/magicbox/creator/application/service/certification/ReviewCreatorCertificationService.java Add review use case
services/creator/src/main/java/kr/magicbox/creator/application/service/certification/GetMyCreatorCertificationsService.java Add my certifications query
services/creator/src/main/java/kr/magicbox/creator/application/service/certification/GetAllPendingCreatorCertificationsService.java Add pending list query
services/creator/src/main/java/kr/magicbox/creator/application/service/certification/CancelCreatorCertificationService.java Add cancel use case
services/creator/src/main/java/kr/magicbox/creator/application/service/certification/ApplyCreatorCertificationService.java Add apply use case
services/creator/src/main/java/kr/magicbox/creator/application/service/WithdrawCreatorService.java Add withdraw + revoked event
services/creator/src/main/java/kr/magicbox/creator/application/service/UpdateCreatorProfileService.java Add profile update use case
services/creator/src/main/java/kr/magicbox/creator/application/service/UnbanCreatorService.java Add unban + event publish
services/creator/src/main/java/kr/magicbox/creator/application/service/SearchCreatorsService.java Add search creators use case
services/creator/src/main/java/kr/magicbox/creator/application/service/HandleUserWithdrawnService.java Add withdrawn handling
services/creator/src/main/java/kr/magicbox/creator/application/service/HandleUserBannedService.java Add banned handling
services/creator/src/main/java/kr/magicbox/creator/application/service/GetMyCreatorProfileService.java Add my profile query
services/creator/src/main/java/kr/magicbox/creator/application/service/GetCreatorProfileService.java Add public profile query
services/creator/src/main/java/kr/magicbox/creator/application/service/GetAllCreatorsService.java Add creators list query
services/creator/src/main/java/kr/magicbox/creator/application/service/CheckCreatorAndSubscriberSamePersonService.java Add self-check query
services/creator/src/main/java/kr/magicbox/creator/application/service/BanCreatorService.java Add ban + revoke event
services/creator/src/main/java/kr/magicbox/creator/application/port/in/* Add creator use case ports
services/creator/src/main/java/kr/magicbox/creator/application/dto/result/* Add creator result DTOs
services/creator/src/main/java/kr/magicbox/creator/application/dto/query/* Add creator query DTOs
services/creator/src/main/java/kr/magicbox/creator/application/dto/command/* Add creator command DTOs
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/validation/CursorSizeValidator.java Add cursor size validator
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/validation/CursorSize.java Add cursor size annotation
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/exception/handler/GlobalExceptionHandler.java Add REST exception handler
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/exception/handler/ErrorResponse.java Add REST error response
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/dto/response/* Add REST response DTOs
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/dto/request/* Add REST request DTOs
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/constants/CursorConstants.java Add paging constants
services/creator/src/main/java/kr/magicbox/creator/adapter/in/web/*Controller.java Add creator REST controllers
services/creator/src/main/java/kr/magicbox/creator/adapter/in/security/* Add trusted-IP auth wiring
services/creator/src/main/java/kr/magicbox/creator/adapter/in/kafka/* Add revoke listeners + DLT
services/creator/src/main/java/kr/magicbox/creator/adapter/in/grpc/CreatorGrpcService.java Add creator gRPC server
services/creator/build.gradle Add protobuf + service deps
services/auth/src/main/resources/application-local.yml Add Kafka consumer config
services/auth/src/main/java/kr/magicbox/auth/domain/exception/UserInactiveException.java Add inactive exception
services/auth/src/main/java/kr/magicbox/auth/domain/exception/UserBannedException.java Add banned exception
services/auth/src/main/java/kr/magicbox/auth/domain/exception/InActiveUserException.java Remove old exception
services/auth/src/main/java/kr/magicbox/auth/application/service/RefreshTokenService.java Switch refresh to command
services/auth/src/main/java/kr/magicbox/auth/application/service/LogoutService.java Rename exception + DTO pkgs
services/auth/src/main/java/kr/magicbox/auth/application/service/LoginService.java Move DTOs to cmd/result
services/auth/src/main/java/kr/magicbox/auth/application/service/HandleUserWithdrawnService.java Add withdraw event handler
services/auth/src/main/java/kr/magicbox/auth/application/service/HandleUserBannedService.java Add ban event handler
services/auth/src/main/java/kr/magicbox/auth/application/port/in/* Update ports for DTO pkgs
services/auth/src/main/java/kr/magicbox/auth/application/dto/result/* Move result DTO packages
services/auth/src/main/java/kr/magicbox/auth/application/dto/command/* Add/move command DTOs
services/auth/src/main/java/kr/magicbox/auth/application/dto/LogoutCommand.java Remove old command record
services/auth/src/main/java/kr/magicbox/auth/adapter/in/web/exception/handler/ErrorResponse.java Add builder-based response
services/auth/src/main/java/kr/magicbox/auth/adapter/in/web/dto/response/AccessTokenResponse.java Add response record (new pkg)
services/auth/src/main/java/kr/magicbox/auth/adapter/in/web/dto/request/LoginRequest.java Move request + update import
services/auth/src/main/java/kr/magicbox/auth/adapter/in/web/dto/AccessTokenResponse.java Remove old response mapper
services/auth/src/main/java/kr/magicbox/auth/adapter/in/web/AuthCommandController.java Update DTO usage + refresh cmd
services/auth/src/main/java/kr/magicbox/auth/adapter/in/security/oauth2/OAuth2LoginSuccessHandler.java Update UserResult import
services/auth/src/main/java/kr/magicbox/auth/adapter/in/kafka/* Add revoke listeners + DLT
services/auth/build.gradle Add Kafka dependencies
docker-compose.local.yml Change kafka-ui port mapping
.github/workflows/sonarcloud-analyze.yml Compile + set sonar binaries
.github/prompts/pr-automation.prompt.md Add PR automation prompt

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return UpdateUserProfileCommand.builder()
.nickname(nickname)
.userId(userId)
.nickname(Nickname.of(nickname))
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nickname 필드가 optional(예: null 허용)인 요청으로 보이는데, 현재 Nickname.of(nickname)를 무조건 호출해서 nickname == null인 부분 수정(PATCH) 요청에서 NPE/InvalidFieldException이 발생할 수 있습니다. nickname이 null이면 command에도 null로 전달하고, 값이 있을 때만 Nickname.of(...)로 변환하도록 조건 분기하세요.

Suggested change
.nickname(Nickname.of(nickname))
.nickname(nickname != null ? Nickname.of(nickname) : null)

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +36
public SecurityFilterChain filterChain(HttpSecurity http) {
return http
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(new UserInfoExtractFilter(trustedIpProperties), UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll())
.build();
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 anyRequest().permitAll()이라서 신뢰되지 않은 IP이거나 X-User-Id 헤더가 없는 요청도 그대로 컨트롤러까지 통과합니다. 그런데 /api/subscribe/** 같은 엔드포인트는 @AuthenticationPrincipal UserId userId를 사용하며 내부에서 userId.value()를 호출하므로, 인증 정보가 없는 경우 500(NPE)로 터질 수 있습니다. permitAll 대신 최소한 구독/구독취소 같은 command 엔드포인트는 authenticated()로 보호하거나, 필터에서 신뢰되지 않은 요청/헤더 누락 시 401/403으로 명확히 차단하도록 변경하는 것이 필요합니다.

Copilot uses AI. Check for mistakes.
java-version: '21'

- name: Compile Java classes
run: ./services/auth/gradlew --no-daemon classes
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sonar 분석 대상이 여러 Java 서비스(creator/subscribe/user/auth)인데, 현재는 services/auth만 컴파일해서 다른 서비스의 build/classes/java/main이 생성되지 않을 수 있습니다. 그 결과 sonar.java.binaries가 auth만 포함되거나(또는 일부만 포함), 나머지 모듈은 심볼 해석 실패로 분석 품질이 크게 떨어질 수 있습니다. CI에서 Sonar 돌리기 전에 분석 대상 서비스들을 모두 classes까지 빌드(예: 각 서비스 gradlew classes 실행 또는 루트 멀티모듈 빌드)하도록 조정하세요.

Suggested change
run: ./services/auth/gradlew --no-daemon classes
run: |
for service in creator subscribe user auth; do
if [ -x "./services/${service}/gradlew" ]; then
"./services/${service}/gradlew" --no-daemon classes
fi
done

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +36
SONAR_JAVA_BINARIES=$(find . -type d -path "*/build/classes/java/main" | sed 's|^\./||' | paste -sd "," -)
echo "SONAR_PROJECT_KEY=$SONAR_PROJECT_KEY" >> $GITHUB_ENV
echo "SONAR_JAVA_BINARIES=$SONAR_JAVA_BINARIES" >> $GITHUB_ENV
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sonar 분석 대상이 여러 Java 서비스(creator/subscribe/user/auth)인데, 현재는 services/auth만 컴파일해서 다른 서비스의 build/classes/java/main이 생성되지 않을 수 있습니다. 그 결과 sonar.java.binaries가 auth만 포함되거나(또는 일부만 포함), 나머지 모듈은 심볼 해석 실패로 분석 품질이 크게 떨어질 수 있습니다. CI에서 Sonar 돌리기 전에 분석 대상 서비스들을 모두 classes까지 빌드(예: 각 서비스 gradlew classes 실행 또는 루트 멀티모듈 빌드)하도록 조정하세요.

Copilot uses AI. Check for mistakes.
Comment on lines 34 to +38
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(AccessTokenResponse.from(result));
.body(AccessTokenResponse.builder()
.accessToken(result.accessToken().accessTokenValue())
.build());
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AccessTokenResponse 매핑 로직이 login/refresh에서 중복되고 있습니다. 기존에 삭제된 AccessTokenResponse.from(TokenResult) 같은 팩토리 메서드를 kr.magicbox.auth.adapter.in.web.dto.response.AccessTokenResponse에 다시 추가하거나, 공통 private 메서드로 추출해서 변경 시점(필드 추가/변경)에 한 곳만 수정하도록 정리하는 편이 유지보수에 유리합니다.

Copilot uses AI. Check for mistakes.
Comment on lines 46 to +50
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body(AccessTokenResponse.from(result));
.body(AccessTokenResponse.builder()
.accessToken(result.accessToken().accessTokenValue())
.build());
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AccessTokenResponse 매핑 로직이 login/refresh에서 중복되고 있습니다. 기존에 삭제된 AccessTokenResponse.from(TokenResult) 같은 팩토리 메서드를 kr.magicbox.auth.adapter.in.web.dto.response.AccessTokenResponse에 다시 추가하거나, 공통 private 메서드로 추출해서 변경 시점(필드 추가/변경)에 한 곳만 수정하도록 정리하는 편이 유지보수에 유리합니다.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +25
public void subscribe(SubscribeCommand command) {
if (creatorIdentityQueryPort.isCreatorAndSubscriberSamePerson(command.creatorId(), command.subscriberId())) {
throw new SelfSubscriptionNotAllowedException();
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 설명은 subscribe↔creator gRPC 및 자기 구독 차단을 중심으로 되어 있지만, 이 PR에는 user/auth/creator 전반의 DTO 패키지 재구성, Kafka 리스너/설정 추가, REST 컨트롤러 경로 변경 등(잠재적 API breaking change 포함) 범위가 함께 포함되어 있습니다. 리뷰/릴리즈 관점에서 영향 범위가 큰 만큼, PR 본문 변경 사항 요약에 user/auth/creator 쪽 변경(특히 REST 경로 변경 여부)을 명시하거나 PR을 분리하는 것이 필요합니다.

Copilot uses AI. Check for mistakes.
@lian2945 lian2945 changed the title Feat/49 feat(subscribe): 구독 서비스 생성 Apr 8, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 8, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants