Files
sodalive-backend-spring-boot/docs/20260429_채팅방쿼터충전방식확장.md

6.4 KiB

채팅방 쿼터 충전 방식 확장

구현 계획

  • purchaseRoomQuota 요청 DTO만 보고도 캔 충전인지 광고 충전인지 구분할 수 있도록 충전 방식 필드를 확장하고, 광고 충전 요청을 구분할 수 있는 최소 스키마를 정의한다.
  • 캔 충전 옵션을 기존 단일 고정값에서 10캔 → 15개, 20캔 → 40개의 2개 시나리오로 분기하도록 컨트롤러/서비스 전달 구조를 정리한다.
  • ChatRoomQuotaService.purchase의 하드코딩된 needCan=10, addPaid=12 로직을 요청값 기반 분기로 치환하고, 광고 충전 시 캔 차감 없이 5 quota를 지급하는 경로를 분리한다.
  • 광고 충전은 1회당 5 quota 지급으로 반영하고, 중복 호출 방지 여부와 추가 검증 조건만 별도 확인한다.
  • 관련 테스트 또는 최소 검증 경로를 정리하고 ./gradlew test 기준으로 회귀 여부를 확인한다.

요구사항 반영 체크

  • Quota 충전 방식은 캔 충전, 광고 보고 충전의 2가지로 확장한다.
  • 서버는 요청 DTO를 통해 캔 충전인지 광고 충전인지 식별할 수 있어야 한다.
  • 캔 충전 옵션은 10캔 → 15개, 20캔 → 40개의 2가지다.
  • 광고 충전은 1회당 5 quota를 지급한다.

영향 범위 메모

  • src/main/kotlin/kr/co/vividnext/sodalive/chat/quota/room/ChatRoomQuotaController.kt
    • 요청 DTO와 purchaseRoomQuota 분기 진입점 변경 대상.
  • src/main/kotlin/kr/co/vividnext/sodalive/chat/quota/room/ChatRoomQuotaService.kt
    • 캔 사용량/유료 quota 지급량 하드코딩 제거 및 충전 방식별 처리 분기 대상.
  • 테스트 코드
    • 현재 src/test/kotlin에서 ChatRoomQuota 관련 테스트가 바로 확인되지 않아, 필요 시 서비스 중심 테스트를 새로 보강한다.

확인 필요 사항

  • 광고 충전은 앱에서 선처리한다고 했으므로 서버는 DTO 기반 분기와 1회당 5 quota 지급만 담당하고, 광고 시청 자체의 검증 책임은 범위 밖으로 본다.
  • 기존 클라이언트 호환을 위해 요청 본문에 container만 오면 서버는 기본값으로 CAN + CAN_10 충전으로 해석한다.
  • 광고 충전 요청에 canOption이 함께 오더라도 서버는 예외를 내지 않고 값을 무시한 뒤 광고 충전으로 처리한다.

검증 기록

1차 계획 수립

  • 무엇을: purchaseRoomQuota API에 광고 충전 구분과 2종 캔 충전 옵션을 추가하기 위한 구현 계획과 예상 영향 범위를 문서화했다.
  • 왜: 현재 구현은 container만 받고 서비스에서 10캔 → 12개 quota를 고정 처리하고 있어, 요구사항을 반영하려면 DTO/서비스 분기와 미정 항목을 먼저 분리해 두는 것이 안전하기 때문이다.
  • 어떻게: ChatRoomQuotaController.kt, ChatRoomQuotaService.kt, docs/agent-guides/작업절차.md, docs/agent-guides/문서유지보수.md, 기존 계획 문서 예시를 읽어 형식과 영향 범위를 맞췄고, 문서 변경 후 ./gradlew tasks --all 실행 결과 BUILD SUCCESSFUL을 확인했다.

2차 요구사항 점검 반영

  • 무엇을: 문서가 충전 방식 2종, 요청 DTO를 통한 충전 방식 식별, 캔 충전 2가지 옵션, 광고 충전 5개 지급을 모두 명시적으로 포함하도록 보강했다.
  • 왜: 기존 문서도 대부분의 요구사항을 담고 있었지만, 요구사항 전체를 한눈에 대조할 수 있는 체크 형태가 없어 일부 표현이 암묵적으로 읽힐 여지가 있었기 때문이다.
  • 어떻게: 계획 문서 본문에 요구사항 반영 체크 섹션을 추가하고 핵심 조건을 체크박스로 정리했으며, 문서 변경 후 ./gradlew tasks --all 실행 결과 BUILD SUCCESSFUL을 다시 확인했다.

3차 구현 및 검증

  • 무엇을: purchaseRoomQuota 요청 DTO에 충전 방식과 캔 옵션 enum을 추가하고, 컨트롤러에서 캔 충전광고 충전을 분기하도록 변경했다. 함께 ChatRoomQuotaServicepurchaseWithCan, purchaseWithAd 경로로 분리해 10캔 → 15개, 20캔 → 40개, 광고 → 5개 지급 규칙을 반영했다. 또한 ChatRoomQuotaControllerTest, ChatRoomQuotaServiceTest를 추가해 컨트롤러 분기와 서비스 적립 로직을 검증했다.
  • 왜: 기존 구현은 container만 받고 10캔 → 12개를 단일 하드코딩으로 처리해 새로운 충전 방식과 옵션을 구분할 수 없었기 때문이다.
  • 어떻게: ChatRoomQuotaController.kt, ChatRoomQuotaService.kt에 최소 분기 로직을 추가하고 ChatRoomQuotaPurchaseOption.kt에 enum을 분리했다. 검증은 Kotlin LSP가 이 환경에서 지원되지 않아 진단 대신 ./gradlew test --tests "kr.co.vividnext.sodalive.chat.quota.room.ChatRoomQuotaServiceTest" --tests "kr.co.vividnext.sodalive.chat.quota.room.ChatRoomQuotaControllerTest"를 실행해 BUILD SUCCESSFUL을 확인했다.

4차 하위 호환 보완

  • 무엇을: 기존 클라이언트가 container만 보내도 동작하도록 PurchaseRoomQuotaRequest의 기본 충전 방식을 CAN, 기본 캔 옵션을 CAN_10으로 해석하도록 보완했고, 이를 검증하는 테스트를 추가했다.
  • 왜: 새 DTO 필드를 필수로 두면 구버전 클라이언트의 기존 요청 본문이 역직렬화 단계에서 바로 깨질 수 있기 때문이다.
  • 어떻게: ChatRoomQuotaController.kt에서 chargeType 기본값을 CAN으로 두고 canOption 누락 시 CAN_10을 사용하도록 변경했다. 검증은 ChatRoomQuotaControllerTestcontainer만 전달하는 직접 호출 케이스를 추가해 수행했다.

5차 광고 옵션 허용 완화

  • 무엇을: 광고 충전 요청에 canOption이 함께 들어와도 예외를 던지지 않고 무시하도록 컨트롤러 분기를 완화했고, 해당 요청이 정상적으로 광고 충전 경로로 전달되는 테스트로 기대값을 바꿨다.
  • 왜: 광고 충전은 지급량이 고정이라 canOption이 의미 없는 부가 필드에 가깝고, 이를 이유로 요청을 실패시키는 것보다 무시하는 편이 클라이언트 호환성과 운영 안정성에 유리하기 때문이다.
  • 어떻게: ChatRoomQuotaController.ktAD 분기에서 canOption 검증 예외를 제거했고, ChatRoomQuotaControllerTest의 광고 케이스를 성공 경로 검증으로 변경했다.