IAP 결제·Tier 게이팅 단위 테스트 14건 일괄 추가
목차
IAP 결제 검증 + Tier 게이팅 로직에 단위 테스트 14건을 한 번에 추가했다.
왜 이 타이밍에 테스트였나
기능 구현은 어느 정도 끝나 있었는데, 테스트가 없는 채로 Tier 게이팅 AOP와 IAP 구독 로직이 main 브랜치에 들어가 있는 상황이 며칠째 이어지고 있었다. 팀 내에서 코드리뷰를 돌릴 때마다 "이 분기 검증은 어디서 해요?"라는 질문이 계속 나왔고, 나도 명쾌하게 답을 못 했다. 솔직히 말하면 구현 속도에 집중하느라 테스트를 뒤로 미뤘던 건데, 그게 결국 리뷰 코스트로 돌아왔다.
IAP + Tier 게이팅은 그 조합 자체가 꽤 예민한 영역이다. 앱 스토어 영수증 검증이 실패했을 때 어떤 상태를 반환하는지, 구독 상태가 만료되면 Tier 게이팅 AOP가 어떤 예외를 던지는지—이 두 흐름이 맞물리는 지점에서 버그가 나면 유저 입장에서는 "결제를 했는데 기능이 안 열린다"거나 반대로 "구독이 끝났는데 콘텐츠가 열린다"는 최악의 상황이 된다. 그러니 이 부분만큼은 테스트로 명세를 고정해두는 게 맞다는 판단이었다.
세 파일이 커버하는 범위
변경된 파일이 세 개인데, 각각 책임이 명확하게 나뉜다.
| 파일 | 커버 범위 | 핵심 검증 포인트 |
|---|---|---|
TierAspectTest |
AOP 게이팅 레이어 | Tier 조건 불충족 시 예외 발생, 충족 시 정상 통과 |
ReceiptVerificationResultTest |
IAP 검증 결과 VO | 상태값 파싱·불변성·엣지케이스 |
SubscriptionServiceTest |
구독 서비스 로직 | 만료/활성/미검증 시나리오 분기 |
TierAspectTest는 AOP가 올바른 시점에 인터셉트하는지를 검증하는 테스트라서, 실제로 메서드 호출이 차단되거나 통과되는 행동 자체를 단언해야 한다. 이게 단위 테스트에서 AOP를 검증할 때 조금 까다로운 부분인데—Spring 컨텍스트를 올리지 않으면 AOP가 위빙되지 않으니 @SpringBootTest로 무겁게 가거나, 아니면 Aspect를 직접 인스턴스화해서 타깃 메서드를 수동으로 호출하는 방식 중 하나를 선택해야 한다. 팀에서는 속도를 위해 후자 방향으로 정리했다.
// Aspect 직접 인스턴스화 패턴 (컨텍스트 없이 단위 테스트)
TierAspect aspect = new TierAspect(tierService);
ProceedingJoinPoint pjp = mock(ProceedingJoinPoint.class);
// Tier 불충족 시나리오
when(tierService.getCurrentTier(userId)).thenReturn(Tier.FREE);
assertThatThrownBy(() -> aspect.checkTierAccess(pjp, requirePremium))
.isInstanceOf(TierAccessDeniedException.class);
ReceiptVerificationResultTest는 VO 성격의 클래스 테스트다. 영수증 검증 결과를 담는 객체가 어떤 상태값을 가지고, 그 상태값에서 파생되는 판단(예: isActive(), isExpired())이 기대대로 동작하는지를 확인한다. 이 클래스는 여러 곳에서 참조되기 때문에 불변 계약을 테스트로 못박아두는 게 리팩터링 안전망이 된다.
14건이라는 숫자의 의미
14건을 한 커밋에 넣은 건 의도적이었다. 각 파일을 독립적으로 PR 올리면 리뷰어가 맥락을 파악하기 어렵고, 세 파일이 함께 봐야 IAP→구독상태→Tier게이팅으로 이어지는 흐름이 테스트 레벨에서 완성되는 게 보인다. 테스트는 그 자체가 문서이기도 하니까, 한 번에 읽혔을 때 "아, 이 기능이 이런 케이스들을 처리하는구나"가 보여야 한다고 생각했다.
팀원들한테 PR 올리면서 "이 테스트 읽으면 기능 스펙이 보여야 한다"고 말했는데, 리뷰 중에 SubscriptionServiceTest의 만료 시나리오 케이스 하나가 빠져 있다는 피드백이 왔다. 구독이 만료된 시점에 재검증을 시도했을 때의 케이스였는데, 이건 다음 커밋에서 보강하기로 했다.
단위 테스트를 나중으로 미루면 결국 이렇게 된다—구현은 다 됐는데 테스트가 없어서 PR이 블로킹되거나, 커버리지가 뭉텅이로 채워지면서 정작 중요한 케이스가 빠진 채로 들어간다. IAP처럼 외부 시스템 연동이 얽힌 도메인일수록 단위 테스트 작성을 구현과 동시에 가져가는 게 맞는데, 이번엔 그걸 못 지켰다. 다음 피처 사이클에서는 Tier 관련 신규 기능부터는 TDD 방향으로 팀 컨벤션을 맞춰보려 한다.
끝.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.