Skip to content

[Feature] 카카오 Gift Biz 기프티콘 발송 및 팅 거래 기록 추가 - #80

Open
Sehi55 wants to merge 49 commits into
developfrom
feat/gifticon
Open

[Feature] 카카오 Gift Biz 기프티콘 발송 및 팅 거래 기록 추가#80
Sehi55 wants to merge 49 commits into
developfrom
feat/gifticon

Conversation

@Sehi55

@Sehi55 Sehi55 commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

작업 내용

기프티콘 상품 관리

  • 카카오 Gift Biz 활성 템플릿 목록 조회 및 DB 동기화
  • 스케줄러를 통한 일 1회 자동 동기화
  • 관리자 화면에서 수동 동기화 지원
  • 동기화에서 사라진 상품은 lastSyncedAt 기준으로 비활성화
  • 브랜드별 조회 및 커서 기반 무한 스크롤 지원
  • 템플릿 토큰이 등록된 상품만 사용자 기프티콘 목록에 노출

기프티콘 템플릿 토큰 관리

  • 관리자 화면에서 상품별 템플릿 토큰 등록 및 수정
  • 템플릿 토큰 암호화 저장
  • 토큰 변경 관리자 및 변경 이력 기록
  • 주문에는 토큰을 복사하지 않고 발송 시 상품의 최신 토큰 사용

메시지 요청 기프티콘

  • 메시지 요청에 선택적으로 gifticonProductId 연결
  • 요청 생성 시 기프티콘 가격만큼 유상팅 차감 및 HELD 처리
  • 요청 수락 시 CAPTURED 처리 후 카카오 Gift Biz 주문 생성
  • 요청 거절 시 RELEASED 처리 후 보류했던 유상팅 복구
  • 카카오 주문을 비동기로 요청하고 실패 시 재시도
  • 발신자명을 만나봄 - {프로필 닉네임} 형식으로 전달
  • externalOrderIdexternalKey를 메시지 요청 기준으로 생성

팅 거래 원장

  • ting_transaction 테이블 추가
  • 유상팅과 이벤트팅 거래 이력 분리
  • 지급·차감·보류·확정·복구 내역 기록
  • 동일 거래의 중복 처리를 방지하기 위한 멱등성 키 적용
  • 이벤트팅 우선 사용 후 부족분을 유상팅에서 차감하는 혼합 결제 지원
  • 관리자 조정, 가입 보상, 메시지, 호감, 프로필 관련 팅 거래 기록

Summary by CodeRabbit

  • 새 기능
    • 기프티콘 상품을 조회하고 카테고리·검색·커서 기반 페이지로 탐색할 수 있습니다.
    • 메시지에 기프티콘을 첨부해 결제 보류·승인·해제 후 주문할 수 있습니다.
    • 주문 실패 시 자동 재시도와 외부 기프티콘 발송을 지원합니다.
    • 관리자 화면에서 상품 동기화, 토큰 등록·변경, 상태 필터링을 제공합니다.
  • 개선
    • 팅 지급·사용·조정 내역이 거래 기록으로 남습니다.
    • 기프티콘 토큰을 암호화해 안전하게 저장합니다.
    • 관리자 작업에 대한 감사 기록이 강화되었습니다.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 106 files, which is 6 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2395aa4c-73e3-4e1b-aca2-d95f5ca3088e

📥 Commits

Reviewing files that changed from the base of the PR and between 331df9a and b35696c.

📒 Files selected for processing (106)
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/request/AdminConfigureGifticonTokenRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/request/AdminGifticonPaymentActionRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/request/AdminUpdatePolicyRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/response/AdminGifticonPaymentPageResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/response/AdminGifticonPaymentResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/response/AdminGifticonProductResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/enums/GifticonPaymentAttentionReason.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/service/AdminAuditService.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/service/AdminGifticonPaymentService.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/service/AdminPolicyService.java
  • manabom/src/main/java/mannabom_server/manabom/application/chat/dto/response/ChatGifticonInfo.java
  • manabom/src/main/java/mannabom_server/manabom/application/chat/dto/response/ChatMessageEvent.java
  • manabom/src/main/java/mannabom_server/manabom/application/chat/dto/response/ChatMessageResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/chat/service/ChatService.java
  • manabom/src/main/java/mannabom_server/manabom/application/currency/service/TingTransactionRecorder.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/request/ConfirmGifticonPaymentRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/request/PrepareChatGifticonPaymentRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/request/PrepareGifticonPaymentRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/response/GifticonPaymentPrepareResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/response/GifticonPaymentResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/response/GifticonProductResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/ChatGifticonDeliveryFailedEvent.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/ChatGifticonDeliveryFailedEventListener.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/ChatGifticonMessageCreatedEvent.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/ChatGifticonMessageCreatedEventListener.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/GifticonOrderReadyEventListener.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/GifticonPaymentRefundEventListener.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/GifticonPaymentRefundRequestedEvent.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/port/GifticonPaymentGateway.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/scheduler/GifticonMessageCreationRetryScheduler.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/scheduler/GifticonOrderRetryScheduler.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/scheduler/GifticonPaymentRefundRetryScheduler.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/scheduler/UnusedGifticonPaymentRefundScheduler.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonCatalogService.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderAttemptService.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderCompletionService.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderProcessor.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderService.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonPaymentService.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonPaymentStateService.java
  • manabom/src/main/java/mannabom_server/manabom/application/messageRequest/dto/request/SendMessageRequestDto.java
  • manabom/src/main/java/mannabom_server/manabom/application/messageRequest/service/MessageRequestService.java
  • manabom/src/main/java/mannabom_server/manabom/application/signal/dto/response/RespondSignalResponseDto.java
  • manabom/src/main/java/mannabom_server/manabom/application/signup/service/SignupService.java
  • manabom/src/main/java/mannabom_server/manabom/domain/admin/enums/AdminAuditActionType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/admin/enums/AdminAuditTargetType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/chat/entity/ChatMessage.java
  • manabom/src/main/java/mannabom_server/manabom/domain/chat/enums/ChatMessageType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/chat/repository/ChatMessageRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/entity/TingTransaction.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/enums/TingTransactionType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/repository/TingTransactionRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/entity/GifticonOrder.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/entity/GifticonPayment.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/entity/GifticonProduct.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/enums/GifticonMessageCreationStatus.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/enums/GifticonOrderStatus.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/enums/GifticonPaymentPurpose.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/enums/GifticonPaymentStatus.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/repository/GifticonOrderRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/repository/GifticonPaymentRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/service/GifticonPriceCalculator.java
  • manabom/src/main/java/mannabom_server/manabom/domain/meeting/enums/SseEventName.java
  • manabom/src/main/java/mannabom_server/manabom/domain/messageRequest/entity/MessageRequest.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/config/GifticonPricingConfiguration.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizClient.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizTemplateMapper.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/config/GiftbizProperties.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/toss/TossPaymentClient.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/toss/config/TossPaymentsProperties.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipher.java
  • manabom/src/main/java/mannabom_server/manabom/policy/config/GifticonPricingProperties.java
  • manabom/src/main/java/mannabom_server/manabom/policy/entity/PolicyConfig.java
  • manabom/src/main/java/mannabom_server/manabom/policy/model/RuntimePolicySnapshot.java
  • manabom/src/main/java/mannabom_server/manabom/policy/service/RuntimePolicyService.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/admin/controller/AdminGifticonPaymentController.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/gifticon/controller/GifticonPaymentController.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/messageRequest/controller/MessageRequestController.java
  • manabom/src/main/resources/application.yml
  • manabom/src/main/resources/db/migration/V24__add_unique_active_chat_member.sql
  • manabom/src/main/resources/db/migration/V38__replace_gifticon_ting_payment_with_toss.sql
  • manabom/src/main/resources/db/migration/V39__add_gifticon_pricing_policy.sql
  • manabom/src/main/resources/db/migration/V40__store_gifticon_message_intent.sql
  • manabom/src/main/resources/db/migration/V41__support_chat_gifticon_payment.sql
  • manabom/src/main/resources/static/admin/app.js
  • manabom/src/main/resources/static/admin/index.html
  • manabom/src/main/resources/static/admin/styles.css
  • manabom/src/test/java/mannabom_server/manabom/application/admin/dto/request/AdminConfigureGifticonTokenRequestTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/admin/service/AdminGifticonPaymentServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/admin/service/AdminPolicyServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/currency/service/TingTransactionRecorderTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/event/ChatGifticonDeliveryFailedEventListenerTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/scheduler/GifticonMessageCreationRetrySchedulerTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/scheduler/UnusedGifticonPaymentRefundSchedulerTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonCatalogServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderCompletionServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderProcessorTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonPaymentServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonPaymentStateServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/domain/gifticon/enums/GifticonStatusDescriptionTest.java
  • manabom/src/test/java/mannabom_server/manabom/domain/gifticon/service/GifticonPriceCalculatorTest.java
  • manabom/src/test/java/mannabom_server/manabom/domain/messageRequest/entity/MessageRequestGiftPaymentTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizTemplateMapperTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/external/toss/TossPaymentClientTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipherTest.java
  • manabom/src/test/java/mannabom_server/manabom/tests/RuntimePolicyServiceTest.java

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

Walkthrough

기프티콘 카탈로그 동기화, 상품 조회, 토큰 암호화·설정, 주문 발송과 재시도, 기프티콘 결제 상태 및 팅 거래 기록을 추가했습니다. 관리자용 API와 화면, Kakao Giftbiz 연동, 관련 데이터베이스 마이그레이션과 테스트도 포함됩니다.

Changes

기프티콘 플랫폼

Layer / File(s) Summary
기프티콘 도메인과 저장 구조
domain/gifticon/*, domain/currency/*, db/migration/V28__* ... V37__*
상품·주문·결제 상태, 팅 거래 엔티티와 저장소 및 데이터베이스 스키마를 추가했습니다.
카탈로그 동기화와 상품 조회
application/gifticon/service/*, infrastructure/external/kakao/giftbiz/*, presentation/gifticon/*
Kakao Giftbiz 템플릿 조회, 상품 동기화, 가격 계산, 커서 기반 상품 조회와 스케줄링을 구현했습니다.
기프티콘 주문 처리
application/gifticon/service/GifticonOrder*.java, application/gifticon/event/*, infrastructure/external/kakao/giftbiz/KakaoGiftbizOrderClient.java
메시지 요청 후 주문을 생성하고 커밋 이후 외부 발송을 수행하며 실패 주문을 재시도합니다.
메시지 요청과 결제 상태
application/messageRequest/*, presentation/messageRequest/*, domain/messageRequest/*
기프티콘 보류·캡처·해제 결제와 주문 상태를 메시지 요청 흐름에 연결했습니다.
팅 거래 기록 연동
application/currency/*, application/admin/service/*, application/like/service/*, application/partner/service/*, application/signup/service/*
지급·차감·관리자 조정 거래를 TingTransaction으로 기록하도록 확장했습니다.
관리자 기프티콘 관리
application/admin/*, presentation/admin/*, static/admin/*, infrastructure/security/crypto/*
관리자 상품 조회·동기화·토큰 설정 API와 SUPER_ADMIN 전용 화면을 추가했습니다.

기존 미팅·채팅 스키마 변경

Layer / File(s) Summary
미팅 및 채팅 마이그레이션
db/migration/V21__* ... V27__*
미팅 취소 요청·투표, 채팅 시스템 메시지, 미팅 검증 결과와 관련 인덱스 및 제약조건을 추가했습니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: kimjuneon

Poem

깡충 뛰는 토끼가 토큰을 감추고
기프티콘 길을 반짝 열었네.
팅 거래는 차곡차곡 기록되고,
주문은 당근처럼 안전히 달려가네.
관리자 화면에도 봄빛이 피었어요! 🐇

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 주요 변경인 카카오 Gift Biz 기프티콘 발송과 팅 거래 기록 추가를 잘 요약합니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/gifticon

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

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

@Sehi55 Sehi55 changed the title [Feature] gifticon 도메인 구현 [Feature] 카카오 Gift Biz 기프티콘 발송 및 팅 거래 기록 추가 Jul 24, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Nitpick comments (5)
manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql (1)

7-18: 🩺 Stability & Availability | 🔵 Trivial

운영 중 테이블에 대한 blocking DDL을 온라인 단계로 분리하세요.

여러 마이그레이션에서 기존 데이터 전체 검증과 일반 인덱스 생성을 수행하므로, 배포 중 쓰기 중단 또는 긴 잠금이 발생할 수 있습니다.

  • manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql#L7-L18: FK와 CHECK를 NOT VALID로 추가한 뒤 별도 검증 단계로 분리하세요.
  • manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql#L20-L25: 인덱스는 CONCURRENTLY 사용 여부를 확인하세요.
  • manabom/src/main/resources/db/migration/V24__add_unique_active_chat_member.sql#L1-L2: UNIQUE 인덱스의 동시 생성과 중복 데이터 사전 정리를 확인하세요.
  • manabom/src/main/resources/db/migration/V25__add_meeting_verification_failure_notification.sql#L4-L5: 운영 테이블 규모에 따라 동시 생성을 검토하세요.
  • manabom/src/main/resources/db/migration/V26__add_structured_system_message_fields.sql#L8-L10: FK를 NOT VALID로 추가한 뒤 검증을 분리하세요.
  • manabom/src/main/resources/db/migration/V26__add_structured_system_message_fields.sql#L12-L14: 인덱스 동시 생성을 검토하세요.
  • manabom/src/main/resources/db/migration/V26__add_structured_system_message_fields.sql#L20-L22: FK를 NOT VALID로 추가한 뒤 검증을 분리하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql`
around lines 7 - 18, 운영 테이블에 대한 검증 및 인덱스 생성을 온라인 단계로 분리하세요. V22의
fk_cancellation_request_meeting_match와 chk_cancellation_request_target은 NOT
VALID로 추가한 뒤 별도 VALIDATE 단계에서 검증하고, 같은 파일의 인덱스는 CONCURRENTLY 사용을 확인하세요. V24의
UNIQUE 인덱스는 중복 데이터를 사전 정리한 후 동시 생성하고, V25 인덱스는 테이블 규모에 맞춰 동시 생성을 적용하세요. V26의 두
FK는 NOT VALID 추가 후 별도 검증으로 분리하며, 해당 인덱스에는 동시 생성을 검토하세요. 영향을 받는 파일은
manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql(7-18,
20-25),
manabom/src/main/resources/db/migration/V24__add_unique_active_chat_member.sql(1-2),
manabom/src/main/resources/db/migration/V25__add_meeting_verification_failure_notification.sql(4-5),
manabom/src/main/resources/db/migration/V26__add_structured_system_message_fields.sql(8-10,
12-14, 20-22)입니다.

Source: Linters/SAST tools

manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql (1)

4-10: 🩺 Stability & Availability | 🔵 Trivial

기존 운영 테이블에 블로킹 DDL을 적용하는 배포 전략을 통일하세요.

  • manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql#L4-L10: FK는 NOT VALID 후 별도 검증하고, 인덱스는 CONCURRENTLY 생성을 검토하세요.
  • manabom/src/main/resources/db/migration/V31__add_gifticon_template_token.sql#L4-L6: UNIQUE 인덱스를 온라인 생성하거나, V32에서 즉시 삭제되는 경우 생성 자체를 제거하세요.
  • manabom/src/main/resources/db/migration/V34__hold_paid_ting_for_gifticon.sql#L5-L17: CHECK 제약조건은 NOT VALID 추가 후 별도 검증하는 방식을 검토하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql`
around lines 4 - 10, Update
manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql
lines 4-10 to add the foreign key as NOT VALID and validate it separately, and
use concurrent index creation where supported. Update
manabom/src/main/resources/db/migration/V31__add_gifticon_template_token.sql
lines 4-6 to create the UNIQUE index online, or remove its creation if V32
immediately drops it. Update
manabom/src/main/resources/db/migration/V34__hold_paid_ting_for_gifticon.sql
lines 5-17 to add CHECK constraints as NOT VALID and validate them separately.

Source: Linters/SAST tools

manabom/src/main/resources/db/migration/V36__remove_gifticon_order_template_token.sql (1)

1-2: 🩺 Stability & Availability | 🔵 Trivial

롤링 배포 시 컬럼 삭제 순서를 확인하세요.

DROP COLUMN은 기존 GifticonOrder 매핑이 해당 컬럼을 조회하는 구버전 인스턴스와 호환되지 않습니다. 먼저 컬럼을 읽지 않는 애플리케이션을 배포한 뒤 후속 마이그레이션에서 삭제하거나, 구버전 인스턴스가 없는 중단 배포인지 확인해 주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@manabom/src/main/resources/db/migration/V36__remove_gifticon_order_template_token.sql`
around lines 1 - 2, Review the V36 migration’s DROP COLUMN operation against the
deployment strategy: for rolling deployments, first deploy an application
version that no longer reads encrypted_template_token, then remove the column in
a subsequent migration; otherwise explicitly confirm this migration runs only
during a coordinated downtime deployment with no old GifticonOrder instances.

Source: Linters/SAST tools

manabom/src/main/resources/db/migration/V37__add_gifticon_order_sender_nickname.sql (1)

16-17: 🩺 Stability & Availability | 🔵 Trivial

대용량 테이블의 NOT NULL 전환을 온라인 방식으로 검토하세요.

ALTER COLUMN ... SET NOT NULL은 기존 테이블을 검사하면서 강한 락을 획득할 수 있어, 주문량이나 트래픽이 많은 환경에서는 읽기·쓰기 지연을 유발할 수 있습니다. 테이블 규모를 확인하고 점검 시간대에 실행하거나, 검증 가능한 단계적 제약 적용 방식을 사용해 주세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@manabom/src/main/resources/db/migration/V37__add_gifticon_order_sender_nickname.sql`
around lines 16 - 17, Update migration V37’s gifticon_order sender_nickname
constraint change to use an online, staged validation approach that avoids a
long strong lock on the large table. Verify existing NULL data first, add and
validate an equivalent constraint in a low-impact step, then enforce NOT NULL
only through the safest supported operation for this database; otherwise
schedule the direct ALTER during a maintenance window.

Source: Linters/SAST tools

manabom/src/main/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipher.java (1)

25-32: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

키 검증을 지연 대신 조기(fail-fast)로 수행하는 것을 고려

secretKey()가 매 encrypt/decrypt 호출마다 Base64 디코딩과 32바이트 검증을 반복합니다. 오버헤드 자체는 작지만, 키가 잘못 설정된 경우 애플리케이션 기동 시점이 아니라 실제로 토큰을 암복호화하는 시점(예: 기프티콘 발송 시)에야 오류가 드러납니다. 생성자 또는 @PostConstruct에서 디코딩된 SecretKey를 한 번만 검증·캐싱해두면 배포 초기에 설정 오류를 감지할 수 있고 반복 디코딩도 피할 수 있습니다. (키를 선택적으로 비워두는 환경이 있다면 해당 트레이드오프를 고려해 적용해 주세요.)

Also applies to: 83-102

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@manabom/src/main/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipher.java`
around lines 25 - 32, Update AesGcmGifticonTokenCipher to decode and validate
the configured key during construction or initialization, then cache and reuse
the validated SecretKey in secretKey() and the encrypt/decrypt paths. Preserve
the existing optional-empty-key behavior if supported, while ensuring invalid
non-empty keys fail during application startup rather than during token
operations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@manabom/src/main/java/mannabom_server/manabom/application/admin/dto/request/AdminConfigureGifticonTokenRequest.java`:
- Around line 16-17: Update the reason field in
AdminConfigureGifticonTokenRequest to require a non-null, non-blank value while
retaining the existing 500-character maximum validation and message. Ensure
configureTemplateToken receives only valid audit-log reasons through request
validation.

In
`@manabom/src/main/java/mannabom_server/manabom/application/currency/service/TingTransactionRecorder.java`:
- Around line 62-87: Update TingTransactionRecorder.record() to check for an
existing transaction by idempotencyKey before saving; add the required
TingTransactionRepository lookup and return the existing record when found,
otherwise save a new transaction. Ensure the persistence model enforces
uniqueness for the idempotency key while preserving the pre-save lookup flow.

In
`@manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/GifticonOrderReadyEventListener.java`:
- Around line 15-17: 외부 발송이 동기 처리되거나 잠금 트랜잭션을 장시간 점유하지 않도록 분리하세요.
GifticonOrderReadyEventListener.java의 requestGift 메서드는 `@Async` 또는 내구성 있는 작업 큐로 주문
ID만 위임하세요. GifticonOrderProcessor.java의 처리 흐름은 PESSIMISTIC_WRITE 잠금 하에서 완료된 요청
처리를 마친 뒤 원격 요청만 수행하고, 성공한 경우 별도 트랜잭션에서 markRequested()를 기록하도록 변경하세요.

In
`@manabom/src/main/java/mannabom_server/manabom/application/signup/service/SignupService.java`:
- Around line 8-13: Update the signup bonus recording flow in SignupService so
TingTransactionRecorder.recordEvent is invoked only when signupBonusEventTing is
greater than zero. Preserve the existing transaction details and behavior for
positive bonuses, while skipping creation of zero-amount ledger rows.

In
`@manabom/src/main/java/mannabom_server/manabom/domain/gifticon/entity/GifticonProduct.java`:
- Around line 163-165: Update GifticonProduct.isOrderableAt to require a
strictly positive tingPrice in addition to hasTemplateToken() and
isAvailableAt(now), so zero-priced products are not reported as orderable.

In
`@manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizTemplateMapper.java`:
- Around line 32-38: Update KakaoGiftbizTemplateMapper’s product mapping to
validate that product and product.productPrice() are present before creating the
snapshot; handle invalid templates explicitly by skipping them at the
individual-item level so GifticonCatalogService catalog synchronization
continues without passing a null price to
GifticonPriceCalculator.calculateTingPrice(int).

In
`@manabom/src/main/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipher.java`:
- Around line 83-102: AesGcmGifticonTokenCipher의 secretKey()에서 사용하는 모든 설정 오류
메시지의 키 이름을 실제 프로퍼티 또는 대응 환경변수명인 APP_KAKAO_GIFTBIZ_TOKEN_ENCRYPTION_KEY로 통일하세요. 빈
값, 잘못된 Base64, 잘못된 키 길이 검증 메시지 모두 동일한 올바른 설정 키를 참조하도록 수정하고 나머지 검증 동작은 유지하세요.

In `@manabom/src/main/resources/application.yml`:
- Around line 94-105: Update the giftbiz.sync.enabled configuration default to
false so synchronization is disabled when KAKAO_GIFTBIZ_AUTHORIZATION is unset,
while preserving explicit environment values that enable synchronization.

In
`@manabom/src/main/resources/db/migration/V24__add_unique_active_chat_member.sql`:
- Around line 1-3: Update the partial unique index
uk_chat_members_active_room_user to filter chat_members rows with status ACTIVE,
matching the existing status default. Before creating the corrected index,
remove any existing duplicate active room/user records if the migration must
handle pre-existing duplicates.

In `@manabom/src/main/resources/db/migration/V28__create_gifticon_product.sql`:
- Around line 19-20: Update the ting_price constraint in the gifticon product
schema to require values greater than zero, aligning catalog validation with
V34__hold_paid_ting_for_gifticon.sql and the existing payment initialization
flow. Preserve the nonnegative product_price constraint unchanged.

In
`@manabom/src/main/resources/db/migration/V32__encrypt_gifticon_template_token.sql`:
- Around line 4-8: Update the V32 migration so existing plaintext values from
template_token are never retained in encrypted_template_token: do not use a
direct rename that carries the data, or clear the renamed column immediately
before any application use. Preserve the encrypted_template_token column
definition while requiring existing products to be re-registered or separately
backfilled through the encryption path.

In
`@manabom/src/main/resources/db/migration/V34__hold_paid_ting_for_gifticon.sql`:
- Around line 8-17: Update the ck_message_request_gift_payment_status CHECK
constraint so the gifticon_product_id IS NOT NULL branch explicitly requires
gift_payment_status IS NOT NULL before validating its allowed values, preventing
NULL statuses from bypassing the constraint.

---

Nitpick comments:
In
`@manabom/src/main/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipher.java`:
- Around line 25-32: Update AesGcmGifticonTokenCipher to decode and validate the
configured key during construction or initialization, then cache and reuse the
validated SecretKey in secretKey() and the encrypt/decrypt paths. Preserve the
existing optional-empty-key behavior if supported, while ensuring invalid
non-empty keys fail during application startup rather than during token
operations.

In
`@manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql`:
- Around line 7-18: 운영 테이블에 대한 검증 및 인덱스 생성을 온라인 단계로 분리하세요. V22의
fk_cancellation_request_meeting_match와 chk_cancellation_request_target은 NOT
VALID로 추가한 뒤 별도 VALIDATE 단계에서 검증하고, 같은 파일의 인덱스는 CONCURRENTLY 사용을 확인하세요. V24의
UNIQUE 인덱스는 중복 데이터를 사전 정리한 후 동시 생성하고, V25 인덱스는 테이블 규모에 맞춰 동시 생성을 적용하세요. V26의 두
FK는 NOT VALID 추가 후 별도 검증으로 분리하며, 해당 인덱스에는 동시 생성을 검토하세요. 영향을 받는 파일은
manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql(7-18,
20-25),
manabom/src/main/resources/db/migration/V24__add_unique_active_chat_member.sql(1-2),
manabom/src/main/resources/db/migration/V25__add_meeting_verification_failure_notification.sql(4-5),
manabom/src/main/resources/db/migration/V26__add_structured_system_message_fields.sql(8-10,
12-14, 20-22)입니다.

In
`@manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql`:
- Around line 4-10: Update
manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql
lines 4-10 to add the foreign key as NOT VALID and validate it separately, and
use concurrent index creation where supported. Update
manabom/src/main/resources/db/migration/V31__add_gifticon_template_token.sql
lines 4-6 to create the UNIQUE index online, or remove its creation if V32
immediately drops it. Update
manabom/src/main/resources/db/migration/V34__hold_paid_ting_for_gifticon.sql
lines 5-17 to add CHECK constraints as NOT VALID and validate them separately.

In
`@manabom/src/main/resources/db/migration/V36__remove_gifticon_order_template_token.sql`:
- Around line 1-2: Review the V36 migration’s DROP COLUMN operation against the
deployment strategy: for rolling deployments, first deploy an application
version that no longer reads encrypted_template_token, then remove the column in
a subsequent migration; otherwise explicitly confirm this migration runs only
during a coordinated downtime deployment with no old GifticonOrder instances.

In
`@manabom/src/main/resources/db/migration/V37__add_gifticon_order_sender_nickname.sql`:
- Around line 16-17: Update migration V37’s gifticon_order sender_nickname
constraint change to use an online, staged validation approach that avoids a
long strong lock on the large table. Verify existing NULL data first, add and
validate an equivalent constraint in a low-impact step, then enforce NOT NULL
only through the safest supported operation for this database; otherwise
schedule the direct ALTER during a maintenance window.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b23044d6-9614-4c18-856b-97dca7dd0e81

📥 Commits

Reviewing files that changed from the base of the PR and between 867151a and 331df9a.

📒 Files selected for processing (87)
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/request/AdminConfigureGifticonTokenRequest.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/response/AdminGifticonProductResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/response/AdminGifticonProductSliceResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/dto/response/AdminGifticonSyncResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/service/AdminGifticonService.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/service/AdminReportService.java
  • manabom/src/main/java/mannabom_server/manabom/application/admin/service/AdminWalletService.java
  • manabom/src/main/java/mannabom_server/manabom/application/currency/service/TingTransactionRecorder.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/response/GifticonProductResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/dto/response/GifticonProductSliceResponse.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/GifticonOrderReadyEvent.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/event/GifticonOrderReadyEventListener.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/port/GifticonOrderRequester.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/port/GifticonTemplateProvider.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/port/GifticonTokenCipher.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/port/command/GifticonOrderCommand.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/scheduler/GifticonCatalogSyncScheduler.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/scheduler/GifticonOrderRetryScheduler.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonCatalogService.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonCatalogSynchronizer.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderProcessor.java
  • manabom/src/main/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderService.java
  • manabom/src/main/java/mannabom_server/manabom/application/like/service/LikeService.java
  • manabom/src/main/java/mannabom_server/manabom/application/messageRequest/dto/request/SendMessageRequestDto.java
  • manabom/src/main/java/mannabom_server/manabom/application/messageRequest/service/MessageRequestService.java
  • manabom/src/main/java/mannabom_server/manabom/application/partner/service/PartnerService.java
  • manabom/src/main/java/mannabom_server/manabom/application/signal/dto/response/RespondSignalResponseDto.java
  • manabom/src/main/java/mannabom_server/manabom/application/signup/service/SignupService.java
  • manabom/src/main/java/mannabom_server/manabom/domain/admin/enums/AdminAuditActionType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/admin/enums/AdminAuditTargetType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/entity/TingTransaction.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/enums/TingBalanceType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/enums/TingTransactionReferenceType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/enums/TingTransactionType.java
  • manabom/src/main/java/mannabom_server/manabom/domain/currency/repository/TingTransactionRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/entity/GifticonOrder.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/entity/GifticonProduct.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/enums/GifticonOrderStatus.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/enums/GifticonPaymentStatus.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/repository/GifticonOrderRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/repository/GifticonProductRepository.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/service/GifticonPriceCalculator.java
  • manabom/src/main/java/mannabom_server/manabom/domain/gifticon/vo/GifticonTemplateSnapshot.java
  • manabom/src/main/java/mannabom_server/manabom/domain/messageRequest/entity/MessageRequest.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/config/GifticonPricingConfiguration.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizClient.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizOrderClient.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizTemplateMapper.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/config/GiftbizProperties.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/dto/KakaoGiftbizOrderRequest.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/dto/KakaoGiftbizTemplatePage.java
  • manabom/src/main/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipher.java
  • manabom/src/main/java/mannabom_server/manabom/policy/config/ConfigRegister.java
  • manabom/src/main/java/mannabom_server/manabom/policy/config/GifticonPricingProperties.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/admin/controller/AdminGifticonController.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/gifticon/controller/GifticonController.java
  • manabom/src/main/java/mannabom_server/manabom/presentation/messageRequest/controller/MessageRequestController.java
  • manabom/src/main/resources/application.yml
  • manabom/src/main/resources/db/migration/V21__add_meeting_cancellation_tables.sql
  • manabom/src/main/resources/db/migration/V22__move_meeting_cancellation_to_match.sql
  • manabom/src/main/resources/db/migration/V23__remove_withdrawn_cancellation_status.sql
  • manabom/src/main/resources/db/migration/V24__add_unique_active_chat_member.sql
  • manabom/src/main/resources/db/migration/V25__add_meeting_verification_failure_notification.sql
  • manabom/src/main/resources/db/migration/V26__add_structured_system_message_fields.sql
  • manabom/src/main/resources/db/migration/V27__persist_meeting_verification_result.sql
  • manabom/src/main/resources/db/migration/V28__create_gifticon_product.sql
  • manabom/src/main/resources/db/migration/V29__allow_null_gifticon_sales_period.sql
  • manabom/src/main/resources/db/migration/V30__link_gifticon_to_message_request.sql
  • manabom/src/main/resources/db/migration/V31__add_gifticon_template_token.sql
  • manabom/src/main/resources/db/migration/V32__encrypt_gifticon_template_token.sql
  • manabom/src/main/resources/db/migration/V33__create_gifticon_order.sql
  • manabom/src/main/resources/db/migration/V34__hold_paid_ting_for_gifticon.sql
  • manabom/src/main/resources/db/migration/V35__create_ting_transaction.sql
  • manabom/src/main/resources/db/migration/V36__remove_gifticon_order_template_token.sql
  • manabom/src/main/resources/db/migration/V37__add_gifticon_order_sender_nickname.sql
  • manabom/src/main/resources/static/admin/app.js
  • manabom/src/main/resources/static/admin/index.html
  • manabom/src/main/resources/static/admin/styles.css
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonCatalogServiceTest.java
  • manabom/src/test/java/mannabom_server/manabom/application/gifticon/service/GifticonOrderProcessorTest.java
  • manabom/src/test/java/mannabom_server/manabom/domain/gifticon/service/GifticonPriceCalculatorTest.java
  • manabom/src/test/java/mannabom_server/manabom/domain/messageRequest/entity/MessageRequestGiftPaymentTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizOrderClientTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/KakaoGiftbizTemplateMapperTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/dto/KakaoGiftbizOrderRequestTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/external/kakao/giftbiz/dto/KakaoGiftbizTemplatePageTest.java
  • manabom/src/test/java/mannabom_server/manabom/infrastructure/security/crypto/AesGcmGifticonTokenCipherTest.java

Comment thread manabom/src/main/resources/application.yml
@Sehi55 Sehi55 self-assigned this Jul 25, 2026
@Sehi55 Sehi55 added the enhancement New feature or request label Aug 6, 2026
@Sehi55
Sehi55 requested a review from kimjuneon August 6, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant