Skip to content

Conversation

@codrin2
Copy link
Member

@codrin2 codrin2 commented Aug 31, 2025

✅ Check List

  • Have all tests passed?
  • Have all commits been pushed?
  • Did you verify the target branch for the merge?
  • Did you assign the appropriate assignee(s)?
  • Did you set the correct label(s)?

codrin2 added 30 commits August 22, 2025 09:36
[REFACTOR] isNew 로직 개선을 통한 불필요한 select 쿼리 제거
- JPQL update 결과가 0일 경우 ConflictException(409)을 발생시켜 재고 부족 상황을 명시적으로 처리
- 기존에는 무조건 상품을 조회하고 주문 생성까지 진행했으나, update 실패 여부를 확인해 예외 대응 가능하도록 개선
[REFACTOR] update 기반 재고 차감 로직 도입으로 X-Lock 보유 시간 최소화
…로 통합 #27

- OrderController 내부의 orderQueryFacade 의존성을 제거하고 orderFacade 단일 책임으로 통합
- placeOrder, getOrderDetail API 응답을 OrderDetailBundle 기반으로 변경하여 order와 productList 동시 반환
- OrderDetailResponse.from() 메서드 시그니처 변경에 따른 사용 방식 반영
- 주문 생성 과정에서 제품 엔터티 리스트를 함께 전달할 수 있도록 OrderCreateCommand에 productList 필드 추가
- OrderDetailResponse 생성 시 order 내부 item의 product 정보를 직접 참조하던 방식에서 productList 기반 매핑 방식으로 전환
- from 메서드에 productList를 전달받아 ID 기준으로 제품 정보를 매핑함으로써 외부 주입 방식으로 의존성 명시
- 일관된 응답 구성을 위해 productName 추출을 product 객체에서 분리하여 처리
- 일부 매핑 실패 가능성을 고려해 items 필드를 List<Item?>로 정의
…답 구조 개선 #27

- 주문 생성 시 제품 존재 여부를 검증하고, 전체 productList를 함께 반환하도록 로직 개선
- getOrderDetail 응답 시 주문에 포함된 상품 목록을 조회하여 OrderDetailBundle로 통합 반환
- OrderCreateCommand 팩토리 호출 방식 변경: userId와 OrderCreateRequest 외에 productList 추가 전달
- UserService.getUserById → checkUserExists로 의미 명확화
- OrderItem 엔티티에서 @manytoone Product 연관 매핑 제거 후 productId 필드로 대체
- 주문 생성 시점에 product.getPrice()를 호출하지 않고, 외부에서 전달받은 priceAtPurchase를 직접 주입하는 방식으로 변경
- 연관 엔티티 로딩 지연 및 복잡도 축소를 통해 성능과 응집도 개선
- findOrderByUserIdAndId → findOrderByIdAndUserId로 파라미터 순서 및 네이밍 일관성 정비
- @entitygraph에서 items.product fetch 제거하여 연관 엔티티 로딩 최소화
- Product 정보는 facade 단에서 productId 기반으로 개별 조회하도록 책임 분리
- 전체 fetch depth 감소로 성능 및 쿼리 효율성 개선
- createOrder 내부에서 Product 조회 로직 제거하고 productList를 미리 주입받아 처리하는 방식으로 리팩토링
- productList를 Map<Long, Product>으로 변환하여 productId 기준으로 빠르게 접근 가능하도록 개선
- addItemsToOrder 메서드에서 productRepository.deductStock 호출 후 재고 부족 시 ConflictException 처리
- OrderItem 생성 시 product 참조 대신 productId와 priceAtPurchase를 명시적으로 주입하여 순수 도메인 로직 유지
- 기존 checkProductsExists 메서드를 getProductsExists로 분리하여 제품 존재 여부 검증과 동시에 Product 리스트 반환
- 중복 로직 방지를 위해 checkProductsExists는 getProductsExists 내부 위임 방식으로 변경
- 주문 생성 등에서 사전 검증과 동시에 Product 리스트가 필요한 흐름을 지원하기 위한 구조 개선
- productIds 중복 제거를 위해 Set으로 변환하여 불필요한 조회 방지
- 주문 상세 응답 시 Order와 관련된 Product 목록을 함께 묶어 반환할 수 있도록 OrderDetailBundle 도입
- 주문 단건 상세 및 커서 기반 목록 조회 기능을 OrderQueryService로 분리
- findOrderByIdAndUserId 사용하여 사용자 접근 제어 포함한 상세 조회 처리
- 커서 기반 페이지네이션을 PageRequest와 함께 적용하여 성능 최적화된 주문 목록 조회 지원
- 주문 쓰기 기능과 읽기 기능을 명확히 분리하여 도메인 계층의 SRP(단일 책임 원칙) 적용
- addItemsToOrder 내부에서 productMapById 조회를 선행하여 존재하지 않는 product에 대한 사전 검증 수행
- 기존에는 재고 차감 후 product 조회하던 흐름을 검증 → 차감 순서로 변경하여 예외 메시지 정확도 향상
- IllegalStateException → IllegalArgumentException으로 예외 유형 통일성 부여
- productFixture에서 category 관련 로직 제거 및 의존성 단순화
- 기존 categoryFixture와 addCategory 호출 제거로 테스트 유연성 및 집중도 향상
- OrderCreateCommand 생성 시 productList 주입 방식에 맞춰 테스트 구조 전면 수정
- categoryFixture 제거 및 productFixture 간소화로 불필요한 도메인 의존도 축소
codrin2 added 24 commits August 30, 2025 21:33
- OUTBOX_MESSAGE_DEAD 항목 추가: 아웃박스 메시지 재시도 실패 상황을 명확히 전달
- 포맷 문자열 포함: eventType 및 id 정보를 로그나 예외 메시지에 출력 가능
- Outbox 장애 추적 및 운영 편의성 향상 목적
- 이벤트 전송을 위한 OutboxMessage JPA 엔티티 정의
- 상태 관리 필드(status, tryCount) 및 인덱스(idx_outbox_status) 설정
- 전송 성공/실패/최종 실패(DEAD) 상태 전이 로직 제공 (markSendSuccess, markSendFail)
- 최대 재시도 횟수는 3회로 제한
- 정적 팩토리 메서드(init)를 통해 초기 상태(INIT)로 메시지 생성
- 주문 항목을 그대로 반영하여 저장, 별도의 중복 병합 및 재고 차감 없이 수행
- OrderItem 생성 시 Product 객체에서 필요한 정보를 직접 추출
- 최대 100건 단위로 INIT, SEND_FAIL 상태 메시지 조회 및 처리
- @transactional(propagation = NOT_SUPPORTED)로 트랜잭션 분리 수행
- 각 메시지는 outboxMessageHandler.handleInNewTx를 통해 별도 트랜잭션으로 처리
- 안정적인 재전송 및 메시지 상태 업데이트를 위한 배치 처리 컴포넌트
- 1분 간격으로 OutboxBatchJob 실행
- 재전송 및 상태 갱신을 위한 주기적 메시지 처리 트리거 역할
- 각 메시지를 새로운 트랜잭션(REQUIRES_NEW)에서 안전하게 처리
- 전송 성공 시 markSendSuccess(), 실패 시 markSendFail()로 상태 전이
- 최종 실패(DEAD) 상태일 경우 에러 로그 출력으로 운영 대응 가능
- 전송 로직 위임을 위한 outboxMessageRouter.route(outboxMessage) 호출
- eventType 기준으로 처리할 핸들러 분기 수행
- "INVENTORY_DEDUCTION_REQUESTED" 이벤트에 대해 InventoryEventHandler로 위임
- payload(JSON)를 InventoryDeductionRequestedEvent로 역직렬화하여 처리
- 정의되지 않은 이벤트 타입에 대해 IllegalStateException 발생 처리
- InventoryDeductionRequestedEvent 수신 시 각 항목에 대해 재고 차감 수행
- InventoryService.deductInventory 호출을 통해 실제 DB 재고 반영
- @transactional 적용으로 이벤트 처리의 일관성 보장
- BEFORE_COMMIT 시점에 InventoryDeductionRequestedEvent 직렬화 후 Outbox 메시지 저장
- 직렬화 또는 저장 실패 시 Redis 재고 복구 시도 및 예외 로그 처리
- Outbox 패턴을 활용한 비동기 재고 차감 이벤트 전파 기반 구성
- 장애 시 일관성 유지를 위한 재고 복구(restoreStocksBatch) 로직 포함
[REFACTOR] 일괄 주문 기능 개선 및 Outbox 기반 재고 차감 이벤트 처리 도입
@coderabbitai
Copy link

coderabbitai bot commented Aug 31, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary or @coderabbitai 요약 to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@codrin2 codrin2 self-assigned this Aug 31, 2025
@codrin2 codrin2 merged commit a7d234f into prod Aug 31, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants