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

# 카트 라인 숨기기 및 레이블 변경하기

> 라인 트랜스폼과 comparator를 사용해 앱이 주입한 라인을 숨기고, 이름을 바꾸고, 렌더링 순서를 제어하는 Cart SDK 사용 사례예요.

쇼핑객이 봐서는 안 되는 라인을 숨기고, 어색하게 읽히는 라인의 이름을 바꾸고, 모든 것이 렌더링되는 순서를 제어하세요. 카트에 실제로 들어 있는 내용은 전혀 건드리지 않아요.

이 방법은 CSS나 `style.display = 'none'`으로 카트 요소를 숨기던 예전 패턴을 대체해요. 라인 트랜스폼은 카트가 렌더링될 때마다 적용되므로 업데이트, 재렌더링, 드로어 재오픈 후에도 유지돼요.

<div id="hide-a-line">
  ## 라인 숨기기
</div>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Hide free lines from the drawer. The cart total is unchanged.
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.finalLinePrice === 0) {
    line.setHidden(true);
  }
});
```

<Warning>
  **숨기기는 제거가 아니에요.** 숨겨진 라인은 쇼핑객의 카트에 남아 있고, 총액에도 포함되며, 체크아웃까지 이어져요; 단지 드로어에 그려지지 않을 뿐이에요. 다만 `getCart().items`와 `itemCount`에서는 빠지므로 여러분의 코드도 더 이상 보지 못해요. 정말로 없애고 싶다면 [`removeItem`](/ko/aftersell/cart/sdk-actions#removeitemkey)을 사용하세요.
</Warning>

숨길 만한 일반적인 것들:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  // An app-injected line, tagged with a private property.
  if (line.properties?._bundle_child) {
    line.setHidden(true);
  }

  // A specific SKU that shouldn't be shopper-managed.
  if (line.variantId === HIDDEN_VARIANT_ID) {
    line.setHidden(true);
  }

  // Gift cards issued by a loyalty app.
  if (line.isGiftCard && line.finalLinePrice === 0) {
    line.setHidden(true);
  }
});
```

<div id="relabel-a-line">
  ## 라인 레이블 변경하기
</div>

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  // Flag discounted lines.
  if (line.finalLinePrice < line.originalLinePrice) {
    line.setTitle(`${line.title} (On sale)`);
  }

  // Make the subscription cadence read naturally.
  if (line.sellingPlan) {
    line.setVariantTitle(`Delivered ${line.sellingPlan.name.toLowerCase()}`);
  }

  // Drop a meaningless variant label.
  if (line.variantTitle === 'Default Title') {
    line.setVariantTitle(null);
  }
});
```

라인에서 사용할 수 있는 네 가지 setter:

| Setter                            | 효과                                                                                                   |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `setHidden(bool)`                 | 드로어에서 라인을 숨겨요.                                                                                       |
| `setTitle(string)`                | 표시되는 제목을 변경해요.                                                                                       |
| `setVariantTitle(string \| null)` | 표시되는 옵션 레이블을 변경해요. `null`이면 제거돼요.                                                                    |
| `setInternalProperties(obj)`      | [커스텀 코드 블록](/ko/aftersell/cart/custom-code-blocks)에서 읽을 수 있도록 렌더링 전용 속성을 병합해요. Shopify에 절대 저장되지 않아요. |

<div id="control-the-order">
  ## 순서 제어하기
</div>

comparator는 `Array.prototype.sort`가 기대하는 것과 동일한 형태이며, 숨기기와 이름 변경 이후에 실행돼요:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Subscriptions first, then everything else.
window.aftersell.cart.hooks.registerLineComparator((lineA, lineB) => {
  return (lineB.sellingPlan ? 1 : 0) - (lineA.sellingPlan ? 1 : 0);
});
```

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
// Push free gifts and add-ons to the bottom.
window.aftersell.cart.hooks.registerLineComparator((lineA, lineB) => {
  return (lineA.finalLinePrice === 0 ? 1 : 0) - (lineB.finalLinePrice === 0 ? 1 : 0);
});
```

관심 없는 쌍에는 `0`을 반환하세요. comparator는 타이브레이커로 조합되므로, 처음으로 0이 아닌 값을 반환하는 것이 그 쌍을 결정하고, `0`을 반환하면 순서를 강제하지 않고 다음 comparator에 결정을 넘겨요.

<div id="hide-a-whole-block-not-a-line">
  ## 라인이 아닌 블록 전체 숨기기
</div>

라인 트랜스폼은 카트 라인에 작동해요. 국가, 마켓 또는 통화별로 다른 **블록** 설정을 표시하려면(예: 다른 Rewards 티어) [카트 에디터의 조건](/ko/aftersell/cart/blocks-overview#show-or-hide-by-market-country-or-currency)을 사용하세요. 코드가 필요 없고 카트 리디자인 후에도 유지돼요. 카트 총액과 카트 내용물은 에디터 조건 유형이 **아니에요**.

규칙이 조건으로 표현할 수 없는 것일 때(카트 내 상품 ID, 커스텀 총액 등) SDK를 사용하세요. 그런 경우 [shadow root](/ko/aftersell/cart/sdk-overview#shadowroot)에서 공개 `cart-external-*` 클래스를 쿼리하세요:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (state) => {
  const root = window.aftersell.cart.shadowRoot;
  if (!root) return;

  const rewards = root.querySelector('.cart-external-rewards');
  if (!rewards) return;

  const hasExcluded = state.items.some((line) => EXCLUDED_PRODUCT_IDS.includes(line.productId));
  rewards.style.display = hasExcluded ? 'none' : '';
});
```

<Warning>
  이 코드는 각 렌더링 이후에 실행되므로, 코드가 숨기기 전에 블록이 잠깐 나타났다 사라질 수 있어요. 조건부 렌더링에는 이런 문제가 없으므로, 가능한 경우 항상 그쪽을 선호하세요.
</Warning>

<div id="things-to-get-right">
  ## 제대로 처리해야 할 것들
</div>

* **트랜스폼은 설정 호출이에요.** Initialization 스크립트 맨 위에서 등록하세요; `ready()`가 필요 없어요.
* **모든 트랜스폼이 실행돼요.** 여러분의 트랜스폼은 다른 앱이 등록한 것과 조합돼요. 다른 앱의 것을 대체할 수 없고, 그쪽에서도 여러분의 것을 제거할 수 없어요.
* **트랜스폼은 가격, 수량, 아이덴티티를 변경할 수 없어요.** 렌더링되는 내용만 변경해요. 실제 변경에는 [액션](/ko/aftersell/cart/sdk-actions)을 사용하세요.
* **throw하는 트랜스폼은 조용히 건너뛰어요.** 나머지는 계속 실행돼요. 개발 중에는 [`aftersellCartDebugEvents`](/ko/aftersell/cart/sdk-overview#debugging)를 확인하세요.
* **`registerLineTransform`은 등록 해제 함수를 반환**하므로, 나중에 되돌려야 할 때 사용하세요.

<div id="where-to-go-next">
  ## 다음 단계
</div>

* **[Hooks](/ko/aftersell/cart/sdk-hooks)**: 전체 훅 레퍼런스.
* **[Cart 객체](/ko/aftersell/cart/sdk-cart-object)**: 분기할 수 있는 모든 필드.
* **[커스텀 CSS](/ko/aftersell/cart/custom-css)**: `cart-external-*` 클래스 규칙.
