[Volume 3] 도메인 모델링 및 구현 - 양권모#123
[Volume 3] 도메인 모델링 및 구현 - 양권모#123Praesentia-YKM wants to merge 23 commits intoLoopers-dev-lab:Praesentia-YKMfrom
Conversation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- spring-security-crypto 의존성 추가 (BCryptPasswordEncoder) - PasswordEncoderConfig 빈 등록 - ErrorType에 UNAUTHORIZED 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 4개 VO 구현 (LoginId, Password, MemberName, Email) - MemberModel 엔티티 (@Embedded VO, matchesPassword 행위 메서드) - MemberRepository 인터페이스 및 JPA 구현 - ErrorType 도메인 에러 코드 추가 (10개) - 단위 테스트: VO 검증 + MemberModel + Repository 통합테스트 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- MemberSignupService (중복 체크, 비밀번호 암호화, 저장) - 단위 테스트: Mock을 활용한 동작 검증 - 통합 테스트: 실제 DB 연동 검증 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- MemberAuthService (loginId/password 검증, 회원 조회) - 단위 테스트: Mock을 활용한 동작 검증 - 통합 테스트: 실제 DB 연동 검증 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- MemberPasswordService (현재 비밀번호 검증, 새 비밀번호 암호화 저장) - 단위 테스트: Mock을 활용한 동작 검증 - 통합 테스트: 실제 DB 연동 검증 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- MemberFacade (signup, getMyInfo, changePassword) - MemberInfo 응답 DTO (이름 마스킹 포함) - MemberV1Controller (POST /members, GET /me, PATCH /me/password) - MemberV1Dto (SignupRequest, MemberResponse, ChangePasswordRequest) - E2E 테스트: MemberV1ApiE2ETest - MemberFacadeTest 단위 테스트 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Example/Core 테스트 DisplayName 자연스럽게 개선 - TEST-README.md 테스트 체크리스트 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fix : 예제 테스트 코드 오류 해결을 위한 testcontainers 버전 업
- 기능요구정의서 - 유비쿼터스 언어 정의서 - 시퀀스 다이어그램 - 클래스 다이어그램 - erd
- BrandName VO: 빈값/null/공백 검증, equals/hashCode
- BrandModel Entity: BaseEntity 상속, soft delete
- BrandService: 등록(중복체크), 조회, 수정(중복체크), 삭제, 목록
- BrandRepository 인터페이스 + JPA 구현체
- Customer API: GET /api/v1/brands/{brandId}
- Admin API: POST/GET/PUT/DELETE /api-admin/v1/brands
- 테스트: BrandNameTest, BrandModelTest, BrandServiceTest,
BrandServiceIntegrationTest, BrandV1ApiE2ETest
- HTTP 테스트 파일: brand-v1.http
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Money VO, ProductModel, StockModel 엔티티 구현 - ProductService, StockService 도메인 서비스 구현 - Customer/Admin API 컨트롤러 및 DTO 구현 - 브랜드 삭제 시 소속 상품 연쇄 soft delete 구현 - Unit/Integration/E2E 테스트 작성 (51개 Unit 테스트 통과) - HTTP 수동 테스트 파일 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feature/week3 product stock
- LikeModel 엔티티 (userId, productId, soft delete)
- LikeService, LikeRepository, LikeRepositoryImpl
- LikeFacade: 좋아요 등록/취소 멱등성 처리 + likeCount 비정규화
- LikeV1Controller: POST/DELETE /api/v1/products/{productId}/likes, GET /api/v1/users/{userId}/likes
- ProductModel: incrementLikeCount/decrementLikeCount 추가 (음수 방지)
- ApiControllerAdvice: MissingRequestHeaderException 핸들러 추가
- 삭제된 상품 좋아요 목록 제외 (JPQL 서브쿼리)
- Unit 6 + Integration 9 + E2E 7 테스트 전체 통과 (총 222개/0실패)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- @LoginMember: ArgumentResolver로 X-Loopers-LoginId/Pw 헤더 인증 후 MemberModel 주입 - @adminuser: X-Loopers-Ldap 헤더 검증 후 AdminInfo 주입 - WebMvcConfig에 ArgumentResolver 등록 - MemberFacade에서 인증 책임 제거 (ArgumentResolver로 이동) - 전체 컨트롤러 리팩토링: 반복적인 인증 보일러플레이트 제거 - Facade 레이어 분리: BrandFacade, ProductFacade, LikeWithProduct 추가 - E2E 테스트에 어드민 LDAP 헤더 적용 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- OrderModel/OrderItemModel 엔티티, OrderStatus 상태 전이 - OrderService, OrderFacade (주문 생성 시 재고 차감 연동) - OrderV1Controller (고객), OrderAdminV1Controller (어드민) - 단위/통합/E2E 테스트 포함 (239 tests, 0 failures) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
auth-annotation(인증인가+DDD리팩토링) + order(주문CRUD) 병합 - 충돌 해결: BrandFacade, ProductService, ApiControllerAdvice - OrderFacadeIntegrationTest: productFacade.register() 사용으로 변경 - OrderV1ApiE2ETest: admin 헤더 추가, /api/v1/users 경로 반영 - ProductServiceTest: 제거된 getBrandNamesByIds 테스트 삭제 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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 |
📌 Summary
🧭 Context & Decision
문제 정의
@RequestHeader로 컨트롤러마다 산재하여 중복 발생 및 변경 취약성 존재.@LoginMember,@AdminUser를 통한 인증 로직 일원화.주요 의사결정 및 트레이드오프
BaseEntity패턴과의 일관성 유지.LikeFacade에서 직접 처리하여 단순성 확보.BrandFacade에서 연쇄 Soft Delete로 정합성 유지.🏗️ Design Overview
@LoginMember,@AdminUserLikeFacade,LikeModellikeCount동기화, Soft Delete 처리OrderFacade,OrderModelBrandFacadeProductFacade🔁 Flow Diagram
1. 주문 생성 (Order Flow)
sequenceDiagram autonumber participant Client as Customer participant Ctrl as OrderV1Controller participant Facade as OrderFacade participant PS as ProductService participant SS as StockService participant OS as OrderService Client->>Ctrl: POST /api/v1/orders (@LoginMember) Ctrl->>Facade: placeOrder(userId, commands) rect rgb(230, 240, 255) Note right of Facade: @Transactional loop 각 주문 상품 Facade->>PS: getProduct(productId) Note over PS: 삭제된 상품 → NOT_FOUND Facade->>SS: getByProductId → stock.decrease() Note over SS: 재고 부족 → BAD_REQUEST (전체 롤백) end Facade->>Facade: 총액 서버 계산 (Money.add/multiply) Facade->>OS: Order + OrderItem 저장 (스냅샷) end OS-->>Facade: OrderResult Facade-->>Ctrl: OrderResult Ctrl-->>Client: 200 OK (주문 정보)2. 좋아요 토글 (Like Flow)
sequenceDiagram autonumber participant Client as Customer participant Facade as LikeFacade participant PS as ProductService participant LS as LikeService Client->>Facade: like(userId, productId) rect rgb(230, 240, 255) Note right of Facade: @Transactional Facade->>PS: getProduct (삭제 확인) Facade->>LS: findByUserIdAndProductId alt 좋아요 없음 Facade->>LS: save(new LikeModel) Facade->>PS: product.incrementLikeCount() else 삭제된 좋아요 존재 Facade->>LS: restore() Facade->>PS: product.incrementLikeCount() else 이미 활성 좋아요 Note over Facade: 무시 (멱등성) end end Facade-->>Client: 200 OK3. 브랜드 삭제 연쇄 (Brand Cascade Flow)
sequenceDiagram autonumber participant Admin participant Facade as BrandFacade participant BS as BrandService participant PS as ProductService Admin->>Facade: delete(brandId) (@AdminUser) rect rgb(230, 240, 255) Note right of Facade: @Transactional Facade->>BS: delete(brandId) → soft delete Facade->>PS: deleteAllByBrandId(brandId) loop 소속 상품 전체 PS->>PS: product.delete() → soft delete end end Facade-->>Admin: 200 OKsequenceDiagram autonumber participant C as Customer participant A as Admin participant F as ProductFacade participant PS as ProductService participant SS as StockService rect rgb(232, 245, 233) Note over C,SS: Customer 상품 목록 조회 (상태 중심) C->>F: GET /api/v1/products?sort=likes_desc F->>PS: 상품 목록 조회 (삭제 제외, 정렬) F->>SS: 재고 정보 조합 Note over F: 재고 상태 변환 로직<br/>>10: IN_STOCK<br/>1~10: LOW_STOCK<br/>0: OUT_OF_STOCK F-->>C: 200 OK (상품 목록 + 재고 상태) end rect rgb(227, 242, 253) Note over A,SS: Admin 상품 목록 조회 (수량 중심) A->>F: GET /api-admin/v1/products (@AdminUser) F->>PS: 상품 목록 조회 (삭제 포함 가능) F->>SS: 재고 정보 조합 Note over F: 정확한 재고 수량 노출 F-->>A: 200 OK (상품 목록 + 실제 재고 수량) end