Skip to content

Latest commit

 

History

History
261 lines (170 loc) · 9.3 KB

File metadata and controls

261 lines (170 loc) · 9.3 KB

쿠폰 할인 시스템 TDD Plan

Kent Beck의 TDD 원칙에 따라 작은 단위부터 시작하여 점진적으로 구현합니다. 각 테스트는 Red → Green → Refactor 사이클을 따릅니다.


Phase 1: 기본 할인 계산 로직 (Domain Core)

1.1 정액 할인 쿠폰

  • [✅] 정액 할인 쿠폰이 상품 가격에서 할인 금액을 차감한다
  • [✅] 정액 할인 금액이 상품 가격보다 크면 0원이 된다
  • 정액 할인 적용 후 최종 금액은 음수가 될 수 없다

1.2 정률 할인 쿠폰

  • 정률 할인 쿠폰이 상품 가격의 N%를 할인한다
  • 정률 할인 시 원 단위 절사 처리를 한다
  • 정률 할인에 최대 할인 금액 제한이 있으면 초과하지 않는다
  • 100% 할인 쿠폰은 상품을 0원으로 만든다

1.3 최소 구매 조건

  • 최소 구매 금액 미달 시 쿠폰 적용이 불가능하다
  • 최소 구매 금액을 정확히 충족하면 쿠폰 적용이 가능하다
  • 최소 구매 수량 미달 시 쿠폰 적용이 불가능하다
  • 할인 적용 전 금액 기준으로 최소 구매 조건을 검증한다

Phase 2: 쿠폰 유효성 검증

2.1 쿠폰 기본 정보

  • 쿠폰은 고유한 쿠폰 코드를 가진다
  • 쿠폰은 이름과 설명을 가진다
  • 쿠폰은 유효 시작일시와 종료일시를 가진다

2.2 유효 기간 검증

  • 유효 기간 시작 전 쿠폰은 사용할 수 없다
  • 유효 기간 내 쿠폰은 사용할 수 있다
  • 유효 기간 만료 후 쿠폰은 사용할 수 없다
  • 발급 후 N일 유효 쿠폰은 발급일 기준으로 만료일이 계산된다

2.3 발급 수량 관리

  • 쿠폰은 총 발급 가능 수량을 가진다
  • 발급 가능 수량이 소진되면 추가 발급이 불가능하다
  • 사용자당 발급 제한이 있으면 중복 발급이 불가능하다
  • 이미 발급받은 쿠폰은 다시 발급할 수 없다

Phase 3: 상품 쿠폰 (Product Coupon)

3.1 단일 상품 대상

  • 특정 상품 ID에만 적용되는 쿠폰을 생성할 수 있다
  • 대상 상품이 아니면 쿠폰 적용이 불가능하다
  • 대상 상품이면 쿠폰 적용이 가능하다

3.2 다중 상품 대상

  • 여러 상품 ID 중 하나라도 포함되면 쿠폰 적용이 가능하다
  • 다중 상품 목록에 없는 상품은 쿠폰 적용이 불가능하다

3.3 카테고리 기반

  • 특정 카테고리의 상품에만 쿠폰을 적용할 수 있다
  • 하위 카테고리 포함 옵션이 켜져 있으면 하위 카테고리 상품도 적용된다
  • 하위 카테고리 포함 옵션이 꺼져 있으면 정확히 일치하는 카테고리만 적용된다

3.4 브랜드 기반

  • 특정 브랜드의 상품에만 쿠폰을 적용할 수 있다
  • 브랜드가 일치하지 않으면 쿠폰 적용이 불가능하다

3.5 조합 조건

  • 브랜드와 카테고리 조건을 AND로 결합할 수 있다
  • 조합 조건을 모두 만족해야 쿠폰이 적용된다

3.6 상품당 적용 개수 제한

  • 쿠폰 1개로 동일 상품 여러 개에 할인을 적용할 수 있다
  • 쿠폰 1개당 상품 1개만 할인하도록 제한할 수 있다

Phase 4: 장바구니 쿠폰 (Cart Coupon)

4.1 전체 금액 기준 할인

  • 장바구니 총액에 정액 할인을 적용할 수 있다
  • 장바구니 총액에 정률 할인을 적용할 수 있다
  • 최소 주문 금액 미달 시 장바구니 쿠폰 적용이 불가능하다

4.2 할인 금액 분배 (비례 분배)

  • 장바구니 할인 금액이 상품 가격 비율에 따라 분배된다
  • 분배 시 소수점은 원 단위로 절사된다
  • 절사로 인한 나머지 금액은 가장 비싼 상품에 할당된다
  • 분배된 할인 금액의 합은 총 할인 금액과 정확히 일치한다

4.3 적용 대상 상품 필터링

  • 특정 카테고리 상품만 장바구니 쿠폰 대상에 포함할 수 있다
  • 제외 상품 목록에 있는 상품은 할인 계산에서 제외된다
  • 필터링 후 남은 상품 금액이 최소 주문 금액 미달이면 적용 불가능하다

4.4 배송비 처리

  • 최소 주문 금액 계산 시 배송비는 제외된다
  • 할인 금액 계산 시 배송비는 제외된다

Phase 5: 쿠폰 중복 적용 정책

5.1 중복 불가 정책

  • 하나의 주문에 하나의 쿠폰만 적용할 수 있다
  • 여러 쿠폰을 동시에 적용하려고 하면 예외가 발생한다
  • 사용자가 적용할 쿠폰을 명시적으로 선택할 수 있다

5.2 자동 최대 할인 선택

  • 여러 쿠폰 중 할인 금액이 가장 큰 쿠폰을 자동 선택한다
  • 정액 할인 금액이 같으면 먼저 만료되는 쿠폰을 선택한다

5.3 순차 적용 정책 (선택적 구현)

  • 상품 쿠폰 적용 후 장바구니 쿠폰을 순차 적용할 수 있다
  • 순차 적용 시 할인 순서를 명확히 정의한다
  • 순차 적용 결과가 중복 불가 정책보다 유리한지 비교한다

Phase 6: 쿠폰 발급 및 사용

6.1 쿠폰 발급

  • 사용자에게 쿠폰을 발급할 수 있다
  • 발급된 쿠폰은 미사용 상태로 시작한다
  • 이미 발급된 쿠폰은 다시 발급할 수 없다
  • 발급 시 발급 일시가 기록된다

6.2 쿠폰 사용

  • 미사용 쿠폰을 사용 처리할 수 있다
  • 사용된 쿠폰은 사용 일시가 기록된다
  • 이미 사용된 쿠폰은 다시 사용할 수 없다
  • 쿠폰 사용 시 주문 ID가 연결된다

6.3 쿠폰 조회

  • 사용자의 사용 가능한 쿠폰 목록을 조회할 수 있다
  • 만료된 쿠폰은 사용 가능 목록에서 제외된다
  • 이미 사용된 쿠폰은 사용 가능 목록에서 제외된다

Phase 7: 주문 취소 및 환불

7.1 전체 취소

  • 주문 전체 취소 시 사용된 쿠폰이 복구된다
  • 복구된 쿠폰은 미사용 상태로 변경된다
  • 쿠폰 사용 이력은 감사 목적으로 유지된다
  • 만료된 쿠폰의 유효기간 연장 정책을 적용할 수 있다

7.2 부분 취소 - 상품 쿠폰

  • 쿠폰이 적용된 상품만 취소 시 쿠폰이 복구된다
  • 쿠폰이 적용되지 않은 상품만 취소 시 쿠폰은 유지된다
  • 부분 취소 시 환불 금액이 정확히 계산된다

7.3 부분 취소 - 장바구니 쿠폰

  • 상품 부분 취소 시 해당 상품에 분배된 할인 금액이 환불된다
  • 부분 취소 후 남은 금액이 최소 주문 금액 미달이어도 쿠폰은 유지된다
  • 부분 취소 후 환불 금액과 남은 주문 금액의 합이 원래 금액과 일치한다

Phase 8: 동시성 제어 (선착순 쿠폰)

8.1 발급 수량 제어

  • 한정 수량 쿠폰의 동시 발급 요청을 올바르게 처리한다
  • 발급 가능 수량을 초과하는 발급 요청은 실패한다
  • 동시성 상황에서 중복 발급이 발생하지 않는다

8.2 쿠폰 사용 제어

  • 동일 쿠폰의 동시 사용 요청은 하나만 성공한다
  • 이미 사용 중인 쿠폰은 다른 주문에서 사용할 수 없다

Phase 9: 성능 최적화 및 캐싱

9.1 쿠폰 적용 미리보기

  • 장바구니 조회 시 적용 가능한 쿠폰 목록을 빠르게 제공한다
  • 쿠폰 적용 미리보기 결과를 캐싱할 수 있다
  • 캐시된 결과의 TTL이 적절하게 설정된다

9.2 데이터베이스 최적화

  • 사용자 쿠폰 조회 쿼리가 인덱스를 활용한다
  • 쿠폰 사용 이력 조회 쿼리가 효율적으로 실행된다

Phase 10: 관리자 기능

10.1 쿠폰 정책 관리

  • 새로운 쿠폰 정책을 생성할 수 있다
  • 기존 쿠폰 정책을 수정할 수 있다
  • 쿠폰 정책을 비활성화할 수 있다
  • 쿠폰 정책 목록을 조회할 수 있다

10.2 쿠폰 발급 통계

  • 쿠폰별 발급 수량을 조회할 수 있다
  • 쿠폰별 사용률을 계산할 수 있다
  • 기간별 쿠폰 사용 통계를 조회할 수 있다

10.3 예외 처리 (CS 도구)

  • 관리자가 사용된 쿠폰을 수동으로 복구할 수 있다
  • 관리자가 만료된 쿠폰의 유효기간을 연장할 수 있다
  • 관리자가 특정 사용자에게 쿠폰을 직접 발급할 수 있다

구현 노트

TDD 원칙 준수:

  • 각 테스트는 하나의 작은 기능만 검증합니다
  • Red → Green → Refactor 사이클을 엄격히 따릅니다
  • 테스트 이름은 "무엇을", "어떤 상황에서", "어떻게 동작하는지" 명확히 표현합니다

구현 순서:

  • Phase 1-3: Domain 로직 (비즈니스 규칙, 외부 의존성 없음)
  • Phase 4-7: Application 로직 (Use Case, 도메인 조합)
  • Phase 8-9: Infrastructure 계층 (동시성, 성능, 영속성)
  • Phase 10: 관리자 기능 (부가 기능)

리팩토링 타이밍:

  • 중복 코드가 3번 이상 반복되면 즉시 추상화
  • 메서드가 5줄 이상이면 Extract Method 검토
  • 클래스가 200줄 이상이면 책임 분리 검토

Kent Beck의 조언:

"Make it work, make it right, make it fast." 먼저 동작하게 만들고, 그 다음 올바르게 만들고, 마지막에 빠르게 만들어라.