[3주차] 도메인 모델 & 서비스 구현 및 SOLID/DDD 리팩토링 - 엄인국 #99
[3주차] 도메인 모델 & 서비스 구현 및 SOLID/DDD 리팩토링 - 엄인국 #99ukukdin wants to merge 2 commits intoLoopers-dev-lab:ukukdinfrom
Conversation
- Domain: User 모델/VO, 공통 AggregateRoot/DomainEvent 구현 - Application: User UseCase 및 Service 구현 - Infrastructure: User JPA Entity/Repository, PasswordEncoder 구현 - Interfaces: User Controller/DTO, 인증 Interceptor, WebMvcConfig - Support: GlobalExceptionHandler, ErrorType 개선 - Test: User 전 레이어 Unit/Integration/E2E 테스트 - Docs: 설계 문서 및 설계 결정 근거 문서 작성
- Domain: Brand/Product/Like/Order 모델, VO, 이벤트 구현 - Application: 각 도메인 UseCase 및 Service 구현 - Infrastructure: JPA Entity 및 Repository 구현체 - Interfaces: Controller 및 DTO 구현 - Test: 전 도메인 Unit/Integration/E2E 테스트
|
Important Review skippedToo many files! This PR contains 167 files, which is 17 over the limit of 150. ⛔ Files ignored due to path filters (6)
📒 Files selected for processing (167)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
|
|
✅ Actions performedFull review triggered. |
|
@CodeRabbit 리뷰 진행사항 확인가능? |
|
Tip For best results, initiate chat on the files or code changes.
별도의 진행률 표시 UI는 제공되지 않으며, 리뷰 완료 시 코멘트 형태로 결과가 게시된다. |
|
@CodeRabbit 리뷰가 안달렸어 파일 갯수가 너무 많거나 용량이 너무 큰가? |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 26136
🔍 원인 분석파일 수 제한 초과로 인한 자동 스킵이 발생했다.
CodeRabbit이 PR을 열었을 때 자동으로 다음 메시지를 남겼다:
이후 ✅ 해결 방법1. PR 분할 (권장)현재 PR을 도메인별로 분할한다:
각 PR이 50개 파일 이하로 유지되면 자동 리뷰가 정상 동작한다. 2. 테스트 파일 제외
reviews:
path_filters:
- "!**/test/**"
- "!**/*Test.java"이 경우 약 60개 테스트 파일이 제외되어 107개 파일만 리뷰 대상이 된다. 3. 수동 파일 선택 리뷰Files changed 탭에서 핵심 파일(Domain, Application 계층)에 직접 코멘트를 남겨 부분 리뷰를 요청할 수 있다. 현재 상태에서는 파일 수를 줄이지 않는 한 자동 전체 리뷰가 불가능하다. 위 방법 중 하나를 선택해 진행하길 권장한다. |
📌 Summary
🧭 Context & Decision
문제 정의
선택지와 결정
Aggregate 간 참조 방식
Product내에Brand필드)Product내에Long brandId)Aggregate 간 정합성 보장 (좋아요 수, 재고 복원)
ProductLikedEvent,OrderCancelledEvent등으로 Aggregate 간 결합도 최소화조회 전용 포트 (Like + Product + Brand 조합 조회)
A:
LikeRepository(domain)에 조회 DTO 포함B: Application 계층에
LikeProductReadPort인터페이스 분리최종 결정: B — DIP 준수.
LikeQueryService(app)→LikeProductReadPort(app)←LikeRepositoryImpl(infra)트레이드오프: 이벤트 기반 처리는 같은 트랜잭션 내에서 동작하므로 강한 일관성을 유지하지만, 향후 비동기 이벤트로 전환 시 추가 작업 필요
추후 개선 여지: Spring ApplicationEvent → 비동기 이벤트(Kafka 등)로 전환 가능한 구조
🏗️ Design Overview
변경 범위
@Data→@Getter @EqualsAndHashCode(VO 불변식 보호)WrongPasswordCountVO 제거 (과도한 원시값 래핑)LikeWithProduct도메인 DTO →LikeProductReadPortApplication 포트로 이동주요 컴포넌트 책임
Domain Layer
AggregateRootProductdecreaseStock), 좋아요 증감, Soft DeleteOrderisCancellable), 주문 취소 이벤트 발행ProductPricingStockdecrease()/hasEnough()Application Layer
ProductService(Command)findActiveById()사용ProductQueryService(Query)findAllByIds()배치LikeService(Command)LikeQueryService(Query)LikeProductReadPort의존OrderService(Command)LikeEventHandlerProductLikedEvent/ProductUnlikedEvent→ likeCount 증감BrandDeletedEventHandlerBrandDeletedEvent→ 하위 상품 Cascade Soft DeleteOrderCancelledEventHandlerOrderCancelledEvent→ 재고 복원🔁 Flow Diagram
Main Flow — 주문 생성
sequenceDiagram autonumber participant Client participant OrderController participant OrderService participant ProductRepo participant OrderRepo Client->>OrderController: POST /api/v1/orders OrderController->>OrderService: createOrder(userId, command) loop 각 주문 상품 OrderService->>ProductRepo: findActiveByIdWithLock(productId) ProductRepo-->>OrderService: Product (비관적 락) OrderService->>OrderService: product.decreaseStock(quantity) OrderService->>ProductRepo: save(decreased) end OrderService->>OrderService: Order.create(userId, orderLines, deliveryInfo, paymentMethod) OrderService->>OrderRepo: save(order) OrderRepo-->>OrderService: saved Order OrderService-->>OrderController: void OrderController-->>Client: 201 CreatedMain Flow — 좋아요 (이벤트 기반 정합성)
sequenceDiagram autonumber participant Client participant LikeController participant LikeService participant LikeRepo participant EventPublisher participant LikeEventHandler participant ProductRepo Client->>LikeController: POST /api/v1/products/{id}/likes LikeController->>LikeService: like(userId, productId) LikeService->>ProductRepo: findActiveById(productId) ProductRepo-->>LikeService: Product (존재 확인) LikeService->>LikeRepo: existsByUserIdAndProductId() LikeRepo-->>LikeService: false (중복 아님) LikeService->>LikeService: Like.create(userId, productId) LikeService->>LikeRepo: save(like) LikeService->>EventPublisher: publishEvents(like) EventPublisher->>LikeEventHandler: handle(ProductLikedEvent) LikeEventHandler->>ProductRepo: findById(productId) LikeEventHandler->>LikeEventHandler: product.increaseLikeCount() LikeEventHandler->>ProductRepo: save(updated) LikeService-->>LikeController: void LikeController-->>Client: 200 OKException Flow — 재고 부족
🤖 Generated with Claude Code