Liquid 템플릿
Liquid는 모든 Shopify Online Store 테마를 구동하는 템플릿 언어입니다. Shopify 공동 창업자 Tobias Lutke가 만들었으며, Liquid는 스토어의 데이터를 사용하여 서버에서 HTML을 렌더링합니다. 테마를 구축하든, 앱 블록을 만들든, 판매자를 위해 스토어프론트를 커스터마이즈하든 Liquid를 이해하는 것이 필수적입니다. 이 레슨에서는 언어 기초, 테마 아키텍처, 성능 모범 사례를 다룹니다.
Liquid 기초
Liquid에는 세 가지 구성 요소가 있습니다: 객체, 태그, 필터.
객체
객체는 데이터를 출력합니다. 이중 중괄호로 감쌉니다:
{{ product.title }}
{{ product.price | money }}
{{ shop.name }}
{{ customer.first_name }}
객체는 현재 페이지 컨텍스트에 따라 Shopify가 제공합니다. 상품 페이지에서는 product를 사용할 수 있습니다. 컬렉션 페이지에서는 collection을 사용할 수 있습니다. shop, cart, settings와 같은 전역 객체는 어디서나 사용할 수 있습니다.
태그
태그는 로직과 제어 흐름을 생성합니다. 퍼센트 기호가 있는 중괄호로 감쌉니다:
{% if product.available %}
<button type="submit">Add to Cart</button>
{% else %}
<button disabled>Sold Out</button>
{% endif %}
{% for product in collection.products %}
<div class="product-card">
<h3>{{ product.title }}</h3>
<p>{{ product.price | money }}</p>
</div>
{% endfor %}
{% unless customer %}
<a href="/account/login">Log in for exclusive pricing</a>
{% endunless %}
일반적인 태그는 다음과 같습니다:
| 태그 | 용도 |
|---|---|
if / elsif / else | 조건부 로직 |
for | 배열 반복 |
unless | 부정 조건 |
case / when | Switch 문 |
assign | 변수 생성 |
capture | 출력을 변수로 캡처 |
render | 스니펫 포함 |
section | 섹션 렌더링 |
form | Shopify 폼 생성 |
paginate | 컬렉션 페이지네이션 |
comment | 코드 주석 (렌더링되지 않음) |
필터
필터는 객체의 출력을 수정합니다. 파이프 |로 구분합니다:
{{ "hello world" | capitalize }}
<!-- 출력: Hello world -->
{{ product.price | money_with_currency }}
<!-- 출력: $29.99 USD -->
{{ product.title | handleize }}
<!-- 출력: premium-widget -->
{{ product.description | strip_html | truncate: 150 }}
<!-- 출력: 처음 150자, HTML 없음 -->
{{ "now" | date: "%B %d, %Y" }}
<!-- 출력: March 30, 2026 -->
Shopify는 전자상거래 전용 필터를 수십 개 제공합니다:
<!-- 금액 포맷팅 -->
{{ 2999 | money }} → $29.99
{{ 2999 | money_with_currency }} → $29.99 USD
{{ 2999 | money_without_trailing_zeros }} → $29.99
<!-- 이미지 조작 -->
{{ product.featured_image | image_url: width: 400 }}
{{ product.featured_image | image_url: width: 800, height: 600, crop: 'center' }}
<!-- URL 생성 -->
{{ product | product_url }}
{{ "cart" | link_to: routes.cart_url }}
<!-- 배열 연산 -->
{{ collection.products | where: "available", true | size }}
{{ collection.products | sort: "price" | first }}
{{ collection.products | map: "title" | join: ", " }}
테마 아키텍처
Shopify 테마는 Liquid 파일, 에셋, 설정으로 구성된 구조화된 컬렉션입니다. 파일 구조를 이해하는 것이 매우 중요합니다.
theme/
├── layout/
│ └── theme.liquid # 메인 레이아웃 래퍼
├── templates/
│ ├── index.json # 홈페이지 템플릿
│ ├── product.json # 상품 페이지 템플릿
│ ├── collection.json # 컬렉션 페이지 템플릿
│ ├── page.json # 커스텀 페이지 템플릿
│ ├── blog.json # 블로그 템플릿
│ ├── article.json # 아티클 템플릿
│ ├── cart.json # 장바구니 페이지 템플릿
│ ├── 404.json # 404 페이지
│ ├── search.json # 검색 결과
│ └── customers/
│ ├── account.json # 고객 계정
│ ├── login.json # 로그인 페이지
│ └── order.json # 주문 상세
├── sections/
│ ├── header.liquid # 사이트 헤더
│ ├── footer.liquid # 사이트 푸터
│ ├── featured-collection.liquid
│ ├── product-info.liquid
│ └── rich-text.liquid
├── snippets/
│ ├── product-card.liquid # 재사용 가능한 상품 카드
│ ├── price.liquid # 가격 표시 로직
│ └── icon-cart.liquid # SVG 아이콘
├── assets/
│ ├── theme.css
│ └── theme.js
├── config/
│ ├── settings_schema.json # 테마 설정 정의
│ └── settings_data.json # 현재 설정 값
└── locales/
├── en.default.json # 영어 번역
└── fr.json # 프랑스어 번역
레이아웃
레이아웃 파일(layout/theme.liquid)은 모든 페이지를 감쌉니다. <html>, <head>, <body> 태그와 {{ content_for_header }} 및 {{ content_for_layout }} 태그를 포함합니다:
<!DOCTYPE html>
<html lang="{{ request.locale.iso_code }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ page_title }} — {{ shop.name }}</title>
{{ content_for_header }}
{{ "theme.css" | asset_url | stylesheet_tag }}
</head>
<body>
{% sections "header-group" %}
<main id="MainContent" role="main">
{{ content_for_layout }}
</main>
{% sections "footer-group" %}
<script src="{{ 'theme.js' | asset_url }}" defer></script>
</body>
</html>
{{ content_for_header }} 태그는 Shopify의 필수 스크립트(분석, App Bridge, 결제 연동 등)를 주입합니다. 이 태그를 제거하면 테마가 작동하지 않게 됩니다.
JSON 템플릿
Online Store 2.0에서 템플릿은 어떤 섹션이 어떤 순서로 나타나는지를 정의하는 JSON 파일입니다. 이것이 테마 에디터가 작동하는 방식입니다:
{
"name": "Product",
"sections": {
"main": {
"type": "product-info",
"settings": {
"show_vendor": true,
"show_sku": false
},
"blocks": {
"title": {
"type": "title",
"settings": {}
},
"price": {
"type": "price",
"settings": {
"show_compare_at": true
}
},
"variant_picker": {
"type": "variant_picker",
"settings": {
"picker_type": "button"
}
},
"buy_buttons": {
"type": "buy_buttons",
"settings": {
"show_dynamic_checkout": true
}
},
"description": {
"type": "description",
"settings": {}
}
},
"block_order": ["title", "price", "variant_picker", "buy_buttons", "description"]
},
"recommendations": {
"type": "related-products",
"settings": {
"heading": "You may also like",
"products_to_show": 4
}
}
},
"order": ["main", "recommendations"]
}
섹션과 섹션 스키마
섹션은 OS 2.0 테마의 핵심 구성 요소입니다. 각 섹션은 자체 마크업, 스타일, 설정, 블록을 갖춘 독립적인 Liquid 파일입니다.
{% comment %} sections/featured-collection.liquid {% endcomment %}
<div class="featured-collection" style="padding: {{ section.settings.padding }}px 0;">
<div class="page-width">
{% if section.settings.heading != blank %}
<h2 class="section-heading">{{ section.settings.heading }}</h2>
{% endif %}
{% assign collection = collections[section.settings.collection] %}
<div class="product-grid" style="
display: grid;
grid-template-columns: repeat({{ section.settings.columns }}, 1fr);
gap: 24px;
">
{% for product in collection.products limit: section.settings.products_to_show %}
{% render 'product-card', product: product %}
{% endfor %}
</div>
</div>
</div>
{% schema %}
{
"name": "Featured Collection",
"tag": "section",
"class": "featured-collection-section",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Featured Collection"
},
{
"type": "collection",
"id": "collection",
"label": "Collection"
},
{
"type": "range",
"id": "products_to_show",
"min": 2,
"max": 12,
"step": 1,
"default": 4,
"label": "Products to show"
},
{
"type": "range",
"id": "columns",
"min": 2,
"max": 5,
"step": 1,
"default": 4,
"label": "Columns"
},
{
"type": "range",
"id": "padding",
"min": 0,
"max": 100,
"step": 4,
"default": 40,
"unit": "px",
"label": "Section padding"
}
],
"presets": [
{
"name": "Featured Collection"
}
]
}
{% endschema %}
하단의 {% schema %} 블록은 다음을 정의합니다:
- settings: 테마 에디터에 나타나는 구성 옵션
- blocks: 섹션 내의 반복 가능한 하위 컴포넌트
- presets: 섹션 추가 시 나타나는 기본 구성
- templates: 이 섹션을 사용할 수 있는 페이지 유형
Shopify는 다양한 설정 유형을 지원합니다: text, textarea, richtext, image_picker, url, video, color, font_picker, collection, product, blog, page, link_list, range, select, checkbox, radio, number, html, liquid. 각각 테마 에디터에서 특정 입력 필드를 렌더링합니다.
Liquid에서의 메타필드
메타필드를 사용하면 Shopify 리소스에 커스텀 데이터를 첨부할 수 있습니다. Liquid에서는 metafields 속성을 통해 접근합니다:
<!-- 상품 메타필드 접근 -->
{{ product.metafields.custom.warranty_years.value }}
<!-- 조건부 로직에서 메타필드 사용 -->
{% if product.metafields.custom.is_featured.value == true %}
<span class="badge badge--featured">Featured</span>
{% endif %}
<!-- 메타필드 이미지 렌더링 -->
{% assign hero_image = product.metafields.custom.hero_image.value %}
{% if hero_image %}
{{ hero_image | image_url: width: 1200 | image_tag: class: 'hero-image' }}
{% endif %}
<!-- 리스트 메타필드 반복 -->
{% assign ingredients = product.metafields.custom.ingredients.value %}
{% if ingredients %}
<ul class="ingredient-list">
{% for ingredient in ingredients %}
<li>{{ ingredient }}</li>
{% endfor %}
</ul>
{% endif %}
테마 에디터에서 메타필드를 사용할 수 있도록 하려면 섹션 스키마에 추가합니다:
{
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading"
}
],
"blocks": [
{
"type": "metafield",
"name": "Custom Metafield",
"settings": [
{
"type": "text",
"id": "metafield_key",
"label": "Metafield key",
"info": "Format: namespace.key"
}
]
}
]
}
성능 최적화
테마 성능은 전환율에 직접적인 영향을 미칩니다. Shopify는 테마를 빠르게 유지하기 위한 도구와 모범 사례를 제공합니다.
핵심 원칙
- Liquid 루프 최소화: 매 반복이 서버 측 처리 시간입니다.
for루프에limit를 사용합니다. - 이미지 지연 로딩:
image_tag에loading: 'lazy'파라미터를 사용합니다. - 중요 에셋 프리로드: 첫 화면에 표시되는 이미지와 폰트에
<link rel="preload">를 사용합니다. - JavaScript 지연: 스크립트 태그에
defer또는async를 사용합니다. - 섹션 중첩 줄이기: 깊이 중첩된 섹션은 렌더링 시간을 증가시킵니다.
<!-- 좋음: 첫 화면 아래 이미지 지연 로딩 -->
{{ product.featured_image | image_url: width: 600 | image_tag:
loading: 'lazy',
widths: '200,400,600,800',
sizes: '(max-width: 600px) 100vw, 50vw'
}}
<!-- 좋음: 첫 화면 히어로 이미지 프리로드 -->
<link
rel="preload"
as="image"
href="{{ section.settings.hero_image | image_url: width: 1400 }}"
media="(min-width: 750px)"
>
Theme Inspector
Shopify의 Theme Inspector는 Liquid 렌더링 시간을 프로파일링하는 Chrome DevTools 확장 프로그램입니다:
- Chrome Web Store에서 설치합니다
- 스토어프론트를 열고 DevTools를 엽니다
- Shopify 탭으로 이동합니다
- Liquid 렌더링의 플레임 그래프를 확인합니다
Inspector는 어떤 섹션, 스니펫, Liquid 연산이 가장 많은 서버 시간을 소비하는지 보여줍니다. 가장 부하가 높은 코드 경로에 최적화 노력을 집중하십시오.
일반적인 성능 실수는 제한 없이 루프 내에서 메타필드나 관련 리소스에 접근하는 것입니다. 각 접근은 데이터베이스 쿼리를 트리거할 수 있습니다. Shopify는 캐싱으로 이를 완화하지만 루프를 간결하게 유지하고 limit를 사용하는 것이 여전히 중요합니다.
<!-- 나쁨: 메타필드 접근이 있는 무제한 루프 -->
{% for product in collection.products %}
{{ product.metafields.custom.badge.value }}
{% endfor %}
<!-- 좋음: 루프 제한 -->
{% for product in collection.products limit: 12 %}
{{ product.metafields.custom.badge.value }}
{% endfor %}
핵심 요약
- Liquid에는 세 가지 구조가 있습니다: 객체 (데이터 출력), 태그 (로직), 필터 (출력 변환)
- OS 2.0 테마는 스키마 정의가 있는 섹션을 참조하는 JSON 템플릿을 사용합니다
- 섹션은 주요 구성 요소입니다 -- 설정과 블록을 갖춘 독립적인 컴포넌트
- 메타필드는 데이터 모델을 확장하며 Liquid와 테마 에디터에서 접근 가능합니다
- 성능 최적화는 루프 제한, 이미지 지연 로딩, JavaScript 지연에 중점을 둡니다
- Theme Inspector Chrome 확장 프로그램은 렌더링 시간 프로파일링에 필수적입니다
다음으로 Hydrogen을 살펴봅니다 -- 헤드리스 스토어프론트를 위한 Shopify의 React 프레임워크입니다.