
Shopify CLI의 theme dev는 저장했지만 아직 스토어에 업로드되지 않은 테마 파일을 요청에 담아 Shopify 서버로 보내고, 서버는 그 파일을 적용해 페이지를 렌더링한다. 이 방식은 문서에 공개되지 않은 replace_templates 매개변수를 사용한다.
theme dev는 http://127.0.0.1:9292에서 실시간 새로고침과 실제 스토어 데이터를 제공하지만, Liquid는 로컬 컴퓨터에서 실행되지 않는다. 렌더링은 Shopify 서버에서 이뤄지고 상품·가격·장바구니 데이터도 스토어에 있다. Shopify CLI는 오픈소스이며, 관련 구현은 packages/theme/src/cli/utilities/theme-environment/ 아래 파일에서 확인할 수 있다.
개발 서버가 시작되면 CLI는 테마를 숨겨진 개발용 테마에 업로드하고, ?preview_theme_id=<id>&_fd=0&pb=0을 붙여 스토어 홈페이지를 요청한다. 이때 받은 _shopify_essential 쿠키를 유지하며, 해당 쿠키가 포함된 요청은 개발용 테마를 렌더링한다. CLI가 보내는 렌더링 요청에는 스토어프런트 토큰도 Bearer 헤더로 들어간다.
파일을 저장하면 CLI는 백그라운드에서 업로드를 시작한다. 업로드가 끝나기 전까지 파일은 unsyncedFileKeys 집합에 남는다. 이 시간 동안 페이지를 요청하면 일반 GET 대신 storefront-renderer.ts가 같은 스토어프런트 URL로 POST를 보내고, 변경된 파일을 요청 본문에 담는다. Shopify는 이를 해당 페이지의 GET 요청으로 처리하면서 저장된 파일 대신 로컬 파일 내용을 사용한다. 업로드가 완료되면 파일이 집합에서 빠지고, 다음 요청은 다시 일반 GET이 된다.
이 방식은 assets/ 밖에 있는 Liquid 및 JSON 파일에만 적용된다. JSON 템플릿은 현재 경로에 해당하는 템플릿만, 로케일 파일은 현재 언어에 해당하는 파일만 전송한다. CSS와 JavaScript는 렌더러에 보내지 않는다. 로컬 서버가 해당 파일을 디스크에서 제공하며 응답에 X-Local-Asset: true 헤더를 붙인다.
실시간 새로고침도 같은 렌더링 방식을 활용해 특정 섹션만 갱신한다. 브라우저는 CLI에 text/event-stream 연결을 열어 두고, 파일을 저장하면 CLI가 이벤트를 즉시 한 번, 업로드가 끝난 뒤 다시 한 번 보낸다. 스토어가 /cdn/shopifycloud/theme-hot-reload/theme-hot-reload.js에서 제공하는 스크립트는 로컬호스트에서 첫 이벤트에 반응하고, myshopify.com 도메인의 미리보기에서는 두 번째 이벤트를 기다린다. 로컬호스트에서는 변경된 섹션만 요청하며, CLI는 공개 Section Rendering API의 section_id와 함께 섹션 파일 및 이를 참조하는 변경된 JSON 템플릿을 replace_templates로 전달한다.
CLI는 실시간 새로고침 스크립트를 추가하기 전에 HTML에 <script id="hot-reload-client">가 이미 있는지 확인한다. 이 검사에는 “Already injected in SFR”이라는 주석이 달려 있다. SFR은 Shopify의 스토어프런트 렌더러를 뜻하므로, 일부 경우에는 렌더러가 CLI 스크립트를 직접 추가하는 것으로 보인다. shptka_로 시작하는 토큰을 사용하는 Theme Access 비밀번호 세션은 스토어 도메인 대신 Shopify 프록시의 /cli/sfr을 통해 렌더링 요청을 보낸다.
Shopify CLI 문서는 실시간 새로고침과 개발용 테마를 설명하지만, 저장한 변경 사항이 업로드되기 전에 페이지를 렌더링하는 방식은 다루지 않는다. Shopify는 CLI와 렌더러를 모두 소유하므로, 이 비공개 매개변수를 유지하거나 언제든 바꿀 수 있다. 다른 도구도 같은 요청을 보낼 수 있지만, 공식 클라이언트가 하나뿐인 API에 의존하게 된다.
동작은 shopify theme dev --verbose로 살펴볼 수 있다. 섹션 파일을 저장하면 로그에 보통 → Rendering <url> (with sections/your-section.liquid)...가 표시된다. 업로드가 끝나면 파일 목록 없이 → Rendering <url>...가 나타난다. 브라우저 개발자 도구의 네트워크 패널에서는 스타일시트와 스크립트 응답에 X-Local-Asset: true가 붙는 것을 확인할 수 있다.
부록: 원문 예시
POST https://your-store.myshopify.com/products/linen-shirt?_fd=0&pb=0 Authorization: Bearer <storefront token> Content-Type: application/x-www-form-urlencoded replace_templates[sections/main-product.liquid]=<your local file> _method=GET
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요