> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aftersell.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription upgrade 블록

> Aftersell Cart Subscription upgrade 하위 블록: 자격이 있는 일회성 라인을 카트에서 구독으로 전환하세요.

> **Subscription upgrade** 블록은 [**Cart items**](/ko/aftersell/cart/cart-items-block) 안에 중첩되는 하위 블록이에요. 쇼핑객이 자격이 있는 일회성 라인 아이템을 카트에서 바로 구독으로 전환하도록 유도하여 결정의 순간에 일회성 구매를 반복 수익으로 바꾸고, 이미 구독 중인 쇼핑객은 해당 라인에서 플랜을 변경하거나 취소할 수 있게 해요.

<div id="behavior">
  ## 동작
</div>

* **자격이 있는 라인에만 나타나요.** 블록은 상품의 판매 플랜을 읽고, 구독 플랜이 없는 상품의 라인에는 아무것도 렌더링하지 않아요.
* **리워드 사은품에는 절대 표시되지 않아요.** 자동으로 지급된 무료 사은품을 구독하면 리워드 상태가 사라지므로, 해당 라인에서는 프롬프트가 표시되지 않아요.
* **일회성 라인**에는 업그레이드 CTA(행동 유도 문구)를 표시해요.
* **이미 구독 중인 라인**에는 플랜 선택기와 "일회성으로 다운그레이드" 옵션을 표시해요.

<div id="settings">
  ## 설정
</div>

| 설정                   | 제어하는 것                                                       | 기본값                             |
| -------------------- | ------------------------------------------------------------ | ------------------------------- |
| **Button text**      | 일회성 라인의 업그레이드 CTA. `{{discount}}`와 `{{plan name}}` 토큰을 지원해요. | `Subscribe & Save`              |
| **Unsubscribe text** | 구독 라인을 일회성 구매로 되돌리는 옵션.                                      | `Downgrade - One time purchase` |

<div id="placement-and-limits">
  ## 배치 및 제한
</div>

* **부모:** Cart items 안에만 중첩돼요.
* **최대:** 카트당 1개.
* 기본으로 추가되지 않아요. 잠겨 있지 않아 제거하거나 숨길 수 있어요.

하위 블록이므로 라인마다 렌더링되며, Product row를 기준으로 어디에 배치하는지에 따라 상품 콘텐츠 위 또는 아래에 위치해요. [하위 블록 위치 지정 방식](/ko/aftersell/cart/cart-items-block#sub-blocks-and-how-they-position)을 참고하세요.

<div id="custom-template">
  ## 커스텀 템플릿
</div>

Code 탭에서 [커스텀 템플릿](/ko/aftersell/cart/custom-templates)을 지원하며, 이 블록의 기본 마크업을 여러분의 JSX로 대체해요. 다음은 블록이 받는 props예요.

이 블록은 두 가지 상태 중 하나를 렌더링하며, `view.state`가 어느 쪽인지 알려줘요. 커스텀 템플릿 안에서 `view`는 절대 `null`이 아니에요: 라인에 플랜이 없으면 블록은 아무것도 렌더링하지 않고 템플릿도 호출되지 않아요.

| Prop              | 타입                                 | 용도                                                                                                           |
| ----------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `view`            | `object`                           | 라인의 상태. `{ state: 'upgrade', buttonText, planId }` 또는 `{ state: 'subscribed', plans, activePlanId }` 중 하나예요. |
| `title`           | `string`                           | 블록의 제목이 아닌 **상품의** 제목이에요. 기본 템플릿은 플랜 선택기의 접근성 레이블을 만드는 데만 사용해요.                                              |
| `unsubscribeText` | `string`                           | 일회성으로 다운그레이드하는 옵션의 레이블.                                                                                      |
| `busy`            | `boolean`                          | 플랜 변경이 진행 중인 동안 `true`.                                                                                      |
| `selectPlan`      | `(planId: number \| null) => void` | 구독하거나 플랜을 전환해요. 구독 해지는 `null`을 전달하세요.                                                                        |
| `onChange`        | `(event: Event) => void`           | `<select>`용으로 미리 만들어진 `onChange`로, 값을 직접 파싱할 필요가 없어요.                                                        |
| `oneTimeValue`    | `string`                           | "일회성 구매"를 나타내는 센티널 `<option>` 값.                                                                             |
| `line`            | `AftersellCartLine`                | 이 블록이 속한 [카트 라인](/ko/aftersell/cart/sdk-cart-object#cart-lines).                                             |
| `productId`       | `number`                           | Shopify 상품 ID.                                                                                               |
| `variantId`       | `number`                           | Shopify 옵션 ID.                                                                                               |

`view.plans`의 각 항목은 `{ id: number, name: string, discountPercent: number }`예요.

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function CustomTemplate(props) {
  const { view } = props;

  if (view.state === 'upgrade') {
    return (
      <button type="button" onClick={() => props.selectPlan(view.planId)} disabled={props.busy}>
        {view.buttonText}
      </button>
    );
  }

  return (
    <div>
      <select
        aria-label={`Subscription plan — ${props.title}`}
        value={String(view.activePlanId)}
        onChange={props.onChange}
        disabled={props.busy}
      >
        {view.plans.map((plan) => (
          <option key={plan.id} value={String(plan.id)}>
            {plan.name}{plan.discountPercent > 0 ? ` (${plan.discountPercent}% off)` : ''}
          </option>
        ))}
        <option value={props.oneTimeValue}>{props.unsubscribeText}</option>
      </select>
    </div>
  );
}
```

<Note>
  `<select>`에는 `onChange`를, 버튼에는 `selectPlan`을 사용하세요. `onChange`는 이미 `oneTimeValue` 센티널을 처리해요; `<select>`에 직접 핸들러를 연결한다면 `oneTimeValue`와 비교해서 직접 `selectPlan(null)`을 호출해야 해요.
</Note>

<div id="design">
  ## 디자인
</div>

설정 패널의 **Design** 섹션에서 이 블록의 스타일을 지정하세요. 이는 전역 디자인 위에 적용되는 블록별 오버라이드이며, 비워 두면 전역 디자인으로 폴백돼요.

디자인 설정이 무엇인가요? 여기서 자세히 알아보세요: [디자인 설정](/ko/aftersell/cart/design-settings).
