본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 07. 09:17

Claude를 이용한 Shopify Admin API 활용: 15개 저장소에서 사용하는 5가지 패턴

요약

브라우저 자동화 대신 Claude와 Shopify Admin API를 결합하여 스토어를 관리하는 효율적인 패턴을 소개합니다. UI 변경에 취약한 Puppeteer 방식에서 벗어나, API를 통해 안정적이고 반복 가능한 자동화 워크플로우를 구축하는 방법을 다룹니다.

핵심 포인트

  • UI 자동화(Puppeteer) 대비 API 활용 시 디버깅 시간 및 작업 시간 대폭 절감
  • Shopify Admin API를 활용한 제품 생성, 메타필드 및 메타오브젝트 동기화 패턴
  • Claude를 통한 구조화된 API 요청으로 작업의 안정성과 반복 가능성 확보
  • 권한 스코프 제한을 통한 보안 강화 및 환경 변수 기반의 안전한 인증 관리
  • Admin API를 통한 제품 생성은 매번 대시보드를 클릭하는 것보다 훨씬 효율적입니다.

  • 메타필드 (metafields)를 포함한 블로그 포스트 POST 작업은 기사당 12분을 절약해 줍니다.

  • 메타오브젝트 (Metaobject) 동기화는 수동 편집 없이 15개 저장소를 일관되게 유지합니다.

  • 스테이지드 업로드 (Staged uploads)는 단순 API가 거부하는 파일 에셋을 처리합니다.

저는 2년 전 Shopify를 위한 브라우저 자동화 (browser automation) 사용을 중단했습니다. 이제 제가 실행하는 모든 스토어 작업은 Claude에서 호출되는 Admin API를 통해 이루어집니다. 제 Shopify 스토어와 연결된 15개 저장소 전반에 걸쳐, 다섯 가지 패턴이 제가 필요로 하는 작업의 약 90%를 커버합니다.

브라우저 자동화를 가장 먼저 폐기한 이유

대시보드를 일일이 클릭하는 방식에 반대하는 이유는 간단합니다. 저는 2023년 초에 스토어 관리를 위해 Puppeteer를 시도했습니다. 하지만 6주 동안 4번이나 작동이 중단되었습니다. Shopify는 끊임없이 UI 변경 사항을 배포하며, 레이아웃이 바뀔 때마다 셀렉터 (selector)가 깨집니다. 버튼 위치가 바뀌거나, 모달 (modal)에 새로운 래퍼 div가 추가되면, 제가 잠든 새벽 2시에 전체 워크플로우가 멈춰버립니다.

Admin API는 변하지 않습니다. 2024-10 엔드포인트는 출시된 날과 오늘 동일하게 동작합니다. Shopify가 특정 버전을 지원 중단 (deprecate)할 때, 저는 조용한 실패를 겪는 대신 몇 달 전부터 미리 날짜를 안내받습니다. 이것만으로도 2024년에 약 30시간의 디버깅 시간을 아꼈습니다.

단일 작업에 대한 계산은 다음과 같습니다. UI를 통해 제품을 생성하는 과정: 관리자 페이지 열기, Products 클릭, Add product 클릭, 9개 필드 채우기, 변형 (variants) 설정, 이미지 업로드, 저장 클릭. 제가 원하는 것을 정확히 알고 있다면 약 4분이 소요됩니다. Claude를 통해 API로 처리하면: 구조화된 요청 한 번에 8초가 걸립니다. 이를 200개 이상의 제품에 적용하면 그 차이는 결코 작지 않습니다.

진정한 승부처는 반복 가능성 (repeatability)입니다. 브라우저 스크립트는 "버튼이 어디에 있는지"를 인코딩합니다. 반면 API 호출은 "무엇이 일어나길 원하는지"를 인코딩합니다. 후자는 디자인이 재설계되어도 살아남습니다. 제가 Claude에게 제품 생성을 요청하면, Claude가 뮤테이션 (mutation)을 구축하고, 제가 검토한 뒤, 실행합니다. 헤드리스 크롬 (headless Chrome)도, 불안정한 대기 (flaky waits)도, 디버깅을 위한 스크린샷도 필요 없습니다.

저는 15개의 모든 저장소(repo)에 걸쳐 단일한 인증 패턴을 유지합니다. 상점당 하나의 프라이빗 앱 토큰(private app token)을 사용하며, 해당 저장소에 정확히 필요한 권한으로 스코프(scope)를 제한합니다. 블로그 포스팅 저장소는 write_content 권한만 가지며 그 외에는 아무것도 가지지 않습니다. 상품 저장소는 write_products를 가집니다. 만약 토큰이 유출되더라도 피해 범위(blast radius)는 매우 작습니다. Claude는 환경 변수 파일(env file)에서 스코프를 읽으며, 채팅창에서 가공되지 않은 비밀값(raw secret)을 절대 보지 않습니다.

모든 것을 Claude를 통해 실행하는 것에 대한 전체적인 논거를 알고 싶다면, Claude Blueprint에서 설정 방법을 설명하고 있습니다. 요약하자면 이렇습니다. API는 계약(contract)이며, 계약은 자동화의 대상입니다. UI는 표면(surface)이며, 표면은 다른 선택지가 없을 때 클릭하는 대상일 뿐입니다.

패턴 1: 변형(Variants)을 포함한 상품 생성

상품 생성은 가장 핵심적인 작업입니다. 저는 REST가 아닌 GraphQL의 productCreate 뮤테이션(mutation)을 통해 이를 수행합니다. GraphQL을 사용하면 상품, 옵션, 그리고 첫 번째 변형(variant)을 단 한 번의 왕복(round trip)으로 설정할 수 있기 때문입니다. 반면 REST는 두세 번의 호출이 필요하며, 변형 가격 설정을 위한 후속 작업도 필요합니다.

제가 Claude에게 전달하는 구조는 항상 동일한 형태를 띱니다. 제목(Title), descriptionHtml, productType, vendor, 배열 형태의 tags, 제가 확인하기 전까지 DRAFT로 설정된 status, 그리고 가격(price), SKU, 재고 정책(inventory policy)이 포함된 variants 블록입니다. 상태를 의도적으로 DRAFT로 유지하는 이유는, 제가 이미지를 확인하기도 전에 상품이 라이브로 공개되어 공개적으로 망신을 당하는 것을 방지하기 위해서입니다.

사람들이 자주 실수하는 부분은 옵션(options)과 변형(variants)의 차이입니다. 상품에 색상이 하나이고 사이즈가 하나뿐이라 하더라도, 여전히 옵션을 선언해야 합니다. Shopify는 부모 항목에 존재하지 않는 옵션 값을 참조하는 변형을 거부합니다. Claude에게

가격의 경우, 저는 Mutation (변형) 내에 숫자를 절대 하드코딩하지 않습니다. 대신 변수 (Variables)로 전달합니다. 일반적인 제품은 라인에 따라 29 EUR 또는 39 EUR로 책정되는데, 이를 설정 파일 (Config)에 유지하면 40개의 Mutation을 일일이 수동으로 수정하는 대신 한 번의 찾기 및 바꾸기 (Find-and-replace)로 전체 카탈로그를 조정할 수 있습니다.

이미지 첨부는 별도의 단계이며, 여기서 패턴 5 (Pattern Five, 단계별 업로드)가 등장합니다. productCreate 호출은 제품 ID를 반환합니다. 저는 그 ID를 파일 흐름 (File flow)에 전달하고 나중에 미디어를 첨부합니다. 큰 이미지를 Base64로 인라인 (Inlining) 처리하는 방식은 작은 파일에는 작동하지만, 수백 킬로바이트(KB)를 초과하는 파일에는 실패합니다. 이미지들은 별도로 관리하세요.

시간을 크게 절약해 준 세부 사항 하나는 다음과 같습니다: 저는 항상 userErrors 필드를 요청합니다. GraphQL은 Mutation이 논리적으로 실패했을 때도 200 상태 코드를 반환합니다. userErrors가 없다면 작업이 성공했다고 착각하게 됩니다. 하지만 이 필드가 있으면, Claude가 왜 변형 (Variant)이 거부되었는지 정확히 읽어내고 다음 시도에서 Payload (페이로드)를 수정합니다. 이러한 피드백 루프(Feedback loop)야말로 이 방식이 UI를 사용하는 것보다 빠른 결정적인 이유입니다.

패턴 2: 블로그 포스트 POST 및 Metafields (메타필드)

이 글을 포함하여 제 스토어의 모든 기사는 Admin API를 통해 게시됩니다. 블로그 콘텐츠 엔드포인트 (Endpoint)는 블로그 ID, 제목, 본문 HTML, 작성자, 태그, 그리고 발행 날짜를 받습니다. 저는 리치 텍스트 에디터 (Rich text editor)에 내용을 붙여넣지 않습니다. 에디터가 제가 원치 않는 방식으로 HTML 형식을 재구성하거나, 제가 유지하고 싶은 속성 (Attributes)들을 삭제해 버리기 때문입니다.

Claude가 실행하는 흐름은 다음과 같습니다: 적절한 블로그 ID를 가져오기 위해 블로그 목록을 페치 (Fetch)한 다음, 기사를 POST 합니다. 저는 블로그 ID를 설정 파일 (Config)에 캐시 (Cache)하여 페치 작업이 한 번만 발생하도록 합니다. 완성된 기사를 게시하는 데는 약 6초가 소요되는데, 이는 예전에 제가 직접 붙여넣고, 형식을 수정하고, 발췌문 (Excerpt)을 설정하고, 태그를 추가하고, 발행하는 데 걸리던 12분에 비하면 엄청난 차이입니다.

Metafields (메타필드)는 이 방식이 매우 유용해지는 지점입니다. 포스트가 등록된 후, 저는 TLDR 데이터, Canonical handle (표준 핸들), 그리고 신디케이션 대상 (Syndication targets)을 위한 메타필드를 첨부합니다. 이것들은 제 테마의 커스텀 블로그 템플릿을 구동합니다. API를 통해 이를 설정하면 모든 기사가 동일한 구조를 갖게 됩니다. 3번째 포스트와 80번째 포스트 사이에 구조적 차이 (Drift)가 발생하지 않습니다.

블로그 메타필드 (Metafields)의 함정은 네임스페이스 (Namespace)와 키 (Key)입니다. 이들은 반드시 정의 (Definition)로서 이미 존재해야 합니다. 그렇지 않으면 값은 저장되지만 관리자 페이지 (Admin)에 나타나지 않으며, 때로는 Liquid에서 렌더링되지 않기도 합니다. 저는 스토어 설정에서 이를 한 번 정의한 다음, 모든 POST 요청에서 정확한 네임스페이스와 키를 참조합니다. Claude는 이를 상수 (Constants) 블록에 유지하므로 제가 오타를 내는 실수를 방지할 수 있습니다.

각 기사를 알리는 소셜 포스트 (Social posts)를 예약하기 위해, 저는 게시된 URL을 Buffer의 자체 API를 통해 전송합니다. Shopify 측은 표준 콘텐츠 (Canonical content)를 처리하고, Buffer는 배포를 담당합니다. 이 시스템들을 분리해 두면 예약 실패가 이미 게시된 기사에 영향을 주지 않습니다.

또한 포스팅하기 전에 본문 HTML을 검증합니다. Shopify의 콘텐츠 엔드포인트 (Content endpoint)는 거의 모든 것을 허용하는데

각 메타오브젝트 (metaobject) 필드는 타입을 가지며, 검증 (validation)은 매우 엄격합니다. single_line_text_field로 정의된 필드는 줄바꿈이 포함된 값을 거부합니다. url 필드는 유효한 URL이 아닌 모든 것을 거부합니다. Claude는 먼저 정의를 읽은 다음, 각 값을 그에 맞춰 형식화 (format)합니다. 이렇게 검증을 앞단에서 처리함으로써, 저는 절반만 작성된 엔트리들이 포함된 배치 (batch)를 받는 일이 전혀 없습니다.

페이지 템플릿 접미사 (page template-suffix) 검증도 여기에 해당합니다. 페이지를 생성하거나 업데이트할 때, 저는 template_suffixpage.studio.liquid와 같은 커스텀 Liquid 템플릿을 가리키도록 page.studio로 설정합니다. API는 해당 템플릿 파일이 실제로 존재하는지 확인하지 않습니다. 만약 접미사가 아무것도 가리키지 않는다면, 페이지는 기본 템플릿으로 렌더링되어 잘못된 모습으로 보이게 됩니다. 따라서 접미사를 설정하기 전에, Claude는 테마의 템플릿 에셋 (template assets) 목록을 나열하고 파일이 있는지 확인합니다. 파일이 없다면, Claude는 깨진 페이지를 배포하는 대신 작업을 중단하고 저에게 알려줍니다.

이 검증 단계는 제가 신뢰할 수 있는 자동화와, 제가 계속 지켜봐야만 하는 자동화 사이의 차이점입니다. 서론에서 API 계약 (API contracts)에 대해 다루었는데, 메타오브젝트가 가장 깔끔한 예시입니다. 정의가 곧 계약입니다. 정의에 따라 검증하면 쓰기 (write) 작업은 안전합니다. 검증을 건너뛰면, 11개의 중복 데이터와 조용히 잘못 렌더링되는 페이지를 정리하느라 오후 시간을 다 허비하게 됩니다.

저는 메타오브젝트 타입별로 매개변수화 (parameterized)하여 동일한 코드로 15개 저장소 전체에서 이 동기화 (sync)를 실행합니다. 하나의 함수, 15개의 호출자. 이것이 Shopify를 웹사이트가 아닌 API로 취급했을 때 얻는 보상입니다.

패턴 4: 스테이지 업로드 (Staged Upload)를 통한 파일 업로드

파일 업로드는 대부분의 사람들을 좌절시키는 부분이기 때문에 별도의 패턴으로 다룹니다. 2MB 크기의 이미지를 제품 미디어 (product media) 엔드포인트에 단순히 POST 한다고 해서 업로드가 완료되지는 않습니다. Shopify는 스테이지 업로드 (staged upload) 흐름을 사용하며, 이는 한 단계가 아닌 세 단계로 이루어져 있습니다.

1단계: 파일 이름, MIME 타입, 파일 크기와 함께 stagedUploadsCreate를 호출합니다. Shopify는 임시 업로드 URL과 일련의 파라미터(parameters)를 반환합니다. 2단계: Shopify가 제공한 정확한 파라미터를 사용하여 해당 URL로 실제 파일 바이트(bytes)를 PUT 요청합니다. 3단계: 1단계에서 받은 리소스 URL을 가져와 productCreateMedia 또는 fileCreate에서 참조하여 파일을 등록합니다.

모든 사람이 저지르는 실수는 2단계에서 발생합니다. 해당 파라미터들은 선택적인 장식이 아닙니다. 이는 업로드 대상이 검증하는 서명된 값(signed values)입니다. 파라미터 없이 파일을 보내거나 순서를 바꾸면, 알 수 없는 403 오류가 발생합니다. Claude는 Shopify가 지정한 정확한 순서대로 멀티파트 폼(multipart form)을 구성하며, 덕분에 업로드가 단 한 번에 성공합니다.

저는 이를 제품 이미지, 블로그 히어로 이미지(hero images), 그리고 다운로드 가능한 에셋(assets)에 사용합니다. 업로드 흐름에 들어가기 전 Magnific을 통해 생성하거나 업스케일링(upscale)한 이미지를 사용하는데, 그 이유는 Shopify가 레티나 디스플레이에서 품질이 낮아 보이는 저해상도 파일을 포함하여 사용자가 제공하는 그대로를 저장하기 때문입니다. 먼저 업스케일링하고, 그다음에 업로드하십시오.

스테이지 업로드 (staged upload) 흐름에서는 크기가 중요합니다. 20MB 미만의 파일은 한 번의 PUT 요청으로 처리됩니다. 더 큰 파일은 파트(parts)를 포함한 멀티파트(multipart) 방식이 필요하지만, 스토어 에셋의 경우 굳이 그럴 가치가 거의 없습니다. 저는 압축 후 이미지 크기를 2MB 미만으로 유지하므로, 멀티파트 경로를 타는 일은 없습니다. 단순한 것이 더 좋습니다.

반복되는 고통을 줄여준 한 가지 방법은 파일을 등록한 후 파일 상태를 폴링(poll)하는 것입니다. Shopify는 업로드된 미디어를 비동기적(asynchronously)으로 처리합니다. fileCreate 호출은 즉시 반환되지만, 상태는 UPLOADED를 거쳐 READY로 변합니다. 아직 처리 중인 파일을 첨부하고 즉시 확인하면, 파일이 깨진 것처럼 보입니다. Claude는 상태가 READY가 될 때까지 폴링하되, 무한 루프에 빠지지 않도록 5회 시도 제한(cap)을 둡니다. 이 제한 덕분에 지난달 실제로 멈춰버린 업로드 하나를 무한 루프 대신 잡아낼 수 있었으며, 이는 브라우저 스크립트였다면 그대로 수행했을 동작이었습니다.

결론 (Bottom Line)

다섯 가지 패턴은 제가 Shopify로 수행하는 거의 모든 작업을 포괄합니다: 상품 생성 (product create), 메타필드 (metafields)를 포함한 블로그 POST, 메타오브젝트 (metaobject) 동기화, 템플릿 접미사 (template-suffix) 검증, 그리고 스테이지 파일 업로드 (staged file upload)입니다. 이 중 어떤 것도 브라우저를 사용하지 않습니다. 모두 Claude를 통해 Admin API를 대상으로 실행되므로, Shopify가 배포하는 모든 대시보드 디자인 변경에도 영향을 받지 않고 생존합니다.

중요한 변화는 Shopify를 웹사이트가 아닌 계약 (contract)으로 취급하는 것이었습니다. 검증 가능하고 자신 있게 자동화할 수 있는 계약 말입니다. 웹사이트는 클릭하며 아무것도 바뀌지 않기를 기도해야 하는 대상입니다. 15개의 저장소 (repos) 전반에 걸쳐 동일한 인증 (auth) 패턴, 동일한 조정 (reconcile) 로직, 동일한 검증 단계를 사용합니다. 함수를 한 번 작성하고, 매개변수화하여, 어디에서나 호출하십시오.

직접 이 시스템을 구축하고 있다면, 상품 생성과 userErrors 필드부터 시작하십시오. 왜냐하면 그 피드백 루프가 API가 어떻게 작동하는지 가르쳐주기 때문입니다. 그다음에는 유일하게 진정으로 까다로운 부분인 스테이지 업로드 (staged uploads)를 추가하십시오. 전체 워크플로우는 Claude Blueprint에 있습니다. 계약을 한 번 구축하면, 상점은 대부분 스스로 운영됩니다.

이 기사에는 제휴 링크가 포함되어 있습니다. 이 링크를 통해 가입하시면, 귀하에게 추가 비용 부담 없이 저에게 소정의 수수료가 지급될 수 있습니다. (광고)

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0