Skip to content

Story: Grandfather 정책 적용 로직

메타

항목
Story IDE-05-S-09
EpicE-05 요금제 정책 재설계 및 가드레일
상태draft
우선순위P0
규모M
담당창훈님 (하록님, 수민님)

사용자 스토리

As a 기존 유료 고객, I want 현재 조건을 유지하면서 새 요금제 체계로 전환되고 싶다, So that 갑작스러운 가격 인상이나 기능 제한 없이 서비스를 이용할 수 있다.


수락 기준 (Acceptance Criteria)

AC-01: Grandfather 고객 식별

항목내용
Given요금제 정보 조회
WhenGrandfather 플래그 확인
ThenisGrandfather = TRUE면 특별 처리

식별 조건:

Grandfather 조건:
1. PortOne PG로 결제 중인 기존 유료 고객
2. 새 요금제 체계 도입 이전 가입

AC-02: 기존 가격 유지

항목내용
GivenGrandfather 고객
When결제 갱신
Then기존 가격으로 결제

가격 매핑:

기존 planType신규 티어기존 가격신규 가격
basic1_*Starter₩22,000₩33,000
pro3_*Basic₩44,000₩55,000
pro10_*Pro₩110,000₩110,000
pro20_*Business₩220,000₩330,000

로직:

typescript
getPrice(bizPlanInfo: BizPlanInfo): number {
  if (bizPlanInfo.isGrandfather) {
    return this.getLegacyPrice(bizPlanInfo.planType);
  }
  return this.getTierPrice(bizPlanInfo.tierId);
}

AC-03: 기존 Feature 한도 유지

항목내용
GivenGrandfather 고객
WhenFeature 체크
Then기존 한도 적용 (더 유리한 경우)

한도 비교:

Feature기존 PRO 10신규 ProGrandfather 적용
사업장 수10개3개10개 (기존 유지)
캠페인 분석제한 없음30개제한 없음

로직:

typescript
getFeatureLimit(bizId: string, featureCode: string): number {
  const planInfo = await this.getPlanInfo(bizId);

  if (planInfo.isGrandfather) {
    const legacyLimit = this.getLegacyLimit(planInfo.planType, featureCode);
    const newLimit = this.getNewLimit(planInfo.tierId, featureCode);

    // 더 유리한 쪽 적용
    return Math.max(legacyLimit, newLimit);
  }

  return this.getNewLimit(planInfo.tierId, featureCode);
}

AC-04: Toss PG 전환 시 Grandfather 해제

항목내용
GivenGrandfather 고객이 Toss PG로 전환
When결제 수단 변경 완료
ThenisGrandfather = FALSE, 신규 가격 적용

전환 플로우:

Grandfather 고객 (PortOne)

  Toss PG 전환 요청

  전환 완료

  isGrandfather = FALSE

  신규 가격 적용 (다음 결제 주기부터)

AC-05: Grandfather 해제 안내

항목내용
GivenGrandfather 고객
WhenToss PG 전환 시도
Then가격 변경 안내 + 확인 요청

UI 스펙:

┌────────────────────────────────────────┐
│ ⚠️ 결제 수단 변경 안내                 │
├────────────────────────────────────────┤
│                                        │
│ 현재 기존 고객 특별 가격이 적용되어     │
│ 있습니다.                              │
│                                        │
│ 결제 수단을 Toss로 변경하시면          │
│ 다음 결제부터 신규 가격이 적용됩니다.   │
│                                        │
│ 현재 가격: ₩49,900/월                  │
│ 변경 후:   ₩110,000/월                 │
│                                        │
│ 변경하시겠습니까?                       │
│                                        │
│    [취소]  [변경하기]                  │
└────────────────────────────────────────┘

태스크 분해

Task 1: Grandfather 조회 로직 AC-01

  • [ ] 1.1: PlanGuardService에 isGrandfather 체크 추가
  • [ ] 1.2: getPlanInfo 응답에 isGrandfather 포함

Task 2: 가격 분기 로직 AC-02

  • [ ] 2.1: 기존 가격 테이블/매핑 정의
  • [ ] 2.2: getPrice() 메서드 분기 처리
  • [ ] 2.3: 결제 서비스에 분기 로직 적용

Task 3: Feature 한도 분기 AC-03

  • [ ] 3.1: 기존 한도 테이블/매핑 정의
  • [ ] 3.2: getFeatureLimit() 메서드 분기 처리
  • [ ] 3.3: Math.max 로직으로 유리한 쪽 적용

Task 4: PG 전환 시 해제 AC-04

  • [ ] 4.1: 결제 수단 변경 API에 Grandfather 해제 로직
  • [ ] 4.2: isGrandfather = FALSE 업데이트
  • [ ] 4.3: 변경 이력 로깅

Task 5: 전환 안내 UI AC-05

  • [ ] 5.1: FE - Toss 전환 시 가격 변경 안내 모달
  • [ ] 5.2: 현재 가격 vs 변경 후 가격 표시
  • [ ] 5.3: 확인 후 전환 진행

Dev Notes (AI Agent 최적화)

영향 받는 소스 트리

BE:
src/
├── service/
│   ├── plan-guard.service.ts         # 🔄 수정 (Grandfather 로직)
│   └── payment.service.ts            # 🔄 수정 (가격 분기)
├── dto/
│   └── plan-info.dto.ts              # 🔄 수정 (isGrandfather)
└── constants/
    └── legacy-plan.constant.ts       # 🆕 기존 가격/한도 매핑

FE:
src/
└── components/
    └── payment/
        └── GrandfatherWarningModal.tsx  # 🆕

기존 가격/한도 매핑 상수

typescript
// legacy-plan.constant.ts
export const LEGACY_PLAN_CONFIG = {
  'basic1': {
    price: 22000,
    limits: {
      maxVendors: 1,
      maxCampaigns: null,  // 무제한
      maxKeywords: null,
    }
  },
  'pro3': {
    price: 44000,
    limits: {
      maxVendors: 3,
      maxCampaigns: null,  // 무제한
      maxKeywords: null,
    }
  },
  'pro10': {
    price: 110000,
    limits: {
      maxVendors: 10,
      maxCampaigns: null,
      maxKeywords: null,
    }
  },
  'pro20': {
    price: 220000,
    limits: {
      maxVendors: 20,
      maxCampaigns: null,
      maxKeywords: null,
    }
  },
};

// planType → legacyKey 매핑
export function getLegacyKey(planType: string): string | null {
  if (planType.startsWith('basic1_')) return 'basic1';
  if (planType.startsWith('pro3_')) return 'pro3';
  if (planType.startsWith('pro10_')) return 'pro10';
  if (planType.startsWith('pro20_')) return 'pro20';
  return null;
}

Grandfather 판정 플로우

요금제 정보 요청

  BizPlanInfo 조회

  isGrandfather 확인

    ┌─── TRUE ───┐        ┌─── FALSE ───┐
    ↓            ↓        ↓             ↓
기존 가격    기존 한도   신규 가격    신규 한도
(유지)     (유리한 쪽)   (적용)      (적용)

의존성

의존설명상태
E-05-S-01PlanTier 테이블선행 필수
E-05-S-08마이그레이션 완료선행 필수

비즈니스 고려사항

Grandfather 정책 목적

  1. 기존 고객 보호: 갑작스러운 가격 인상 방지
  2. Toss PG 전환 유도: 전환 조건으로 활용
  3. 점진적 전환: 자연스러운 신규 체계 도입

예상 시나리오

시나리오Grandfather가격
기존 PRO 10, PortOne 유지₩49,900
기존 PRO 10, Toss 전환₩110,000
신규 가입₩110,000
Trial 후 Pro 결제₩110,000

생성일: 2026-01-27

장사왕 Product Team