자체 방문 통계는 항상 수집됩니다. 사용자가 공개 페이지를 어떻게 이용하는지 파악하는 데 쓰이는 Google Analytics(로그인한 워크스페이스는 제외)는 동의한 경우에만 사용됩니다. 자세한 내용은 개인정보 처리방침을 참고하세요.

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의 공개 문서와 보도자료에서 가져왔습니다.

일러스트: 왼쪽에는 잠긴 문이 있고, 그 앞에 자물쇠에 맞지 않는 열쇠가 놓여 있습니다. 오른쪽에는 청록색 옆문이 열려 있고, 그 사이로 컨베이어 벨트가 지나가며 빈 리뷰 카드 더미를 유리 보관 큐브로 옮기고 있습니다.
MCP 커넥터라는 문은 등록된 OAuth 클라이언트가 있어야 열리며, API 키로는 열리지 않습니다. 외부 액세스라는 옆문은 고정된 호스트 하나만 허용하고 데이터를 곧바로 테이블로 옮깁니다.

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 예시는 동적 등록을 사용합니다.

Snowflake 문서의 MCP 커넥터 페이지 중 Key considerations and best practices 섹션 스크린샷. 청록색 상자가 두 줄을 표시합니다. 하나는 Custom MCP servers 항목으로, 사용 가능한 커넥터 목록에 없는 MCP 엔드포인트에는 커스텀 서버를 사용하라는 내용입니다. 다른 하나는 OAuth authentication 항목으로, Snowflake가 MCP 서버 연결에 OAuth만 지원한다는 내용입니다.
2026-11-06 싱가포르 시간 기준으로 확인한 Snowflake MCP 커넥터 문서 스크린샷입니다. 청록색 상자는 저희가 표시한 것입니다. docs.snowflake.com, Cortex Agents MCP connectors

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에서 질문합니다.

왼쪽에서 오른쪽으로 다섯 단계가 이어지는 애니메이션 흐름도. 1단계는 EveryInfra API이며, 그 아래에 amazon/reviews, reddit/search, tiktok/comments가 나열되어 있습니다. 2단계는 Snowflake 외부 액세스 통합으로, api.everyinfra.com만 허용하는 규칙과 키를 보관하는 시크릿이 표시되어 있습니다. 3단계는 예약된 태스크 두 개로, 하나는 비동기 요청을 제출하고 다른 하나는 결과를 수집합니다. 4단계는 리뷰, 소셜 미디어 언급, 판매, 반품 테이블 네 개입니다. 5단계는 시맨틱 뷰와 Cortex Agent이며, 옆의 말풍선은 반품률과 함께 늘어나는 불만 주제가 무엇인지 묻습니다. 작은 청록색 점들이 화살표를 따라 움직입니다.

외부 액세스 통합은 프로시저와 함수가 인터넷에 접근하도록 허용하는 Snowflake의 표준 방식입니다. 여기에는 객체 세 개가 사용됩니다. 네트워크 규칙은 코드가 접근할 수 있는 호스트와 포트를 나열합니다. 시크릿은 자격 증명을 보관합니다. 통합은 이 둘을 묶습니다. 특정 역할에 이 통합의 사용 권한을 부여합니다(External network access overview, Creating and using an external access integration).

저희 규칙은 api.everyinfra.com만 허용합니다. 누군가 프로시저 코드를 수정하더라도 다른 호스트에는 접근할 수 없습니다. 키는 시크릿 객체에 보관되므로 코드에 평문으로 들어가지 않습니다. 프로시저를 실행하는 역할도 키를 읽을 수 없습니다. 아래 예시에서 voc는 데이터베이스 이름이며, "voice of the customer(고객의 소리)"를 뜻합니다.

sql
-- 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_keyEveryInfra API 키 보관계정 관리자
외부 액세스 통합 everyinfra_access규칙과 시크릿 연결계정 관리자
프로시저 submit_pulls관심 목록(watchlist)의 각 행에 대해 비동기 작업 제출데이터 엔지니어
프로시저 collect_results완료된 작업을 원본 테이블로 수집데이터 엔지니어
태스크 t_submit, t_collect두 프로시저를 일정에 따라 실행데이터 엔지니어
시맨틱 뷰 voc_returns주제, 주차, 반품 지표 정의애널리틱스 엔지니어
VocAnalyst가 포함된 에이전트CoWork에서 질문에 답변애널리틱스 엔지니어
sql
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초로 설정하기를 권장합니다.

sql
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개입니다. 매출과 반품 데이터는 자체 시스템에서 가져오므로 구조만 보여 드립니다.

sql
-- 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/reviewsreview_id, product_asin, countryreviews.review_id, asin, country리뷰 ID 기준으로 중복 제거
amazon/reviewsrating, title, text, posted_atrating, title, body, posted_at1~5점 평점
amazon/reviewsis_verified_purchase, helpful_count, variant이름 동일색상과 사이즈는 variant에 포함
amazon/reviewsauthor_name, author_id, author_avatar_url저장하지 않음분석에 필요 없는 개인정보
tiktok/commentsid, text, like_count, reply_count, is_reply, posted_at대응하는 social_mentions 열최상위 댓글마다 답글 최대 2개 포함
tiktok/commentsauthor_username, author_id저장하지 않음같은 이유
reddit/searchid, url, title 및 text, community, like_count, comment_countsource_id, source_url, body, community, like_count, reply_count제목과 본문을 하나의 텍스트로 결합
reddit/searchauthor_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기능모드결과소요 시간과금
100:16:52amazon/search, 키워드 portable blender동기상품 10개, 그중 9개가 Ninja42.14 s$0.002236
200:17:41amazon/reviews, 상품 B0C2FF4JD1동기503, 일시적으로 사용 불가(과금 없음)60.12 s$0
300:18:41amazon/reviews, 상품 B0CN3S2SW2동기50358.57 s$0
400:19:47amazon/reviews, 상품 B09B8V1LZ3동기0행, 빈 결과 환불67.25 s$0
500:20:55reddit/search, portable blender, 최신순동기게시물 14건6.56 s$0.000556
600:21:13tiktok/search, ninja blast portable blender review동기동영상 10개3.78 s$0.000556
700:21:21tiktok/comments, 저가 vs 고가 비교 테스트 동영상동기댓글 200개52.30 s$0.000556
800:22:13walmart/reviews, 상품 페이지동기0행, 빈 결과 환불54.34 s$0
900:24:22amazon/reviews, 상품 B0D2YYHN1B동기50319.48 s$0
1000:25:26reddit/search, ninja blastMCP게시물 7건7.62 s$0.000556
1100:27:36tiktok/comments, 단일 상품 체험 동영상비동기202, 약 100초 후 완료, 댓글 73개제출 1.95초$0.000556
1200:36:23amazon/reviews, 상품 B0C2FF4JD1 재요청동기50338.42 s$0

12건 중 6건이 과금되었고, 합계는 $0.005016입니다. 나머지 6건은 503 또는 빈 결과를 반환했으며 모두 과금되지 않았습니다. 8번 호출의 Walmart 상품 URL은 상품명으로 추측한 것이어서 빈 결과는 저희 실수입니다. 그래도 Walmart 리뷰에도 빈 결과 환불이 적용된다는 점은 확인할 수 있었습니다.

실제 API 응답 스크린샷으로, 밝은 배경의 코드 카드가 세 부분으로 나뉘어 있습니다. 첫 번째 부분은 비동기 제출입니다. platform을 tiktok, action을 comments, mode를 async로 설정해 POST https://api.everyinfra.com/api/v1/social을 호출했으며, 1.95초 만에 HTTP 상태 코드 202와 state running, 작업 ID, 폴링 URL이 반환되었습니다. 청록색 상자는 0.000556달러(USD)의 과금액을 표시합니다. 두 번째 부분은 완료된 작업 응답의 일부로, state succeeded, 댓글 73개와 처음 두 댓글의 시각, 좋아요 수, 텍스트가 표시되며 작성자 필드는 가려져 있습니다. 세 번째 부분은 Amazon 리뷰 응답으로, HTTP 상태 코드 503, 사유 access_blocked, 재시도 대기 시간 900초, 과금액 0이 표시됩니다.
2026-11-06 SGT 00:27의 비동기 제출 및 결과와 00:17의 503 응답 스크린샷. 작성자 정보는 가렸습니다. EveryInfra API 응답

스크린샷의 첫 번째 부분은 제출 프로시저가 받는 응답입니다. 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자 전체가 입력 토큰으로 모델 컨텍스트에 들어갔을 것입니다. 같은 데이터를 테이블에 적재해 두면 에이전트가 처리하는 입력은 실제로 읽는 몇 개 행뿐입니다. 그래서 저희는 "대화마다 실시간으로 가져오기"보다 "먼저 적재하고 나중에 질문하기"를 선호합니다.

0~120초 축 위에 실제 호출 한 건당 막대 하나씩, 막대 12개로 이루어진 가로 막대 차트입니다. 청록색 막대 6개는 과금된 호출로, Amazon 검색 42.14초, Reddit 검색 6.56초, TikTok 검색 3.78초, TikTok 댓글 동기 호출 52.30초, MCP를 통한 Reddit 검색 7.62초, TikTok 댓글 비동기 제출 1.95초입니다. 회색 막대 6개는 과금되지 않은 호출로, 19~67초 사이의 Amazon 리뷰 오류 4건과 Amazon 빈 결과 1건, 그리고 54.34초의 Walmart 빈 결과입니다. 부제는 2026-11-06 싱가포르 시간 00:16~00:36입니다.

이 지연 시간 차트가 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-272,586,7032512002342.0%
단일 상품 체험2026-01-20208,9169873171317.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

수동 라벨링 기준은 엄격했습니다. 이 제품에 문제가 있었다고 말하는 댓글만 집계했습니다. 문제 유형은 뚜껑 문제나 내용물 쏟아짐, 짧은 배터리 수명, 얼음 분쇄력 부족, 부품 누락, 세척 어려움, 빠른 고장입니다. "돈값 못 해서 반품했다" 같은 일반적인 불만도 포함합니다. 가격 불만, 브랜드 비교, 농담, 이모지는 제외합니다. 이 기준으로 보면 두 동영상은 크게 다릅니다.

막대 2개로 구성된 가로 누적 막대 차트입니다. 위쪽 막대는 조회수 2.59백만 회를 기록한 저가 대 고가 비교 테스트 영상으로, 댓글 200개 중 4개가 제품 문제를 언급해 비율은 2.0%입니다. 아래쪽 막대는 조회수 209천 회를 기록한 단일 제품 착용 영상으로, 댓글 73개 중 13개가 제품 문제를 언급해 비율은 17.8%입니다. 청록색은 제품 문제 댓글, 회색은 그 밖의 모든 댓글을 나타냅니다.

조회수가 10배 많은 동영상은 제품 문제 댓글이 2.0%에 불과합니다. 규모가 작은 체험 동영상은 17.8%입니다. 차이는 시청자에서 옵니다. 비교 동영상에는 재미로 보는 사람이 모입니다. 체험 동영상에는 제품을 가지고 있거나 구매를 고려하는 사람이 모이고, "내 것도 샜어요"라고 쓰는 사람이 바로 이들입니다. Snowflake 설계에서는 동영상당 댓글 수보다 product_map에 어떤 동영상을 넣느냐가 더 중요합니다.

호출당 $0.000556로 가격이 같은데도 체험 동영상에서 거의 9배 많은 신호를 얻었습니다. 이 선택도 자동화할 수 있습니다. tiktok/search로 검색한 뒤, 캡션에 "review", "trying", "honest" 같은 단어가 있고 댓글이 수십~수백 개인 동영상만 남기면 됩니다.

두 동영상을 합치면 댓글 273개 중 17개가 제품 문제를 설명했습니다. 주제별 분포는 다음과 같습니다.

주제댓글예시(원문, 작성자 비공개)좋아요
뚜껑 또는 내용물 쏟음6The way I just gasped when it spilled. Were you supposed to open it from the top instead?79
배터리3the batteries do not last long enough to make a full smoothie9
일반적 불만, 반품2Not worth it, returned after a week0
얼음·냉동 과일 분쇄력 부족2It's not. I returned mine. Barely could get through frozen fruit97
부품 누락2ours both didn't come with the blade cap0
빠른 고장1완전 쓰레기예요, 2번 돌리면 끝나요1
세척이 어려움1씻기 어려움0
댓글이 많은 순서대로 7개 테마를 나타낸 가로 막대 차트: 뚜껑 또는 내용물 쏟음 6건(청록색), 배터리 3건, 전반적인 부정 의견 2건, 냉동 과일에 약함 2건, 부품 누락 2건, 빨리 고장남 1건, 세척이 어려움 1건. 부제에 따르면 뚜껑 관련 댓글 대부분은 뚜껑 여는 방법을 몰랐다는 내용이며, 댓글 2건에는 구매자가 제품을 반품했다고 나와 있습니다.

뚜껑 또는 내용물 쏟음 문제가 가장 큰 그룹입니다. 이 그룹에서 좋아요가 가장 많은 댓글은 79개를 받았으며, 뚜껑을 위쪽에서 여는 게 맞는 것 아니냐고 묻습니다. 다른 댓글 작성자는 처음에 똑같이 내용물을 쏟았고 캡을 쓸 생각을 못 했다고 말합니다. 2026-01-22에 작성된 댓글은 뚜껑의 버튼이 부러지고 교체 부품도 판매되지 않으니 사용하지 말라고 경고합니다.

이런 문제는 배터리나 모터 불만과 성격이 다릅니다. 설명서, 포장, 제품 사진을 개선하면 해결되는 경우가 많고, 그러면 반품률도 빠르게 떨어질 수 있습니다. "어떤 불만 테마가 반품과 함께 늘어나는가"라는 질문이 찾으려는 것이 바로 이것입니다. 어떤 테마가 반품 급증과 맞물리면 실행할 액션이 구체적으로 정해집니다.

테이블에 좋아요 수를 남겨 두세요. 좋아요 97개를 받은 "반품했어요" 댓글과 좋아요 0개인 불만은 같은 수의 사람을 대변하지 않습니다. 시맨틱 뷰에서 댓글 수와 좋아요 가중 댓글 수, 두 가지 측정값을 정의하세요. 에이전트에게 두 값을 모두 보고하도록 요청하세요.

Snowflake에서는 AI_CLASSIFY로 라벨링할 수 있습니다. 7개 테마에 "제품 문제 아님"을 더해 카테고리로 사용합니다. 다중 라벨 출력을 설정합니다. 가격 불만과 농담을 제외하는 작업 설명을 추가합니다. 문서에서는 카테고리를 약 20개 이하로 둘 것을 권장하며, 예시도 넣을 수 있습니다(AI_CLASSIFY 문서).

이 문서의 사용 참고 사항 중 중요한 것이 하나 있습니다. 영어 입력에서 결과가 가장 좋고, 다른 언어에서는 성능이 떨어질 수 있습니다. TikTok과 Amazon US 댓글은 대부분 영어이므로 미국 브랜드에는 크게 문제되지 않습니다. 스페인어권이나 다른 시장도 추적한다면 먼저 사람이 직접 라벨링한 샘플로 확인하세요. 작업 설명과 카테고리도 모든 행에서 토큰으로 계산됩니다. 따라서 행당 실제 토큰 수는 댓글 길이보다 많습니다.

sql
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)1410402026-10-30 ~ 2026-11-05
ninja blast (MCP)74302026-11-03 ~ 2026-11-05
막대 2개로 된 가로 누적 막대 차트. portable blender, 게시물 14개: 할인 게시물 10개, 주제와 무관 4개, 제품 관련 논의 0개. MCP를 통한 ninja blast, 게시물 7개: 할인 게시물 4개, 주제와 무관 3개, 제품 관련 논의 0개. 부제에 따르면 검색은 최신순으로 정렬되었고, 14개 게시물은 10월 30일부터 11월 5일까지만 포함하며, 주제와 무관한 게시물은 3D 소프트웨어 Blender, Ninjago 시리즈, 게임처럼 단어만 일치한 경우입니다.

그렇다고 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:41B0C2FF4JD1503access_blocked60.12 s$0
00:18:41B0CN3S2SW2503access_blocked58.57 s$0
00:19:47B09B8V1LZ3200빈 결과, 환불됨67.25 s$0
00:24:22B0D2YYHN1B503access_blocked19.48 s$0
00:36:23B0C2FF4JD1503access_blocked38.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에게 묻기: 어떤 불만 테마가 반품률과 함께 오를까?

테이블이 준비되면 주간 뷰를 만듭니다. 각 행에는 제품 하나, 테마 하나, 주 하나에 대한 소셜 언급 수, 반품 수량, 판매 수량이 들어갑니다. 테마 반품률은 해당 테마의 반품 수량을 그 주의 판매 수량으로 나눈 값입니다.

sql
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).

yaml
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-20079
뚜껑 버튼은 부러지니 쓰지 말 것뚜껑 또는 내용물 쏟음2026-01-2225
다들 이 블렌더가 최악이라고 한다고 말함전반적인 부정 의견2026-03-014023
반품함, 냉동 과일에 약함얼음에 약함2026-03-135297
배터리가 스무디 한 번을 다 못 버팀배터리2026-03-14539
두 제품 모두 칼날 캡 없이 배송됨부품 누락2026-07-311920
여분 뚜껑을 얻으려고 한 대 더 구매함뚜껑 또는 내용물 쏟음2026-09-122350
누적 세로 막대 차트. 가로축은 댓글 작성 월로, 2025년 8월과 9월, 이어서 2026년 1월, 3월, 4월, 7월, 9월입니다. 세로축은 제품 문제 댓글 수로 0부터 8까지입니다. 2026년 3월이 8개로 가장 많으며, 빨리 고장남, 전반적인 부정 의견, 냉동 과일에 약함, 배터리, 뚜껑, 세척이 어려움으로 구성됩니다. 2026년 1월은 뚜껑 댓글 2개, 4월은 3개, 나머지 달은 각각 1개입니다. 뚜껑 또는 내용물 쏟음은 청록색입니다. 부제에 따르면 댓글 대부분은 영상 게시 1~2개월 후에 달리므로 한 번만 수집하면 이후의 불만을 놓칩니다.

이 차트를 보면 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
월간 비용 8가지를 로그 스케일로 나타낸 가로 막대 차트: EveryInfra API 요금 1.26달러(청록색), 순차 대기 시 웨어하우스 40.54달러로 가장 긴 막대, 병렬 호출 10개 4.05달러, AI_CLASSIFY 라벨 4.86달러, Cortex Agent 질문 50개는 Sonnet 5.5 3.58달러, Haiku 5.5 0.18달러, 웨어하우스에서 실행되는 에이전트 SQL 1.67달러, 스토리지 1GB 0.022달러. 부제에 따르면 API 요금은 실제 가격이고, 나머지는 측정값이 아니라 Snowflake 소비 테이블을 바탕으로 한 추정치입니다.

눈여겨볼 항목은 두 번째 행입니다. 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.306.50에이전트 오케스트레이션, 비용 표의 기본값
claude-haiku-5-5 (CoWork, Agents)0.0650.325저비용 오케스트레이션
claude-opus-5-5 (CoWork, Agents)2.6013.00정기 리포트에는 불필요
openai-gpt-6.1-sol (CoWork, Agents)1.306.50Sonnet과 같은 가격
AI_CLASSIFY1.62 (합계)댓글과 반품 메모의 주제 라벨
AI_SENTIMENT1.60 (합계)감성 점수(선택)
AI_AGG1.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입니다. 비동기 모드에서는 제출 시점에 과금되며, 이후 작업이 실패하면 같은 과금 건이 환불됩니다.

시작하기

  1. EveryInfra에 회원가입하고 빠른 시작을 따라 진행합니다. Snowflake 전용 API 키를 만들고 별도의 분당 요청 속도 제한을 설정합니다.
  2. 각 상품 URL, 동영상 URL, 키워드를 curl로 한 번씩 호출합니다. 대상을 watchlist 테이블에 추가하기 전에 필드와 행 수를 확인합니다.
  3. Snowflake에서 위 예시를 참고해 네트워크 규칙, 시크릿, 외부 액세스 통합을 만듭니다. 그런 다음 프로시저 2개와 태스크 2개를 만듭니다.
  4. 며칠간 데이터를 적재한 뒤 주간 뷰와 시맨틱 뷰를 만듭니다. 댓글과 반품 메모에 같은 AI_CLASSIFY 주제로 라벨을 붙입니다.
  5. Cortex Agent를 만들고 CoWork에서 몇 가지 질문을 해 봅니다. 누락된 주를 정확히 보고하면 주간 자동화를 설정합니다.

모든 데이터 기능은 EveryInfra 카탈로그에서 확인할 수 있습니다. 원격 MCP 설정은 MCP 서버 페이지에, 호출당 가격은 요금 페이지에 나와 있습니다.

참고 자료

  1. Snowflake 보도자료, “Expedition 2026: CoCo and CoWork”, 2026-11-06 확인: https://www.snowflake.com/en/news/press-releases/expedition-2026-coco-cowork/
  2. Snowflake 보도자료, “Business Ontology and Cortex AI Gateway”, 2026-11-06 확인: https://www.snowflake.com/en/news/press-releases/expedition-2026-business-ontology-ai-gateway/
  3. Snowflake 블로그, “AI agents, governed data and business context”, 2026-11-06 확인: https://www.snowflake.com/en/blog/ai-agents-governed-data-business-context/
  4. Snowflake 블로그, “Snowflake CoWork Adds Profiles, Dashboards and Automations”, 2026-11-06 확인: https://www.snowflake.com/en/blog/snowflake-cowork-profiles-automations-dashboards
  5. Snowflake 블로그, “Snowflake CoCo cloud agents and automations”, 2026-11-06 확인: https://www.snowflake.com/en/blog/snowflake-coco-cloud-agents-automations/
  6. Snowflake CoWork 제품 페이지, 2026-11-06 확인: https://www.snowflake.com/en/product/snowflake-cowork/
  7. “Snowflake pricing options”, 2026-11-06 확인: https://www.snowflake.com/en/pricing-options/
  8. “Snowflake Service Consumption Table”, 2026-11-04 시행, 2026-11-06 확인: https://www.snowflake.com/legal-files/CreditConsumptionTable.pdf
  9. Snowflake 문서, “Cortex Agents MCP connectors”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp-connectors
  10. Snowflake 문서, “Cortex Agents MCP connectors”, Limitations 섹션, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp-connectors#limitations
  11. Snowflake 문서, “Cortex Agents”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents
  12. Snowflake 문서, “Create and manage agents”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-manage
  13. Snowflake 문서, “CREATE AGENT”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-agent
  14. Snowflake 문서, “Cortex Agents Run API”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-run
  15. Snowflake 문서, “Cortex Agents resource budgets”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-resource-budgets
  16. Snowflake 문서, “Cortex Agents code execution tool”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-code-execution-tool
  17. Snowflake 문서, “Snowflake-managed MCP server”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp
  18. Snowflake 문서, “CREATE MCP SERVER”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-mcp-server
  19. 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
  20. 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
  21. 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
  22. Snowflake 문서, “Cortex Code”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/cortex-code/cortex-code
  23. Snowflake 문서, “Snowflake CoWork”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/snowflake-cowork
  24. Snowflake 문서, “CoWork Automations”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/snowflake-cowork/automations
  25. Snowflake 문서, “Cortex AI pricing”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/pricing
  26. Snowflake 문서, “Cortex AI Functions”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/snowflake-cortex/aisql
  27. Snowflake 문서, “AI_CLASSIFY”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/functions/ai_classify
  28. Snowflake 문서, “AI_SENTIMENT”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/functions/ai_sentiment
  29. Snowflake 문서, “Semantic views overview”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/views-semantic/overview
  30. Snowflake 문서, “CREATE SEMANTIC VIEW”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-semantic-view
  31. Snowflake 문서, “External network access overview”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/external-network-access/external-network-access-overview
  32. 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
  33. Snowflake 문서, “External network access examples”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/external-network-access/external-network-access-examples
  34. Snowflake 문서, “CREATE NETWORK RULE”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-network-rule
  35. Snowflake 문서, “CREATE SECRET”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-secret
  36. Snowflake 문서, “CREATE EXTERNAL ACCESS INTEGRATION”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-external-access-integration
  37. Snowflake 문서, “Writing stored procedures in Python”, 2026-11-06 확인: https://docs.snowflake.com/en/developer-guide/stored-procedure/python/procedure-python-overview
  38. Snowflake 문서, “CREATE TASK”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/sql/create-task
  39. Snowflake 문서, “Introduction to tasks”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/tasks-intro
  40. Snowflake 문서, “Snowpipe”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/data-load-snowpipe-intro
  41. Snowflake 문서, “Overview of warehouses”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/warehouses-overview
  42. Snowflake 문서, “Understanding compute cost”, 2026-11-06 확인: https://docs.snowflake.com/en/user-guide/cost-understanding-compute
  43. Snowflake 문서, “CORTEX_AGENT_USAGE_HISTORY view”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/account-usage/cortex_agent_usage_history
  44. Snowflake 문서, “SNOWFLAKE_COWORK_USAGE_HISTORY view”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/account-usage/snowflake_cowork_usage_history_view
  45. Snowflake 문서, “EXTERNAL_ACCESS_HISTORY view”, 2026-11-06 확인: https://docs.snowflake.com/en/sql-reference/account-usage/external_access_history
  46. MCP 사양, “Authorization”, 버전 2025-06-18, 2026-11-06 확인: https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization
  47. IETF RFC 9728, “OAuth 2.0 Protected Resource Metadata”, 2026-11-06 확인: https://datatracker.ietf.org/doc/html/rfc9728
  48. IETF RFC 8414, “OAuth 2.0 Authorization Server Metadata”, 2026-11-06 확인: https://datatracker.ietf.org/doc/html/rfc8414
  49. IETF RFC 7591, “OAuth 2.0 Dynamic Client Registration Protocol”, 2026-11-06 확인: https://datatracker.ietf.org/doc/html/rfc7591
  50. Amazon SP-API 문서, “FBA report type values”, 2026-11-06 확인: https://developer-docs.amazon/sp-api/docs/report-type-values-fba
  51. 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
  52. 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
  53. EveryInfra 기능 카탈로그, GET /api/v1/social/catalog, 2026-11-06 확인: https://api.everyinfra.com/api/v1/social/catalog
  54. EveryInfra 원격 MCP 주소, 2026-11-06 테스트: https://api.everyinfra.com/mcp
  55. EveryInfra 전체 MCP 주소의 보호 리소스 메타데이터, 2026-11-06 테스트: https://api.everyinfra.com/.well-known/oauth-protected-resource/mcp/all

참고 BL-97