Skip to main content
커스텀 템플릿을 사용하면 개별 블록의 렌더링 방식을 재정의할 수 있어요. 블록의 기본 UI 대신, 블록이 평소 사용하는 것과 동일한 데이터를 사용해 여러분의 JSX를 렌더링해요. 자체 블록이 아니라 여러 블록에 걸친 기능이에요: 대부분의 블록이 Code 탭에서 이 기능을 제공해요. 이 페이지는 모든 블록에 적용되는 내용을 다뤄요. 특정 블록이 전달하는 props는 해당 블록의 레퍼런스로 이동하세요.

커스텀 템플릿 vs. 커스텀 코드 블록

이름은 비슷하지만 하는 일이 달라요:
  • 커스텀 템플릿기존 블록의 렌더링을 직접 만든 마크업으로 대체하고, 해당 블록의 자체 데이터(Header의 제목과 아이템 수, Summary의 총액 등)를 전달해요. 새로운 것을 추가하지 않고 블록 하나의 스타일을 바꿔요.
  • Custom code 블록은 장바구니 어디에나 임의의 HTML 또는 React로 된 새 블록을 추가해요.
기본 블록이 거의 맞지만 다른 레이아웃이나 마크업이 필요할 때는 커스텀 템플릿을, 기본 블록이 다루지 않는 것을 추가하고 싶을 때는 Custom code 블록을 사용하세요.

커스텀 템플릿 사용하기

  1. 에디터에서 블록을 선택하고 Code 탭을 여세요.
  2. 기본 템플릿을 편집하세요. 커스텀 템플릿은 JSX 전용이에요(HTML/JSX 선택은 Custom code 블록에만 있어요).
  3. Compile을 클릭하세요. 컴파일은 타입을 제거하고 JSX를 트랜스파일하므로 구문(syntax) 오류를 잡아내요. 타입 오류는 컴파일을 막지 않아요 — 에디터가 입력하는 동안 인라인으로 표시하며, 블록의 props를 자동 완성하는 것과 같은 IntelliSense를 사용해요.
  4. 템플릿을 켜서 장바구니가 기본 렌더링 대신 이를 사용하도록 하세요.
  5. Reset to default는 언제든지 블록의 원래 템플릿을 복원해요.

AI로 템플릿 작성하기

Code 탭에는 Copy AI prompt 버튼(✦ 마법봉 아이콘)이 있어요. 클릭하면 AI 채팅 세션(Claude, ChatGPT 등)에 바로 붙여넣을 수 있는 완결된 브리프가 클립보드에 복사돼요. 프롬프트에는 AI가 해당 블록에 유효한 템플릿을 작성하는 데 필요한 모든 것이 포함돼요:
  • 컴파일 규칙(단일 표현식, export default 없음, import 없음)
  • 에디터의 IntelliSense가 표시하는 것과 일치하는, 블록이 받는 정확한 props
  • 에디터가 강제하는 잠긴 함수 시그니처
  • 블록별 규칙(금액 형식, 연결해야 할 핸들러, 접근성 요구 사항)
  • 현재 템플릿을 붙여넣고 원하는 변경 사항을 설명하는 작성란
복사한 후 AI 세션을 열고 프롬프트를 붙여넣은 다음, 하단의 두 빈칸(현재 템플릿과 원하는 변경 사항)을 채우고 전송하세요. AI가 에디터에 다시 붙여넣고 컴파일할 수 있는 완전한 템플릿을 반환해요.
작성란을 비워 두지 말고 기존 템플릿을 붙여넣으세요. AI가 이를 출발점으로 사용하므로, 이미 적용한 커스터마이징이 기본값으로 대체되지 않고 그대로 유지돼요.
프롬프트는 각 블록에 특화되어 있어요. Copy AI prompt 버튼은 커스텀 템플릿을 지원하는 블록에만 표시돼요.
시작점이 되는 기본 템플릿은 블록의 기본 마크업이 그대로 작동하는 사본이므로, 빈 페이지가 아니라 항상 올바르게 렌더링되는 참조본을 수정하게 돼요. 그 참조본이 다시 필요하면 언제든 Reset to default를 사용하세요.항상 바이트 단위로 동일하지는 않아요. Header의 기본 템플릿은 기본 마크업에는 배치 위치가 없는 logoUrl도 렌더링하므로, 그 템플릿을 켜는 것이 업로드한 헤더 이미지가 처음 나타나는 방법이에요.

템플릿이 대체하는 것

템플릿은 블록의 렌더링을 전부 대체해요. JSX 주위에 남는 래퍼가 없으므로, 무언가를 삭제하기 전에 알아 둘 결과가 있어요:
Design 탭이 사람들이 가장 많이 걸리는 부분이에요. 커스텀 템플릿이 활성화되어 있는 동안 Design 탭의 필드는 비활성화되고 “Design” 제목 옆에 경고 아이콘이 표시돼요. 아이콘 위에 마우스를 올리면 이유를 볼 수 있어요. 대신 인라인 스타일이나 직접 만든 CSS로 템플릿에서 블록의 스타일을 지정하세요. 커스텀 템플릿을 끄는 즉시 필드가 다시 활성화돼요.
유지되는 것: 장바구니 내 블록의 위치, 표시 여부 토글, 설정(여전히 받는 props에 반영됨), 장바구니의 커스텀 CSS 패널, 그리고 기본 로딩 스켈레톤이에요. 마지막 항목이 사람들을 놀라게 해요. 블록은 템플릿에 도달하기 전에 장바구니가 아직 로딩 중인지 확인하므로, 로드 중에는 기본 스켈레톤이 렌더링되고 장바구니가 준비된 후에만 템플릿이 실행돼요. 로딩 상태를 직접 만들 필요가 없어요.

템플릿 안에서 사용 가능한 것

템플릿은 하나의 함수 컴포넌트예요. TSX에서 컴파일되므로 타입 주석이 허용되며 컴파일 시 제거돼요. 그래서 기본 템플릿에 타입 주석이 있어요:
시그니처 줄과 닫는 중괄호는 잠겨 있어요 — 에디터가 둘 다 편집을 허용하지 않으며, 마우스를 올리면 “Locked — this line can’t be edited.”가 표시돼요. 그 사이에 본문을 작성해요. Reset to default만이 이를 교체할 수 있어요. 그 밖에 중요한 것:
  • 다섯 가지 훅을 사용할 수 있어요: useState, useEffect, useMemo, useRef, useCallback. 그리고 <>…</>를 위한 Fragment도 있어요.
  • import는 없어요. 아무것도 import할 수 없고, 스코프에 React 객체가 없으므로 React.useReducer, React.Children도 없어요. 위 목록에 없는 훅은 사용할 수 없어요.
  • props는 읽기 전용이에요. prop을 변경해도 유용한 결과가 없어요. 장바구니를 변경하려면 props에 직접 쓰지 말고 블록이 제공하는 핸들러 props(onClose, increment, selectPlan 등)를 사용하세요.
  • window에 접근할 수 있으므로, 블록의 props가 다루지 않는 것이 필요할 때 템플릿에서 window.aftersell.cart를 통해 Cart SDK를 호출할 수 있어요.

모든 블록에 공통되는 규칙

세 가지 규칙이 어디서나 적용되며, 알아 두면 대부분의 추측이 사라져요:
  • *Html props는 미리 정제된 리치 텍스트예요. dangerouslySetInnerHTML로 렌더링하세요. 이미 장바구니의 정제기(sanitizer)를 거쳤고, {{total_price}} 같은 머천트 토큰은 이미 치환되어 있어요.
  • string으로 도착하는 가격은 이미 스토어 통화 형식으로 포맷되어 있어요. number 가격은 센트 단위예요. 블록은 둘 중 하나를 제공하며, 각 블록의 표에 어느 것인지 나와 있어요.
  • 템플릿 안에서 isLoading은 항상 false예요. 블록은 기본 스켈레톤을 렌더링하고 장바구니가 로드된 후에만 템플릿을 호출하므로, 이 prop은 분기용이 아니라 완결성을 위해 전달돼요.
일부 블록은 특정 상태에서 아무것도 반환하지 않으므로, 템플릿이 빈 데이터로 호출되는 일이 없어요. Rewards 템플릿은 빈 milestones를 절대 보지 않고, Subscription upgrade 템플릿은 null인 view를 절대 보지 않아요. 각 블록의 레퍼런스에 해당 여부가 명시되어 있으므로 빈 상태 분기를 생략할 수 있어요.

커스텀 템플릿 스타일링

시작점이 되는 기본 템플릿에는 블록의 클래스명이 있어요. 편집 내용의 스타일 지정 방법은 그 시작점에서 얼마나 멀어지는지에 따라 달라져요.

두 가지 클래스 패밀리

기본 템플릿의 모든 요소에는 짝을 이루는 클래스명이 있으며, 이 둘은 매우 다른 역할을 해요: cart-internal-header__title은 제목을 기본 제목처럼 보이게 만드는 것이고, cart-external-header__title은 모양을 바꾸고 싶을 때 잡아야 하는 손잡이예요.

작은 변경: 두 클래스명 모두 유지

요소 순서를 바꾸거나, 라벨을 변경하거나, 기존 구조 안에 무언가를 추가하는 정도라면 클래스명을 그대로 두세요. 기본 외관을 그대로 유지하면서, cart-external-* 연결 지점을 대상으로 하는 커스텀 CSS로 스타일을 변경하세요.

구조 변경: 두 클래스명 모두 제거

구조를 손보는 수준을 넘어 DOM 구조 자체를 변경한다면, 마크업에서 패밀리 모두 제거하고 대신 직접 만든 클래스명을 사용하세요. 각각 별도의 이유가 있어요. 기본 CSS는 기본 DOM을 위해 작성되었으므로 cart-internal-*을 제거하세요. 구조가 바뀐 마크업에 그 클래스를 유지하면, 더 이상 존재하지 않는 요소를 가정하는 레이아웃 규칙을 상속해요: 다른 자식을 기대하는 flex 컨테이너, 이동한 요소 사이의 간격, 제거한 것을 기준으로 한 위치 지정 등이에요. 보통 기본 규칙이 이기고 있는데 여러분의 CSS가 “작동하지 않는” 것으로 나타나요.
cart-external-*은 공유된 이름이지 여러분의 것이 아니므로 제거하세요. 이 클래스명들은 기본 마크업에서 특정한 의미를 가지며, 커스텀 CSS는 장바구니 전체에 대해 한 번 작성돼요. 구조가 바뀐 템플릿이 이를 재사용하면, 작성하는 모든 규칙이 여러분의 구조와 기본 구조 모두를 대상으로 하게 돼요.커스텀 템플릿을 끄는 순간 문제가 발생해요: 블록이 기본 마크업으로 돌아가는데, CSS가 여전히 그것을 가리키며 원래 작성 대상이 아닌 DOM에 스타일을 적용해요. 자신만의 접두사를 사용하면 둘이 깔끔하게 분리되어, 템플릿을 꺼도 깔끔하게 되돌아가요.
만든 것에 스타일을 지정하는 두 가지 방법:

방법 1: 직접 만든 클래스명 + 커스텀 CSS

유지하거나 재사용할 것에 가장 좋아요. 아무도 충돌하지 않을 접두사(보통 스토어나 브랜드 이름)를 클래스에 붙이세요:
그런 다음 카트 에디터의 왼쪽 패널에서 Cart settings를 선택하고 오른쪽에서 Custom CSS 탭을 여세요:
접두사는 보기보다 중요해요. 접두사가 없으면 .header.title 같은 클래스가 장바구니 자체의 클래스, 다른 앱의 템플릿, 또는 미래의 블록과 충돌할 위험이 있어요.

방법 2: 인라인 스타일

CSS 패널을 오갈 필요가 없고 모든 것이 한곳에 있어요:
레이아웃 골격 잡기와 일회성 작업에 좋아요. 한계는 늘 그렇듯: :hover 같은 의사 클래스가 없고, 미디어 쿼리가 없고, 블록 간 재사용이 안 돼요. 이 중 하나라도 필요해지면 방법 1을 사용하세요.

접근 방식 선택하기

장바구니는 shadow root 안에 렌더링되므로 테마의 스타일시트가 안에 접근할 수 없어요. 커스텀 템플릿의 스타일은 테마가 아니라 장바구니 자체의 Custom CSS 패널이나 인라인 스타일에서 와야 해요. 커스텀 CSS를 참고하세요.

템플릿이 실패할 때

고장 난 템플릿이 장바구니를 망가뜨리는 일은 없어요. 블록이 아무것도 렌더링하지 않고 주변의 모든 것은 계속 작동해요. 안전하지만 놓치기 쉬워요: 블록이 있어야 할 자리의 빈 공간이 증상이에요. 블록이 눈에 보이는 오류 없이 조용히 사라지므로, 게시하기 전에 항상 미리보기에서 템플릿을 확인하세요. 블록이 사라졌다면 먼저 브라우저 콘솔을 여세요. 주의해야 할 두 가지가 있어요. 둘 다 그렇지 않다고 가정하는 템플릿을 크래시시키니까요:
  • null이 될 수 있는 props. 많은 props가 정상 상황에서 null이에요(로고가 없을 때 logoUrl, 이미지가 없을 때 imageUrl, 단일 옵션 상품의 variantTitle). 사용하기 전에 확인하세요.
  • 비어 있을 수 있는 배열. discountTagsdiscountCodes는 비어 있는 []인 경우가 훨씬 많아요.

제한 사항

  • 커스텀 템플릿은 표시 재정의예요. 장바구니에 대한 로직 실행(이벤트 구독, 아이템 추가, 변경에 반응)은 커스텀 스크립트Cart SDK를 사용하세요.
  • 거의 모든 블록이 지원해요. 예외는 Shopify 자체 결제 버튼을 담는 Express payments 블록과 Cart items 컨테이너 자체예요. 다만 그 안의 Product 행은 커스텀 템플릿을 지원해요.
  • 템플릿은 블록의 근본적인 동작을 바꿀 수 없어요. 블록 데이터의 표시 방식을 바꾸는 것이지, 그 뒤의 데이터나 동작을 바꾸는 것이 아니에요.

각 블록의 props

모든 블록은 자체 데이터를 전달해요. 타입과 실습 예제가 포함된 전체 prop 표는 각 블록의 페이지에 있어요: Custom code 블록은 블록의 렌더링을 대체하는 것이 아니라 마크업을 추가하는 유일한 영역이므로 props가 달라요: 전체 장바구니와 장바구니 추가 액션이에요. 커스텀 코드 블록 → Props를 참고하세요.