> ## 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.

# Upsells 블록

> Aftersell Cart Upsells 블록 — 드로어에 표시되는 Strategy가 선택한 상품 제안이에요.

> **Upsells** 블록은 여러분이 선택한 **Strategy**가 고른 상품 제안을 카트 드로어에 표시해요. 쇼핑객이 카트를 열면, 블록은 현재 카트 내용과 구성한 타겟팅 규칙을 기반으로 Strategy가 반환하는 상품을 보여줘요.<br /><br />쇼핑객이 카트를 여는 순간에 관련성 높은 상품 제안을 표시하여 평균 주문 금액을 높이세요. Strategy가 카트 내용과 타겟팅 규칙을 기반으로 표시할 항목을 선택해요.

<Info>
  항상 여러분이 선택한 하나의 상품을 표시하는 [**Product add-on**](/ko/aftersell/cart/product-add-on-block) 블록과 달리, Upsells는 표시할 항목을 결정하는 Strategy에 의해 구동돼요.
</Info>

<Frame>
  <img src="https://mintcdn.com/aftersell/1Y3gBpUfxv16VGSW/images/aftersell/cart-upsells-block-strategy-picked-product-recommendations.png?fit=max&auto=format&n=1Y3gBpUfxv16VGSW&q=85&s=5ce00c7f12e1ddf32a0533eb700d22ee" alt="카트 드로어에서 Strategy가 선택한 상품 추천을 표시하는 Upsells 블록" width="1228" height="510" data-path="images/aftersell/cart-upsells-block-strategy-picked-product-recommendations.png" />
</Frame>

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

* 상품은 쇼핑객의 현재 카트를 기반으로 실시간으로 가져오므로, 제안이 실제 카트 내용을 반영해요.
* **상품이 하나도 확인되지 않으면 전체 섹션이 숨겨져요** — Strategy가 연결되지 않았거나, Strategy가 아무것도 반환하지 않거나, 반환된 상품 중 구매 가능한 것이 없는 경우예요. 쇼핑객이 빈 Upsells 섹션을 보는 일은 없어요.
* 반환된 제안에 할인이 포함되어 있으면 쇼핑객은 정직한 취소선과 할인 배지를 보게 되고, 할인은 체크아웃 시 적용돼요.

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

| 설정                        | 제어하는 것                                                                    | 기본값                     |
| ------------------------- | ------------------------------------------------------------------------- | ----------------------- |
| **Title**                 | 제안 위의 서식 있는 텍스트 제목. 굵게, 기울임, 정렬, 색상을 지원해요.                                | `You may also like`     |
| **Add button text**       | 각 상품의 추가 버튼 레이블.                                                          | `Add`                   |
| **Strategy**              | 표시할 상품을 선택하는 Strategy.                                                    | 자동으로 할당되는 Shopify AI 전략 |
| **Layout**                | **Carousel** 또는 **List**.                                                 | Carousel                |
| **Maximum products**      | 최대 표시 상품 수. `1`–`12`를 허용해요.                                               | `4`                     |
| **Show compare-at price** | 취소선 처리된 비교 가격 표시 여부.                                                      | 켜짐                      |
| **Show product reviews**  | 각 업셀 카드에 별점과 리뷰 수 표시 여부. 평점은 리뷰 앱의 상품 메타필드에서 가져오며 유효한 리뷰 데이터가 있을 때만 나타나요. | 꺼짐                      |

<div id="supported-review-apps">
  ### 지원되는 리뷰 앱
</div>

다음 메타필드 기반 리뷰 앱이 지원돼요: Shopify Product Reviews, Junip, Okendo, Growave, Fera, Stamped, Loox, REVIEWS.io, Automizely Reviews, Judge.me, Ali Reviews, Trustoo, Rivo, Rivyo, Vitals. Yotpo는 상품 메타필드가 아닌 별도의 API를 사용하기 때문에 지원되지 않아요.

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

Upsells 블록은 **Design** 패널에 블록별 디자인 오버라이드가 있어요. 이 블록에 한해 카트의 전역 디자인 설정을 재정의해요. 값을 비워 두면 전역 설정을 상속해요.

<div id="text-styling">
  ### 텍스트 스타일
</div>

Upsells 블록의 Design 설정에는 **Text** 섹션이 있어요. 각 업셀 카드의 개별 텍스트 요소의 타이포그래피를 제어하는 데 사용하세요. 선택기에서 텍스트 요소를 선택해 설정을 조정하세요:

| 설정                 | 제어 대상                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| **Text color**     | 선택한 텍스트 요소의 색상이에요.                                                                               |
| **Font**           | **Theme font**(테마의 폰트를 상속) 또는 **Custom font**(테마가 이미 로드하는 폰트의 이름을 입력). **Heading**에서만 사용할 수 있어요. |
| **Size**           | 픽셀 단위의 글꼴 크기예요.                                                                                  |
| **Weight**         | 글꼴 굵기: Light, Regular, Medium, Semibold, Bold.                                                   |
| **Line height**    | 글꼴 크기에 대한 배수로 지정하는 줄 높이예요(예: `1.4`).                                                             |
| **Letter spacing** | 픽셀 단위의 자간이에요. 음수 값은 텍스트를 좁혀요.                                                                    |

스타일을 지정할 수 있는 텍스트 요소는 카테고리별로 그룹화되어 있어요:

**Heading**

* **Heading** — 업셀 카드 위의 섹션 헤딩이에요(예: *You may also like*). 커스텀 폰트 패밀리도 지원해요. 굵기와 색상은 위의 Rich Text Editor에서 설정해요.

**Product**

* **Product title** — 각 업셀 카드의 상품 이름이에요.
* **Review count** — **Show product reviews**가 활성화되었을 때 표시되는 리뷰 수예요.

**Pricing**

* **Price** — 각 카드의 현재 가격이에요.
* **Compare-at price** — 취소선 처리된 원래 가격이에요.
* **Discount** — 할인 라벨이에요(예: *20% off*).

필드를 비워두면 요소의 기본값이 유지돼요.

<Tip>
  장바구니 미리보기에서 텍스트 요소를 직접 클릭하면 해당 요소가 강조 표시되고 패널에서 컨트롤이 자동으로 열려요.
</Tip>

<div id="tile-colors">
  ### 타일 색상
</div>

| 설정                        | 제어하는 것              | 기본값       |
| ------------------------- | ------------------- | --------- |
| **Tile background color** | 각 업셀 상품 카드의 배경 채우기. | 투명        |
| **Tile border color**     | 각 업셀 상품 카드의 테두리 색상. | `#F6F6F7` |

<div id="reviews">
  ### 리뷰
</div>

**Show product reviews**가 활성화되면 Design 패널의 **Reviews** 섹션에서 별 색상을 커스터마이즈할 수 있어요.

| 설정                   | 제어하는 것           | 기본값       |
| -------------------- | ---------------- | --------- |
| **Star color**       | 각 별의 채워진 부분.     | `#FDCC0D` |
| **Empty star color** | 각 별의 채워지지 않은 부분. | `#D1D5DB` |

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

* **영역:** 본문(body) 또는 하단(bottom).
* **최대:** 카트 상태당 1개 — 채워진 카트와 빈 카트가 각각 하나씩 가질 수 있어요.
* **상태:** 채워진 카트와 빈 카트 모두.
* 기본으로 추가되지 않아요. 잠겨 있지 않아 제거하거나 숨길 수 있어요.

<div id="selecting-a-strategy">
  ## 전략 선택하기
</div>

Upsells 블록은 비어 있는 상태로 시작하지 않아요: Strategy가 설정되지 않으면 Aftersell이 스토어의 Shopify AI 전략을 찾아 — 아직 없다면 생성해서 — 채워 넣으므로 블록이 바로 작동해요. 변경하려면 **Strategy** 선택기를 여세요. 선택기에는 두 그룹이 있어요:

**Quick start**

* **Create strategy from selected products** — 특정 상품을 직접 선택하면 Strategy가 자동으로 생성돼요.
* **Create strategy from scratch** — 카트 에디터를 떠나지 않고 규칙을 만들 수 있도록 Strategy 에디터를 열어요.

**Strategies**

* **Shopify AI recommendations** — Shopify 자체 추천을 기반으로 하는 Strategy를 생성하며, 이후 모든 곳에서 **Shopify AI recommended products**라는 이름으로 표시돼요. 스토어에는 하나의 Shopify AI 전략만 필요하기 때문에, 이미 있으면 이 항목은 사라져요.
* 기존 Strategy들이 이름별로 나열돼요. 검색 필드에 입력해서 필터링하세요.

Strategy가 선택되면 블록 안의 전략 행에 그 이름이 나타나요.

<div id="managing-a-selected-strategy">
  ## 선택된 전략 관리하기
</div>

Strategy가 연결되면 전략 행에 **•••**(줄임표) 버튼이 나타나요. 클릭하면 액션 메뉴가 열려요:

* **Edit strategy** — 새 탭에서 Strategy 에디터를 열어, 카트 에디터 세션과 저장하지 않은 변경 사항이 그대로 유지돼요. 이 옵션은 자동으로 관리되고 편집 가능한 규칙이 없는 Shopify AI 추천 전략에는 제공되지 않아요.
* **Remove from upsell** — 이 블록에서 Strategy를 분리해요. Strategy 자체는 삭제되지 않고 Strategies 목록에 그대로 남아 있어요.

새 탭에서 Strategy를 편집해도 카트 에디터 세션에는 영향이 없어요 — 카트 에디터 탭으로 돌아가 작업 손실 없이 계속 구성할 수 있어요.

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

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

<div id="block-content">
  ### 블록 콘텐츠
</div>

| Prop            | 타입                     | 용도                                                 |
| --------------- | ---------------------- | -------------------------------------------------- |
| `title`         | `string`               | 섹션 제목.                                             |
| `addButtonText` | `string`               | 장바구니 담기 버튼 레이블.                                    |
| `layout`        | `'carousel' \| 'list'` | 가로 스크롤 또는 줄바꿈. 이 값으로 마크업을 분기하세요.                   |
| `upsells`       | `UpsellCard[]`         | 표시 준비가 된 상품들. 아래 [카드 구조](#the-upsell-card)를 참고하세요. |
| `isLoading`     | `boolean`              | 업셀 상품을 아직 가져오는 동안 `true`.                          |

<div id="adding-to-cart">
  ### 카트에 추가하기
</div>

| Prop              | 타입                                               | 용도                                               |
| ----------------- | ------------------------------------------------ | ------------------------------------------------ |
| `selectVariant`   | `(productId: string, variantId: number) => void` | 상품의 옵션을 선택해요.                                    |
| `handleAdd`       | `(productId: string) => void`                    | 해당 상품의 선택된 옵션을 카트에 추가해요.                         |
| `addingProductId` | `string \| null`                                 | 현재 추가 중인 상품으로, 그 버튼만 비활성화할 수 있어요. 유휴 상태면 `null`. |

<div id="carousel-controls">
  ### 캐러셀 컨트롤
</div>

`layout`이 `'carousel'`일 때만 해당돼요.

| Prop           | 타입                                    | 용도                                                   |
| -------------- | ------------------------------------- | ---------------------------------------------------- |
| `trackRef`     | `{ current: HTMLDivElement \| null }` | 화살표가 스크롤할 수 있도록 `ref={props.trackRef}`로 스크롤러에 연결하세요. |
| `atStart`      | `boolean`                             | 트랙이 시작 가장자리에 있으면 `true`. 왼쪽 화살표를 비활성화하세요.            |
| `atEnd`        | `boolean`                             | 트랙이 끝 가장자리에 있으면 `true`. 오른쪽 화살표를 비활성화하세요.            |
| `scrollByCard` | `(direction: 1 \| -1) => void`        | 트랙을 카드 하나만큼 왼쪽(`-1`) 또는 오른쪽(`1`)으로 스크롤해요.            |

<div id="the-upsell-card">
  ### 업셀 카드
</div>

`upsells`의 각 항목:

| 필드                        | 타입                        | 용도                                                                                                                                                                                                                           |
| ------------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `productId`               | `string`                  | 상품 GID. React key와 장바구니 담기 대상으로 사용하세요.                                                                                                                                                                                       |
| `title`                   | `string`                  | 상품 제목.                                                                                                                                                                                                                       |
| `description`             | `string`                  | 일반 텍스트 설명. 상품에 없으면 `''`.                                                                                                                                                                                                     |
| `url`                     | `string \| null`          | 상품 페이지 URL. 사용할 수 없으면 `null`.                                                                                                                                                                                                |
| `imageUrl`                | `string \| null`          | 대표 이미지. 상품에 없으면 `null`.                                                                                                                                                                                                      |
| `priceLabel`              | `string`                  | 표시할 가격으로, 이미 포맷되어 있어요. 할인 시에는 할인 가격, 그 외에는 옵션 가격이에요.                                                                                                                                                                         |
| `compareAtLabel`          | `string \| null`          | 이미 포맷된 취소선 원래 가격. 취소선 처리할 것이 없으면 `null`.                                                                                                                                                                                     |
| `discountLabel`           | `string \| null`          | `(20% off)` 같은 인라인 할인 레이블. 할인이 없으면 `null`.                                                                                                                                                                                   |
| `review`                  | `object \| null`          | `{ rating, count, stars }`이며, `stars`는 부분 채우기가 반영된 미리 렌더링된 이미지 URL 5개예요. 각각 이미지 요소로 렌더링하세요. 리뷰가 꺼져 있거나 상품에 리뷰가 없으면 `null`.                                                                                                   |
| `options`                 | `Array<{ name, values }>` | 선택기나 스와치를 만들기 위한 옵션 그룹.                                                                                                                                                                                                      |
| `variants`                | `array`                   | 옵션 조합들. 아래를 참고하세요.                                                                                                                                                                                                           |
| `selectedVariantId`       | `number`                  | 현재 선택된 옵션. `selectVariant`에 전달하세요.                                                                                                                                                                                           |
| `hasMultipleVariants`     | `boolean`                 | 옵션 선택기를 렌더링할지 여부.                                                                                                                                                                                                            |
| `vendor`                  | `string`                  | 상품의 공급업체.                                                                                                                                                                                                                    |
| `selectedVariantImageUrl` | `string \| null`          | 선택된 옵션 자체의 이미지. 없으면 `null` — `imageUrl`로 폴백하세요.                                                                                                                                                                              |
| `variantTitle`            | `string \| null`          | 선택된 옵션의 옵션 값들(예: `Medium / Blue`)로, 이미 해석되어 있어요. 옵션에 실제 제목이 없을 때는 `null` — 비어 있거나 Shopify의 `Default Title` 자리표시자일 때예요. 이름이 지정된 옵션이 하나뿐인 상품도 그 이름을 반환하므로, `hasMultipleVariants`로 분기하지 말고 `{upsell.variantTitle && …}`로 가드하세요. |

`variants`의 각 항목은 `id`, `title`, `price`와 `compareAtPrice`(원시, 미포맷, 통화의 주 단위 문자열), `availableForSale`, `imageUrl`, `sku`, `selectedOptions`(`[{ name, value }]`)를 가져요.

<Warning>
  **구매 가능 여부는 옵션별이 아니라 조합별이에요.** `options`는 렌더링할 그룹을 제공하지만, 특정 선택이 구매 가능한지는 `variants`의 일치하는 항목에 있어요. 쇼핑객이 선택한 조합을 `variants`와 대조해서 해당 항목의 `availableForSale`로 게이트하세요. `options`의 모든 값이 주문 가능하다고 가정하지 마세요.
</Warning>

<Note>
  `priceLabel`과 `compareAtLabel`은 이미 표시용으로 포맷되어 있고, `variants[].price`와 `variants[].compareAtPrice`는 통화의 주 단위 원시 문자열이에요. 둘을 섞지 마세요: 레이블은 표시용으로 쓰고, 원시 값은 비교에만 사용하세요.
</Note>

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

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

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