Snowflake Cortex Agents MCP: 소셜 미디어의 불만 데이터를 반품 데이터와 함께 적재하는 방법
Snowflake MCP 커넥터는 OAuth만 지원합니다. 외부 액세스 구성 예시, 월 비용 추정치, API 호출 12회의 결과를 정리했습니다(Amazon 리뷰 데이터는 가져오지 못했습니다).

반품은 소비재 리테일에서 가장 큰 숨은 비용 중 하나입니다. 전미소매협회(NRF)는 2025년 미국 소비자가 반품할 상품 규모를 약 $849.9 billion으로 추산했습니다. 이는 매출의 15.8%에 해당하며, 온라인 구매의 반품률은 19.3%에 이릅니다(NRF 보도자료). 대부분의 브랜드는 이미 판매 및 반품 데이터를 데이터 웨어하우스에 적재하고 있습니다. 하지만 고객이 제품에 대해 공개적으로 남기는 의견까지 적재하는 브랜드는 훨씬 적습니다. 이 글에서는 Snowflake 안에서 이 두 데이터를 연결하는 방법을 살펴봅니다.
계기는 Snowflake Expedition 2026입니다. 2026년 11월 3일, Snowflake는 Snowflake Intelligence의 새 이름인 CoWork와 Cortex Agents의 새로운 기능을 출시했습니다(보도자료). 저희가 주목한 기능은 MCP 커넥터입니다. MCP 커넥터를 사용하면 에이전트가 외부 MCP 서버의 도구를 호출할 수 있습니다(MCP 커넥터 문서). 브랜드 팀이라면 활용 사례가 바로 떠오를 것입니다. Amazon 리뷰, Reddit 게시물, TikTok 댓글을 판매 및 반품 테이블과 함께 배치합니다. 그런 다음 에이전트에게 어떤 불만 주제가 반품률과 함께 늘어나는지 묻습니다.
데이터 쪽은 실제로 테스트했습니다. 2026-11-06 싱가포르 시간(SGT) 00:16부터 00:36까지 EveryInfra API를 12회 호출했고, 모든 요청과 응답을 보관했습니다. 이 글의 Snowflake 부분은 구성 예시일 뿐입니다. 이 머신에는 Snowflake 계정이 없어 SQL, 프로시저, 에이전트를 실행하지 않았습니다. Snowflake에 관한 모든 사실은 snowflake.com 또는 docs.snowflake.com에서 가져왔으며, 확인 날짜는 참고 자료에 적어 두었습니다.
결론부터 말하면, 현재는 EveryInfra MCP 서버를 Snowflake MCP 커넥터로 추가할 수 없습니다.
Snowflake는 OAuth만 허용하며 특정 방식의 클라이언트 등록이 필요한데, 저희 서버는 아직 이를 제공하지 않습니다. OAuth가 지원되더라도 커넥터로는 이 문제를 해결할 수 없습니다. 커넥터 결과는 하나의 채팅 안에만 머물고 테이블에 저장되지 않기 때문입니다. 실제로 작동하는 방법은 Snowflake 외부 액세스 통합(external access integration)입니다. Python 저장 프로시저가 일정에 따라 API를 호출하고 리뷰를 테이블에 기록합니다. 그다음 Cortex Agent가 이 테이블을 판매 및 반품 테이블과 조인합니다. 이 글에서 보여 주지 않는 부분도 분명히 해 두겠습니다. 그날 밤 Amazon 리뷰 호출은 데이터를 반환하지 않았고, 저희에게는 반품 데이터가 없습니다. 따라서 이 글은 어떤 불만이 반품을 유발하는지에 대한 분석 결과가 아니라 구축 계획과 비용 추정을 제공합니다. EveryInfra는 Snowflake와 파트너십 관계가 없습니다. 이 글의 Snowflake 관련 사실은 모두 Snowflake의 공개 문서와 보도자료에서 가져왔습니다.

Snowflake가 Expedition 2026에서 선보인 Snowflake CoWork와 Cortex Agents
이번 행사의 핵심 제품은 Snowflake CoWork입니다. 보도자료는 이 제품을 ai.snowflake.com에서 제공되는 비즈니스 사용자용 에이전트 워크스페이스로 소개합니다. Cortex Code(CoCo)는 개발자와 데이터 엔지니어를 위해 함께 제공되는 도구입니다(Expedition 2026 보도자료, CoWork 제품 페이지).
같은 날 나온 두 번째 보도자료에서는 Business Ontology와 Cortex AI Gateway를 발표했습니다. Business Ontology는 비즈니스 용어에 대해 승인된 의미를 저장하고, 그 정의를 에이전트에 제공합니다. Cortex AI Gateway는 에이전트가 모델에 접근하고, 도구를 호출하고, 회사 시스템 전반에서 액션을 수행하는 방식을 관리합니다(Business Ontology 및 AI Gateway 보도자료). 두 기능 모두 뒤에서 다룰 질문과 관련이 있습니다. "반품률" 같은 용어에 합의된 공식이 하나 없으면, 두 에이전트가 서로 다른 두 가지 답을 내놓게 됩니다.
이 글에서 CoWork는 사람이 질문하는 곳이고, 실제 작업은 Cortex Agents가 수행합니다.
각 CoWork 어시스턴트는 Cortex Agent 객체입니다. 에이전트 사양에는 모델, 지침, 도구가 정의됩니다. 도구로는 시맨틱 뷰에 SQL을 실행하는 Cortex Analyst와 텍스트를 검색하는 Cortex Search가 있습니다. 그 밖에 코드 실행, 커스텀 도구, MCP 커넥터, 웹 검색도 있습니다(Cortex Agents overview, Create and manage agents). 따라서 답변의 품질은 대부분 테이블과 시맨틱 뷰에 달려 있습니다. 에이전트는 질문을 SQL로 바꾸고 결과를 설명합니다.
아래 표는 저희가 2026-11-06에 확인한 내용을 기준으로 여기서 중요한 두 기능의 상태를 정리한 것입니다. "명시되지 않음"은 문서와 보도자료 어디에도 상태가 적혀 있지 않다는 뜻입니다.
| 기능 | 2026-11-06 기준 상태 | 출처 |
|---|---|---|
| CoWork Automations | 명시되지 않음 | Automations 문서 |
| Cortex Agents MCP 커넥터 | 문서에 상태 명시 없음, OAuth만 지원 | 커넥터 문서 |
CoWork 블로그 글에는 프리뷰 단계인 분석 검색(analytical search)도 소개되어 있습니다. 그 예시는 저희 사례와 비슷하며, 지난달 가장 많이 제기된 고객 문제가 무엇인지 묻습니다(CoWork 블로그). Automations의 제한과 접근 규칙은 아래 주간 이메일 섹션에서 다룹니다.
분석 검색은 이미 Snowflake 안에 있는 문서를 대상으로 동작합니다. Cortex Search로 대상을 좁힌 뒤 AI 함수와 SQL로 집계하고 비교합니다. 저희 문제에는 단계가 하나 더 있습니다. 고객의 소리는 웨어하우스 밖인 Amazon, Reddit, TikTok에 있습니다. 따라서 첫 번째 작업은 이 데이터를 일정에 따라 판매 및 반품 데이터와 조인할 수 있는 형태로 Snowflake에 가져오는 것입니다.
Snowflake Cortex Agents에서 MCP로 EveryInfra에 직접 연결할 수 있을까?
가장 먼저 떠오르는 방법입니다. EveryInfra는 이미 원격 MCP 서버를 운영하고 있습니다(EveryInfra MCP 서버). Cortex Agents는 이제 외부 MCP 서버를 호출할 수 있습니다. 그렇다면 서버 주소를 Snowflake에 붙여 넣으면 되지 않을까요? 저희는 Snowflake의 요구 사항과 저희 서버의 동작을 항목별로 비교했습니다. 결론은 불가능하다는 것이며, 걸림돌은 OAuth 클라이언트 등록 방식입니다.
Snowflake 문서는 이 점을 분명히 밝힙니다. Snowflake는 MCP 서버 연결에 OAuth만 지원한다고 명시합니다. 관리자는 OAuth 설정을 담은 API 통합을 API_PROVIDER = external_mcp로 생성한 다음, 이 통합을 가리키는 외부 MCP 서버 객체를 생성합니다(MCP 커넥터 문서). OAuth 설정을 채우는 방법은 두 가지입니다.
첫 번째는 표준 OAuth입니다. 원격 인가 서버에 앱을 등록하고 클라이언트 ID를 발급받습니다. 클라이언트에는 시크릿이 있을 수도 있고, 시크릿 없는 퍼블릭 클라이언트일 수도 있습니다.
또한 해당 앱에 콜백 URL https://identity.snowflake.com/oauth2/callback을 등록해야 합니다. 두 번째는 동적 클라이언트 등록으로, Snowflake가 원격 서버에 직접 클라이언트 ID를 요청합니다. 이 방식을 쓰려면 원격 서버가 RFC 7591을 구현해야 합니다(RFC 7591). 기본 제공 커넥터는 Atlassian, GitHub, Glean, Linear, Salesforce이며, Atlassian 예시는 동적 등록을 사용합니다.

EveryInfra에는 MCP 주소가 두 개 있습니다. 일반 주소인 https://api.everyinfra.com/mcp는 Bearer 헤더에 API 키를 담아 인증합니다. 2026-11-06 00:43 SGT에 이 주소의 보호 리소스 메타데이터와 인가 서버 메타데이터를 요청했습니다. 둘 다 404를 반환했으므로 이 주소는 OAuth 디스커버리를 제공하지 않습니다. 전체 주소인 https://api.everyinfra.com/mcp/all은 다르게 동작합니다. 같은 시각에 자격 증명 없이 보낸 요청은 WWW-Authenticate 헤더와 함께 401을 반환했습니다.
이 헤더는 RFC 9728 형식의 리소스 메타데이터를 가리키며, 이 메타데이터는 auth.everyinfra.com/oidc를 인가 서버로 지정합니다(RFC 9728). 이어서 RFC 8414를 따르는 인가 서버 메타데이터를 확인했습니다(RFC 8414). 이 서버는 S256 방식의 PKCE와 시크릿 없는 퍼블릭 클라이언트를 지원합니다. 하지만 registration_endpoint 값이 비어 있어 동적 등록은 지원하지 않습니다. 또한 공개 문서에는 고객이 직접 OAuth 클라이언트를 등록할 수 있는 셀프서비스 페이지가 없습니다.
| Snowflake 요구 사항 | EveryInfra `/mcp`(API 키) | EveryInfra `/mcp/all`(2026-11-06 00:43 SGT 테스트) |
|---|---|---|
| OAuth만 지원 | 아니요, Bearer API 키 사용 | 예, RFC 9728 메타데이터와 함께 401 반환 |
| 동적 클라이언트 등록(RFC 7591) | 해당 없음 | 아니요, 메타데이터에 등록 엔드포인트 없음 |
| 등록된 클라이언트와 콜백을 사용하는 표준 OAuth | 해당 없음 | 공개 문서에 셀프서비스 등록 없음 |
| 도구 기능만 지원 | 예, 모든 도구가 MCP 도구 | 예 |
| 밑줄 없는 호스트 이름 | 예 | 예 |
MCP 사양 자체는 OAuth를 요구하지 않습니다. 2025-06-18 버전은 인가를 선택 사항으로 규정합니다. 서버가 인가를 지원한다면 RFC 9728과 RFC 8414 메타데이터를 게시해야 하며, 동적 등록은 "must"가 아닌 "should" 수준의 요구 사항입니다(MCP authorization, 2025-06-18). 따라서 API 키 방식의 서버도 사양을 따르고, OAuth 전용 클라이언트도 사양을 따릅니다. 두 방식이 서로 맞물리지 않을 뿐입니다.
Snowflake에는 외부 MCP 서버를 연결하는 곳이 하나 더 있습니다. Cortex AI Gateway에서는 관리자가 커스텀 MCP 서버를 추가할 수 있습니다. 이 기능의 문서도 OAuth, /mcp로 끝나는 URL, ACCOUNTADMIN 역할을 요구합니다(AI Gateway custom apps). 저희의 OAuth 주소는 /mcp/all로 끝나고, /mcp로 끝나는 주소는 키만 받습니다. 두 조건을 모두 충족하는 주소는 없습니다.
등록 문제가 해결된다고 가정해 보겠습니다. 그래도 커넥터는 이 작업에 맞지 않습니다. 각 사용자가 CoWork에서 Connect를 클릭하고, 원격 페이지에서 로그인한 뒤 접근을 승인해야 합니다. 그 후 에이전트는 채팅 중에 원격 도구를 호출하며, 결과는 해당 채팅 안에만 남습니다(Use MCP connectors in Snowflake CoWork). 질문하는 사람마다 각자 EveryInfra 계정이 필요합니다. 더 중요한 점은 리뷰가 테이블에 전혀 저장되지 않는다는 것입니다. 그래서 에이전트는 3개월 치 리뷰를 3개월 치 반품 데이터와 조인할 수 없습니다.
추세에 관한 질문에는 이력이 필요하고, 이력은 테이블에 있습니다. 커넥터는 다른 종류의 질문에 적합합니다. 예를 들어 "지금 이 영상 아래에서 사람들이 무엇을 두고 논쟁하고 있나" 같은 질문입니다. 이런 질문은 일회성이며 저장이 필요하지 않습니다.
저희가 찾은 Snowflake와 외부 데이터 API의 연결 방법은 네 가지입니다. 아래 표는 데이터가 테이블에 저장되는지, 그리고 해당 경로에 OAuth가 필요한지를 기준으로 이 방법들을 정리한 것입니다.
| 경로 | 테이블에 데이터 저장 | OAuth 필요 | 적합한 용도 | 출처 |
|---|---|---|---|---|
| MCP 커넥터(외부 MCP 서버 객체) | 아니요, 채팅에만 남음 | 예 | 일회성 질문 | 커넥터 문서 |
| 외부 액세스 통합, 저장 프로시저, 태스크 | 예 | 아니요, 키는 시크릿에 보관 | 일일 적재, 저희 추천 | External network access |
| Snowflake 외부 수집기 + Snowpipe | 예 | 아니요 | 이미 수집기를 운영하는 팀 | Snowpipe |
| Cortex Code Agent SDK의 외부 MCP | 아니요, 코드에서 직접 기록하지 않는 한 | 아니요, 헤더 사용 가능 | 코드로 테스트하는 개발자 | Agent SDK custom tools |
네 번째 경로에서는 Snowflake 개발자 도구로 요청 헤더에 API 키를 넣을 수 있습니다(Agent SDK 문서). 이 경로는 CoWork 비즈니스 인터페이스가 아닌 개발자 코드 안에서 동작합니다. 이 글의 나머지 부분은 두 번째 경로를 따릅니다. 일반적인 Snowflake 접근 제어 아래에서 일정에 따라 데이터를 테이블에 기록하기 때문입니다.
실제로 동작하는 방법: 외부 액세스와 저장 프로시저(구성 예시)
전체 흐름은 그림 하나로 정리됩니다. EveryInfra API가 Amazon, Reddit, TikTok에서 공개 리뷰와 댓글을 수집합니다. Snowflake 안에서는 예약된 태스크가 하루에 한 번 저장 프로시저를 호출합니다. 프로시저는 외부 액세스 통합을 통해 API를 호출하고, 각 원본 응답을 저장한 다음 이를 리뷰 테이블로 펼칩니다. 자체 판매 데이터와 Amazon FBA 반품 리포트는 지금처럼 별도의 테이블 두 개에 적재됩니다. 그 위에 시맨틱 뷰와 Cortex Agent가 있고, 비즈니스 사용자는 CoWork에서 질문합니다.
외부 액세스 통합은 프로시저와 함수가 인터넷에 접근하도록 허용하는 Snowflake의 표준 방식입니다. 여기에는 객체 세 개가 사용됩니다. 네트워크 규칙은 코드가 접근할 수 있는 호스트와 포트를 나열합니다. 시크릿은 자격 증명을 보관합니다. 통합은 이 둘을 묶습니다. 특정 역할에 이 통합의 사용 권한을 부여합니다(External network access overview, Creating and using an external access integration).
저희 규칙은 api.everyinfra.com만 허용합니다. 누군가 프로시저 코드를 수정하더라도 다른 호스트에는 접근할 수 없습니다. 키는 시크릿 객체에 보관되므로 코드에 평문으로 들어가지 않습니다. 프로시저를 실행하는 역할도 키를 읽을 수 없습니다. 아래 예시에서 voc는 데이터베이스 이름이며, "voice of the customer(고객의 소리)"를 뜻합니다.
-- 1. Allow outbound traffic to one host only
CREATE OR REPLACE NETWORK RULE voc.raw.everyinfra_egress
MODE = EGRESS
TYPE = HOST_PORT
VALUE_LIST = ('api.everyinfra.com');
-- 2. Store the API key. Create a separate key in the EveryInfra console
-- and give it its own per-minute call limit.
CREATE OR REPLACE SECRET voc.raw.everyinfra_key
TYPE = GENERIC_STRING
SECRET_STRING = '<EveryInfra API key>';
-- 3. Tie the rule and the secret together
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION everyinfra_access
ALLOWED_NETWORK_RULES = (voc.raw.everyinfra_egress)
ALLOWED_AUTHENTICATION_SECRETS = (voc.raw.everyinfra_key)
ENABLED = TRUE;
-- 4. Grant it only to the loading role
GRANT USAGE ON INTEGRATION everyinfra_access TO ROLE voc_loader;
GRANT READ ON SECRET voc.raw.everyinfra_key TO ROLE voc_loader;구문은 Snowflake SQL 레퍼런스를 따릅니다(CREATE NETWORK RULE, CREATE SECRET, CREATE EXTERNAL ACCESS INTEGRATION). 통합을 생성하려면 계정 수준 권한이 필요하므로 보통 관리자가 한 번만 생성합니다. 그 후 적재 역할에는 통합에 대한 USAGE 권한과 시크릿에 대한 READ 권한만 있으면 됩니다. Snowflake 예시 페이지에서 시크릿으로 외부 API를 호출하는 전체 프로시저를 확인할 수 있습니다(External network access examples).
프로시저 설계에는 비용을 좌우하는 선택이 하나 있습니다. 결과를 하나씩 기다릴지, 아니면 제출해 두고 나중에 가져올지입니다. EveryInfra API는 두 방식을 모두 지원합니다.
동기 호출은 데이터가 도착할 때까지 연결을 유지합니다. 저희 테스트에서 가장 느린 Amazon 리뷰 호출은 연결을 67초 동안 유지했습니다. 비동기 호출은 요청 본문에 "mode": "async"를 추가합니다. API는 약 2초 만에 상태 코드 202와 작업 ID를 반환합니다. 결과는 나중에 GET /api/v1/jobs/{job_id}로 가져옵니다(문서).
Snowflake에서는 이 차이가 곧 비용으로 이어집니다. 프로시저는 웨어하우스에서 실행되고, 웨어하우스는 실행 시간 1초마다 과금됩니다. 기다리는 1초도 과금되는 1초입니다. 그래서 저희는 적재 작업을 프로시저 두 개와 태스크 두 개로 나눴습니다. 한 프로시저는 제출만 하며 몇 초 안에 끝납니다. 다른 프로시저는 완료된 작업을 수집합니다.
아래 표는 이 구성에 사용되는 모든 Snowflake 객체와 각 객체의 역할, 그리고 주로 누가 생성하는지를 정리한 것입니다.
| 객체 | 용도 | 주로 생성하는 사람 |
|---|---|---|
네트워크 규칙 everyinfra_egress | 호스트 하나로의 아웃바운드 트래픽 허용 | 계정 관리자 |
시크릿 everyinfra_key | EveryInfra API 키 보관 | 계정 관리자 |
외부 액세스 통합 everyinfra_access | 규칙과 시크릿 연결 | 계정 관리자 |
프로시저 submit_pulls | 관심 목록(watchlist)의 각 행에 대해 비동기 작업 제출 | 데이터 엔지니어 |
프로시저 collect_results | 완료된 작업을 원본 테이블로 수집 | 데이터 엔지니어 |
태스크 t_submit, t_collect | 두 프로시저를 일정에 따라 실행 | 데이터 엔지니어 |
시맨틱 뷰 voc_returns | 주제, 주차, 반품 지표 정의 | 애널리틱스 엔지니어 |
VocAnalyst가 포함된 에이전트 | CoWork에서 질문에 답변 | 애널리틱스 엔지니어 |
CREATE OR REPLACE PROCEDURE voc.raw.submit_pulls()
RETURNS VARIANT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.11'
PACKAGES = ('snowflake-snowpark-python', 'requests')
HANDLER = 'run'
EXTERNAL_ACCESS_INTEGRATIONS = (everyinfra_access)
SECRETS = ('ei' = voc.raw.everyinfra_key)
AS
$$
import json, requests, _snowflake
API = "https://api.everyinfra.com/api/v1/social"
def run(session):
key = _snowflake.get_generic_secret_string("ei")
headers = {"Authorization": f"Bearer {key}", "Content-Type": "application/json"}
# watchlist: one row per product URL, video URL or search keyword
rows = session.sql(
"SELECT watch_id, platform, action, params FROM voc.raw.watchlist WHERE active"
).collect()
submitted = 0
for r in rows:
body = {"platform": r["PLATFORM"], "action": r["ACTION"],
"params": json.loads(r["PARAMS"]), "mode": "async"}
resp = requests.post(API, headers=headers, json=body, timeout=30)
payload = resp.json()
session.sql(
"""INSERT INTO voc.raw.jobs
(watch_id, job_id, http_status, charged_usd, first_payload, submitted_at)
SELECT ?, ?, ?, ?, PARSE_JSON(?), CURRENT_TIMESTAMP()""",
params=[r["WATCH_ID"], payload.get("job_id"), resp.status_code,
(payload.get("billing") or {}).get("charged_usd"), json.dumps(payload)],
).collect()
submitted += 1
return {"submitted": submitted}
$$;프로시저는 Python 프로시저에 대한 Snowflake 가이드를 따릅니다. SECRETS 절은 시크릿 객체를 이름에 매핑하고, 코드는 _snowflake.get_generic_secret_string으로 이 값을 읽습니다. PACKAGES 절에는 외부 패키지를 나열합니다(Python stored procedures overview). 그대로 따라 할 만한 세부 사항이 두 가지 있습니다. 첫째, 첫 번째 응답 전체를 보관해 두는 것이 좋습니다. 이 응답에는 정확한 달러 청구 금액이 나와 있으므로, 매월 EveryInfra 결제 페이지와 대조할 수 있습니다.
둘째, 프로시저 안에서 같은 대상을 재시도하지 마세요. API는 잘못된 파라미터, 일시적으로 사용할 수 없는 대상, 빈 결과에는 과금하지 않으며, 응답에 그 이유가 명시됩니다. 재시도는 다음 날 실행에 맡기세요. 실제로 저희가 받은 Amazon 503 응답에도 같은 항목을 바로 재시도해도 효과가 없을 가능성이 높다고 적혀 있었습니다.
수집기도 구조는 같습니다. voc.raw.jobs에서 아직 수집되지 않은 작업 ID를 읽고 각 작업의 상태를 조회합니다. running 또는 finalizing 상태인 작업은 건너뜁니다. 완료된 작업의 결과는 voc.raw.api_responses에 기록하고 해당 작업을 수집 완료로 표시합니다. 저희 테스트에서는 처음에 running만 미완료 상태로 처리했습니다. 그 결과 아직 finalizing 상태인 작업 하나의 결과를 너무 일찍 읽었습니다. 두 상태를 모두 조건에 넣으세요.
제출 태스크는 매일 싱가포르 시간 02:00에 실행되도록 예약하세요. 수집기는 02:20과 03:20에 예약해, 첫 번째 실행에서 놓친 결과를 두 번째 실행이 가져오게 합니다. 수집기를 몇 분마다 실행하지는 마세요. 웨어하우스는 재개될 때마다 최소 60초가 과금되므로, 자주 실행하면 대부분 유휴 시간에 비용을 쓰게 됩니다. 자동 일시 중단도 기본값인 10분 대신 60초로 설정하기를 권장합니다.
CREATE OR REPLACE TASK voc.raw.t_submit
WAREHOUSE = voc_xs_wh
SCHEDULE = 'USING CRON 0 2 * * * Asia/Singapore'
AS
CALL voc.raw.submit_pulls();
CREATE OR REPLACE TASK voc.raw.t_collect
WAREHOUSE = voc_xs_wh
SCHEDULE = 'USING CRON 20 2,3 * * * Asia/Singapore'
AS
CALL voc.raw.collect_results();
ALTER TASK voc.raw.t_collect RESUME;
ALTER TASK voc.raw.t_submit RESUME;태스크 문법은 CREATE TASK와 Introduction to tasks 문서를 참고하세요. WAREHOUSE를 제거하고 서버리스 태스크를 사용할 수도 있으며, 이 경우 Snowflake는 실제 사용한 컴퓨팅만큼 과금합니다. Service Consumption Table에는 서버리스 태스크의 배율이 0.9로 나와 있습니다(Service Consumption Table).
리뷰, 소셜 언급, 매출, 반품을 담는 테이블 4개
테이블 설계에는 세 가지 원칙이 있습니다. 원본 응답은 받은 그대로 보관합니다. 펼친 테이블에는 분석에 필요한 필드만 남깁니다. 가능하면 개인정보는 버립니다. API는 리뷰 작성자의 이름과 아바타를 반환하지만, 반품률 분석에는 전혀 쓰이지 않습니다. 이를 버리면 저장 공간을 아끼고 개인정보 문제도 없앨 수 있습니다. 아래는 핵심 테이블 4개와 매핑 테이블 1개입니다. 매출과 반품 데이터는 자체 시스템에서 가져오므로 구조만 보여 드립니다.
-- Raw responses: one row per API response, stored as VARIANT
CREATE TABLE IF NOT EXISTS voc.raw.api_responses (
job_id STRING,
platform STRING,
action STRING,
fetched_at TIMESTAMP_TZ,
payload VARIANT
);
-- Amazon reviews (expanded from amazon/reviews)
CREATE TABLE IF NOT EXISTS voc.core.reviews (
review_id STRING PRIMARY KEY,
asin STRING,
country STRING,
rating NUMBER(3,1),
title STRING,
body STRING,
posted_at TIMESTAMP_TZ,
is_verified_purchase BOOLEAN,
helpful_count NUMBER,
variant STRING,
fetched_at TIMESTAMP_TZ
);
-- Social mentions: TikTok comments and Reddit posts in one table
CREATE TABLE IF NOT EXISTS voc.core.social_mentions (
platform STRING, -- tiktok or reddit
source_id STRING, -- comment or post ID
source_url STRING, -- video URL or post URL
community STRING, -- Reddit community, empty for TikTok
product_key STRING, -- key from product_map
body STRING,
like_count NUMBER,
reply_count NUMBER,
is_reply BOOLEAN,
posted_at TIMESTAMP_TZ,
fetched_at TIMESTAMP_TZ,
themes ARRAY, -- labels from AI_CLASSIFY
PRIMARY KEY (platform, source_id)
);
-- Daily sales from your order system
CREATE TABLE IF NOT EXISTS voc.core.sales_daily (
sale_date DATE,
sku STRING,
asin STRING,
units_ordered NUMBER,
PRIMARY KEY (sale_date, sku)
);
-- FBA customer returns report (GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA)
CREATE TABLE IF NOT EXISTS voc.core.fba_returns (
return_date TIMESTAMP_TZ,
order_id STRING,
sku STRING,
asin STRING,
fnsku STRING,
quantity NUMBER,
fulfillment_center_id STRING,
detailed_disposition STRING,
reason STRING,
status STRING,
customer_comments STRING,
return_themes ARRAY
);
-- Product map: which ASINs, SKUs, videos and keywords belong to one product
CREATE TABLE IF NOT EXISTS voc.core.product_map (
product_key STRING,
asin STRING,
sku STRING,
tiktok_urls ARRAY,
reddit_terms ARRAY
);반품 테이블은 Amazon SP-API의 FBA 고객 반품 보고서를 그대로 옮깁니다. 보고서 유형은 GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA입니다. 필드에는 반품 날짜, 주문 ID, SKU, ASIN, FNSKU, 상품명, 수량, 풀필먼트 센터, 상세 처리 상태(detailed disposition), 반품 사유, 상태, LPN(license plate number), 고객 댓글이 포함됩니다. 문서에 따르면 Amazon은 이 보고서를 매일 업데이트합니다(SP-API FBA report types).
여기서 가장 중요한 것은 고객 댓글 열입니다. TikTok 댓글처럼 자유 형식 텍스트이기 때문입니다. 둘을 같은 주제 목록으로 분류하면 양쪽을 주제 기준으로 맞춰 볼 수 있습니다. 반품 사유 열은 Amazon의 고정 코드를 쓰는데, "뚜껑에서 샌다" 같은 주제보다 분류 단위가 훨씬 큽니다. 사유 코드만으로는 어떤 주제가 반품을 일으키는지 알 수 없습니다.
다음 표는 API 필드와 테이블 열의 매핑입니다. 필드 이름은 2026-11-06에 조회한 GET /api/v1/social/catalog의 EveryInfra 카탈로그를 기준으로 합니다(카탈로그).
| 기능 | API 필드 | 테이블 열 | 비고 |
|---|---|---|---|
amazon/reviews | review_id, product_asin, country | reviews.review_id, asin, country | 리뷰 ID 기준으로 중복 제거 |
amazon/reviews | rating, title, text, posted_at | rating, title, body, posted_at | 1~5점 평점 |
amazon/reviews | is_verified_purchase, helpful_count, variant | 이름 동일 | 색상과 사이즈는 variant에 포함 |
amazon/reviews | author_name, author_id, author_avatar_url | 저장하지 않음 | 분석에 필요 없는 개인정보 |
tiktok/comments | id, text, like_count, reply_count, is_reply, posted_at | 대응하는 social_mentions 열 | 최상위 댓글마다 답글 최대 2개 포함 |
tiktok/comments | author_username, author_id | 저장하지 않음 | 같은 이유 |
reddit/search | id, url, title 및 text, community, like_count, comment_count | source_id, source_url, body, community, like_count, reply_count | 제목과 본문을 하나의 텍스트로 결합 |
reddit/search | author_username | 저장하지 않음 | 같은 이유 |
펼치기 단계는 SQL만으로 충분합니다. api_responses에서 플랫폼별로 행을 선택하고, payload:results에 LATERAL FLATTEN을 적용한 뒤, ID 기준으로 대상 테이블에 MERGE합니다. 같은 동영상을 다시 가져오면 기존 댓글은 좋아요 수가 갱신되고 새 댓글은 추가됩니다. 이 글 후반에서 보겠지만, 몇 달 뒤 같은 동영상을 다시 가져오는 것이 이 구성에서 가장 유용한 단계입니다.
실제 API 요청·응답 한 번 살펴보기: REST, 비동기, MCP
Snowflake 쪽은 직접 실행하지 못했습니다. 하지만 프로시저는 저희가 로컬 머신에서 사용한 것과 같은 API에 같은 요청을 보내고, 같은 형식의 응답을 받습니다. 2026-11-06 SGT 00:16~00:36에 테스트 키로 12건의 API 호출을 했습니다. 이 글에서 다루는 세 가지 기능과 함께, 대상을 고르는 데 쓴 검색 2건도 포함됩니다. 호출마다 요청, 시작·종료 시각, HTTP 상태, 소요 시간, 과금액을 기록했습니다.
| # | SGT | 기능 | 모드 | 결과 | 소요 시간 | 과금 |
|---|---|---|---|---|---|---|
| 1 | 00:16:52 | amazon/search, 키워드 portable blender | 동기 | 상품 10개, 그중 9개가 Ninja | 42.14 s | $0.002236 |
| 2 | 00:17:41 | amazon/reviews, 상품 B0C2FF4JD1 | 동기 | 503, 일시적으로 사용 불가(과금 없음) | 60.12 s | $0 |
| 3 | 00:18:41 | amazon/reviews, 상품 B0CN3S2SW2 | 동기 | 503 | 58.57 s | $0 |
| 4 | 00:19:47 | amazon/reviews, 상품 B09B8V1LZ3 | 동기 | 0행, 빈 결과 환불 | 67.25 s | $0 |
| 5 | 00:20:55 | reddit/search, portable blender, 최신순 | 동기 | 게시물 14건 | 6.56 s | $0.000556 |
| 6 | 00:21:13 | tiktok/search, ninja blast portable blender review | 동기 | 동영상 10개 | 3.78 s | $0.000556 |
| 7 | 00:21:21 | tiktok/comments, 저가 vs 고가 비교 테스트 동영상 | 동기 | 댓글 200개 | 52.30 s | $0.000556 |
| 8 | 00:22:13 | walmart/reviews, 상품 페이지 | 동기 | 0행, 빈 결과 환불 | 54.34 s | $0 |
| 9 | 00:24:22 | amazon/reviews, 상품 B0D2YYHN1B | 동기 | 503 | 19.48 s | $0 |
| 10 | 00:25:26 | reddit/search, ninja blast | MCP | 게시물 7건 | 7.62 s | $0.000556 |
| 11 | 00:27:36 | tiktok/comments, 단일 상품 체험 동영상 | 비동기 | 202, 약 100초 후 완료, 댓글 73개 | 제출 1.95초 | $0.000556 |
| 12 | 00:36:23 | amazon/reviews, 상품 B0C2FF4JD1 재요청 | 동기 | 503 | 38.42 s | $0 |
12건 중 6건이 과금되었고, 합계는 $0.005016입니다. 나머지 6건은 503 또는 빈 결과를 반환했으며 모두 과금되지 않았습니다. 8번 호출의 Walmart 상품 URL은 상품명으로 추측한 것이어서 빈 결과는 저희 실수입니다. 그래도 Walmart 리뷰에도 빈 결과 환불이 적용된다는 점은 확인할 수 있었습니다.

스크린샷의 첫 번째 부분은 제출 프로시저가 받는 응답입니다. 1.95초 만에 작업 ID와 함께 202를 반환했으며, 응답에는 제출 시점의 과금액 $0.000556이 명시되어 있습니다. 두 번째 부분은 수집기가 받는 응답입니다. 상태는 running에서 finalizing을 거쳐 succeeded로 바뀌었습니다. 약 8초 간격으로 총 12번 폴링했고, 작업은 제출 후 약 100초 만에 완료되었습니다.
세 번째 부분은 실패 사례입니다. 상태는 503, 사유는 access_blocked, 권장 재시도 시점은 900초 후, 과금액은 0입니다. 프로시저는 상태 코드와 이 필드들만 보고 분기하면 됩니다.
10번 호출은 비교용입니다. 같은 Reddit 검색을 MCP 도구 everyinfra_call_api로 실행했습니다. 7.62초 만에 게시물 7개를 반환했으며, 19,490바이트 응답 안에 18,619자의 도구 결과가 담겨 있었습니다. Cortex Agent가 MCP 커넥터로 이 호출을 했다면 이 18,619자 전체가 입력 토큰으로 모델 컨텍스트에 들어갔을 것입니다. 같은 데이터를 테이블에 적재해 두면 에이전트가 처리하는 입력은 실제로 읽는 몇 개 행뿐입니다. 그래서 저희는 "대화마다 실시간으로 가져오기"보다 "먼저 적재하고 나중에 질문하기"를 선호합니다.
이 지연 시간 차트가 Snowflake 비용 모델을 결정합니다. 데이터 크기로 보면 세 기능 모두 가볍습니다. 댓글 200개를 받은 TikTok 댓글 호출 1건이 71,228바이트였고, Reddit 검색 1건은 약 30,000바이트였습니다. 반면 대기 시간으로 보면 동기 방식의 리뷰나 댓글 호출은 50~70초가 걸리는 경우가 많습니다.
웨어하우스는 초 단위로 과금되며, 재개될 때마다 최소 60초가 청구됩니다(Warehouses overview, Understanding compute cost). 동기 호출 중에는 웨어하우스가 거의 모든 시간을 네트워크 대기에 씁니다. 비용 섹션에서 이를 달러로 환산합니다.
테스트 1: 제품 문제를 언급한 TikTok 댓글은 얼마나 될까?
대부분의 독자에게 익숙한 카테고리인 휴대용 블렌더를 골랐습니다. 1번 호출에서는 amazon/search로 "portable blender"를 검색했습니다. 상위 결과 10개 중 9개가 Ninja 제품이었고, 가격은 $19.95~$59.99였습니다(Amazon 데이터 API, Amazon 검색). 6번 호출에서는 tiktok/search로 "ninja blast portable blender review"를 검색했습니다. 반환된 동영상 10개 중 댓글이 가장 많은 2개를 골라 tiktok/comments로 댓글을 가져왔습니다(TikTok 데이터 API, TikTok 댓글 API, TikTok 검색 API).
첫 번째 동영상은 2025-07-27에 게시된 "저가 vs 고가" 블렌더 비교 테스트입니다. 수집 당시 조회수는 2,586,703회, 댓글은 251개였습니다. 1회 호출 한도인 200개를 받았습니다. 두 번째 동영상은 2026-01-20에 게시된 단일 상품 체험 영상으로, 조회수 208,916회, 댓글 98개였습니다. 그중 73개를 받았고, 17개는 답글이었습니다. 이 글에서는 두 크리에이터 모두 밝히지 않습니다.
| 동영상 | 게시일 | 조회 결과 | 동영상 댓글 수 | 받은 댓글 수 | 답글 | 제품 문제 | 비율 |
|---|---|---|---|---|---|---|---|
| 저가 vs 고가 비교 테스트 | 2025-07-27 | 2,586,703 | 251 | 200 | 23 | 4 | 2.0% |
| 단일 상품 체험 | 2026-01-20 | 208,916 | 98 | 73 | 17 | 13 | 17.8% |
먼저 가장 흔히 쓰는 지름길인 키워드 목록부터 시도했습니다. 키워드는 "battery", "leak", "broke", "returned", "expensive", "too small"이었습니다. 댓글에 이 중 하나라도 포함되면 불만으로 집계했습니다. 첫 번째 영상에서는 댓글 200개 중 42개가 목록과 일치했습니다. 그런 다음 모든 댓글을 직접 읽었습니다. 42개 중 블렌더의 문제를 언급한 댓글은 4개뿐이었으므로, 키워드 규칙이 맞은 비율은 9.5%에 그쳤습니다.
이유는 쉽게 알 수 있습니다. "저가 vs 고가" 동영상의 댓글은 대부분 영상 형식에 대한 농담이거나, 다른 물건의 저가·고가 버전도 테스트해 달라는 요청입니다. 댓글 30개가 "expensive"나 가격 관련 단어에 걸렸지만, 그중 블렌더가 가격만큼의 가치가 없다고 말한 댓글은 7개뿐이었습니다. Snowflake에서는 주제 라벨을 모델이 붙여야 하며, 그 전에 "제품 문제"의 정의를 글로 명확히 정해 두어야 합니다.
아래 표는 첫 번째 동영상에서 키워드 목록에 걸린 댓글 42개에 저희가 직접 붙인 라벨입니다.
| 수동 라벨 | 댓글 |
|---|---|
| 제품 신호 아님(농담, 다른 주제) | 29 |
| 가격 불만만 있음 | 7 |
| 제품 문제 | 4 |
| 불분명 | 2 |
| 키워드 일치 합계 | 42 |
수동 라벨링 기준은 엄격했습니다. 이 제품에 문제가 있었다고 말하는 댓글만 집계했습니다. 문제 유형은 뚜껑 문제나 내용물 쏟아짐, 짧은 배터리 수명, 얼음 분쇄력 부족, 부품 누락, 세척 어려움, 빠른 고장입니다. "돈값 못 해서 반품했다" 같은 일반적인 불만도 포함합니다. 가격 불만, 브랜드 비교, 농담, 이모지는 제외합니다. 이 기준으로 보면 두 동영상은 크게 다릅니다.
조회수가 10배 많은 동영상은 제품 문제 댓글이 2.0%에 불과합니다. 규모가 작은 체험 동영상은 17.8%입니다. 차이는 시청자에서 옵니다. 비교 동영상에는 재미로 보는 사람이 모입니다. 체험 동영상에는 제품을 가지고 있거나 구매를 고려하는 사람이 모이고, "내 것도 샜어요"라고 쓰는 사람이 바로 이들입니다. Snowflake 설계에서는 동영상당 댓글 수보다 product_map에 어떤 동영상을 넣느냐가 더 중요합니다.
호출당 $0.000556로 가격이 같은데도 체험 동영상에서 거의 9배 많은 신호를 얻었습니다. 이 선택도 자동화할 수 있습니다. tiktok/search로 검색한 뒤, 캡션에 "review", "trying", "honest" 같은 단어가 있고 댓글이 수십~수백 개인 동영상만 남기면 됩니다.
두 동영상을 합치면 댓글 273개 중 17개가 제품 문제를 설명했습니다. 주제별 분포는 다음과 같습니다.
| 주제 | 댓글 | 예시(원문, 작성자 비공개) | 좋아요 |
|---|---|---|---|
| 뚜껑 또는 내용물 쏟음 | 6 | The way I just gasped when it spilled. Were you supposed to open it from the top instead? | 79 |
| 배터리 | 3 | the batteries do not last long enough to make a full smoothie | 9 |
| 일반적 불만, 반품 | 2 | Not worth it, returned after a week | 0 |
| 얼음·냉동 과일 분쇄력 부족 | 2 | It's not. I returned mine. Barely could get through frozen fruit | 97 |
| 부품 누락 | 2 | ours both didn't come with the blade cap | 0 |
| 빠른 고장 | 1 | 완전 쓰레기예요, 2번 돌리면 끝나요 | 1 |
| 세척이 어려움 | 1 | 씻기 어려움 | 0 |
뚜껑 또는 내용물 쏟음 문제가 가장 큰 그룹입니다. 이 그룹에서 좋아요가 가장 많은 댓글은 79개를 받았으며, 뚜껑을 위쪽에서 여는 게 맞는 것 아니냐고 묻습니다. 다른 댓글 작성자는 처음에 똑같이 내용물을 쏟았고 캡을 쓸 생각을 못 했다고 말합니다. 2026-01-22에 작성된 댓글은 뚜껑의 버튼이 부러지고 교체 부품도 판매되지 않으니 사용하지 말라고 경고합니다.
이런 문제는 배터리나 모터 불만과 성격이 다릅니다. 설명서, 포장, 제품 사진을 개선하면 해결되는 경우가 많고, 그러면 반품률도 빠르게 떨어질 수 있습니다. "어떤 불만 테마가 반품과 함께 늘어나는가"라는 질문이 찾으려는 것이 바로 이것입니다. 어떤 테마가 반품 급증과 맞물리면 실행할 액션이 구체적으로 정해집니다.
테이블에 좋아요 수를 남겨 두세요. 좋아요 97개를 받은 "반품했어요" 댓글과 좋아요 0개인 불만은 같은 수의 사람을 대변하지 않습니다. 시맨틱 뷰에서 댓글 수와 좋아요 가중 댓글 수, 두 가지 측정값을 정의하세요. 에이전트에게 두 값을 모두 보고하도록 요청하세요.
Snowflake에서는 AI_CLASSIFY로 라벨링할 수 있습니다. 7개 테마에 "제품 문제 아님"을 더해 카테고리로 사용합니다. 다중 라벨 출력을 설정합니다. 가격 불만과 농담을 제외하는 작업 설명을 추가합니다. 문서에서는 카테고리를 약 20개 이하로 둘 것을 권장하며, 예시도 넣을 수 있습니다(AI_CLASSIFY 문서).
이 문서의 사용 참고 사항 중 중요한 것이 하나 있습니다. 영어 입력에서 결과가 가장 좋고, 다른 언어에서는 성능이 떨어질 수 있습니다. TikTok과 Amazon US 댓글은 대부분 영어이므로 미국 브랜드에는 크게 문제되지 않습니다. 스페인어권이나 다른 시장도 추적한다면 먼저 사람이 직접 라벨링한 샘플로 확인하세요. 작업 설명과 카테고리도 모든 행에서 토큰으로 계산됩니다. 따라서 행당 실제 토큰 수는 댓글 길이보다 많습니다.
UPDATE voc.core.social_mentions
SET themes = AI_CLASSIFY(
body,
['lid_or_spill', 'battery', 'weak_on_ice', 'missing_part',
'breaks_quickly', 'hard_to_clean', 'general_negative', 'not_a_product_issue'],
{'output_mode': 'multi',
'task_description': 'Label only comments that report a problem with this blender. Price complaints, jokes and brand comparisons are not_a_product_issue.'}
):labels
WHERE themes IS NULL;반품 테이블의 customer_comments 열에도 같은 분류를 실행하고 결과를 return_themes에 기록합니다. 그러면 양쪽이 같은 테마, 같은 모델, 같은 설명을 사용하므로 테마별 비교가 의미를 갖습니다. AI_SENTIMENT로 각 댓글을 부정에서 긍정까지 점수화할 수도 있습니다(AI_SENTIMENT 문서). 다만 여기서 알고 싶은 것은 얼마나 불만인지가 아니라 어떤 문제인지이므로 큰 도움은 되지 않습니다.
테스트 2: Reddit 검색으로는 무엇이 나올까?
많은 팀이 Reddit을 솔직한 사용자 의견이 모이는 곳으로 여기기 때문에, TikTok을 보완할 수 있는지 확인했습니다. 5번째 호출은 reddit/search로 "portable blender"를 최신순으로 검색해 게시물 14개를 반환했습니다. 10번째 호출은 MCP를 통해 "ninja blast"를 검색해 게시물 7개를 반환했습니다(Reddit 데이터 API, Reddit 검색 API). 이 기능은 항상 최근 1개월을 검색하며 호출당 최대 25개 게시물을 반환합니다. 14개 게시물은 2026-10-30부터 2026-11-05(UTC)까지만, 7개 게시물은 11월 3일부터 11월 5일까지만 포함했습니다.
게시물을 모두 읽어 보았습니다. 21개 중 블렌더 성능을 다룬 게시물은 하나도 없었습니다. "portable blender" 게시물 14개 중 10개는 할인 게시물이었습니다. 대부분 r/priceglitch 같은 할인 커뮤니티에 올라왔고, 제목은 "Ninja Blast Max Portable Blender, Twist & Go, 22oz"에 색상과 가격이 붙은 형태였습니다. 할인 게시물은 2026-10-31, 2026-11-01, 2026-11-05에 올라왔습니다. 일일 Amazon 할인 모음 게시물은 2026-11-02와 2026-11-03에 올라왔습니다.
나머지 4개 게시물은 블렌더와 무관했습니다. 한 사용자는 휴대용 ThinkPad에 대해 물었고, 3D 소프트웨어 Blender 커뮤니티의 게시물 2개는 노트북 사양을 물었습니다. "ninja blast" 게시물 7개 중 4개는 할인 게시물이었습니다. 나머지 3개는 우연히 단어가 일치한 것으로, 하나는 비디오 게임에 관한 글이었고 2개는 애니메이션 시리즈 Ninjago 커뮤니티의 게시물이었습니다.
| 쿼리 | 게시물 | 할인 게시물 | 주제와 무관 | 제품 관련 논의 | 기간(UTC) |
|---|---|---|---|---|---|
| portable blender (REST) | 14 | 10 | 4 | 0 | 2026-10-30 ~ 2026-11-05 |
| ninja blast (MCP) | 7 | 4 | 3 | 0 | 2026-11-03 ~ 2026-11-05 |
그렇다고 Reddit이 쓸모없다는 뜻은 아닙니다. 짧은 키워드를 최신순으로 정렬한 쿼리가 잘못되었다는 뜻입니다. Snowflake에 적재할 때는 세 가지를 바꾸세요. 첫째, 관련성은 제목만으로 판단하고, "blender" 바로 앞에 portable, personal, smoothie 또는 브랜드 이름이 와야 한다는 조건을 거세요. 처음 규칙은 게시물 본문의 "blender"까지 일치시켜 3D 소프트웨어 게시물을 제품 게시물로 셌습니다.
둘째, 할인 게시물은 유용한 데이터이므로 별도 카테고리로 남겨 두세요. 한 달 동안 특정 블렌더가 할인 커뮤니티에 얼마나 자주, 어떤 가격으로 등장하는지를 판매 테이블과 나란히 볼 수 있습니다. 그러면 할인 주간이 반품 급증으로 이어지는지 확인할 수 있습니다. 셋째, 실제 제품 관련 논의는 스무디나 피트니스 식단을 다루는 일부 커뮤니티에 모이는 경향이 있습니다. 사이트 전체 검색 대신 그런 커뮤니티의 관련 스레드에 reddit/comments를 사용하세요.
테스트 3: Amazon 리뷰에서 503이 반환됐고 과금되지 않았다
가장 원했던 데이터는 Amazon 리뷰였습니다. 리뷰와 반품은 같은 플랫폼의 같은 구매자에게서 나옵니다. 하지만 5번의 amazon/reviews 호출에서 리뷰는 하나도 반환되지 않았습니다(Amazon 리뷰 API). SGT 기준 00:17, 00:18, 00:24에 Ninja와 Hamilton Beach의 서로 다른 제품 3개에 대한 호출이 각각 access_blocked 사유와 함께 503을 반환했습니다. 이는 해당 항목의 리뷰를 일시적으로 가져올 수 없으며 과금되지 않았다는 뜻이고, 응답에서는 900초 후 재시도를 권장합니다.
SGT 기준 00:19에는 더 오래된 제품으로 시도했습니다. 200과 함께 0행이 반환되었고, 빈 결과로 처리되어 호출 비용이 환불되었습니다. 첫 시도 19분 후인 SGT 00:36에 첫 번째 제품을 다시 호출했지만 또 503이 반환되었습니다. 5번의 호출 모두 charged_usd가 0입니다.
| SGT | 제품 | HTTP 상태 | 이유 | 소요 시간 | 과금 |
|---|---|---|---|---|---|
| 00:17:41 | B0C2FF4JD1 | 503 | access_blocked | 60.12 s | $0 |
| 00:18:41 | B0CN3S2SW2 | 503 | access_blocked | 58.57 s | $0 |
| 00:19:47 | B09B8V1LZ3 | 200 | 빈 결과, 환불됨 | 67.25 s | $0 |
| 00:24:22 | B0D2YYHN1B | 503 | access_blocked | 19.48 s | $0 |
| 00:36:23 | B0C2FF4JD1 | 503 | access_blocked | 38.42 s | $0 |
매일 실행되는 Snowflake 태스크도 같은 상황을 겪게 되므로 있었던 그대로 보고합니다. EveryInfra 규칙상 일시적으로 접근할 수 없거나 로그인이 필요한 대상은 사유와 재시도 힌트와 함께 503을 반환합니다. 리뷰가 없다고 주장하는 빈 200을 반환하는 일은 없습니다. 이 차이는 로더에 중요합니다. 503은 "오늘은 데이터가 없으니 내일 다시 시도"라는 뜻입니다. 빈 200은 "정말로 아무것도 없다"는 뜻입니다.
프로시저가 두 경우를 섞어 버리면 시맨틱 뷰에 일부 제품의 가짜 "불만 0건" 날짜가 생깁니다. 그러면 에이전트는 이를 근거로 잘못된 결론을 내립니다. HTTP 상태와 사유를 jobs 테이블에 저장하세요. 상태가 200인 응답만 펼치세요. 시맨틱 뷰에 "데이터 누락 일수" 측정값을 추가해 에이전트가 어떤 날에 데이터가 없었는지 말할 수 있게 하세요.
카탈로그에 따르면 amazon/reviews는 상품 페이지에 표시되는 주요 리뷰만 반환합니다. 보통 상품당 십여 개 정도이며, 호출당 최대 100개, 11개 Amazon 마켓플레이스를 지원합니다.
따라서 상황이 좋은 날에도 모든 리뷰를 가져오지는 못합니다. Amazon이 보여 주기로 선택한 리뷰들입니다. 이 리뷰들로 "가장 눈에 띄는 불만은 무엇인가"는 충분히 알 수 있습니다. 하지만 모든 불만을 세기에는 부족합니다. 전체 건수가 필요하다면 Seller Central 데이터와 FBA 반품 보고서의 고객 댓글이 더 완전합니다. 이 보고서가 위의 fba_returns 테이블에 들어갑니다.
Cortex Agent에게 묻기: 어떤 불만 테마가 반품률과 함께 오를까?
테이블이 준비되면 주간 뷰를 만듭니다. 각 행에는 제품 하나, 테마 하나, 주 하나에 대한 소셜 언급 수, 반품 수량, 판매 수량이 들어갑니다. 테마 반품률은 해당 테마의 반품 수량을 그 주의 판매 수량으로 나눈 값입니다.
CREATE OR REPLACE VIEW voc.core.theme_returns_weekly AS
WITH mentions AS (
SELECT s.product_key,
DATE_TRUNC('week', s.posted_at)::DATE AS week_start,
t.value::STRING AS theme,
COUNT(*) AS mentions,
SUM(1 + COALESCE(s.like_count, 0)) AS weighted_mentions
FROM voc.core.social_mentions s,
LATERAL FLATTEN(input => s.themes) t
WHERE t.value::STRING <> 'not_a_product_issue'
GROUP BY 1, 2, 3
),
returns AS (
SELECT pm.product_key,
DATE_TRUNC('week', f.return_date)::DATE AS week_start,
COALESCE(t.value::STRING, 'unclassified') AS theme,
SUM(f.quantity) AS returned_units
FROM voc.core.fba_returns f
JOIN (SELECT DISTINCT product_key, asin FROM voc.core.product_map) pm
ON pm.asin = f.asin,
LATERAL FLATTEN(input => f.return_themes, OUTER => TRUE) t
GROUP BY 1, 2, 3
),
sales AS (
SELECT pm.product_key,
DATE_TRUNC('week', d.sale_date)::DATE AS week_start,
SUM(d.units_ordered) AS units_sold
FROM voc.core.sales_daily d
JOIN (SELECT DISTINCT product_key, asin FROM voc.core.product_map) pm
ON pm.asin = d.asin
GROUP BY 1, 2
),
theme_weeks AS (
SELECT COALESCE(m.product_key, r.product_key) AS product_key,
COALESCE(m.week_start, r.week_start) AS week_start,
COALESCE(m.theme, r.theme) AS theme,
COALESCE(m.mentions, 0) AS mentions,
COALESCE(m.weighted_mentions, 0) AS weighted_mentions,
COALESCE(r.returned_units, 0) AS returned_units
FROM mentions m
FULL OUTER JOIN returns r
ON r.product_key = m.product_key
AND r.week_start = m.week_start
AND r.theme = m.theme
)
SELECT tw.product_key, tw.week_start, tw.theme,
tw.mentions, tw.weighted_mentions, tw.returned_units,
s.units_sold,
tw.returned_units / NULLIF(s.units_sold, 0) AS theme_return_rate
FROM theme_weeks tw
LEFT JOIN sales s
ON s.product_key = tw.product_key AND s.week_start = tw.week_start;이 뷰에는 반품이 누락되지 않도록 하는 세 가지 설계가 들어 있습니다. 첫째, 언급과 반품은 제품, 주, 테마 기준으로 full outer join하고, 판매는 그 뒤에 제품과 주 기준으로 조인합니다. 따라서 어떤 주의 소셜 게시물이 뚜껑 문제만 언급하더라도 그 주의 배터리 반품은 별도 행으로 남습니다. 둘째, OUTER => TRUE는 댓글이나 테마가 없는 반품을 unclassified 라벨로 유지합니다. 셋째, product_map에서 ASIN 하나가 여러 SKU에 매핑될 수 있으므로, 뷰는 중복을 제거한 제품-ASIN 쌍으로 조인합니다. 그렇지 않으면 반품과 판매가 중복 집계됩니다. 주의할 점이 하나 있습니다. 댓글 하나에 테마가 두 개 붙을 수 있으므로, 테마 행을 합하면 실제 반품 수량보다 커질 수 있습니다. 전체 반품률은 테마 행을 더하지 말고 fba_returns를 직접 합산하세요.
다음으로 그 위에 시맨틱 뷰를 만듭니다. 시맨틱 뷰는 Cortex Analyst에게 각 열의 의미와 어떤 열이 측정값인지 알려 줍니다(Semantic views overview, CREATE SEMANTIC VIEW). 측정값은 최소 네 가지를 정의하세요. 테마 언급 수, 좋아요 가중 언급 수, 테마별 반품 수량, 테마별 반품률입니다. 차원은 제품, 테마, 주입니다. 동의어도 추가하세요. "leak", "spill", "cap"을 lid_or_spill에 매핑하면 에이전트가 비즈니스 사용자가 실제로 입력하는 단어를 이해합니다.
에이전트 사양은 YAML로 작성합니다. 최소 구성은 이 시맨틱 뷰를 대상으로 하는 Cortex Analyst 도구 하나입니다. 여기에 제품과 테마별로 좋아요가 가장 많은 댓글을 반환하는 커스텀 도구 하나를 추가합니다. 구조는 CREATE AGENT를 따릅니다. Cortex Agents 문서에 따르면 커스텀 도구 파라미터에는 object 타입을 쓸 수 없으므로 파라미터는 단순하게 유지하세요(Cortex Agents overview).
models:
orchestration: claude-sonnet-5-5
orchestration:
budget:
seconds: 120
tokens: 40000
instructions:
orchestration: >
For questions about complaint themes and returns, use VocAnalyst on weekly data.
Compare each theme's mentions with the same week and the next 1 to 4 weeks of
theme_return_rate. Report weeks with missing review data. Never treat a missing
week as zero complaints.
response: >
Give the theme, the weeks, both raw and like-weighted mention counts, and the
return rate change. Quote at most two comments from TopComments, without author names.
sample_questions:
- question: "Which complaint theme rises together with the return rate?"
- question: "Did lid complaints for the Ninja Blast track returns over the last four weeks?"
tools:
- tool_spec:
type: cortex_analyst_text_to_sql
name: VocAnalyst
description: Weekly social complaint themes, returns and sales by product.
- tool_spec:
type: generic
name: TopComments
description: Returns the most liked comments for one product and one theme.
input_schema:
type: object
properties:
product_key: {type: string, description: Product key from product_map}
theme: {type: string, description: One theme label}
required: [product_key, theme]
tool_resources:
VocAnalyst:
semantic_view: voc.core.voc_returns
TopComments:
type: procedure
identifier: voc.core.top_comments
execution_environment:
type: warehouse
warehouse: voc_xs_wh"함께 오른다"는 말은 정확하게 정의해야 합니다. 지침은 에이전트에게 같은 주와 그 후 1~4주의 반품을 비교하도록 합니다. 그 이유는 저희 데이터에서 드러납니다. 불만과 반품은 같은 시점에 일어나지 않습니다. 아래 차트는 제품 문제 댓글 17개를 월별로 보여 줍니다.
비교 영상은 2025-07-27에 올라왔고, 문제 댓글 4개는 각각 6일, 44일, 245일, 245일 후에 달렸습니다. 사용 체험 영상은 2026-01-20에 올라왔습니다. 문제 댓글 13개 중 첫 주에 달린 것은 2개뿐이고, 나머지는 3월부터 9월까지 흩어져 있습니다. 반품을 언급한 두 댓글은 모두 2026년 3월에 달렸으며, 하나는 영상 게시 245일 후, 다른 하나는 52일 후였습니다.
| 댓글(작성자 비공개) | 주제 | 댓글 날짜 | 영상 게시 후 일수 | 좋아요 |
|---|---|---|---|---|
| 뚜껑을 위쪽에서 열어야 하는지 질문 | 뚜껑 또는 내용물 쏟음 | 2026-01-20 | 0 | 79 |
| 뚜껑 버튼은 부러지니 쓰지 말 것 | 뚜껑 또는 내용물 쏟음 | 2026-01-22 | 2 | 5 |
| 다들 이 블렌더가 최악이라고 한다고 말함 | 전반적인 부정 의견 | 2026-03-01 | 40 | 23 |
| 반품함, 냉동 과일에 약함 | 얼음에 약함 | 2026-03-13 | 52 | 97 |
| 배터리가 스무디 한 번을 다 못 버팀 | 배터리 | 2026-03-14 | 53 | 9 |
| 두 제품 모두 칼날 캡 없이 배송됨 | 부품 누락 | 2026-07-31 | 192 | 0 |
| 여분 뚜껑을 얻으려고 한 대 더 구매함 | 뚜껑 또는 내용물 쏟음 | 2026-09-12 | 235 | 0 |
이 차트를 보면 Snowflake 설계에서 두 가지를 바꿔야 합니다. 첫째, 영상을 한 번만 수집하지 마세요. 첫 주에만 수집했다면 첫 번째 영상의 문제 댓글 3개를 놓쳤을 것입니다. 두 번째 영상에서는 11개를 놓쳤을 것입니다. 따라서 watchlist는 같은 영상을 매주 또는 매월 다시 수집해야 하며, MERGE가 새 댓글을 추가합니다.
둘째, 불만과 반품을 같은 주 기준으로 조인하면 아마 아무것도 나오지 않을 것입니다. 구매자는 제품을 한동안 쓴 뒤에 불만을 남기고 반품합니다. 지연 기간을 가정하지 말고 데이터로 찾으세요.
데이터 양에 대해서도 솔직해야 합니다. 영상 2개에서 14개월 동안 나온 문제 댓글은 17개이므로 대부분의 주는 0건입니다. 이렇게 희소한 데이터로 구한 상관관계는 의미가 없습니다.
에이전트에게 탄탄한 기반을 주려면 제품당 사용 체험형 영상 20~30개와 함께 Amazon 리뷰와 반품 댓글을 추적하세요. 처음에는 월 단위로 시작하고 데이터가 충분해지면 주 단위로 바꾸세요. 이 한계는 Snowflake가 아니라 데이터 양에서 비롯되며, 어떤 도구를 써도 마찬가지입니다. 지침에서 에이전트에게 데이터가 누락된 주를 보고하도록 하는 이유도 여기에 있습니다. 댓글 3개로 만들어 낸 추세보다 솔직한 "데이터 부족"이 낫습니다.
한 달 비용은 얼마일까: API 요금과 Snowflake 요금
먼저 구체적인 계획을 세운 뒤 비용을 계산합니다. 한 브랜드가 ASIN 20개와 TikTok 영상 20개를 추적하며, 각각의 리뷰나 댓글을 하루에 한 번 수집합니다. 새 영상을 찾기 위해 Reddit 키워드 5개를 매일, TikTok 키워드 5개를 매주 검색합니다. 30일 동안 API 호출은 1,370건입니다. API 요금은 2026-11-06에 확인한 카탈로그 가격을 적용했으므로 실제 가격입니다.
Snowflake 항목은 모두 추정치이며, 계산 방법은 표에 적었습니다. 가격은 2026-11-04부터 적용되는 Service Consumption Table과 AWS US East의 온디맨드 Standard 에디션 가격을 기준으로 합니다. 플랫폼 크레딧은 $2.00입니다. AI 크레딧은 글로벌 요금 기준 $2.00입니다(Service Consumption Table, 요금 페이지, Cortex AI 요금).
| 항목 | 방법 | 월 비용 |
|---|---|---|
| EveryInfra API 요금 | amazon/reviews 600건 × $0.001389 + tiktok/comments 600건 × $0.000556 + reddit/search 150건 × $0.000556 + tiktok/search 20건 × $0.000556 | $1.26 |
| 웨어하우스 응답 대기(동기, 순차) | 측정된 소요 시간: Amazon 리뷰 67.25초(5번 호출 중 가장 느렸던 빈 결과 호출 기준이며, 503 호출의 19.48~60.12초를 적용하면 이 항목은 $24.61~$38.16), TikTok 댓글 52.3초, Reddit 7.62초, TikTok 검색 3.78초. 총 20.27시간 × XS 기준 시간당 1크레딧 × $2 | $40.54 |
| 웨어하우스 대기(동기, 병렬 호출 10개) | 위와 같음, 10으로 나눔 | $4.05 |
| 웨어하우스(비동기, 태스크 2개) | 하루 약 46회 제출 × 2초 + 수집기 2회 실행 × 최소 60초 + 실행 3회 각각 이후 자동 일시 중단 전 유휴 시간 60초. 하루 약 392초, 월 약 3.3시간 | 약 $6.5 |
AI_CLASSIFY 테마 라벨 | 댓글 10,000개 × 약 150토큰 = 1.5백만 토큰 × 백만 토큰당 1.62 AI 크레딧 × $2 | $4.86 |
| Cortex Agent 질문(Sonnet 5.5) | 질문 50개 × (입력 20,000토큰 + 출력 1,500토큰), 100만 토큰당 입력 1.30 AI 크레딧 및 출력 6.50 AI 크레딧 적용 | $3.58 |
| Cortex Agent 질문(Haiku 5.5) | 위와 같음, 입력 0.065, 출력 0.325 기준 | $0.18 |
| 웨어하우스에서 실행되는 에이전트 SQL | 쿼리 50개 × 최소 60초 × 크레딧-시간당 $2 | $1.67 |
| 저장 | 1GB, 월 TB당 $23 | 약 $0.02 |
눈여겨볼 항목은 두 번째 행입니다. API 자체 비용은 월 $1.26입니다. 하지만 프로시저를 가장 단순한 코드, 즉 동기 호출을 하나씩 차례로 실행하는 방식으로 작성하면 웨어하우스가 한 달에 20시간 넘게 돌아갑니다. 약 $40.54로, API 요금의 32배입니다. 병렬 호출 10개나 태스크 2개를 사용하는 비동기 설계를 쓰면 이 항목은 $4~$7로 줄어듭니다.
추정상으로는 병렬 호출이 가장 저렴하지만, Python에서 스레드와 타임아웃을 직접 관리해야 합니다. 비동기 설계는 2~3달러 더 듭니다. 대신 개별 요청이 너무 오래 기다리다 끊기는 일이 없고, 실패한 작업은 다음 날 다시 실행됩니다. 저희는 비동기 설계를 선호합니다.
합계로 보면 순차 설계는 월 약 $51.93, 병렬 설계는 약 $15.44입니다. 싱가포르 리전에서는 Standard 에디션 크레딧이 $2.50이므로 웨어하우스 항목에 1.25를 곱하세요. Enterprise 에디션의 US East 온디맨드 가격은 크레딧당 $3.00이며, 같은 방식으로 환산합니다.
두 번째 조정 수단은 모델입니다. Cortex Agent 오케스트레이션은 토큰 기준으로 과금되며, 소비 테이블에 나온 모델별 가격 차이가 큽니다. 같은 질문 50개 기준으로 Sonnet 5.5는 약 $3.58, Haiku 5.5는 약 $0.18입니다. Opus 5.5는 입력 토큰 100만 개당 2.60, 출력 토큰 100만 개당 13.00으로 Sonnet의 두 배입니다. 아래 표는 이 글과 관련된 가격을 토큰 100만 개당 AI 크레딧으로 정리한 것입니다. AI 함수는 입력과 출력을 구분하지 않고 전체 토큰 기준으로 과금됩니다.
| 모델 또는 함수 | 입력 | 출력 | 이 글에서의 용도 |
|---|---|---|---|
| claude-sonnet-5-5 (CoWork, Agents) | 1.30 | 6.50 | 에이전트 오케스트레이션, 비용 표의 기본값 |
| claude-haiku-5-5 (CoWork, Agents) | 0.065 | 0.325 | 저비용 오케스트레이션 |
| claude-opus-5-5 (CoWork, Agents) | 2.60 | 13.00 | 정기 리포트에는 불필요 |
| openai-gpt-6.1-sol (CoWork, Agents) | 1.30 | 6.50 | Sonnet과 같은 가격 |
AI_CLASSIFY | 1.62 (합계) | 댓글과 반품 메모의 주제 라벨 | |
AI_SENTIMENT | 1.60 (합계) | 감성 점수(선택) | |
AI_AGG | 1.85 (합계) | 주제별 텍스트 요약(선택) |
질문당 입력 토큰 20,000개는 저희가 가정한 수치입니다. 여기에는 시맨틱 뷰, 지침, 한두 차례의 도구 결과가 포함됩니다. 에이전트가 한 채팅에서 도구를 여러 번 호출하거나 긴 댓글을 컨텍스트로 읽어 들이면 실제 수치는 늘어납니다. 도입 후에는 CORTEX_AGENT_USAGE_HISTORY 뷰에서 실제 수치를 확인할 수 있습니다. CoWork 질문은 SNOWFLAKE_COWORK_USAGE_HISTORY에 기록되며, 각 뷰에는 다른 쪽에서 집계되는 요청이 포함되지 않습니다(Cortex Agent 사용량 뷰, CoWork 사용량 뷰).
프로시저가 보내는 각 아웃바운드 요청은 EXTERNAL_ACCESS_HISTORY 뷰에 기록되며, 반영까지 최대 3시간이 걸릴 수 있습니다(External access history). 이를 voc.raw.jobs의 charged_usd 값과 시간 기준으로 대조하면 매월 양쪽의 호출 수와 지출을 확인할 수 있습니다. Snowflake에서는 에이전트별 리소스 예산과 사용자별 할당량도 설정할 수 있습니다(Cortex Agents resource budgets). EveryInfra 쪽에서는 이 키에 별도의 분당 호출 한도를 지정하세요. 양쪽에 한도를 두면 오작동한 태스크가 밤사이 수만 건을 호출하는 일을 막을 수 있습니다.
소비 테이블에서 오해하기 쉬운 항목이 하나 있습니다. “Cortex Tools”는 서드파티 에이전트가 Snowflake 외부 엔드포인트에 접근할 때 도구 호출 1,000건당 AI 크레딧 8을 부과하며, Snowflake 엔드포인트에는 부과하지 않습니다. 저희 설계에서는 에이전트가 아니라 Snowflake 저장 프로시저가 EveryInfra API를 호출합니다. 에이전트는 Snowflake 테이블만 읽으므로 이 항목은 포함하지 않았습니다.
MCP 커넥터로 전환해 에이전트가 채팅 중에 외부 도구를 호출하게 한다고 가정해 보겠습니다. 이 경우 해당 항목이 적용되는지, 어떻게 집계되는지는 문서에 나와 있지 않습니다. 도입 전에 Snowflake 계정 팀에 문의하세요. 신규 계정은 무료 체험으로 전체 구성을 시험해 볼 수 있습니다. 요금 페이지에는 무료 체험 기간이 30일이며 $400 상당의 크레딧이 제공된다고 나와 있습니다.
Snowflake CoWork Automations로 주간 이메일 받기
데이터와 에이전트가 준비되었다면, 마지막 단계는 적절한 사람에게 제때 답을 전달하는 것입니다. CoWork Automations가 바로 이 역할을 합니다. 예를 들어 매주 월요일 09:00처럼 일정에 따라 실행할 질문을 설정합니다. 좋은 질문의 예는 “지난 4주 동안 반품률과 함께 증가한 불만 주제는 무엇인가?”입니다. 결과는 이메일로 전달됩니다(Automations 문서).
먼저 문서에 명시된 제한 사항을 알아 두세요. 자동화는 1시간에 한 번까지만 실행할 수 있습니다. 결과는 이메일로만 전송되며, 각 수신자는 먼저 Snowflake에서 이메일 주소를 인증해야 합니다. 실행 기록은 60일간 보관됩니다. 각 자동화는 생성한 사람의 권한으로 실행되므로, 그 사람이 읽을 수 있는 테이블이라면 무엇이든 이메일에 포함될 수 있습니다.
| 문서상 제한 | 값 | 주간 불만 리포트에 미치는 영향 |
|---|---|---|
| 최단 실행 주기 | 한 시간에 한 번 | 영향 없음(주간 리포트) |
| 전달 방식 | 이메일만 가능(인증된 주소) | 수신자가 먼저 인증해야 함 |
| 실행 기록 | 60일 | 더 긴 기록이 필요하면 답변을 테이블에 저장 |
| 권한 | 생성자의 권한 | 생성자가 읽을 수 있는 모든 테이블이 이메일에 포함될 수 있음 |
| EXECUTE AGENT TASK | 기본적으로 PUBLIC에 부여됨 | 필요하면 회수 후 역할별로 부여 |
이 제한 중 저희 사용 사례를 가로막는 것은 없습니다. 불만과 반품은 주 단위로 살펴보는 주제이므로 1시간 주기면 충분하고도 남습니다. 이메일로만 전달되므로 Slack에 바로 게시할 수는 없습니다. 보도자료에 따르면 Snowflake for Slack은 현재 퍼블릭 프리뷰 단계입니다(Expedition 2026 보도자료).
실제로 주의할 부분은 접근 권한입니다. EXECUTE AGENT TASK 권한은 기본적으로 PUBLIC 역할에 부여되므로, 계정 내 누구나 자신을 위한 자동화를 만들 수 있습니다. 자동화는 생성자의 권한으로 실행됩니다. 따라서 전체 판매 데이터를 읽을 수 있는 사람은 그 데이터를 자신이 입력한 어떤 주소로든 보낼 수 있습니다. 이를 허용할 수 없다면 관리자가 PUBLIC에서 권한을 회수하고 역할별로 부여해야 합니다.
이번 테스트의 한계
Snowflake 쪽 내용은 모두 구성 예시입니다. 저희는 Snowflake 계정이 없으며, 이 SQL, 프로시저, 에이전트 명세를 실제로 실행하지 않았습니다. 문법은 2026-11-06에 확인한 docs.snowflake.com을 따릅니다. Snowflake가 이번 달 대규모 릴리스를 내놓았으므로 문법과 제한은 아직 바뀔 수 있습니다. 각 블록을 실제 작업에 사용하기 전에 본인 계정에서 실행해 확인하세요.
비용 표에서 실제 가격은 API 요금뿐입니다. Snowflake 관련 항목은 모두 공개 가격과 저희 가정을 바탕으로 한 추정치입니다. 가장 큰 미지수 두 가지는 분류한 댓글 1개당 실제 토큰 수와 에이전트 질문 1개당 실제 토큰 수입니다.
데이터 측면에서는 이번에 Amazon 리뷰 호출 5건 모두 리뷰를 반환하지 못했습니다. 따라서 주제 분석에는 TikTok 댓글 273개만 사용했습니다. 작성자 한 명이 위 규칙에 따라 직접 라벨을 붙였고, 라벨을 따로 재검토한 사람은 없습니다. 문제를 지적한 댓글 17개만으로도 뚜껑 문제와 내용물이 쏟아지는 문제에 주목할 필요가 있다고 판단할 수 있습니다. 하지만 이 제품의 실제 문제 발생률을 추정하기에는 부족합니다.
이 글에서는 판매 및 반품 테이블의 구조만 다루며, 실제 수치나 가상의 수치는 넣지 않았습니다. “반품이 늘어날 때 함께 증가하는 불만 주제는 무엇인가”라는 질문의 답은 여러분의 데이터가 들어와야 알 수 있습니다.
EveryInfra 자체와 관련된 제한도 하나 있습니다. 앞서 설명한 이유로 현재 EveryInfra MCP 서버는 Snowflake 커넥터로 추가할 수 없습니다. 외부 액세스 경로는 이와 무관하며, 저희가 권장하는 경로이기도 합니다. 다만 팀에서 CoWork 안에서 원클릭 연결을 원한다면 아직은 불가능합니다. 이 글이 게시될 때 이 상태를 다시 확인하겠습니다.
이전 글과 무엇이 다른가
이전 리뷰 관련 글에서는 데이터를 에이전트나 파일 안에 두었습니다. Claude Cowork 예약 작업, Claude Managed Agents로 매일 밤 리뷰 점검하기, Qwen Agent MCP 실전 활용, Claude Code에서 DeepSeek V4로 리뷰 정제하기가 그렇습니다. 이 글들은 “요즘 사람들이 무엇에 불만을 갖는가”에 답합니다. 이번에는 리뷰가 판매·반품 데이터와 같은 접근 규칙과 비즈니스 정의 아래 회사 데이터 웨어하우스로 들어가므로, 질문은 “어떤 불만이 실제로 비용을 발생시키는가”로 바뀝니다. 그 대가로 웨어하우스 비용이 추가되고 테이블 몇 개를 더 관리해야 하며, 앞서 계산한 대로 브랜드 하나당 비용은 월 약 15달러입니다. 판매와 반품 데이터가 아직 Snowflake에 없다면 이전 방식이 더 가볍습니다. 이미 Snowflake에 있다면 이 구성으로 처음으로 불만 데이터를 재무 수치와 함께 볼 수 있습니다.
최근 변경 사항
2026-11-04부터 새로운 Snowflake Service Consumption Table이 적용되었습니다. 이 글에 나오는 모든 모델 가격, AI 함수 가격, “Cortex Tools” 항목은 해당 버전을 기준으로 합니다(Service Consumption Table).
같은 날 릴리스 노트를 통해 Snowflake 관리형 MCP 서버에 백그라운드 실행이 추가되었습니다. CORTEX_AGENT_RUN 및 CODING_AGENT 도구에 즉시 핸들을 반환하는 background 인수가 생겼습니다. 이 도구가 있는 서버에는 이제 ASYNC_AGENT_RUN_STATUS, ASYNC_AGENT_RUN_CANCEL, AGENT_RUN_RESULT 세 가지 도구가 자동으로 추가됩니다. 새 content_cel_filter 파라미터를 사용하면 클라이언트가 먼저 개요를 읽은 뒤 필요한 부분만 읽을 수 있습니다(2026년 11월 4일 릴리스 노트).
FAQ: Snowflake Cortex Agents MCP와 Snowflake CoWork
Snowflake Cortex Agents MCP 서버는 MCP 커넥터와 같은 것인가요?
아닙니다. 둘은 방향이 정반대입니다. 출처: “snowflake cortex agents mcp server”에 대한 Google 자동완성. Snowflake 관리형 MCP 서버에서는 Snowflake가 서버 역할을 합니다. 외부 클라이언트가 MCP를 통해 사용자의 에이전트, Cortex Search, Cortex Analyst, SQL을 호출합니다. 도구 유형은 CORTEX_AGENT_RUN, CODING_AGENT, CORTEX_SEARCH_SERVICE_QUERY, CORTEX_ANALYST_MESSAGE, SYSTEM_EXECUTE_SQL, GENERIC입니다. 문서에서는 하드코딩된 토큰보다 OAuth를 권장합니다(Snowflake-managed MCP server, CREATE MCP SERVER).
MCP 커넥터는 Snowflake를 클라이언트로 만들어 Cortex Agents와 CoWork가 외부 MCP 서버를 호출할 수 있게 하며, OAuth만 지원합니다(커넥터 문서). 이 글에 필요한 것은 두 번째 방향이지만, 최종적으로는 MCP 대신 외부 액세스를 사용합니다.
Snowflake CoWork와 CoCo(Cortex Code)의 차이는 무엇인가요?
출처: “snowflake cowork vs coco”에 대한 Google 자동완성. 2026-11-03 보도자료에 따르면 CoWork는 비즈니스 사용자를 위한 제품입니다. 비즈니스 사용자는 ai.snowflake.com에서 자연어로 질문하고, 대시보드를 열고, 자동화를 설정합니다. CoCo는 개발자와 데이터 엔지니어를 위한 제품입니다. 이들은 CoCo로 코드를 작성하고 데이터 객체를 만듭니다. 분석가는 원하는 대시보드를 CoCo에 설명해 생성할 수도 있습니다(Expedition 2026 보도자료, Cortex Code 문서).
이 글에서는 데이터 엔지니어가 CoCo 또는 일반 SQL로 테이블, 프로시저, 시맨틱 뷰를 만듭니다. 비즈니스 사용자는 CoWork에서 질문하고 주간 리포트를 받습니다.
Cortex Agents가 OAuth 대신 API 키로 외부 API를 호출할 수 있나요?
가능하지만 MCP 커넥터로는 안 됩니다. 출처: Snowflake 커넥터 문서의 “OAuth만 지원” 문구에서 자연스럽게 나오는 후속 질문. 외부 액세스 통합을 통해 키를 GENERIC_STRING 유형의 시크릿에 저장합니다. API를 호출하는 Python 저장 프로시저를 작성하고, 이 프로시저를 에이전트에 커스텀 도구로 추가합니다. 에이전트가 이를 호출하면 프로시저는 웨어하우스에서 실행되며 웨어하우스 사용 시간 기준으로 과금됩니다(외부 네트워크 액세스, Cortex Agents 개요). 저희는 질문할 때마다 API 응답을 기다리지 않도록 예약 태스크로 테이블을 적재하는 방식을 선호합니다.
AI_CLASSIFY는 영어가 아닌 댓글에도 작동하나요?
작동하지만 먼저 검증해 보세요. 출처: Snowflake AI_CLASSIFY 문서의 사용 참고 사항. 문서에 따르면 영어 입력에서 가장 잘 작동하며 다른 언어에서는 성능이 떨어질 수 있습니다(AI_CLASSIFY 문서). 스페인어권 등 다른 시장을 추적한다면 댓글 약 100개에 직접 라벨을 붙여 비교해 보세요. 분류 결과가 일치하지 않으면 작업 설명과 예시를 더 구체적으로 다듬으세요. 비용은 더 들지만 Cortex Agents에서 더 강력한 모델이 각 댓글을 판단하게 할 수도 있습니다.
EveryInfra는 실패하거나 결과가 비어 있는 호출에도 과금하나요?
아닙니다. 출처: 저희가 실제로 수행한 호출 12건의 응답. 잘못된 파라미터, 일시적으로 사용할 수 없는 대상(상태 503), 빈 결과에는 과금되지 않으며, 과금된 응답에는 모두 정확한 금액이 표시됩니다. 이 글에서 데이터를 반환하지 않은 호출 6건은 모두 charged_usd가 0입니다. 비동기 모드에서는 제출 시점에 과금되며, 이후 작업이 실패하면 같은 과금 건이 환불됩니다.
시작하기
- EveryInfra에 회원가입하고 빠른 시작을 따라 진행합니다. Snowflake 전용 API 키를 만들고 별도의 분당 요청 속도 제한을 설정합니다.
- 각 상품 URL, 동영상 URL, 키워드를
curl로 한 번씩 호출합니다. 대상을watchlist테이블에 추가하기 전에 필드와 행 수를 확인합니다. - Snowflake에서 위 예시를 참고해 네트워크 규칙, 시크릿, 외부 액세스 통합을 만듭니다. 그런 다음 프로시저 2개와 태스크 2개를 만듭니다.
- 며칠간 데이터를 적재한 뒤 주간 뷰와 시맨틱 뷰를 만듭니다. 댓글과 반품 메모에 같은
AI_CLASSIFY주제로 라벨을 붙입니다. - Cortex Agent를 만들고 CoWork에서 몇 가지 질문을 해 봅니다. 누락된 주를 정확히 보고하면 주간 자동화를 설정합니다.
모든 데이터 기능은 EveryInfra 카탈로그에서 확인할 수 있습니다. 원격 MCP 설정은 MCP 서버 페이지에, 호출당 가격은 요금 페이지에 나와 있습니다.
참고 자료
- Snowflake 보도자료, “Expedition 2026: CoCo and CoWork”, 2026-11-06 확인: https://www.snowflake.com/en/news/press-releases/expedition-2026-coco-cowork/
- Snowflake 보도자료, “Business Ontology and Cortex AI Gateway”, 2026-11-06 확인: https://www.snowflake.com/en/news/press-releases/expedition-2026-business-ontology-ai-gateway/
- Snowflake 블로그, “AI agents, governed data and business context”, 2026-11-06 확인: https://www.snowflake.com/en/blog/ai-agents-governed-data-business-context/
- Snowflake 블로그, “Snowflake CoWork Adds Profiles, Dashboards and Automations”, 2026-11-06 확인: https://www.snowflake.com/en/blog/snowflake-cowork-profiles-automations-dashboards
- Snowflake 블로그, “Snowflake CoCo cloud agents and automations”, 2026-11-06 확인: https://www.snowflake.com/en/blog/snowflake-coco-cloud-agents-automations/
- Snowflake CoWork 제품 페이지, 2026-11-06 확인: https://www.snowflake.com/en/product/snowflake-cowork/
- “Snowflake pricing options”, 2026-11-06 확인: https://www.snowflake.com/en/pricing-options/
- “Snowflake Service Consumption Table”, 2026-11-04 시행, 2026-11-06 확인: https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf
- Snowflake 문서, “Cortex Agents MCP connectors”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp-connectors
- Snowflake 문서, “Cortex Agents MCP connectors”, Limitations 섹션, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp-connectors#limitations
- Snowflake 문서, “Cortex Agents”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents
- Snowflake 문서, “Create and manage agents”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-manage
- Snowflake 문서, “CREATE AGENT”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-agent
- Snowflake 문서, “Cortex Agents Run API”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-run
- Snowflake 문서, “Cortex Agents resource budgets”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-resource-budgets
- Snowflake 문서, “Cortex Agents code execution tool”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-code-execution-tool
- Snowflake 문서, “Snowflake-managed MCP server”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp
- Snowflake 문서, “CREATE MCP SERVER”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-mcp-server
- Snowflake 릴리스 노트, “November 4, 2026: Background runs and additional supplementary tools for agents”, 2026-11-06 확인: https://docs.snowflake.com/en/release-notes/2026/other/2026-11-04-mcp-async-agent-tools
- Snowflake 문서, “Cortex AI Gateway custom apps and MCP servers”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-ai-gateway/tools/admin-custom-apps
- Snowflake 문서, “Cortex Code Agent SDK, MCP and custom tools”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/cortex-code-agent-sdk/mcp-custom-tools
- Snowflake 문서, “Cortex Code”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code
- Snowflake 문서, “Snowflake CoWork”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/snowflake-cowork
- Snowflake 문서, “CoWork Automations”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/snowflake-cowork/automations
- Snowflake 문서, “Cortex AI pricing”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/pricing
- Snowflake 문서, “Cortex AI Functions”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/aisql
- Snowflake 문서, “AI_CLASSIFY”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/functions/ai_classify
- Snowflake 문서, “AI_SENTIMENT”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/functions/ai_sentiment
- Snowflake 문서, “Semantic views overview”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/views-semantic/overview
- Snowflake 문서, “CREATE SEMANTIC VIEW”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-semantic-view
- Snowflake 문서, “External network access overview”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/external-network-access/external-network-access-overview
- Snowflake 문서, “Creating and using an external access integration”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/external-network-access/creating-using-external-network-access
- Snowflake 문서, “External network access examples”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/external-network-access/external-network-access-examples
- Snowflake 문서, “CREATE NETWORK RULE”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-network-rule
- Snowflake 문서, “CREATE SECRET”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-secret
- Snowflake 문서, “CREATE EXTERNAL ACCESS INTEGRATION”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-external-access-integration
- Snowflake 문서, “Writing stored procedures in Python”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/stored-procedure/python/procedure-python-overview
- Snowflake 문서, “CREATE TASK”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-task
- Snowflake 문서, “Introduction to tasks”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/tasks-intro
- Snowflake 문서, “Snowpipe”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/data-load-snowpipe-intro
- Snowflake 문서, “Overview of warehouses”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/warehouses-overview
- Snowflake 문서, “Understanding compute cost”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/cost-understanding-compute
- Snowflake 문서, “CORTEX_AGENT_USAGE_HISTORY view”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/account-usage/cortex_agent_usage_history
- Snowflake 문서, “SNOWFLAKE_COWORK_USAGE_HISTORY view”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/account-usage/snowflake_cowork_usage_history_view
- Snowflake 문서, “EXTERNAL_ACCESS_HISTORY view”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/account-usage/external_access_history
- MCP 사양, “Authorization”, 버전 2025-06-18, 2026-11-06 확인: https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization
- IETF RFC 9728, “OAuth 2.0 Protected Resource Metadata”, 2026-11-06 확인: https://datatracker.ietf.org/doc/html/rfc9728
- IETF RFC 8414, “OAuth 2.0 Authorization Server Metadata”, 2026-11-06 확인: https://datatracker.ietf.org/doc/html/rfc8414
- IETF RFC 7591, “OAuth 2.0 Dynamic Client Registration Protocol”, 2026-11-06 확인: https://datatracker.ietf.org/doc/html/rfc7591
- Amazon SP-API 문서, “FBA report type values”, 2026-11-06 확인: https://developer-docs.amazon/sp-api/docs/report-type-values-fba
- National Retail Federation, “Consumers expected to return nearly $850 billion in merchandise in 2025”, 2026-11-06 확인: https://nrf.com/media-center/press-releases/consumers-expected-to-return-nearly-850-billion-in-merchandise-in-2025
- Analytics India Magazine, “Snowflake introduces Business Ontology and Cortex AI Gateway”, 2026-11-06 확인: https://analyticsindiamag.com/ai-news/snowflake-introduces-business-ontology-cortex-ai-gateway-to-bring-ai-agents-into-enterprise-workflows
- EveryInfra 기능 카탈로그, GET /api/v1/social/catalog, 2026-11-06 확인: https://api.everyinfra.com/api/v1/social/catalog
- EveryInfra 원격 MCP 주소, 2026-11-06 테스트: https://api.everyinfra.com/mcp
- EveryInfra 전체 MCP 주소의 보호 리소스 메타데이터, 2026-11-06 테스트: https://api.everyinfra.com/.well-known/oauth-protected-resource/mcp/all
참고 BL-97