<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rihpig</title>
    <description>The latest articles on Forem by Rihpig (@rihpig).</description>
    <link>https://forem.com/rihpig</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2745155%2Ff727be57-3d98-4e9b-90ef-46211b492018.jpg</url>
      <title>Forem: Rihpig</title>
      <link>https://forem.com/rihpig</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rihpig"/>
    <language>en</language>
    <item>
      <title>GPT-5.5 Pro vs Instant: 6배 가격 가치가 있을까?</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Tue, 12 May 2026 06:51:32 +0000</pubDate>
      <link>https://forem.com/rihpig/gpt-55-pro-vs-instant-6bae-gagyeog-gaciga-isseulgga-1f98</link>
      <guid>https://forem.com/rihpig/gpt-55-pro-vs-instant-6bae-gagyeog-gaciga-isseulgga-1f98</guid>
      <description>&lt;p&gt;OpenAI는 두 가지 GPT-5.5 티어를 제공합니다. &lt;strong&gt;Instant&lt;/strong&gt;는 백만 토큰당 입력 $5, 출력 $30이고, &lt;strong&gt;Pro&lt;/strong&gt;는 백만 토큰당 입력 $30, 출력 $180입니다. 즉 Pro는 전반적으로 &lt;strong&gt;6배 비쌉니다&lt;/strong&gt;. 엔지니어링 팀이 답해야 할 질문은 단순합니다. &lt;strong&gt;언제 Pro가 비용만큼의 가치를 만들고, 언제 Instant로 충분한가?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;이 글에서는 실제 워크로드 기준으로 비용을 계산하고, Pro가 유리한 작업 유형을 구분하며, 지연 시간과 &lt;code&gt;reasoning_effort&lt;/code&gt;까지 포함해 모델 선택 규칙을 만드는 방법을 다룹니다. 마지막에는 Apidog에서 그대로 구현할 수 있는 테스트 하네스와 회귀 테스트 절차를 제공합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;p&gt;기본값은 &lt;strong&gt;GPT-5.5 Instant&lt;/strong&gt;로 두십시오.&lt;/p&gt;

&lt;p&gt;Instant가 적합한 작업은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;채팅&lt;/li&gt;
&lt;li&gt;요약&lt;/li&gt;
&lt;li&gt;분류&lt;/li&gt;
&lt;li&gt;FAQ 또는 검색 기반 QA&lt;/li&gt;
&lt;li&gt;단순 의도 라우팅&lt;/li&gt;
&lt;li&gt;잘못된 답변을 감지하거나 수정하는 비용이 낮은 작업&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pro는 잘못된 결과 하나의 비용이 Pro의 6배 토큰 프리미엄보다 클 때만 사용&lt;/strong&gt;하십시오. 일반적으로 다음 작업이 여기에 해당합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;법률 초안 작성 및 검토&lt;/li&gt;
&lt;li&gt;의료 분류 또는 감별 진단 보조&lt;/li&gt;
&lt;li&gt;금융 문서 분석&lt;/li&gt;
&lt;li&gt;다단계 에이전트 계획&lt;/li&gt;
&lt;li&gt;여러 파일을 동시에 수정하는 코드 리팩토링&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;특정 기능에서 잘못된 답변의 금전적 비용을 설명할 수 없다면, 그 기능은 아직 Pro를 기본값으로 사용할 준비가 되지 않은 것입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  서론
&lt;/h2&gt;

&lt;p&gt;GPT-5.5 가격 구조는 모델 선택을 감이 아니라 숫자로 결정하게 만듭니다.&lt;/p&gt;

&lt;p&gt;예를 들어 하루 100,000개의 고객 지원 메시지를 처리하는 기능이 있다고 가정합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant 사용 시 월 약 $4,500&lt;/li&gt;
&lt;li&gt;Pro 사용 시 월 약 $27,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;같은 기능에서 월 $22,500 차이가 납니다. 이 차이는 “더 좋은 모델이라서”가 아니라, 실제 오류 비용과 품질 개선 폭으로 정당화해야 합니다.&lt;/p&gt;

&lt;p&gt;이 글에서는 다음을 구현 관점에서 정리합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Instant와 Pro의 API 차이&lt;/li&gt;
&lt;li&gt;정확도 차이가 실제로 발생하는 작업 유형&lt;/li&gt;
&lt;li&gt;기능별 비용 계산 방식&lt;/li&gt;
&lt;li&gt;Apidog에서 Pro/Instant 비교 테스트를 구성하는 방법&lt;/li&gt;
&lt;li&gt;운영 환경에서 모델 라우팅 규칙을 만드는 방법&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GPT-5.5 제품군 자체가 처음이라면 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-instant?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 Instant 액세스 및 API 가이드&lt;/a&gt;를 먼저 확인하십시오. 비용을 기능별로 추적하려면 &lt;a href="http://apidog.com/blog/track-openai-api-spend-per-feature?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;OpenAI API 지출 추적 플레이북&lt;/a&gt;이 도움이 됩니다. 전체 API 표면은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API 참조 가이드&lt;/a&gt;에서 다룹니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPT-5.5 제품군을 구성하는 두 가지 모델
&lt;/h2&gt;

&lt;p&gt;Instant와 Pro는 같은 모델 제품군, 컨텍스트 창, API 형태를 공유합니다. 차이는 주로 다음 세 가지입니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;엔드포인트 뒤의 모델 가중치&lt;/li&gt;
&lt;li&gt;기본 추론 예산&lt;/li&gt;
&lt;li&gt;토큰당 가격&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x1k3x38ylev1jc1q0e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x1k3x38ylev1jc1q0e4.png" alt="GPT-5.5 모델 비교" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;모델 ID는 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;티어&lt;/th&gt;
&lt;th&gt;모델 ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gpt-5.5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gpt-5.5-pro&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;두 모델 모두 다음을 지원합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;272,000 토큰 입력 컨텍스트&lt;/li&gt;
&lt;li&gt;128,000 토큰 출력&lt;/li&gt;
&lt;li&gt;동일한 &lt;code&gt;reasoning_effort&lt;/code&gt; 값

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;minimal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;low&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;medium&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;high&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Responses API 기반 스트리밍&lt;/li&gt;

&lt;li&gt;동일한 요청 구조&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;즉, 프로덕션 코드에서 모델을 전환할 때 요청 형식은 거의 바뀌지 않습니다. &lt;code&gt;model&lt;/code&gt; 값과 &lt;code&gt;reasoning.effort&lt;/code&gt;만 바꾸면 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhse5av7can1797a2fds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhhse5av7can1797a2fds.png" alt="GPT-5.5 API 설정" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;가격은 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;티어&lt;/th&gt;
&lt;th&gt;입력 / 1M 토큰&lt;/th&gt;
&lt;th&gt;출력 / 1M 토큰&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;$5&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;td&gt;$180&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Pro는 입력과 출력 모두 &lt;strong&gt;6배&lt;/strong&gt; 비쌉니다.&lt;/p&gt;

&lt;p&gt;비실시간 작업에는 Batch 티어를 사용할 수 있습니다. Batch를 사용하면 두 모델 모두 비용이 절반으로 줄어듭니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;티어&lt;/th&gt;
&lt;th&gt;Batch 입력 / 1M 토큰&lt;/th&gt;
&lt;th&gt;Batch 출력 / 1M 토큰&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;$2.50&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$15&lt;/td&gt;
&lt;td&gt;$90&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;프롬프트 캐싱도 중요합니다. 캐시된 입력 토큰은 다음처럼 저렴해집니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;티어&lt;/th&gt;
&lt;th&gt;캐시된 입력 / 1M 토큰&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Instant&lt;/td&gt;
&lt;td&gt;$0.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pro&lt;/td&gt;
&lt;td&gt;$3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;반복되는 시스템 프롬프트나 긴 고정 컨텍스트가 있다면 캐싱을 적용하지 않는 것은 비용 낭비입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  지연 시간과 &lt;code&gt;reasoning_effort&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;지연 시간 차이는 가격 차이만큼 중요합니다.&lt;/p&gt;

&lt;p&gt;일반적인 경향은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5&lt;/code&gt; + &lt;code&gt;reasoning_effort=minimal&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;짧은 프롬프트에서 첫 토큰까지 약 200~400ms&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;gpt-5.5-pro&lt;/code&gt; + &lt;code&gt;reasoning_effort=high&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;내부 추론 루프 때문에 첫 토큰까지 8~30초&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://techcrunch.com/2026/05/05/openai-releases-gpt-5-5-instant-a-new-default-model-for-chatgpt/" rel="noopener noreferrer"&gt;GPT-5.5 Pro 릴리스 노트&lt;/a&gt;에 대한 TechCrunch 기사도 이 지연 시간 차이를 지적했습니다.&lt;/p&gt;

&lt;p&gt;UX 관점에서는 다음처럼 판단하십시오.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;제품 표면&lt;/th&gt;
&lt;th&gt;권장 접근&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;실시간 채팅 UI&lt;/td&gt;
&lt;td&gt;Instant 기본값, 필요 시 Pro 에스컬레이션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;백그라운드 분석&lt;/td&gt;
&lt;td&gt;Pro 또는 Batch 사용 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;야간 리포트 생성&lt;/td&gt;
&lt;td&gt;Batch 우선&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사용자 입력 중 자동완성&lt;/td&gt;
&lt;td&gt;Instant 우선&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;reasoning_effort&lt;/code&gt;는 모델 선택과 별개의 옵션이 아닙니다. 실제로는 세 번째 축입니다.&lt;/p&gt;

&lt;p&gt;예를 들어:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5-pro&lt;/code&gt; + &lt;code&gt;low&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5&lt;/code&gt; + &lt;code&gt;high&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;두 조합은 비용, 지연 시간, 품질 면에서 일부 겹칠 수 있습니다. 따라서 모델만 비교하지 말고 &lt;strong&gt;모델 + effort 조합&lt;/strong&gt;으로 비교해야 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  정확도 차이: Pro가 앞서는 지점
&lt;/h2&gt;

&lt;p&gt;OpenAI가 발표한 평가 결과는 명확한 패턴을 보여줍니다.&lt;/p&gt;

&lt;p&gt;Pro는 오류가 누적되는 &lt;strong&gt;다단계 추론 작업&lt;/strong&gt;에서 유리합니다. 반대로 단순 검색, 요약, 분류, 형식 변환에서는 Instant와 차이가 작습니다.&lt;/p&gt;

&lt;p&gt;발표된 수치 예시는 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;평가&lt;/th&gt;
&lt;th&gt;Pro&lt;/th&gt;
&lt;th&gt;Instant&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GPQA Diamond&lt;/td&gt;
&lt;td&gt;87%&lt;/td&gt;
&lt;td&gt;71%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SWE-bench Verified&lt;/td&gt;
&lt;td&gt;약 78%&lt;/td&gt;
&lt;td&gt;약 61%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MMLU / HellaSwag&lt;/td&gt;
&lt;td&gt;둘 다 90점대 후반&lt;/td&gt;
&lt;td&gt;둘 다 90점대 후반&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenAI의 안전 중요 응답 관련 내부 환각률 측정에서는 Pro가 적대적인 의료 및 법률 프롬프트에서 Instant보다 확신에 찬 잘못된 답변을 약 40% 적게 생성한다고 보고되었습니다.&lt;/p&gt;

&lt;p&gt;Pro가 특히 유리한 작업은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;법률 계약 초안 작성 및 검토&lt;/li&gt;
&lt;li&gt;의료 감별 진단 보조&lt;/li&gt;
&lt;li&gt;금융 문서 분석&lt;/li&gt;
&lt;li&gt;다단계 에이전트 계획&lt;/li&gt;
&lt;li&gt;여러 파일을 동시에 수정하는 코드 작업&lt;/li&gt;
&lt;li&gt;긴 제약 조건을 유지해야 하는 작업&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instant가 비용 대비 더 적합한 작업은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;고객 지원 채팅&lt;/li&gt;
&lt;li&gt;FAQ 검색&lt;/li&gt;
&lt;li&gt;콘텐츠 요약&lt;/li&gt;
&lt;li&gt;감정 분류&lt;/li&gt;
&lt;li&gt;단순 의도 라우팅&lt;/li&gt;
&lt;li&gt;잘 정의된 도구 호출&lt;/li&gt;
&lt;li&gt;단일 파일 코드 완성&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;답변이 이미 프롬프트 안에 있거나, 고정 템플릿을 따르거나, 다운스트림 검증으로 쉽게 걸러지는 작업에는 Pro의 긴 추론 루프가 큰 가치를 만들지 않습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  같은 프롬프트로 Instant와 Pro 비교하기
&lt;/h2&gt;

&lt;p&gt;두 모델은 같은 Responses API 호출 형태를 사용합니다. 아래 코드는 모델과 effort만 바꿔 같은 프롬프트를 비교합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Analyze this contract clause for unilateral termination risk:
&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Either party may terminate this agreement for convenience upon
thirty (30) days written notice, provided that the terminating party
shall pay any amounts then due.&lt;/span&gt;&lt;span class="sh"&gt;'"""&lt;/span&gt;

&lt;span class="c1"&gt;# Instant, fastest config
&lt;/span&gt;&lt;span class="n"&gt;instant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minimal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Pro, deepest config
&lt;/span&gt;&lt;span class="n"&gt;pro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INSTANT:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PRO:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;테스트 실행에서 이 프롬프트에 대해 Instant는 약 1.4초 만에 기본적인 해지 권한을 지적하는 짧은 답변을 반환했습니다. Pro는 약 22초 만에 더 긴 답변을 반환했고, 미지급 금액 정의의 간극, 지급 기한 조항, 수정안 제안, 관련 계약 원칙까지 포함했습니다.&lt;/p&gt;

&lt;p&gt;즉, 같은 프롬프트라도 결과의 깊이가 달라집니다. 하지만 이 차이가 항상 비용을 정당화하지는 않습니다. 그래서 자체 평가 세트가 필요합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  간단한 벤치마크 하네스 만들기
&lt;/h2&gt;

&lt;p&gt;실제 프롬프트 50~200개를 준비한 뒤 네 가지 조합을 비교하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5&lt;/code&gt; + &lt;code&gt;minimal&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5&lt;/code&gt; + &lt;code&gt;high&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5-pro&lt;/code&gt; + &lt;code&gt;minimal&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpt-5.5-pro&lt;/code&gt; + &lt;code&gt;high&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;PROMPTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eval_prompts.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;CONFIGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minimal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minimal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PROMPTS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;effort&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;CONFIGS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;t0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;latency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;t0&lt;/span&gt;
            &lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_tokens&lt;/span&gt;
            &lt;span class="n"&gt;output_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_tokens&lt;/span&gt;

            &lt;span class="n"&gt;rate_in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rate_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;input_tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate_in&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="n"&gt;output_tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rate_out&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;

            &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;input_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;output_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;실행 후에는 다음을 비교하십시오.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;사람이 블라인드로 평가한 품질 점수&lt;/li&gt;
&lt;li&gt;프롬프트당 비용&lt;/li&gt;
&lt;li&gt;평균 및 p95 지연 시간&lt;/li&gt;
&lt;li&gt;스키마 검증 실패율&lt;/li&gt;
&lt;li&gt;다운스트림 도구 호출 실패율&lt;/li&gt;
&lt;li&gt;재시도 또는 에스컬레이션 비율&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;게시된 벤치마크와 실제 워크로드의 차이는 자주 다릅니다. 따라서 자체 프롬프트로 평가해야 합니다.&lt;/p&gt;

&lt;p&gt;AI 에이전트 평가 워크플로는 &lt;a href="http://apidog.com/blog/how-to-test-ai-agents-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;AI 에이전트 API 테스트 가이드&lt;/a&gt;를 참고하십시오. 프로덕션 추적에서 테스트 프롬프트를 만드는 방법은 &lt;a href="http://apidog.com/blog/ai-api-test-generation?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;AI 기반 테스트 생성&lt;/a&gt;에서 다룹니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  비용 계산: 6배 프리미엄이 가치 있는 경우
&lt;/h2&gt;

&lt;h3&gt;
  
  
  기능 1: 고객 지원 봇
&lt;/h3&gt;

&lt;p&gt;조건:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;하루 100,000 메시지&lt;/li&gt;
&lt;li&gt;평균 입력 800토큰&lt;/li&gt;
&lt;li&gt;평균 출력 250토큰&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;일일 토큰 볼륨:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;입력 80,000,000&lt;/li&gt;
&lt;li&gt;출력 25,000,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instant 비용:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;입력: 80M * $5 / 1M = $400
출력: 25M * $30 / 1M = $750
합계: 하루 $1,150
월 약 $34,500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pro 비용:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;입력: 80M * $30 / 1M = $2,400
출력: 25M * $180 / 1M = $4,500
합계: 하루 $6,900
월 약 $207,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;월 프리미엄은 약 $172,500입니다.&lt;/p&gt;

&lt;p&gt;고객 지원, FAQ, 검색 기반 답변처럼 Instant가 충분히 강한 영역에서는 이 차이를 정당화하기 어렵습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;판결: Instant 유지.&lt;/strong&gt; 절감한 비용을 검색 품질, 컨텍스트 정제, 시스템 프롬프트 개선에 쓰십시오.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcujtmxawytreicbl6911.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcujtmxawytreicbl6911.png" alt="고객 지원 비용 비교" width="800" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  기능 2: 코드 리뷰 도우미
&lt;/h3&gt;

&lt;p&gt;조건:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;하루 5,000개 리뷰 댓글&lt;/li&gt;
&lt;li&gt;평균 입력 8,000토큰&lt;/li&gt;
&lt;li&gt;평균 출력 1,200토큰&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;일일 토큰 볼륨:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;입력 40,000,000&lt;/li&gt;
&lt;li&gt;출력 6,000,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instant 비용:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;입력: 40M * $5 / 1M = $200
출력: 6M * $30 / 1M = $180
합계: 하루 $380
월 약 $11,400
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pro 비용:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;입력: 40M * $30 / 1M = $1,200
출력: 6M * $180 / 1M = $1,080
합계: 하루 $2,280
월 약 $68,400
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;월 프리미엄은 약 $57,000입니다.&lt;/p&gt;

&lt;p&gt;이 경우 비교 대상은 API 비용이 아니라 엔지니어 시간입니다.&lt;/p&gt;

&lt;p&gt;예를 들어 Pro가 Instant가 놓치는 실제 버그를 1,000개 리뷰당 5개 더 찾고, 각 버그가 시니어 엔지니어 1시간($150)에 해당한다고 가정합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1,000개 리뷰당 추가 버그 5개
각 버그당 1시간
5,000개 리뷰당 하루 25개 추가 버그
하루 25시간 * $150 = $3,750
월 약 $112,500 절감
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 경우 월 $57,000 프리미엄은 정당화될 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;판결: Pro 사용 가능. 단, 실제 버그 탐지율을 측정해야 합니다.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  기능 3: 법률 문서 요약기
&lt;/h3&gt;

&lt;p&gt;조건:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;하루 500개 문서&lt;/li&gt;
&lt;li&gt;평균 입력 40,000토큰&lt;/li&gt;
&lt;li&gt;평균 출력 3,000토큰&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;일일 토큰 볼륨:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;입력 20,000,000&lt;/li&gt;
&lt;li&gt;출력 1,500,000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instant 비용:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;입력: 20M * $5 / 1M = $100
출력: 1.5M * $30 / 1M = $45
합계: 하루 $145
월 약 $4,350
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pro 비용:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;입력: 20M * $30 / 1M = $600
출력: 1.5M * $180 / 1M = $270
합계: 하루 $870
월 약 $26,100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;월 프리미엄은 약 $21,750입니다.&lt;/p&gt;

&lt;p&gt;공급업체 계약에서 중요한 면책 조항 하나를 놓치는 비용이 Pro 연간 프리미엄보다 클 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;판결: Pro 사용. 실시간이 필요 없다면 Batch 티어로 월 비용을 약 $13,050까지 줄이십시오.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  손익분기점 규칙
&lt;/h2&gt;

&lt;p&gt;모델 선택 기준은 호출량이 아니라 &lt;strong&gt;잘못될 경우의 비용&lt;/strong&gt;입니다.&lt;/p&gt;

&lt;p&gt;간단한 규칙은 다음과 같습니다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;하나의 오류를 방지했을 때 절감되는 비용이 해당 대화에서 Pro 사용으로 증가하는 비용보다 크면 Pro를 사용하십시오.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;즉:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;오류 비용이 낮고 검증이 쉬운 작업 → Instant&lt;/li&gt;
&lt;li&gt;오류 비용이 높고 사후 수정이 어려운 작업 → Pro&lt;/li&gt;
&lt;li&gt;대부분은 Instant로 처리하고, 실패 징후가 있을 때만 Pro로 에스컬레이션&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;또한 두 티어 모두에서 캐싱을 적극적으로 사용해야 합니다. 시스템 프롬프트가 반복된다면 프롬프트 캐싱으로 입력 토큰 비용을 크게 줄일 수 있습니다. 기능별 절감액을 계측하는 방법은 &lt;a href="http://apidog.com/blog/track-openai-api-spend-per-feature?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;OpenAI 지출 할당 가이드&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog로 Pro/Instant 트레이드오프 테스트하기
&lt;/h2&gt;

&lt;p&gt;게시된 벤치마크만 보고 프로덕션 모델을 선택하지 마십시오. Apidog에서 작은 회귀 테스트 스위트를 만들고, 프롬프트나 모델이 바뀔 때마다 실행하십시오.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74l0vndjmkcpll4rtof8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74l0vndjmkcpll4rtof8.png" alt="Apidog 테스트 화면" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1단계: 프로젝트 생성
&lt;/h3&gt;

&lt;p&gt;Apidog에서 새 프로젝트를 생성합니다.&lt;/p&gt;

&lt;p&gt;그 안에 OpenAI Responses API를 호출하는 요청 두 개를 만듭니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://api.openai.com/v1/responses
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;요청 이름 예시:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gpt55-instant-minimal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpt55-pro-high&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2단계: 공통 헤더 설정
&lt;/h3&gt;

&lt;p&gt;두 요청 모두 같은 헤더를 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Authorization: Bearer {{OPENAI_KEY}}
Content-Type: application/json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OPENAI_KEY&lt;/code&gt;는 Apidog 환경 변수로 저장하십시오. 요청 본문에 API 키를 직접 넣지 마십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  3단계: Instant 요청 본문 작성
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-5.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"minimal"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{prompt}}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4단계: Pro 요청 본문 작성
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-5.5-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{prompt}}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5단계: 프롬프트 데이터셋 바인딩
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;{{prompt}}&lt;/code&gt; 변수를 데이터 파일에 연결합니다.&lt;/p&gt;

&lt;p&gt;데이터 파일은 다음처럼 구성할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prompt
"Summarize this customer complaint and classify urgency..."
"Review this contract clause for termination risk..."
"Analyze this pull request for potential concurrency bugs..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;권장 크기:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;최소 50개&lt;/li&gt;
&lt;li&gt;가능하면 100~200개&lt;/li&gt;
&lt;li&gt;실제 프로덕션 트래픽에서 샘플링&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6단계: 테스트 스크립트로 메트릭 캡처
&lt;/h3&gt;

&lt;p&gt;각 요청에서 다음 값을 기록하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;response.usage.input_tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;response.usage.output_tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;응답 시간&lt;/li&gt;
&lt;li&gt;출력 본문&lt;/li&gt;
&lt;li&gt;스키마 검증 결과&lt;/li&gt;
&lt;li&gt;비즈니스 규칙 검증 결과&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apidog는 응답 본문과 실행 시간을 저장하므로, 이후 Diff 뷰에서 두 모델의 응답을 나란히 비교할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  7단계: CSV로 내보내 비용 계산
&lt;/h3&gt;

&lt;p&gt;실행 결과를 CSV로 내보낸 뒤 프롬프트별 비용을 계산합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Instant 비용 = (input_tokens * 5 + output_tokens * 30) / 1,000,000
Pro 비용     = (input_tokens * 30 + output_tokens * 180) / 1,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그 다음 각 프롬프트에 대해 다음 질문에 답합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pro가 실제로 더 좋은가?&lt;/li&gt;
&lt;li&gt;더 좋다면 오류 비용을 줄이는가?&lt;/li&gt;
&lt;li&gt;지연 시간 증가를 UX가 감당할 수 있는가?&lt;/li&gt;
&lt;li&gt;Instant 실패 시 Pro 에스컬레이션으로 충분한가?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 과정을 거치면 분기 내내 추측하는 대신, 한 시간 안에 기능별 모델 라우팅 규칙을 만들 수 있습니다.&lt;/p&gt;

&lt;p&gt;전체 프로젝트를 회귀 테스트 스위트로 저장하십시오. OpenAI가 새 모델을 출시하거나 시스템 프롬프트가 바뀔 때마다 다시 실행하면 됩니다. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt; 워크스페이스는 기록을 보관하므로, 정확도가 언제 떨어졌고 어떤 프롬프트 변경이 원인이었는지 추적할 수 있습니다. &lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드&lt;/a&gt;하고 &lt;a href="http://apidog.com/blog/how-to-test-ai-agents-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 워크플로&lt;/a&gt;를 참고해 회귀 테스트를 구성하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  운영 라우팅 패턴
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 사용자별이 아니라 기능별로 라우팅
&lt;/h3&gt;

&lt;p&gt;가장 흔한 실수는 “프리미엄 사용자는 항상 Pro” 같은 정책입니다.&lt;/p&gt;

&lt;p&gt;대신 모든 API 호출에 다음 태그를 붙이십시오.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contract_review"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error_cost_class"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_class"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"async"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model_policy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pro_preferred"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;라우팅은 사용자 플랜이 아니라 기능과 오류 비용 기준으로 결정해야 합니다.&lt;/p&gt;

&lt;p&gt;대부분의 제품에서는 다음 분포가 현실적입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant: 75~95%&lt;/li&gt;
&lt;li&gt;Pro: 5~25%&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Instant 기본값 + Pro 에스컬레이션
&lt;/h3&gt;

&lt;p&gt;권장 패턴은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;모든 요청을 Instant로 처리&lt;/li&gt;
&lt;li&gt;응답을 검증&lt;/li&gt;
&lt;li&gt;실패하면 Pro로 재시도&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;에스컬레이션 조건 예시:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON 스키마 검증 실패&lt;/li&gt;
&lt;li&gt;필수 필드 누락&lt;/li&gt;
&lt;li&gt;신뢰도 점수 낮음&lt;/li&gt;
&lt;li&gt;정책상 위험한 카테고리&lt;/li&gt;
&lt;li&gt;다운스트림 도구 호출 실패&lt;/li&gt;
&lt;li&gt;특정 파일 수 이상 변경&lt;/li&gt;
&lt;li&gt;특정 법률/의료/금융 태그 감지&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;예시 코드:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jsonschema&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;responses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;reasoning&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;effort&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;effort&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;jsonschema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_with_escalation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;instant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minimal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;instant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;escalated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;pro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;output_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;escalated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 방식은 모든 요청에 Pro 비용을 지불하지 않고, 실제로 필요한 5~15% 요청에만 프리미엄을 지불하게 만듭니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 프롬프트 캐싱 적극 사용
&lt;/h3&gt;

&lt;p&gt;캐시된 입력 토큰은 훨씬 저렴합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instant: $5 → $0.50 / 1M 입력 토큰&lt;/li&gt;
&lt;li&gt;Pro: $30 → $3 / 1M 입력 토큰&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;시스템 프롬프트가 1,000토큰 이상이고 안정적이라면 캐시 히트율을 반드시 추적하십시오.&lt;/p&gt;

&lt;p&gt;관찰해야 할 지표:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cached_tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;캐시 히트율&lt;/li&gt;
&lt;li&gt;기능별 캐시 절감액&lt;/li&gt;
&lt;li&gt;프롬프트 변경 후 캐시 미스 증가&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. 비실시간 작업은 Batch 우선
&lt;/h3&gt;

&lt;p&gt;10분 이내 응답이 필요 없는 작업은 Batch API 후보입니다.&lt;/p&gt;

&lt;p&gt;예시:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;야간 콘텐츠 생성&lt;/li&gt;
&lt;li&gt;주간 요약&lt;/li&gt;
&lt;li&gt;대량 분류&lt;/li&gt;
&lt;li&gt;소급 로그 분석&lt;/li&gt;
&lt;li&gt;백오피스 문서 처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Batch는 모델 품질을 낮추는 것이 아니라 전달 시간을 늦추고 비용을 절반으로 줄이는 방식입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 272K 컨텍스트 창을 무작정 채우지 않기
&lt;/h3&gt;

&lt;p&gt;Instant와 Pro 모두 272,000 토큰 입력 컨텍스트를 지원합니다. 그러나 컨텍스트가 길수록 비용은 선형 증가합니다.&lt;/p&gt;

&lt;p&gt;또한 약 180,000 토큰을 넘으면 검색 정확도가 저하되기 시작할 수 있습니다. 전체 컨텍스트를 무조건 넣는 대신 다음을 적용하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;문서 청크 분할&lt;/li&gt;
&lt;li&gt;검색 기반 컨텍스트 선택&lt;/li&gt;
&lt;li&gt;중복 제거&lt;/li&gt;
&lt;li&gt;요약 후 재입력&lt;/li&gt;
&lt;li&gt;긴 고정 프롬프트 캐싱&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  흔한 실수
&lt;/h2&gt;

&lt;p&gt;피해야 할 패턴은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;라우팅 계층 없이 클라이언트 코드에서 모델을 직접 선택&lt;/li&gt;
&lt;li&gt;실제 프롬프트가 아니라 공개 벤치마크만 보고 결정&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;minimal&lt;/code&gt;로 충분한 작업에 Pro &lt;code&gt;high&lt;/code&gt; 사용&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;max_output_tokens&lt;/code&gt;를 설정하지 않음&lt;/li&gt;
&lt;li&gt;캐시 미스를 무료처럼 취급&lt;/li&gt;
&lt;li&gt;기능별 비용 대신 전체 API 비용만 추적&lt;/li&gt;
&lt;li&gt;Pro를 사용자 플랜 기준으로 일괄 적용&lt;/li&gt;
&lt;li&gt;배치 가능한 작업을 실시간 API로 처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;max_output_tokens&lt;/code&gt;는 특히 중요합니다. Pro 호출이 8,000 출력 토큰까지 늘어나면 단일 호출에서 출력 비용만 $1.44가 발생할 수 있습니다.&lt;/p&gt;

&lt;p&gt;더 넓은 모델 선택이 필요하다면 &lt;a href="http://apidog.com/blog/how-to-use-gemini-3-flash-preview-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Gemini 3 Flash 미리보기 API 가이드&lt;/a&gt;와 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 GPT-5.5 API 액세스 옵션&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  실제 사용 사례
&lt;/h2&gt;

&lt;h3&gt;
  
  
  보험 청구 분류
&lt;/h3&gt;

&lt;p&gt;중견 보험사는 초기 접수 요약을 Instant로 처리하고, 복잡한 정책 질문만 Pro로 에스컬레이션합니다.&lt;/p&gt;

&lt;p&gt;운영 결과:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;약 12%의 청구만 Pro 경로 사용&lt;/li&gt;
&lt;li&gt;모든 요청을 Pro로 처리하던 정책 대비 총 지출 60% 감소&lt;/li&gt;
&lt;li&gt;규제 기관 감사 세트의 정확도 향상&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;핵심은 Pro를 전체 트래픽에 쓰지 않고, 어려운 12%에 집중시킨 것입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  코드 리뷰 도우미
&lt;/h3&gt;

&lt;p&gt;개발 도구 회사는 모든 PR을 Instant로 먼저 검사합니다.&lt;/p&gt;

&lt;p&gt;Instant가 담당하는 작업:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;스타일 이슈&lt;/li&gt;
&lt;li&gt;명백한 버그&lt;/li&gt;
&lt;li&gt;단순 리뷰 코멘트&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pro로 보내는 조건:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;세 개 이상의 파일 변경&lt;/li&gt;
&lt;li&gt;위험한 경로 패턴&lt;/li&gt;
&lt;li&gt;동시성 관련 코드&lt;/li&gt;
&lt;li&gt;마이그레이션 또는 보안 관련 변경&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;결과적으로 Pro는 추가 API 지출 연간 $40,000으로 3.8%의 버그를 추가로 탐지했고, 이는 초기 버그 감지로부터 추정되는 엔지니어링 시간 절감 $300,000에 해당했습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  병원 접수 요약기
&lt;/h3&gt;

&lt;p&gt;병원 접수 요약은 &lt;code&gt;reasoning_effort=high&lt;/code&gt;인 Pro를 사용합니다.&lt;/p&gt;

&lt;p&gt;이유는 단순합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;오류 비용이 높음&lt;/li&gt;
&lt;li&gt;사후 수정이 어려움&lt;/li&gt;
&lt;li&gt;안전 관련 영향이 큼&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;다만 실시간 응답이 필요 없는 80%의 요약은 야간 Batch로 처리해 비용을 50% 줄입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;Instant와 Pro의 6배 가격 차이는 단점이 아니라 의사결정 장치입니다. 팀이 “정확함의 가치”를 숫자로 표현하게 만들기 때문입니다.&lt;/p&gt;

&lt;p&gt;실무 규칙은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;기본값은 Instant로 둡니다.&lt;/li&gt;
&lt;li&gt;잘못된 답변의 금전적 비용을 기능별로 계산합니다.&lt;/li&gt;
&lt;li&gt;오류 비용이 명확할 때만 Pro로 에스컬레이션합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;reasoning_effort&lt;/code&gt;를 모델 선택의 일부로 봅니다.&lt;/li&gt;
&lt;li&gt;시스템 프롬프트는 캐싱합니다.&lt;/li&gt;
&lt;li&gt;비실시간 작업은 Batch를 사용합니다.&lt;/li&gt;
&lt;li&gt;프로덕션 반영 전 Apidog에서 회귀 테스트 스위트를 실행합니다.&lt;/li&gt;
&lt;li&gt;캐시 히트율과 기능별 비용을 매월 측정합니다.&lt;/li&gt;
&lt;li&gt;새 모델이나 가격 변경이 나오면 손익분기점을 다시 계산합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;대부분의 팀은 전체 API 호출 중 5~25%만 Pro를 사용할 가치가 있다는 결론에 도달합니다. 나머지는 품질 개선이 아니라 비용 낭비일 가능성이 큽니다.&lt;/p&gt;

&lt;p&gt;다음 계획 주기 전에 Apidog에서 프롬프트별 비용 및 정확도 비교를 실행하십시오. 더 넓은 GPT-5.5 맥락은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-instant?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 Instant 액세스 가이드&lt;/a&gt;와 &lt;a href="http://apidog.com/blog/track-openai-api-spend-per-feature?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;OpenAI 기능별 지출 할당 플레이북&lt;/a&gt;을 참고하면 됩니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: GPT-5.5 Pro는 Instant보다 6배 더 좋은가요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: 아닙니다. 토큰당 비용이 6배 더 비쌀 뿐입니다. 대부분의 워크로드에서는 조금 더 좋고, 일부 고위험 다단계 작업에서는 훨씬 더 좋습니다. 중요한 것은 여러분의 기능 중 어떤 것이 그 소수에 속하는지 식별하는 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: 두 모델에 동일한 API 코드를 사용할 수 있나요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: 네. 둘 다 OpenAI Responses API에서 동일한 요청 형태를 사용합니다. &lt;code&gt;model: "gpt-5.5"&lt;/code&gt;를 &lt;code&gt;model: "gpt-5.5-pro"&lt;/code&gt;로 바꾸면 나머지 호출은 동일합니다. 자세한 매개변수는 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API 가이드&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: &lt;code&gt;reasoning_effort&lt;/code&gt;는 두 모델에서 동일하게 작동하나요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: 두 모델 모두 &lt;code&gt;minimal&lt;/code&gt;, &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt; 값을 허용합니다. 다만 Pro는 더 많은 추론 용량을 사용할 수 있으므로 효과가 더 큽니다. &lt;code&gt;minimal&lt;/code&gt;의 Pro는 &lt;code&gt;high&lt;/code&gt;의 Pro보다 &lt;code&gt;high&lt;/code&gt;의 Instant에 더 가까울 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Pro에서 프롬프트 캐싱은 얼마나 절약되나요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: 캐시된 입력 토큰은 Pro에서 백만 토큰당 $30에서 $3로 줄어듭니다. Instant는 $5에서 $0.50으로 줄어듭니다. 시스템 프롬프트가 안정적이고 1,000토큰 이상이라면 캐싱을 적용해야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: 기본적으로 Pro를 사용하고 다운그레이드해야 하나요, 아니면 Instant를 기본값으로 두고 에스컬레이션해야 하나요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: Instant를 기본값으로 두고 에스컬레이션하는 편이 일반적으로 낫습니다. 실패 징후가 있는 요청에만 Pro 비용을 지불하므로 전체 비용을 훨씬 낮게 유지할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: 높은 추론 노력에서 Pro의 지연 시간 페널티는 어느 정도인가요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: &lt;code&gt;high&lt;/code&gt;로 설정된 Pro는 첫 토큰까지 8~30초가 걸릴 수 있습니다. 반면 &lt;code&gt;minimal&lt;/code&gt; Instant는 짧은 프롬프트에서 200~400ms 수준입니다. 긴 Pro 응답은 엔드투엔드로 20~60초가 걸릴 수 있으므로 UX를 그에 맞게 설계해야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Batch 티어는 실시간 티어와 같은 답변을 제공하나요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: 네. Batch는 모델을 바꾸는 것이 아니라 전달 시간을 늦추고 가격을 낮추는 방식입니다. 동일한 모델 가중치와 동일한 출력 품질을 사용하며, 비용은 절반입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: 언제 모델 선택을 재평가해야 하나요?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A: OpenAI의 모델 업데이트나 가격 변경이 있을 때마다 회귀 테스트 스위트를 다시 실행하십시오. 가격 인하와 모델 개선은 모두 손익분기점을 바꿉니다. &lt;a href="http://apidog.com/blog/how-to-test-ai-agents-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;회귀 테스트 스위트 워크플로&lt;/a&gt;를 구성해 비교를 반복 가능하게 유지하십시오.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Playwright 테스트에서 API 응답 검증 방법</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Tue, 12 May 2026 06:18:56 +0000</pubDate>
      <link>https://forem.com/rihpig/playwright-teseuteueseo-api-eungdab-geomjeung-bangbeob-2cm</link>
      <guid>https://forem.com/rihpig/playwright-teseuteueseo-api-eungdab-geomjeung-bangbeob-2cm</guid>
      <description>&lt;p&gt;Playwright 테스트는 통과했지만 고객은 “차트 숫자가 틀렸다”고 보고합니다. 확인해 보니 API가 잘못된 페이로드를 &lt;code&gt;200 OK&lt;/code&gt;로 반환했고, E2E 테스트는 화면에 차트가 렌더링되는지만 확인했습니다. 이 간극을 줄이려면 브라우저 테스트에 API 단언(assertion)을 얇게 추가하고, &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;와 같은 도구로 API 계약, 스키마, 응답 의미를 별도로 검증해야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;p&gt;Playwright의 &lt;code&gt;request&lt;/code&gt; 픽스처와 &lt;code&gt;page.route&lt;/code&gt; 인터셉터를 OpenAPI 기반 Apidog 시나리오와 함께 사용하면 UI 테스트와 API 테스트를 같은 계약 위에서 실행할 수 있습니다.&lt;/p&gt;

&lt;p&gt;핵심은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;openapi.yaml&lt;/code&gt;을 단일 진실 소스(source of truth)로 둡니다.&lt;/li&gt;
&lt;li&gt;Playwright에서는 핵심 API 스모크 테스트와 UI 플로우를 검증합니다.&lt;/li&gt;
&lt;li&gt;Apidog에서는 스키마, 연쇄 API 시나리오, 오류 경로를 깊게 검증합니다.&lt;/li&gt;
&lt;li&gt;두 스위트를 CI에서 함께 실행해 계약 변경을 빠르게 감지합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  소개
&lt;/h2&gt;

&lt;p&gt;Playwright는 브라우저 자동화에 강력합니다. &lt;a href="https://playwright.dev/docs/api-testing" rel="noopener noreferrer"&gt;Playwright API testing 문서&lt;/a&gt;를 보면 &lt;code&gt;request.get()&lt;/code&gt;과 &lt;code&gt;expect(response.status()).toBe(200)&lt;/code&gt;만으로 API 테스트를 쉽게 추가할 수 있어 보입니다.&lt;/p&gt;

&lt;p&gt;하지만 실제 프로젝트에서는 다음 문제가 빠르게 발생합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;상태 코드만 확인하고 응답 스키마는 확인하지 않는 테스트가 늘어남&lt;/li&gt;
&lt;li&gt;UI 테스트와 API 테스트가 서로 다른 fixture를 사용함&lt;/li&gt;
&lt;li&gt;OpenAPI 사양과 테스트 데이터가 동기화되지 않음&lt;/li&gt;
&lt;li&gt;백엔드가 느리거나 불안정할 때 오프라인으로 API를 mock하기 어려움&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;해결 방법은 OpenAPI 사양을 계약으로 취급하는 것입니다. 같은 &lt;code&gt;openapi.yaml&lt;/code&gt;을 기준으로 Playwright &lt;code&gt;request&lt;/code&gt; 호출, &lt;code&gt;page.route&lt;/code&gt; stub, Apidog 시나리오를 구성합니다.&lt;/p&gt;

&lt;p&gt;도구를 먼저 설치하려면 &lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog 다운로드&lt;/a&gt; 후 아래 단계를 진행하십시오.&lt;/p&gt;

&lt;p&gt;이 글에서는 다음을 구현합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playwright 테스트에서 API 단언을 어디까지 넣을지 결정하는 기준&lt;/li&gt;
&lt;li&gt;재사용 가능한 &lt;code&gt;request&lt;/code&gt; fixture 패턴&lt;/li&gt;
&lt;li&gt;Playwright와 Apidog 간 fixture 공유 방식&lt;/li&gt;
&lt;li&gt;CI에서 두 스위트를 함께 실행하는 GitHub Actions 예시&lt;/li&gt;
&lt;li&gt;mocking, schema drift 감지, retry 정책&lt;/li&gt;
&lt;li&gt;대안 도구 비교&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;테스트 도구 선택에 대한 더 넓은 맥락은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  Playwright 테스트와 API 단언 간의 간극
&lt;/h2&gt;

&lt;p&gt;일반적인 Playwright 테스트는 다음을 확인합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;로그인한다.&lt;/li&gt;
&lt;li&gt;대시보드로 이동한다.&lt;/li&gt;
&lt;li&gt;차트나 테이블이 보이는지 확인한다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이 테스트는 사용자 플로우가 작동하는지 알려줍니다. 하지만 API가 올바른 데이터를 반환하는지는 보장하지 않습니다.&lt;/p&gt;

&lt;p&gt;다음 문제는 UI 테스트만으로 놓치기 쉽습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 페이로드 형태 회귀
&lt;/h3&gt;

&lt;p&gt;API가 기존 &lt;code&gt;total_count&lt;/code&gt; 대신 &lt;code&gt;totalCount&lt;/code&gt;를 반환합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"totalCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;UI가 이를 &lt;code&gt;0&lt;/code&gt;으로 처리하거나 fallback 값을 보여줘도 Playwright 테스트는 “숫자가 보인다”는 이유로 통과할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 비즈니스 로직 이탈
&lt;/h3&gt;

&lt;p&gt;할인 API가 계약된 15% 대신 10% 할인을 적용합니다.&lt;/p&gt;

&lt;p&gt;UI는 API 응답을 그대로 렌더링하므로 E2E 테스트는 통과합니다. 하지만 실제 금액은 잘못됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 오류 경로 미검증
&lt;/h3&gt;

&lt;p&gt;E2E 테스트는 보통 happy path 중심입니다.&lt;/p&gt;

&lt;p&gt;하지만 API에는 다음과 같은 오류 분기가 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;만료된 토큰&lt;/li&gt;
&lt;li&gt;rate limit&lt;/li&gt;
&lt;li&gt;부분 실패&lt;/li&gt;
&lt;li&gt;idempotency 충돌&lt;/li&gt;
&lt;li&gt;webhook 재시도 실패&lt;/li&gt;
&lt;li&gt;4xx / 5xx 응답&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 경로는 별도 API 테스트 없이는 거의 실행되지 않습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  역할 분리: Playwright와 Apidog
&lt;/h2&gt;

&lt;p&gt;모든 API 테스트를 Playwright에 넣는 방식은 처음에는 단순합니다. 하지만 엔드포인트가 많아지고, “주문 생성 → 주문 조회 → 주문 취소 → 환불 webhook 검증” 같은 상태 기반 시나리오가 필요해지면 유지보수가 어려워집니다.&lt;/p&gt;

&lt;p&gt;권장 분리는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Playwright&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI 플로우 검증&lt;/li&gt;
&lt;li&gt;핵심 API smoke assertion&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;page.route&lt;/code&gt; 기반 network stub&lt;/li&gt;
&lt;li&gt;사용자 행동 경계에서의 검증&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Apidog&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAPI 스키마 적합성 검증&lt;/li&gt;
&lt;li&gt;연쇄 API workflow 검증&lt;/li&gt;
&lt;li&gt;계약 준수 검증&lt;/li&gt;
&lt;li&gt;오류 경로 검증&lt;/li&gt;
&lt;li&gt;mock server 기반 오프라인 개발&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;두 도구가 같은 OpenAPI 사양을 사용하면 테스트의 기준점이 하나로 유지됩니다.&lt;/p&gt;

&lt;p&gt;계약 우선 접근 방식은 &lt;a href="http://apidog.com/blog/api-platform-design-first-api-workflow?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;설계 우선 API 워크플로우&lt;/a&gt;에서 더 자세히 다룹니다. Postman에서 전환을 검토 중이라면 &lt;a href="http://apidog.com/blog/best-self-hosted-postman-alternatives-2026-2?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;자체 호스팅 Postman 대안&lt;/a&gt;도 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  Playwright와 Apidog 간 fixture 공유 방법
&lt;/h2&gt;

&lt;p&gt;프로젝트 루트에 OpenAPI 사양을 둡니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── openapi.yaml
├── fixtures/
│   └── order.json
├── tests/
│   ├── fixtures/
│   │   └── api.ts
│   └── orders.spec.ts
└── playwright.config.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;openapi.yaml&lt;/code&gt;은 API 계약입니다. Playwright는 요청 helper와 fixture를 통해 이 계약을 따르고, Apidog는 같은 파일을 import해 endpoint, request example, schema assertion을 생성합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 공유 fixture 파일 만들기
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;fixtures/order.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sku"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SKU-123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subtotal_cents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KRW"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 파일은 Playwright와 Apidog에서 모두 같은 request body로 사용합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Playwright API fixture 작성
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/fixtures/api.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;APIRequestContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ApiFixtures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIRequestContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApiFixtures&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;playwright&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;playwright&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.staging.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;extraHTTPHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;apiRequest&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qa@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QA_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixtures&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;order.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이제 각 테스트는 &lt;code&gt;@playwright/test&lt;/code&gt; 대신 이 fixture 파일에서 &lt;code&gt;test&lt;/code&gt;와 &lt;code&gt;expect&lt;/code&gt;를 가져옵니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Playwright에서 핵심 API 단언 추가
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/orders.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./fixtures/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST /orders returns a valid order with 15 percent discount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;apiRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/orders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;coupon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SAVE15&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMatchObject&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;discount_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;total_cents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;total_cents&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeLessThan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtotal_cents&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Playwright에서는 모든 필드를 검증하려고 하지 마십시오. 대신 비즈니스적으로 중요한 필드만 명시적으로 검증합니다.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;할인율&lt;/li&gt;
&lt;li&gt;상태값&lt;/li&gt;
&lt;li&gt;총액&lt;/li&gt;
&lt;li&gt;권한별 응답 차이&lt;/li&gt;
&lt;li&gt;사용자에게 직접 노출되는 데이터&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;나머지 스키마 전체 검증은 Apidog 시나리오에서 담당합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog에서 같은 OpenAPI 사양 사용하기
&lt;/h2&gt;

&lt;p&gt;Apidog에서는 다음 순서로 설정합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apidog 프로젝트를 엽니다.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import&lt;/strong&gt;를 클릭합니다.&lt;/li&gt;
&lt;li&gt;저장소의 &lt;code&gt;openapi.yaml&lt;/code&gt;을 선택합니다.&lt;/li&gt;
&lt;li&gt;생성된 endpoint, request example, schema를 확인합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fixtures/order.json&lt;/code&gt;과 동일한 payload를 환경 변수 또는 데이터 세트로 저장합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /orders&lt;/code&gt; 시나리오를 만듭니다.&lt;/li&gt;
&lt;li&gt;응답을 &lt;code&gt;Order&lt;/code&gt; schema에 대해 검증합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;discount_pct&lt;/code&gt;, &lt;code&gt;total_cents&lt;/code&gt; 같은 비즈니스 필드를 assertion으로 추가합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Apidog 시나리오는 다음 역할을 합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;필수 필드 누락 감지&lt;/li&gt;
&lt;li&gt;타입 변경 감지&lt;/li&gt;
&lt;li&gt;enum 값 변경 감지&lt;/li&gt;
&lt;li&gt;응답 schema drift 감지&lt;/li&gt;
&lt;li&gt;연쇄 요청 간 데이터 전달 검증&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Playwright는 높은 가치의 의미론적 단언을 수행하고, Apidog는 수동으로 놓치기 쉬운 schema 전체를 검증합니다.&lt;/p&gt;

&lt;p&gt;사양 기반 테스트가 처음이라면 &lt;a href="http://apidog.com/blog/api-platform-design-first-api-workflow?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;설계 우선 API 워크플로우&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog + Playwright 워크플로우 설정
&lt;/h2&gt;

&lt;p&gt;아래는 CI까지 연결하는 기본 구현 순서입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1단계: OpenAPI 사양을 저장소 루트에 둔다
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openapi.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 파일을 코드처럼 관리하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PR 리뷰 필수&lt;/li&gt;
&lt;li&gt;breaking change는 명시적으로 기록&lt;/li&gt;
&lt;li&gt;request / response example 유지&lt;/li&gt;
&lt;li&gt;schema와 실제 구현 간 drift 감지&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;아직 OpenAPI 사양이 없다면 FastAPI, NestJS 등 프레임워크의 OpenAPI export 기능으로 초안을 만든 뒤 수동으로 정리합니다.&lt;/p&gt;

&lt;p&gt;Apidog는 HAR 파일을 가져와 실제 트래픽에서 사양을 역설계할 수도 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2단계: Playwright 설치 및 설정
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init playwright@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;에 테스트 스크립트를 추가합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:e2e"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"playwright test"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;playwright.config.ts&lt;/code&gt;에서는 staging API와 retry 정책을 명시합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APP_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;on-first-retry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3단계: Apidog 시나리오 계층 추가
&lt;/h3&gt;

&lt;p&gt;Apidog에서 중요한 사용자 여정별 시나리오를 만듭니다.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;회원가입&lt;/li&gt;
&lt;li&gt;로그인&lt;/li&gt;
&lt;li&gt;결제&lt;/li&gt;
&lt;li&gt;주문 취소&lt;/li&gt;
&lt;li&gt;환불&lt;/li&gt;
&lt;li&gt;webhook 전달&lt;/li&gt;
&lt;li&gt;토큰 만료&lt;/li&gt;
&lt;li&gt;rate limit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;각 시나리오는 API 호출의 시퀀스입니다. 이전 응답에서 값을 추출해 다음 요청에 전달합니다.&lt;/p&gt;

&lt;p&gt;예:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /auth/token
  → access_token 저장

POST /orders
  → order_id 저장

GET /orders/{order_id}
  → status 검증

POST /orders/{order_id}/cancel
  → cancellation status 검증
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apidog CLI로 CI에서 실행 가능한 시나리오를 내보냅니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apidog-cli run ./apidog/scenarios/checkout.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4단계: Playwright에서 network stub 사용
&lt;/h3&gt;

&lt;p&gt;UI가 실제 백엔드 데이터에 의존하지 않도록 &lt;code&gt;page.route&lt;/code&gt;를 사용할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./fixtures/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dashboard renders cached order list when offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;**/api/orders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fulfill&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;contentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sampleOrder&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;order-row&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toHaveCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;주의할 점은 &lt;code&gt;page.route&lt;/code&gt; stub을 실제 API 테스트의 대체물로 사용하지 않는 것입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stub: UI 격리용&lt;/li&gt;
&lt;li&gt;Apidog scenario: 실제 API 계약 검증용&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;같은 fixture를 사용하되 목적은 분리합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5단계: GitHub Actions에서 두 스위트 실행
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;playwright&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx playwright install --with-deps&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx playwright test&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;API_BASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.API_BASE_URL }}&lt;/span&gt;
          &lt;span class="na"&gt;APP_BASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.APP_BASE_URL }}&lt;/span&gt;
          &lt;span class="na"&gt;QA_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.QA_PASSWORD }}&lt;/span&gt;

  &lt;span class="na"&gt;apidog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm i -g apidog-cli&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apidog-cli run ./apidog/scenarios/checkout.json --reporters cli,junit&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;API_BASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.API_BASE_URL }}&lt;/span&gt;
          &lt;span class="na"&gt;QA_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.QA_PASSWORD }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;어느 job이든 실패하면 merge를 차단합니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--reporters junit&lt;/code&gt;를 사용하면 CI에서 실패한 assertion을 더 쉽게 추적할 수 있습니다. GitHub Actions의 matrix, cache, artifact 설정은 &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions 문서&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;p&gt;전담 QA 조직이 없는 팀이라면 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;에서 스위트 소유권을 나누는 방식을 확인할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  6단계: schema drift 감지
&lt;/h3&gt;

&lt;p&gt;매일 예약 job을 실행해 현재 &lt;code&gt;openapi.yaml&lt;/code&gt;과 실제 API 응답을 비교합니다.&lt;/p&gt;

&lt;p&gt;감지해야 할 변경 예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;필드명 변경&lt;/li&gt;
&lt;li&gt;타입 변경&lt;/li&gt;
&lt;li&gt;필수 필드 제거&lt;/li&gt;
&lt;li&gt;enum 값 변경&lt;/li&gt;
&lt;li&gt;response status code 변경&lt;/li&gt;
&lt;li&gt;nullable 여부 변경&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 작업은 “잘못된 payload와 함께 &lt;code&gt;200 OK&lt;/code&gt;가 반환되는 문제”를 조기에 잡는 데 효과적입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  고급 기술 및 전문가 팁
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Playwright trace viewer 활성화
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;playwright.config.ts&lt;/code&gt;에 다음을 설정합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;on-first-retry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;불안정한 테스트가 실패하면 다음을 함께 확인할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;network call&lt;/li&gt;
&lt;li&gt;DOM snapshot&lt;/li&gt;
&lt;li&gt;console log&lt;/li&gt;
&lt;li&gt;screenshot&lt;/li&gt;
&lt;li&gt;action timeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;API 쪽에서는 Apidog HTML report와 함께 사용하면 UI 문제인지 API 변경인지 빠르게 분리할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apidog mock server로 오프라인 실행
&lt;/h3&gt;

&lt;p&gt;백엔드가 배포 중이거나 staging DB가 초기화되는 동안에는 Apidog mock server를 사용합니다.&lt;/p&gt;

&lt;p&gt;패턴은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;로컬 Playwright는 Apidog mock server를 바라봄&lt;/li&gt;
&lt;li&gt;Apidog scenario는 실제 backend 또는 mock server 둘 다 실행 가능&lt;/li&gt;
&lt;li&gt;OpenAPI example response를 기준으로 UI 개발 지속&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mock이 중요한 테스트 자동화 흐름은 &lt;a href="http://apidog.com/blog/ai-api-test-generation?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;AI 지원 API 테스트 생성&lt;/a&gt;에서도 다룹니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  retry는 작게 유지
&lt;/h3&gt;

&lt;p&gt;Playwright retry는 보통 2회로 충분합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;테스트가 통과하기 위해 5회 retry가 필요하다면 테스트 또는 시스템에 문제가 있는 것입니다.&lt;/p&gt;

&lt;p&gt;Apidog scenario도 요청당 retry를 과도하게 늘리지 마십시오. 일시적인 네트워크 문제를 흡수할 정도만 설정합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  schema drift는 기본적으로 실패 처리
&lt;/h3&gt;

&lt;p&gt;Apidog가 schema mismatch를 감지하면 CI를 실패시켜야 합니다.&lt;/p&gt;

&lt;p&gt;일시적으로 허용해야 한다면 환경 변수로 명시합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ALLOW_SCHEMA_DRIFT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그리고 PR에 이유를 남기도록 팀 규칙을 둡니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  테스트를 우선순위별로 태그 지정
&lt;/h3&gt;

&lt;p&gt;Playwright에서는 smoke, regression, nightly를 분리합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checkout flow @smoke&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;권장 실행 전략:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;모든 push: &lt;code&gt;@smoke&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;main 대상 PR: regression&lt;/li&gt;
&lt;li&gt;nightly: 전체 Playwright + 전체 Apidog scenario&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;상태를 공유하는 테스트는 serial 모드를 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;serial&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  피해야 할 실수
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;status === 200&lt;/code&gt;만 검증하는 것&lt;/li&gt;
&lt;li&gt;bearer token을 fixture에 하드코딩하는 것&lt;/li&gt;
&lt;li&gt;Playwright와 Apidog가 서로 다른 payload를 사용하는 것&lt;/li&gt;
&lt;li&gt;OpenAPI 사양을 수동 문서처럼 방치하는 것&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;page.route&lt;/code&gt; stub을 실제 API 테스트로 착각하는 것&lt;/li&gt;
&lt;li&gt;CI에서 Apidog CLI 실행을 생략하는 것&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI 기반 API를 테스트한다면 &lt;a href="http://apidog.com/blog/how-to-test-ai-agents-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;AI 에이전트 API 테스트 방법&lt;/a&gt;도 참고하십시오. 비결정론적 응답은 일반 REST API보다 assertion 설계가 더 중요합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  대안 및 도구 비교
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;스택&lt;/th&gt;
&lt;th&gt;장점&lt;/th&gt;
&lt;th&gt;단점&lt;/th&gt;
&lt;th&gt;가장 적합한 경우&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Playwright 단독 (&lt;code&gt;request&lt;/code&gt; fixture)&lt;/td&gt;
&lt;td&gt;하나의 도구로 UI와 API smoke test 작성 가능&lt;/td&gt;
&lt;td&gt;깊은 schema 검증, 연쇄 scenario, 오류 경로 커버리지가 약함&lt;/td&gt;
&lt;td&gt;소규모 팀, 단순 API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playwright + Postman&lt;/td&gt;
&lt;td&gt;성숙한 Postman 생태계, Newman CLI&lt;/td&gt;
&lt;td&gt;OpenAPI와 collection이 어긋날 수 있음, 두 가지 진실 소스 발생&lt;/td&gt;
&lt;td&gt;이미 Postman을 표준으로 쓰는 팀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playwright + Apidog&lt;/td&gt;
&lt;td&gt;단일 OpenAPI 소스, schema validation, mock, CLI, design-first workflow&lt;/td&gt;
&lt;td&gt;두 도구 학습 필요, 사양 관리 규율 필요&lt;/td&gt;
&lt;td&gt;사양 기반으로 UI/API 회귀를 함께 잡고 싶은 팀&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cypress + cy-api plugin&lt;/td&gt;
&lt;td&gt;Cypress 사용자에게 익숙함&lt;/td&gt;
&lt;td&gt;API 테스트 기능이 제한적이고 plugin 의존&lt;/td&gt;
&lt;td&gt;기존 Cypress 코드베이스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pact&lt;/td&gt;
&lt;td&gt;consumer-driven contract에 강함&lt;/td&gt;
&lt;td&gt;학습 곡선, broker 인프라, UI 테스트와 직접 연결되지 않음&lt;/td&gt;
&lt;td&gt;내부 API consumer가 많은 microservice 조직&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SOAP 또는 ReadyAPI 기반 테스트에서 전환한다면 &lt;a href="http://apidog.com/blog/soapui-groovy-script-alternatives-apidog?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;SoapUI Groovy 스크립트 대안&lt;/a&gt;, &lt;a href="http://apidog.com/blog/readyapi-alternatives-2026?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;ReadyAPI 대안&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;p&gt;로컬 우선 API 호출 도구를 찾는다면 &lt;a href="http://apidog.com/blog/best-rest-client-vscode-extensions-2026?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;REST 클라이언트 VSCode 확장&lt;/a&gt;도 볼 만합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  실제 사용 사례
&lt;/h2&gt;

&lt;h3&gt;
  
  
  전자상거래 결제
&lt;/h3&gt;

&lt;p&gt;소매팀은 Playwright로 장바구니에서 결제 완료까지의 UI 플로우를 검증합니다.&lt;/p&gt;

&lt;p&gt;동시에 Apidog에서는 다음 API 체인을 검증합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /payment-intents
POST /fraud-checks
POST /inventory/reservations
POST /orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;결제 게이트웨이가 응답 필드를 &lt;code&gt;error_code&lt;/code&gt;에서 &lt;code&gt;errorCode&lt;/code&gt;로 변경했을 때 Apidog schema 검증이 이를 빠르게 감지합니다. Playwright만 있었다면 단순히 “결제 실패 화면이 보인다”는 수준에서 멈췄을 가능성이 높습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  차트가 있는 SaaS 대시보드
&lt;/h3&gt;

&lt;p&gt;B2B 분석 제품은 Playwright로 차트 렌더링을 확인합니다.&lt;/p&gt;

&lt;p&gt;Apidog에서는 집계 API가 다음 값을 올바르게 반환하는지 검증합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;합계&lt;/li&gt;
&lt;li&gt;평균&lt;/li&gt;
&lt;li&gt;백분위수&lt;/li&gt;
&lt;li&gt;시간 구간별 series&lt;/li&gt;
&lt;li&gt;필터별 segment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;차트는 정상적으로 렌더링되어도 API가 이상치(outlier)를 누락하면 데이터는 잘못됩니다. 이 문제는 API 계층에서 잡아야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  webhook 기반 workflow
&lt;/h3&gt;

&lt;p&gt;핀테크 팀은 Playwright로 사용자 포털을 검증하고, Apidog로 webhook 전달과 retry 로직을 검증합니다.&lt;/p&gt;

&lt;p&gt;검증 항목 예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;중복 webhook ID 거부&lt;/li&gt;
&lt;li&gt;signature 유효성&lt;/li&gt;
&lt;li&gt;idempotency key 처리&lt;/li&gt;
&lt;li&gt;retry 횟수&lt;/li&gt;
&lt;li&gt;eventual consistency 시간이 30초 미만인지&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;Playwright는 브라우저 플로우 테스트에 적합합니다. 하지만 깊은 API 계약 검증을 모두 담당하기에는 한계가 있습니다.&lt;/p&gt;

&lt;p&gt;Playwright와 Apidog를 함께 사용하면 다음 구조를 만들 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;단일 &lt;code&gt;openapi.yaml&lt;/code&gt;을 계약으로 사용&lt;/li&gt;
&lt;li&gt;Playwright와 Apidog가 같은 fixture 공유&lt;/li&gt;
&lt;li&gt;UI 테스트와 API schema 검증 분리&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;page.route&lt;/code&gt;로 UI 격리&lt;/li&gt;
&lt;li&gt;Apidog scenario로 연쇄 API workflow 검증&lt;/li&gt;
&lt;li&gt;mock server로 오프라인 개발 지원&lt;/li&gt;
&lt;li&gt;CI에서 UI/API 회귀를 동시에 차단&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;처음부터 모든 API를 옮길 필요는 없습니다.&lt;/p&gt;

&lt;p&gt;가장 중요한 여정 하나를 고르십시오.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;회원가입&lt;/li&gt;
&lt;li&gt;로그인&lt;/li&gt;
&lt;li&gt;결제&lt;/li&gt;
&lt;li&gt;주문 생성&lt;/li&gt;
&lt;li&gt;환불&lt;/li&gt;
&lt;li&gt;webhook 처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;그 여정에 대해 다음만 먼저 구성하면 됩니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;openapi.yaml&lt;/code&gt; 정리&lt;/li&gt;
&lt;li&gt;Playwright fixture 작성&lt;/li&gt;
&lt;li&gt;핵심 API smoke assertion 추가&lt;/li&gt;
&lt;li&gt;Apidog scenario 생성&lt;/li&gt;
&lt;li&gt;GitHub Actions에서 두 스위트 실행&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;그다음 endpoint와 scenario를 점진적으로 확장하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Apidog 없이 Playwright 테스트에서 API를 검증할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;네. Playwright의 &lt;code&gt;request&lt;/code&gt; fixture와 &lt;code&gt;expect&lt;/code&gt;를 사용하면 됩니다.&lt;/p&gt;

&lt;p&gt;다만 다음이 필요해지면 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt; 같은 전용 도구가 더 적합합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;전체 schema validation&lt;/li&gt;
&lt;li&gt;연쇄 API scenario&lt;/li&gt;
&lt;li&gt;mock server&lt;/li&gt;
&lt;li&gt;오류 경로 테스트&lt;/li&gt;
&lt;li&gt;OpenAPI 기반 계약 검증&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;장단점 비교는 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  이 설정을 사용하려면 OpenAPI 사양이 필요한가요?
&lt;/h3&gt;

&lt;p&gt;필수는 아니지만, 권장됩니다.&lt;/p&gt;

&lt;p&gt;OpenAPI 사양이 없으면 Playwright와 Apidog가 같은 계약을 공유하지 못합니다. 그러면 request example, response schema, fixture를 두 곳에서 따로 관리해야 합니다.&lt;/p&gt;

&lt;p&gt;기존 API에서 OpenAPI 초안을 생성한 뒤 점진적으로 정리하는 방식으로 시작할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  인증은 어떻게 처리하나요?
&lt;/h3&gt;

&lt;p&gt;테스트 시작 시 인증 API에서 새 token을 발급받으십시오.&lt;/p&gt;

&lt;p&gt;Playwright에서는 fixture로 노출합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;authToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;apiRequest&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;apiRequest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/auth/token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;qa@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QA_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apidog에서는 같은 값을 environment variable에 저장해 다음 요청에서 사용합니다.&lt;/p&gt;

&lt;p&gt;오래된 token을 fixture에 하드코딩하지 마십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apidog 시나리오가 Playwright를 완전히 대체할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;아닙니다.&lt;/p&gt;

&lt;p&gt;Apidog는 API workflow 검증에 적합하지만 브라우저를 렌더링하지 않습니다. 다음 검증에는 Playwright가 필요합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;클릭 플로우&lt;/li&gt;
&lt;li&gt;화면에 보이는 텍스트&lt;/li&gt;
&lt;li&gt;레이아웃&lt;/li&gt;
&lt;li&gt;접근성 흐름&lt;/li&gt;
&lt;li&gt;브라우저 이벤트&lt;/li&gt;
&lt;li&gt;실제 사용자 상호작용&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;두 도구는 대체 관계가 아니라 보완 관계입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  안정적인 staging backend가 없으면 어떻게 하나요?
&lt;/h3&gt;

&lt;p&gt;Apidog mock server를 사용하십시오.&lt;/p&gt;

&lt;p&gt;OpenAPI 사양에 정의된 example response를 기반으로 mock server를 실행하고, Playwright를 해당 mock server로 연결합니다.&lt;/p&gt;

&lt;p&gt;이렇게 하면 백엔드가 불안정해도 UI 개발과 테스트를 계속할 수 있습니다. staging이 안정화되면 같은 테스트를 실제 backend에 대해 다시 실행합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI를 빠르게 유지하려면 어떻게 해야 하나요?
&lt;/h3&gt;

&lt;p&gt;테스트를 우선순위별로 나누십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;push: smoke&lt;/li&gt;
&lt;li&gt;PR: regression&lt;/li&gt;
&lt;li&gt;nightly: full suite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Playwright는 worker를 늘려 병렬 실행합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apidog scenario는 CLI의 parallel 옵션을 사용해 병렬화합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI를 위해 Apidog 유료 플랜이 필요한가요?
&lt;/h3&gt;

&lt;p&gt;Apidog CLI는 로컬과 CI에서 scenario 실행에 사용할 수 있습니다. 다만 팀 규모, 협업 기능, 현재 가격 정책에 따라 플랜 조건은 달라질 수 있으므로 도입 전 최신 가격 정책을 확인하십시오.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OpenAI 데이브레이크 vs 클로드 미토스: 비교 분석</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Tue, 12 May 2026 06:08:35 +0000</pubDate>
      <link>https://forem.com/rihpig/openai-deibeureikeu-vs-keulrodeu-mitoseu-bigyo-bunseog-31b4</link>
      <guid>https://forem.com/rihpig/openai-deibeureikeu-vs-keulrodeu-mitoseu-bigyo-bunseog-31b4</guid>
      <description>&lt;p&gt;세계에서 가장 영향력 있는 두 AI 연구소가 5주 간격으로 사이버 보안 플랫폼을 출시했습니다. Anthropic은 2026년 4월 7일 Claude Mythos를 발표했고, OpenAI는 2026년 5월 11일 Daybreak을 공개했습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;오늘 Apidog을 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;겉보기에는 비슷합니다. 둘 다 최첨단 모델로 취약점을 찾고, 익스플로잇을 생성하며, 방어자가 더 빠르게 대응하도록 돕습니다. 하지만 실제로는 접근 방식이 크게 다릅니다. 사용할 수 있는 사람, 접근 권한을 부여하는 방식, 모델이 수행할 수 있는 작업, 위험한 기능을 배포하는 철학이 모두 다릅니다.&lt;/p&gt;

&lt;p&gt;이 글에서는 Claude Mythos와 OpenAI Daybreak을 실무 관점에서 비교하고, 보안 팀이 어떤 선택을 해야 하는지 정리합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  간단한 결론
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://apidog.com/blog/claude-mythos/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;&lt;strong&gt;Claude Mythos&lt;/strong&gt;&lt;/a&gt;는 Anthropic의 최첨단 연구 모델입니다. Project Glasswing이라는 초청 전용 컨소시엄을 통해서만 접근할 수 있도록 제한되어 있습니다. 공개된 벤치마크 기준으로는 더 강력한 사이버 모델입니다. 하지만 대부분의 팀은 사용할 수 없습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-54.png" alt="" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://openai.com/daybreak/" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenAI Daybreak&lt;/strong&gt;&lt;/a&gt;은 GPT-5.5 기반 플랫폼입니다. 세 가지 접근 계층, Codex Security 플러그인, 파트너 생태계를 포함합니다. 원시 공격 능력은 Mythos보다 덜 공개되어 있지만, 실제 배포와 워크플로우 통합 측면에서는 더 현실적입니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-55.png" alt="" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;정리하면 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;순수한 취약점 발견 및 익스플로잇 성능이 중요하다면:&lt;/strong&gt; Mythos가 이론상 우세합니다.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;이번 분기에 팀에 실제로 배포해야 한다면:&lt;/strong&gt; Daybreak이 실전 선택지입니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Claude Mythos vs OpenAI Daybreak 비교
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기능&lt;/th&gt;
&lt;th&gt;Claude Mythos&lt;/th&gt;
&lt;th&gt;OpenAI Daybreak&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;출시일&lt;/td&gt;
&lt;td&gt;2026년 4월 7일&lt;/td&gt;
&lt;td&gt;2026년 5월 11일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;벤더&lt;/td&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;유형&lt;/td&gt;
&lt;td&gt;최첨단 연구 모델&lt;/td&gt;
&lt;td&gt;플랫폼: 복수 모델 + Codex Security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공개 가용성&lt;/td&gt;
&lt;td&gt;없음, Project Glasswing 전용&lt;/td&gt;
&lt;td&gt;있음, 검증 계층을 통해 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;계층&lt;/td&gt;
&lt;td&gt;단일 연구 모델&lt;/td&gt;
&lt;td&gt;GPT-5.5 / 사이버 보안을 위한 신뢰할 수 있는 접근 / GPT-5.5-Cyber&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;코드 플랫폼&lt;/td&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Codex Security 플러그인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTF 성공률&lt;/td&gt;
&lt;td&gt;전문가 수준 CTF에서 73%&lt;/td&gt;
&lt;td&gt;공개되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제로데이 발견&lt;/td&gt;
&lt;td&gt;사전 출시 테스트에서 수천 건&lt;/td&gt;
&lt;td&gt;기능 주장, 공개 수치 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;익스플로잇 재현&lt;/td&gt;
&lt;td&gt;첫 시도에 83% 성공&lt;/td&gt;
&lt;td&gt;공개되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파트너&lt;/td&gt;
&lt;td&gt;AWS, Apple, Microsoft, Google, CrowdStrike, Palo Alto 포함 약 40개 조직&lt;/td&gt;
&lt;td&gt;Cisco, Cloudflare, Snyk, Tenable, Fortinet, Zscaler 포함 20개 이상 벤더&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;접근 모델&lt;/td&gt;
&lt;td&gt;Project Glasswing을 통한 초청 전용&lt;/td&gt;
&lt;td&gt;상위 계층에 대한 신청 + 심사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주요 사용 사례&lt;/td&gt;
&lt;td&gt;핵심 인프라 취약점 연구&lt;/td&gt;
&lt;td&gt;지속적인 보안 개발 워크플로우&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;가격&lt;/td&gt;
&lt;td&gt;비공개, 컨소시엄 기반&lt;/td&gt;
&lt;td&gt;접근 가능한 계층에 대한 OpenAI 플랫폼 가격 책정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Claude Mythos란 무엇인가
&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://apidog.com/blog/claude-mythos/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Claude Mythos Preview&lt;/a&gt;는 공개 &lt;a href="https://www.anthropic.com/news/claude-4" rel="noopener noreferrer"&gt;Claude 4 제품군&lt;/a&gt;을 능가하는 Anthropic의 최첨단 모델입니다. 범용 모델이지만, 장기 추론과 소프트웨어 보안에 특히 초점을 둡니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-56.png" alt="" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;공개된 핵심 수치는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;이전 모델이 해결하지 못한 전문가 수준 CTF 챌린지에서 &lt;strong&gt;73% 성공&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;사전 출시 테스트에서 주요 운영 체제와 브라우저의 &lt;strong&gt;수천 개 제로데이 취약점 식별&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;취약점 재현 후 첫 시도에 &lt;strong&gt;83% 확률로 작동하는 익스플로잇 생성&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 정도의 기능은 방어자에게 강력하지만, 동시에 위험합니다. 그래서 Anthropic은 Mythos를 공개 제품으로 출시하지 않았습니다. 대신 &lt;strong&gt;Project Glasswing&lt;/strong&gt;을 만들었습니다.&lt;/p&gt;

&lt;p&gt;Project Glasswing은 공격자가 유사한 기능을 사용하기 전에, 신뢰할 수 있는 조직들이 Mythos를 이용해 중요한 소프트웨어를 강화하도록 설계된 비공개 컨소시엄입니다.&lt;/p&gt;

&lt;p&gt;현재 파트너에는 AWS, Apple, Microsoft, Google, CrowdStrike, Palo Alto Networks 등이 포함되며, 약 40개 조직이 초청을 통해 참여했습니다. 컨소시엄에 속해 있지 않다면 Mythos를 직접 사용할 수 없습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI Daybreak이란 무엇인가
&lt;/h2&gt;

&lt;p&gt;Daybreak은 단일 모델이 아니라 플랫폼입니다. 세 가지 기능 계층, Codex 기반 에이전트 하네스, 파트너 생태계를 결합합니다.&lt;/p&gt;

&lt;p&gt;Daybreak의 계층은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GPT-5.5&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
모든 OpenAI 사용자에게 제공되는 범용 모델입니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;사이버 보안을 위한 신뢰할 수 있는 접근 권한을 가진 GPT-5.5&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
검증된 방어자는 악성 코드 분석, 리버스 엔지니어링 등 합법적인 보안 작업에서 거부율이 낮아집니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GPT-5.5-Cyber&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
제한된 프리뷰입니다. 승인된 환경에서 레드 팀 및 침투 테스트에 사용됩니다.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;운영 계층은 &lt;strong&gt;Codex Security&lt;/strong&gt;입니다. Codex Security는 다음 흐름으로 작동합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;리포지토리에 연결&lt;/li&gt;
&lt;li&gt;코드 기반 위협 모델 생성&lt;/li&gt;
&lt;li&gt;취약점 지속 모니터링&lt;/li&gt;
&lt;li&gt;기존 보안 도구로 발견 사항 전달&lt;/li&gt;
&lt;li&gt;패치 생성 및 검증&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;전체 플랫폼 분석은 &lt;a href="http://apidog.com/blog/what-is-openai-daybreak?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;OpenAI Daybreak이란 무엇인가&lt;/a&gt;에서 다뤘습니다.&lt;/p&gt;

&lt;p&gt;핵심은 간단합니다. Daybreak은 수동으로 질의하는 연구 모델이 아니라, 보안 팀의 일상 워크플로우에 AI 기능을 넣기 위한 플랫폼입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  기능: Mythos가 앞서는 부분
&lt;/h2&gt;

&lt;p&gt;순수한 벤치마크 기준으로는 Mythos가 앞섭니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  취약점 발견
&lt;/h3&gt;

&lt;p&gt;Mythos는 사전 출시 테스트에서 운영 체제와 브라우저에서 수천 개의 제로데이를 발견했습니다. OpenAI도 GPT-5.5-Cyber의 유사 기능을 언급했지만, 비교 가능한 공개 수치는 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  익스플로잇 재현
&lt;/h3&gt;

&lt;p&gt;Mythos는 첫 시도에 83% 확률로 작동하는 익스플로잇을 생성합니다. 이는 두 가지 상황에서 중요합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;레드 팀이 실제 익스플로잇 가능성을 검증할 때&lt;/li&gt;
&lt;li&gt;방어자가 수정 우선순위를 정하기 전에 취약점의 실질적 위험도를 판단할 때&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  장기 추론
&lt;/h3&gt;

&lt;p&gt;Mythos는 인간 전문가에게 며칠이 걸릴 수 있는 다단계 공격 흐름을 자율적으로 실행할 수 있습니다. 발견, 익스플로잇, 사후 익스플로잇 단계를 컨텍스트 손실 없이 연결합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  독립 평가
&lt;/h3&gt;

&lt;p&gt;영국 AI 안전 연구소의 &lt;a href="https://www.aisi.gov.uk/blog/our-evaluation-of-claude-mythos-previews-cyber-capabilities" rel="noopener noreferrer"&gt;Mythos 사이버 기능 평가&lt;/a&gt;는 이전 세대 대비 성능 향상을 확인했습니다. AISI는 GPT-5.5 사이버 기능 평가도 발표했지만, 주요 공개 수치는 Mythos에 유리합니다.&lt;/p&gt;

&lt;p&gt;질문이 “지금 취약점을 찾고 익스플로잇하는 데 어떤 모델이 더 강한가”라면 답은 Mythos입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  가용성 및 워크플로우: Daybreak이 앞서는 부분
&lt;/h2&gt;

&lt;p&gt;보안 팀 입장에서 접근할 수 없는 기능은 운영 가치가 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  배포
&lt;/h3&gt;

&lt;p&gt;OpenAI 계정이 있다면 GPT-5.5를 보안 관련 작업에 사용할 수 있습니다. 사이버 보안을 위한 신뢰할 수 있는 접근 권한은 신청이 필요하지만, 검증된 방어자에게 열려 있습니다.&lt;/p&gt;

&lt;p&gt;반면 Mythos는 초청 전용입니다. 공개 신청 경로가 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  워크플로우 통합
&lt;/h3&gt;

&lt;p&gt;Codex Security는 제품화된 워크플로우를 제공합니다.&lt;/p&gt;

&lt;p&gt;실무 흐름은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;리포지토리 연결&lt;/li&gt;
&lt;li&gt;보안 도구와 통합&lt;/li&gt;
&lt;li&gt;취약점 지속 탐지&lt;/li&gt;
&lt;li&gt;패치 제안&lt;/li&gt;
&lt;li&gt;검증 루프 실행&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Project Glasswing을 통한 Mythos 접근은 연구 중심입니다. 파트너는 취약점 연구 프로그램에 모델 접근 권한을 얻지만, 일반 개발팀을 위한 패키지화된 워크플로우는 아닙니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  생태계 폭
&lt;/h3&gt;

&lt;p&gt;Daybreak은 보안 스택 전반의 통합을 제공합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;엔드포인트: CrowdStrike, SentinelOne&lt;/li&gt;
&lt;li&gt;클라우드: Cloudflare, Akamai&lt;/li&gt;
&lt;li&gt;ID: Okta&lt;/li&gt;
&lt;li&gt;코드 보안: Snyk, Semgrep, Socket&lt;/li&gt;
&lt;li&gt;취약점 관리: Qualys, Rapid7, Tenable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Project Glasswing도 강력한 파트너를 보유하고 있지만, 범위는 더 좁고 개발자 도구 통합도 제한적입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  셀프 서비스 경로
&lt;/h3&gt;

&lt;p&gt;Daybreak은 다음과 같은 도입 경로가 있습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OpenAI 계정으로 시작&lt;/li&gt;
&lt;li&gt;필요한 경우 상위 접근 권한 신청&lt;/li&gt;
&lt;li&gt;리포지토리 연결&lt;/li&gt;
&lt;li&gt;기존 보안 도구와 통합&lt;/li&gt;
&lt;li&gt;팀 워크플로우에 배포&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mythos에는 이에 해당하는 셀프 서비스 경로가 없습니다.&lt;/p&gt;

&lt;p&gt;대부분의 보안 및 엔지니어링 팀에게는 이 차이가 결정적입니다. Daybreak은 구매하고 배포할 수 있는 도구입니다. Mythos는 추적해야 할 연구 플랫폼입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  안전 철학: 두 가지 다른 접근
&lt;/h2&gt;

&lt;p&gt;두 플랫폼의 가장 큰 차이는 “위험한 기능을 어떻게 배포할 것인가”에 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anthropic의 접근
&lt;/h3&gt;

&lt;p&gt;Anthropic의 판단은 다음에 가깝습니다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;이 기능은 너무 강력하므로 일반 공개는 위험하다. 공격자가 따라잡기 전에 신뢰할 수 있는 소수 파트너와 비공개로 사용해 핵심 소프트웨어를 강화해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;이 관점에서는 Project Glasswing이 실제 제품이고, Mythos는 그 내부에서 사용되는 모델입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI의 접근
&lt;/h3&gt;

&lt;p&gt;OpenAI의 판단은 다릅니다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;검증과 계층화를 통해 위험한 기능도 안전하게 확장할 수 있다. 일반 사용자는 방어 모델을 사용하고, 검증된 방어자는 낮은 거부율을 얻으며, 민감한 워크플로우는 전용 모델과 강력한 계정 보안 요구 사항으로 제한한다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;이 접근에서는 시스템 전체가 안전장치입니다.&lt;/p&gt;

&lt;p&gt;두 방식 모두 논리가 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic 방식은 공격 기능 확산을 줄입니다.&lt;/li&gt;
&lt;li&gt;OpenAI 방식은 더 많은 방어자에게 기능을 제공합니다.&lt;/li&gt;
&lt;li&gt;Anthropic 방식은 영향 범위가 좁습니다.&lt;/li&gt;
&lt;li&gt;OpenAI 방식은 검증 시스템의 정확성에 의존합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;실무적으로는 둘 다 추적해야 합니다. Glasswing 관련 공개 자료를 모니터링하고, 실제로 사용할 수 있는 도구로 Daybreak을 평가하는 것이 현실적인 접근입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  보안 작업에서 Claude Code는 어떻게 활용할 수 있나
&lt;/h2&gt;

&lt;p&gt;Mythos에 접근할 수 없어도 공개 Claude 4 제품군과 Claude Code를 보안 관련 작업에 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;예를 들어 다음 작업에 활용할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;코드베이스 보안 리뷰&lt;/li&gt;
&lt;li&gt;의심스러운 입력 처리 경로 분석&lt;/li&gt;
&lt;li&gt;취약점 가설 작성&lt;/li&gt;
&lt;li&gt;간단한 PoC 생성&lt;/li&gt;
&lt;li&gt;패치 후보 검토&lt;/li&gt;
&lt;li&gt;테스트 케이스 작성&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mythos가 대규모로 보여주는 기능, 즉 코드 읽기, 익스플로잇 가설 수립, 개념 증명 생성은 공개 Claude 모델에서도 더 작은 범위로 적용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;Claude API 표면에 대해서는 &lt;a href="http://apidog.com/blog/get-free-unlimited-claude-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 무제한 Claude API 접근 얻기&lt;/a&gt;에서 다뤘습니다. 이미 Anthropic 생태계를 사용하는 보안 팀이라면, Glasswing이 열리거나 후속 모델이 공개될 때까지 이 경로가 가장 현실적입니다.&lt;/p&gt;

&lt;p&gt;OpenAI 쪽에서는 사이버 보안을 위한 신뢰할 수 있는 접근을 신청하기 전에 &lt;a href="http://apidog.com/blog/get-free-unlimited-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API&lt;/a&gt;를 보안 관련 작업에 먼저 적용할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  어떤 것을 선택해야 할까
&lt;/h2&gt;

&lt;p&gt;대부분의 팀에게 답은 &lt;strong&gt;Daybreak&lt;/strong&gt;입니다.&lt;/p&gt;

&lt;p&gt;이유는 단순합니다. Daybreak이 항상 더 강력해서가 아니라, 실제로 사용할 수 있는 선택지이기 때문입니다.&lt;/p&gt;

&lt;p&gt;Mythos는 Project Glasswing 뒤에 있습니다. 자신이 Project Glasswing에 속해 있는지 확인해야 한다면, 사실상 속해 있지 않은 것입니다. 컨소시엄은 AWS, Apple, Microsoft, Google, CrowdStrike, Palo Alto Networks 등 약 40개 조직으로 구성되어 있습니다. 공개 신청 양식, 가격 페이지, 대기 목록은 없습니다.&lt;/p&gt;

&lt;p&gt;실제 의사 결정 트리는 다음과 같습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Glasswing 파트너라면
&lt;/h3&gt;

&lt;p&gt;둘 다 사용하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;중요한 시스템의 심층 취약점 연구: Mythos&lt;/li&gt;
&lt;li&gt;더 넓은 엔지니어링 팀의 일상 방어 워크플로우: Daybreak&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;두 도구는 같은 파이프라인의 다른 부분을 담당합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Glasswing 파트너가 아니라면
&lt;/h3&gt;

&lt;p&gt;Daybreak을 평가하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;지금 시작할 수 있습니다.&lt;/li&gt;
&lt;li&gt;기존 보안 도구와 통합할 수 있습니다.&lt;/li&gt;
&lt;li&gt;이번 분기에 팀에 배포할 수 있습니다.&lt;/li&gt;
&lt;li&gt;셀프 서비스 및 검증 기반 접근 경로가 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mythos는 공개 보고서와 AISI 평가를 통해 추적하되, 접근할 수 없는 모델을 중심으로 보안 전략을 설계하지 않는 것이 좋습니다.&lt;/p&gt;

&lt;p&gt;“Mythos vs Daybreak”은 보도 관점의 비교에 가깝습니다. 실무 관점에서는 “Daybreak vs 기다리기”입니다. 이 경우 Daybreak이 이깁니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  API 개발자에게 의미하는 것
&lt;/h2&gt;

&lt;p&gt;대부분의 실제 공격은 API를 노립니다.&lt;/p&gt;

&lt;p&gt;대표적인 공격 표면은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;인증 우회&lt;/li&gt;
&lt;li&gt;잘못된 권한 부여&lt;/li&gt;
&lt;li&gt;요청 경계에서의 인젝션&lt;/li&gt;
&lt;li&gt;서비스 코드의 종속성 취약점&lt;/li&gt;
&lt;li&gt;스키마와 구현 간 불일치&lt;/li&gt;
&lt;li&gt;예상하지 못한 상태 전이&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-57.png" alt="" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mythos와 Daybreak은 API 보안 전용 도구는 아닙니다. 둘 다 API 코드를 분석할 수 있지만, API를 더 넓은 코드베이스의 일부로 취급합니다.&lt;/p&gt;

&lt;p&gt;API 보안을 강화하려면 이 모델들을 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt; 같은 API 디자인 및 테스트 도구와 함께 사용하는 편이 더 실용적입니다.&lt;/p&gt;

&lt;p&gt;실무 조합은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Apidog으로 API 계약 정의&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;스키마, 요청, 응답, 인증 흐름 테스트&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;계약 불일치와 동작 변경 감지&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Daybreak 또는 Mythos로 구현 코드의 논리적 결함 분석&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;테스트와 패치 루프를 CI/CD에 연결&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Apidog은 &lt;a href="http://apidog.com/blog/api-tool-contract-first-development?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;계약 우선 API 개발&lt;/a&gt;과 &lt;a href="http://apidog.com/blog/mcp-server-testing-apidog?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;MCP 서버 테스트&lt;/a&gt;를 통해 계약 불일치, 깨진 스키마, 동작 변경을 감지합니다. Daybreak 또는 Mythos는 구현 내부의 악용 가능한 논리 결함을 탐지합니다.&lt;/p&gt;

&lt;p&gt;함께 사용하면 사양부터 런타임까지 API 공격 표면을 더 넓게 커버할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문 FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Mythos는 대중에게 공개됩니까?
&lt;/h3&gt;

&lt;p&gt;아니요. Mythos는 Project Glasswing 파트너에게만 제한됩니다. Anthropic은 공개 출시 일정을 발표하지 않았습니다. 2026년 5월 기준으로 개인이나 소규모 조직을 위한 신청 절차는 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI에서 사이버 보안을 위한 신뢰할 수 있는 접근 권한을 얻을 수 있습니까?
&lt;/h3&gt;

&lt;p&gt;예, 검증을 통해 가능합니다. OpenAI 플랫폼을 통해 신청해야 합니다. 승인은 합법적인 방어 사용 사례를 기반으로 합니다. GPT-5.5-Cyber에 대한 개별 접근은 2026년 6월 1일까지 고급 계정 보안이 활성화되어 있어야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mythos가 GPT-5.5-Cyber보다 더 유능합니까?
&lt;/h3&gt;

&lt;p&gt;공개된 벤치마크 기준으로는 그렇습니다. Mythos는 전문가 CTF에서 73%를 기록했고, 첫 시도에 83% 확률로 작동하는 익스플로잇을 생성합니다. OpenAI는 GPT-5.5-Cyber에 대한 동등한 수치를 공개하지 않았습니다.&lt;/p&gt;

&lt;p&gt;다만 Daybreak이 성숙하고 OpenAI가 더 강력한 사이버 모델을 출시하면 격차는 줄어들 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mythos와 Daybreak은 경쟁 제품입니까?
&lt;/h3&gt;

&lt;p&gt;시장 포지셔닝에서는 경쟁 제품처럼 보입니다. 하지만 실무적으로는 다릅니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mythos: 비공개 컨소시엄 뒤에 있는 연구 모델&lt;/li&gt;
&lt;li&gt;Daybreak: 워크플로우 통합 기능을 갖춘 셀프 서비스 플랫폼&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;대부분의 보안 팀은 Mythos와 Daybreak 중 하나를 고르는 것이 아니라, Daybreak을 사용할지 또는 공개 Mythos 접근을 기다릴지를 결정하게 됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  두 모델 중 어느 것이 제3자에 대한 공격적 보안에 사용될 수 있습니까?
&lt;/h3&gt;

&lt;p&gt;둘 다 소유하지 않은 시스템에 대한 익스플로잇을 차단하는 안전장치를 갖추고 있습니다.&lt;/p&gt;

&lt;p&gt;GPT-5.5-Cyber는 승인된 환경에서 레드 팀 및 침투 테스트를 지원합니다. Glasswing을 통한 Mythos는 파트너 시스템에 대한 방어적 취약점 발견에 사용됩니다. 접근 계층과 관계없이 제3자에 대한 공격적 사용은 차단됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Microsoft Security Copilot과는 어떻게 다릅니까?
&lt;/h3&gt;

&lt;p&gt;Microsoft Security Copilot은 SOC 운영에 초점을 둡니다.&lt;/p&gt;

&lt;p&gt;예를 들면 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;경고 분류&lt;/li&gt;
&lt;li&gt;사고 대응&lt;/li&gt;
&lt;li&gt;위협 인텔리전스&lt;/li&gt;
&lt;li&gt;보안 운영 자동화&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Daybreak과 Mythos는 코드 수준의 취약점 발견 및 개선에 더 가깝습니다. 즉, 보안 워크플로우의 다른 부분을 담당합니다.&lt;/p&gt;

&lt;p&gt;관련 컨텍스트는 &lt;a href="http://apidog.com/blog/what-is-gpt-realtime-2-and-how-to-use-the-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT Realtime 2란 무엇이며 API를 사용하는 방법&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;Claude Mythos와 OpenAI Daybreak은 같은 분기에 등장한 AI 기반 사이버 보안 플랫폼이지만, 전략은 완전히 다릅니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mythos는 일부 기능이 너무 위험해 광범위하게 공개할 수 없다는 판단을 보여줍니다.&lt;/li&gt;
&lt;li&gt;Daybreak은 검증, 계층화, 워크플로우 통합으로 위험한 기능을 확장할 수 있다는 접근을 보여줍니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;팀 입장에서 실질적인 선택은 간단합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;지금 Daybreak을 평가하세요.&lt;/li&gt;
&lt;li&gt;공개 보고서로 Mythos를 추적하세요.&lt;/li&gt;
&lt;li&gt;접근할 수 없는 모델이 아니라, 배포 가능한 보안 워크플로우를 기준으로 계획하세요.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>OpenAI API 기능별 사용량 추적: 비용 귀속 가이드</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Tue, 12 May 2026 02:38:49 +0000</pubDate>
      <link>https://forem.com/rihpig/openai-api-gineungbyeol-sayongryang-cujeog-biyong-gwisog-gaideu-3h6b</link>
      <guid>https://forem.com/rihpig/openai-api-gineungbyeol-sayongryang-cujeog-biyong-gwisog-gaideu-3h6b</guid>
      <description>&lt;p&gt;OpenAI 인보이스는 지난달 $4,237를 썼다고 알려줍니다. 하지만 그중 $3,100가 폭주한 요약 엔드포인트에서 발생했고, $700는 월 $50를 내는 고객에게서, $437는 아무도 쓰지 않는 기능에서 발생했다는 사실은 알려주지 않습니다. 기본 대시보드만으로는 가격 책정, 용량 계획, 로드맵 결정을 할 수 없습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog 사용해 보기&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;이 글에서는 OpenAI API 비용을 기능, 경로, 고객 단위로 귀속하는 구현 방법을 다룹니다. 핵심은 모든 요청에 메타데이터를 붙이고, 토큰 수와 비용을 구조화된 로그로 남기고, 데이터 웨어하우스에서 집계한 뒤, 키별 예산 상한과 알림을 설정하는 것입니다.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 Apidog는 비용 추적 래퍼를 프로덕션에 배포하기 전에 요청 수준 가시성과 시나리오 테스트를 제공합니다. 태그가 지정된 요청을 재생하고, 로그 형태를 확인하며, 모든 호출이 데이터 웨어하우스가 기대하는 메타데이터를 포함하는지 검증하는 데 사용할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  요약 (TL;DR)
&lt;/h2&gt;

&lt;p&gt;구현해야 할 것은 단순합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;모든 OpenAI API 호출을 하나의 래퍼 함수로 통과시킵니다.&lt;/li&gt;
&lt;li&gt;각 호출에 &lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;, &lt;code&gt;customer_id&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;를 필수로 붙입니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response.usage&lt;/code&gt;에서 토큰 수를 읽고, 쓰기 시점에 &lt;code&gt;cost_usd&lt;/code&gt;를 계산합니다.&lt;/li&gt;
&lt;li&gt;요청당 JSON 로그 한 줄을 남깁니다.&lt;/li&gt;
&lt;li&gt;BigQuery, ClickHouse, Snowflake, Postgres 같은 웨어하우스에서 집계합니다.&lt;/li&gt;
&lt;li&gt;OpenAI 프로젝트 키별 상한과 자체 알림을 함께 둡니다.&lt;/li&gt;
&lt;li&gt;Apidog 시나리오 테스트로 래퍼와 로그 스키마를 검증합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  왜 OpenAI 청구 대시보드만으로는 부족한가
&lt;/h2&gt;

&lt;p&gt;OpenAI 청구 페이지는 일일 지출, 모델별 사용량, 조직 수준 제한을 보여줍니다. 애플리케이션 하나, 고객 하나, 기능 하나만 있다면 충분할 수 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 실제 프로덕션에서는 보통 다음 질문에 답해야 합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;어떤 기능이 비용을 만들었는가?&lt;/li&gt;
&lt;li&gt;어떤 고객이 가장 많은 비용을 발생시키는가?&lt;/li&gt;
&lt;li&gt;어떤 API 경로가 폭주하고 있는가?&lt;/li&gt;
&lt;li&gt;스테이징 비용과 프로덕션 비용은 분리되어 있는가?&lt;/li&gt;
&lt;li&gt;특정 기능의 시간당 지출이 평소보다 급증했는가?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;기본 대시보드는 이 질문에 답하지 못합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  기본 대시보드의 한계
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;컨텍스트 없는 총액&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;대시보드는 어제 GPT-5.5에 $312를 썼다고 알려줄 수 있습니다. 하지만 이것이 고객 한 명의 지원 채팅 호출 때문인지, 잘못된 배치 작업이 전체 지식 기반을 다시 요약했기 때문인지는 알려주지 않습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;기능별 분석 없음&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenAI는 모델과 키 기준 사용량은 보여주지만, 제품 기능, HTTP 경로, 고객 ID, 환경 같은 애플리케이션 수준 차원은 제공하지 않습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;보고 지연&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;사용량 데이터는 수십 분에서 몇 시간 지연될 수 있습니다. 폭주 루프를 대시보드에서 확인했을 때는 이미 비용이 발생한 뒤입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;세밀한 알림 부족&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;조직 단위 예산 상한과 이메일 알림은 가능하지만, “지원 채팅 엔드포인트가 한 시간에 $50를 넘으면 Slack으로 알림” 같은 조건은 직접 만들어야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;고객별 귀속 없음&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;B2B SaaS에서 AI 기능을 제공한다면 고객별 LLM 원가를 알아야 합니다. 그래야 가격 책정, 사용량 제한, 상향 판매, 총마진 계산이 가능합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;프로젝트 키만으로는 부족함&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenAI 프로젝트 키는 프로젝트별 분리를 제공합니다. 하지만 기능별, 고객별, 경로별 귀속은 여전히 애플리케이션에서 직접 처리해야 합니다. &lt;a href="https://platform.openai.com/docs/api-reference/usage" rel="noopener noreferrer"&gt;OpenAI 사용량 API&lt;/a&gt;도 요청 단위가 아니라 집계 데이터를 반환합니다.&lt;/p&gt;

&lt;p&gt;이 문제는 LLM 기능을 운영하는 대부분의 팀에서 반복됩니다. &lt;a href="http://Dev.to" rel="noopener noreferrer"&gt;Dev.to&lt;/a&gt;의 “OpenAI는 당신이 얼마를 썼는지 알려줍니다. 어디에 썼는지는 아닙니다. 그래서 대시보드를 만들었습니다”라는 주제가 공감을 얻은 이유도 여기에 있습니다.&lt;/p&gt;

&lt;p&gt;비용 계산에 필요한 가격 맥락은 &lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격 분석&lt;/a&gt;을 참고하십시오. 개발자 도구 측면의 관련 문제는 &lt;a href="http://apidog.com/blog/github-copilot-usage-billing-api-teams?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;API 팀을 위한 GitHub Copilot 사용량 청구&lt;/a&gt;를 참고할 수 있습니다. OpenAI API 기본 사항은 &lt;a href="https://platform.openai.com/docs/api-reference" rel="noopener noreferrer"&gt;공식 OpenAI API 참조&lt;/a&gt;를 확인하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  비용 귀속 데이터 모델 설계
&lt;/h2&gt;

&lt;p&gt;비용 귀속의 기본 단위는 “OpenAI 요청 1건”입니다.&lt;/p&gt;

&lt;p&gt;모든 요청은 다음 정보를 가진 이벤트로 기록되어야 합니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;열&lt;/th&gt;
&lt;th&gt;유형&lt;/th&gt;
&lt;th&gt;예시&lt;/th&gt;
&lt;th&gt;용도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;request_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;uuid&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7a91...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;멱등성, 중복 제거, 재시도 추적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timestamp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;timestamptz&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2026-05-06T14:23:01Z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;시계열 분석, 이상 감지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feature&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;code&gt;support-chat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;호출을 발생시킨 제품 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;route&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/v1/chat/answer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HTTP 경로 또는 백그라운드 작업 ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;customer_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cust_4291&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;고객별 지출, 총마진 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;environment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;prod&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;개발/운영 비용 분리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;model&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gpt-5.5&lt;/code&gt;, &lt;code&gt;gpt-5.4-mini&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;모델별 가격 적용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prompt_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;15234&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;입력 토큰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;completion_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;812&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;출력 토큰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reasoning_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4500&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;추론 토큰, 출력 요금으로 계산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cached_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;프롬프트 캐시 적중 토큰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;latency_ms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2341&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;비용과 성능 상관관계 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cost_usd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;numeric&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0.045672&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;쓰기 시점 계산 비용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prompt_cache_key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;&lt;code&gt;system-v3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;캐시 적중률 추적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;error_code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;null&lt;/code&gt;, &lt;code&gt;429&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;실패/재시도 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;중요한 원칙은 &lt;strong&gt;쿼리 시점이 아니라 쓰기 시점에 비용을 계산하는 것&lt;/strong&gt;입니다. 가격은 바뀔 수 있습니다. 과거 이벤트는 해당 요청이 발생한 날의 요율로 고정되어야 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  비용 계산 함수 만들기
&lt;/h2&gt;

&lt;p&gt;다음은 GPT-5.5 계열 가격을 기준으로 한 예시입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PRICING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  &lt;span class="c1"&gt;# USD per 1M tokens, as of May 2026
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;30.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5-pro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;30.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;15.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;180.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;15.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.4-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.125&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_cost_usd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cached_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;completion_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reasoning_tokens&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PRICING&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;uncached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt_tokens&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cached_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;input_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uncached&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;
    &lt;span class="n"&gt;cache_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cached_tokens&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;
    &lt;span class="n"&gt;output_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;completion_tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;reasoning_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;rates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cache_cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;output_cost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;주의할 점은 &lt;code&gt;reasoning_tokens&lt;/code&gt;입니다. OpenAI API는 이를 &lt;code&gt;usage.completion_tokens_details.reasoning_tokens&lt;/code&gt;에 반환하지만, 요금은 출력 토큰 기준으로 계산됩니다. 이를 입력으로 처리하면 Thinking 모드 호출 비용을 잘못 계산하게 됩니다.&lt;/p&gt;

&lt;p&gt;전체 가격 맥락은 &lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격 분석&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenAI 클라이언트 래퍼 구현
&lt;/h2&gt;

&lt;p&gt;이제 모든 OpenAI 호출이 하나의 함수만 통과하도록 만듭니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llm.cost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call_with_attribution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;openai_kwargs&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;request_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;openai_kwargs&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown_error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt;

    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;latency_ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;started&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="n"&gt;prompt_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;completion_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;cached_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_tokens_details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;reasoning_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion_tokens_details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;cost_usd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;compute_cost_usd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;cached_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;completion_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;reasoning_tokens&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai.request&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;feature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;environment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completion_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;completion_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reasoning_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;reasoning_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cached_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cached_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;latency_ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost_usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cost_usd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error_code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 래퍼가 비용 귀속의 단일 진입점입니다.&lt;/p&gt;

&lt;p&gt;코드베이스에서 다음 패턴을 검색해 모두 교체합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OpenAI(
client.chat.completions.create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;모든 호출은 다음처럼 명시적으로 태그를 전달해야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;call_with_attribution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;support-chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/v1/chat/answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prod&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-5.5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;, &lt;code&gt;customer_id&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;는 기본값을 두지 않는 것이 좋습니다. 누락되면 &lt;code&gt;"unknown"&lt;/code&gt;으로 기록하지 말고 오류를 발생시키십시오. &lt;code&gt;"unknown"&lt;/code&gt;은 나중에 귀속 블랙홀이 됩니다.&lt;/p&gt;

&lt;p&gt;Node.js에서도 구조는 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI SDK를 직접 호출하지 않습니다.&lt;/li&gt;
&lt;li&gt;래퍼 함수가 메타데이터를 받습니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response.usage&lt;/code&gt;를 읽습니다.&lt;/li&gt;
&lt;li&gt;비용을 계산합니다.&lt;/li&gt;
&lt;li&gt;JSON 이벤트를 stdout, Kafka, NATS, Pub/Sub, OTLP 중 하나로 보냅니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  구조화 로그를 데이터 웨어하우스로 보내기
&lt;/h2&gt;

&lt;p&gt;요청당 JSON 한 줄이면 충분합니다.&lt;/p&gt;

&lt;p&gt;예시 로그:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openai.request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7a91d2d3-1d7f-4a21-91b5-f29b7f12a111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"feature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support-chat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/v1/chat/answer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cust_4291"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"environment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-5.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"completion_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;812&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2341&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cost_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.045672&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;기존 로그 파이프라인을 재사용하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vector&lt;/li&gt;
&lt;li&gt;Fluent Bit&lt;/li&gt;
&lt;li&gt;Logstash&lt;/li&gt;
&lt;li&gt;OpenTelemetry Collector&lt;/li&gt;
&lt;li&gt;Cloud Logging&lt;/li&gt;
&lt;li&gt;Datadog&lt;/li&gt;
&lt;li&gt;Kafka 기반 이벤트 파이프라인&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;대상은 BigQuery, ClickHouse, Snowflake, Postgres 등 무엇이든 됩니다. 별도 서비스가 꼭 필요한 것은 아닙니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  기능별 비용 집계 쿼리
&lt;/h2&gt;

&lt;p&gt;이벤트가 웨어하우스에 들어오면, 대시보드는 SQL 문제로 바뀝니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;DATE_TRUNC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;DAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="k"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cost_usd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;spend_usd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt_tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;completion_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latency_ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;avg_latency_ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cached_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="k"&gt;NULLIF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;cache_hit_rate&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;openai_events&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'prod'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMP_SUB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="k"&gt;DAY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;day&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="k"&gt;day&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spend_usd&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;운영 대시보드에는 최소한 다음 세 가지 뷰를 만드십시오.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;시간대별 기능별 지출&lt;/li&gt;
&lt;li&gt;시간대별 고객별 지출&lt;/li&gt;
&lt;li&gt;어제 지출 기준 상위 20개 경로&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Grafana, Metabase, Looker, Superset 등 어떤 BI 도구든 사용할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog로 배포 전 검증하기
&lt;/h2&gt;

&lt;p&gt;많은 팀이 래퍼는 만들지만 검증을 건너뜁니다. 그러면 스키마가 조용히 틀어지고, 대시보드는 그럴듯한 거짓말을 보여줍니다.&lt;/p&gt;

&lt;p&gt;Apidog로 다음 시나리오를 만드십시오.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;알려진 &lt;code&gt;customer_id&lt;/code&gt;, &lt;code&gt;feature&lt;/code&gt;를 사용해 AI 엔드포인트에 요청을 보냅니다.&lt;/li&gt;
&lt;li&gt;응답과 로그 방출을 함께 확인합니다.&lt;/li&gt;
&lt;li&gt;로그 페이로드에 다음 필드가 있는지 검증합니다.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;feature&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;route&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;customer_id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;environment&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;model&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompt_tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;completion_tokens&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cost_usd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cost_usd &amp;gt; 0&lt;/code&gt;인지 확인합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;prompt_tokens &amp;gt; 0&lt;/code&gt;인지 확인합니다.&lt;/li&gt;
&lt;li&gt;Apidog 환경 변수를 사용해 staging/prod에서 같은 시나리오를 실행합니다.&lt;/li&gt;
&lt;li&gt;동일 요청을 재생하여 재시도 시 비용이 중복 집계되지 않는지 확인합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;재시도 처리에서는 &lt;code&gt;request_id&lt;/code&gt;가 중요합니다. 애플리케이션 레벨에서 같은 작업을 재시도한다면 같은 &lt;code&gt;request_id&lt;/code&gt;를 전달하고, 웨어하우스 적재 또는 집계 단계에서 중복 제거해야 합니다.&lt;/p&gt;

&lt;p&gt;API 테스트 접근 방식은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;를 참고하십시오. 계약 기반 API 개발과 함께 운영하려면 &lt;a href="http://apidog.com/blog/api-tool-contract-first-development?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;계약 우선 API 개발&lt;/a&gt;도 참고할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  프로젝트 키와 예산 상한 설정
&lt;/h2&gt;

&lt;p&gt;애플리케이션 수준 귀속과 별개로 OpenAI 프로젝트 키는 방어선으로 사용하십시오.&lt;/p&gt;

&lt;p&gt;예시:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prod-support-chat&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prod-summarization&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prod-agent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;staging-all&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dev-all&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;각 키에 하드 상한을 설정하면 하나의 기능이 폭주해도 조직 전체 예산을 소진하지 않습니다.&lt;/p&gt;

&lt;p&gt;그 위에 자체 알림을 둡니다.&lt;/p&gt;

&lt;p&gt;예를 들어 10분마다 다음 로직을 실행합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;기능별 최근 1시간 지출 계산&lt;/li&gt;
&lt;li&gt;같은 기능의 7일 이동 평균 시간당 지출 계산&lt;/li&gt;
&lt;li&gt;현재 지출이 평균의 3배를 넘으면 Slack/PagerDuty/Opsgenie 알림&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;트리거는 OpenAI 대시보드가 아니라 데이터 웨어하우스에서 나와야 합니다. 그래야 지연을 줄이고 원하는 차원으로 감지할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  고급 최적화 패턴
&lt;/h2&gt;

&lt;h3&gt;
  
  
  프롬프트 캐싱
&lt;/h3&gt;

&lt;p&gt;GPT-5.5는 캐시된 토큰에 대해 입력 요금의 50%를 청구합니다.&lt;/p&gt;

&lt;p&gt;캐시 적중률을 높이려면 다음처럼 프롬프트를 구성하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;안정적인 시스템 프롬프트를 앞에 둡니다.&lt;/li&gt;
&lt;li&gt;자주 바뀌는 사용자 입력은 뒤에 둡니다.&lt;/li&gt;
&lt;li&gt;버전이 바뀌는 프롬프트에는 &lt;code&gt;prompt_cache_key&lt;/code&gt;를 명시적으로 기록합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;대시보드에서는 기능별 &lt;code&gt;cache_hit_rate&lt;/code&gt;를 추적하십시오. 프롬프트 변경 후 캐시 적중률이 떨어지면 입력 비용이 조용히 증가할 수 있습니다.&lt;/p&gt;

&lt;p&gt;공식 규칙은 &lt;a href="https://platform.openai.com/docs/guides/prompt-caching" rel="noopener noreferrer"&gt;OpenAI 프롬프트 캐싱 문서&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  배치 API 사용
&lt;/h3&gt;

&lt;p&gt;동기 응답이 필요 없는 작업은 배치 API로 보내십시오.&lt;/p&gt;

&lt;p&gt;대표 예시:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;야간 요약&lt;/li&gt;
&lt;li&gt;평가 실행&lt;/li&gt;
&lt;li&gt;임베딩 백필&lt;/li&gt;
&lt;li&gt;문서 재처리&lt;/li&gt;
&lt;li&gt;대량 분류 작업&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;배치 작업에도 동일한 귀속 스키마를 적용하십시오. &lt;code&gt;batch_job_id&lt;/code&gt;를 추가하면 원래 워크로드와 연결할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  추론 노력 튜닝
&lt;/h3&gt;

&lt;p&gt;GPT-5.5 Thinking 계열은 &lt;code&gt;reasoning.effort&lt;/code&gt;에 따라 출력 토큰이 늘어납니다.&lt;/p&gt;

&lt;p&gt;각 기능에 대해 다음을 점검하십시오.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;medium&lt;/code&gt;이 꼭 필요한가?&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;low&lt;/code&gt;로 품질 기준을 통과하는가?&lt;/li&gt;
&lt;li&gt;노력 수준별 비용 대비 품질은 어떤가?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A/B 테스트를 통해 품질과 비용을 함께 기록하고, 품질이 유지된다면 더 낮은 옵션을 배포하십시오. 관련 구현 맥락은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API 사용 방법&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  컨텍스트 창 관리
&lt;/h3&gt;

&lt;p&gt;긴 프롬프트는 비용을 빠르게 증가시킵니다.&lt;/p&gt;

&lt;p&gt;RAG를 사용한다면 전체 문서를 컨텍스트 창에 넣지 말고 검색 예산을 제한하십시오.&lt;/p&gt;

&lt;p&gt;기능별로 다음 지표를 추적합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;avg_prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;PERCENTILE_CONT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;p95_prompt_tokens&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;openai_events&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'prod'&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;avg_prompt_tokens&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;기능 변경이 없는데 &lt;code&gt;prompt_tokens&lt;/code&gt;가 매주 증가한다면 프롬프트가 비대해지고 있는 것입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT-5.5 272K 토큰 절벽 감지
&lt;/h3&gt;

&lt;p&gt;GPT-5.5는 272K 토큰을 초과하는 요청에 대해 입력 2배, 출력 1.5배 승수가 적용됩니다.&lt;/p&gt;

&lt;p&gt;래퍼에 다음 가드를 추가하십시오.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prompt_tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;250_000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai.large_context_warning&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;feature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;route&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt_tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;가격 세부 정보는 &lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격 책정 게시물&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  고객별 지출 상한
&lt;/h3&gt;

&lt;p&gt;B2B SaaS에서는 고객별 AI 사용량 제한이 필요합니다.&lt;/p&gt;

&lt;p&gt;간단한 패턴은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;고객별 월 누적 &lt;code&gt;cost_usd&lt;/code&gt;를 계산합니다.&lt;/li&gt;
&lt;li&gt;각 OpenAI 호출 전에 고객의 사용량을 확인합니다.&lt;/li&gt;
&lt;li&gt;한도를 넘으면 OpenAI를 호출하지 않고 429를 반환합니다.&lt;/li&gt;
&lt;li&gt;응답에는 “월별 AI 할당량 초과” 메시지와 업그레이드 CTA를 포함합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;예시:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ensure_customer_budget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;spend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_month_to_date_llm_spend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_customer_llm_limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;spend&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;AiQuotaExceeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Monthly AI quota exceeded for customer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이렇게 해야 AI 기능이 마진 리스크가 아니라 가격 책정 가능한 제품 기능이 됩니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  피해야 할 실수
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;추론 토큰을 입력 토큰으로 계산하는 것&lt;/li&gt;
&lt;li&gt;실시간 알림을 OpenAI 대시보드에 의존하는 것&lt;/li&gt;
&lt;li&gt;SDK 내부에서만 태그를 붙이고 호출 지점의 기능 컨텍스트를 잃는 것&lt;/li&gt;
&lt;li&gt;Cron, 큐 워커, 웹훅 같은 백그라운드 작업에 태그를 붙이지 않는 것&lt;/li&gt;
&lt;li&gt;요청을 샘플링하는 것&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;customer_id&lt;/code&gt;를 &lt;code&gt;null&lt;/code&gt;로 두는 것&lt;/li&gt;
&lt;li&gt;실패한 요청과 성공 후 재시도된 요청을 구분하지 않는 것&lt;/li&gt;
&lt;li&gt;가격표를 코드에 넣고 업데이트 절차를 만들지 않는 것&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;백그라운드 작업에는 다음처럼 합성 route를 사용하십시오.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cron:nightly-summarize
queue:image-caption
webhook:crm-sync
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;customer_id&lt;/code&gt;를 모를 경우에도 &lt;code&gt;null&lt;/code&gt; 대신 &lt;code&gt;internal&lt;/code&gt;, &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;unknown_customer&lt;/code&gt;처럼 명시적인 값을 사용하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  대안 및 도구 비교
&lt;/h2&gt;

&lt;p&gt;직접 구축하지 않아도 됩니다. 선택지는 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;접근 방식&lt;/th&gt;
&lt;th&gt;강점&lt;/th&gt;
&lt;th&gt;비용&lt;/th&gt;
&lt;th&gt;적합한 경우&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI 사용량 API&lt;/td&gt;
&lt;td&gt;기본 제공, 설정 불필요, 정확도 높음&lt;/td&gt;
&lt;td&gt;무료&lt;/td&gt;
&lt;td&gt;프로젝트/기능 수가 적고 고객별 귀속이 필요 없을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Helicone&lt;/td&gt;
&lt;td&gt;드롭인 프록시, 대시보드, 캐싱, 사용자별 비용&lt;/td&gt;
&lt;td&gt;무료 티어, 유료는 월 $20부터&lt;/td&gt;
&lt;td&gt;빠르게 호스팅 대시보드가 필요하고 프록시를 허용할 수 있을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Langfuse&lt;/td&gt;
&lt;td&gt;오픈 소스, 자체 호스팅/클라우드, 추적 + 비용&lt;/td&gt;
&lt;td&gt;자체 호스팅 무료, 클라우드 월 $29부터&lt;/td&gt;
&lt;td&gt;추적과 비용 관찰성을 한 도구에서 원할 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LangSmith&lt;/td&gt;
&lt;td&gt;LangChain 통합, 평가 + 비용&lt;/td&gt;
&lt;td&gt;사용자당 월 $39부터&lt;/td&gt;
&lt;td&gt;이미 LangChain을 사용하고 있을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;맞춤형 데이터 웨어하우스&lt;/td&gt;
&lt;td&gt;완전한 제어, 기존 스택과 통합, 프록시 없음&lt;/td&gt;
&lt;td&gt;엔지니어링 시간&lt;/td&gt;
&lt;td&gt;대규모 워크로드, 맞춤형 차원, 데이터 상주 요건이 있을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;프록시 기반 도구는 빠르게 시작할 수 있지만 경로에 추가 홉이 생깁니다. 자체 호스팅 관찰성 도구는 제어권이 크지만 운영 부담이 있습니다. 맞춤형 웨어하우스 접근은 초기 구현이 필요하지만 대규모 팀이 결국 선택하는 경우가 많습니다.&lt;/p&gt;

&lt;p&gt;프록시 기반 접근은 &lt;a href="https://www.helicone.ai/blog/monitor-and-optimize-llm-costs" rel="noopener noreferrer"&gt;Helicone 팀의 LLM 비용 추적 가이드&lt;/a&gt;를 참고하십시오. 오픈 소스 접근은 &lt;a href="https://langfuse.com/docs/model-usage-and-cost" rel="noopener noreferrer"&gt;Langfuse 비용 추적 문서&lt;/a&gt;를 참고할 수 있습니다.&lt;/p&gt;

&lt;p&gt;플랫폼 규모에서 이 패턴을 운영한다면 &lt;a href="http://apidog.com/blog/api-platform-microservices-architecture?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;마이크로서비스 아키텍처를 위한 API 플랫폼&lt;/a&gt;도 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  실제 사용 사례
&lt;/h2&gt;

&lt;h3&gt;
  
  
  고객별 LLM 지출이 필요한 B2B SaaS
&lt;/h3&gt;

&lt;p&gt;한 영업 인텔리전스 제품은 고객의 요약 요청마다 GPT-5.5를 호출합니다.&lt;/p&gt;

&lt;p&gt;귀속을 도입하기 전에는 월 OpenAI 비용이 $80,000라는 사실만 알 수 있었습니다. 고객별 귀속을 적용한 뒤에는 고객의 12%가 지출의 71%를 만든다는 것을 확인했습니다.&lt;/p&gt;

&lt;p&gt;이후 팀은 다음을 도입했습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;계층별 가격&lt;/li&gt;
&lt;li&gt;하위 플랜의 소프트 할당량&lt;/li&gt;
&lt;li&gt;좌석당 초과 요금&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;그 결과 AI 기능의 총마진이 한 분기 만에 41%에서 73%로 증가했습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  내부 개발자 도구 비용 추적
&lt;/h3&gt;

&lt;p&gt;한 엔지니어링 조직은 모든 개발자에게 개인 GPT-5.5 채팅 도우미를 제공합니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;customer_id&lt;/code&gt;에 개발자 이메일을 기록하자, 세 명의 개발자가 내부 LLM 지출의 50%를 차지한다는 사실이 드러났습니다.&lt;/p&gt;

&lt;p&gt;두 명은 끄는 것을 잊은 자동화 에이전트 루프를 실행 중이었고, 이를 중단해 월 $1,800를 절감했습니다. 나머지 한 명은 실제 업무상 높은 사용량이 필요했고, 데이터는 더 높은 할당량을 정당화하는 근거가 되었습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI 기능 출시 전 비용 예측
&lt;/h3&gt;

&lt;p&gt;제품팀이 새 요약 기능을 출시하려 할 때, 과거 기능별 데이터를 사용해 다음을 예측할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;호출당 평균 입력 토큰&lt;/li&gt;
&lt;li&gt;호출당 평균 출력 토큰&lt;/li&gt;
&lt;li&gt;활성 사용자당 예상 호출 수&lt;/li&gt;
&lt;li&gt;예상 활성 사용자 수&lt;/li&gt;
&lt;li&gt;사용자당 일/월 비용&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;예측 결과가 활성 사용자당 하루 $0.04, 월 $1.20이라면, 가격 책정팀은 기능을 사용자당 월 $5로 책정할 수 있습니다. 단위 경제학이 보이면 재무 승인도 쉬워집니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;OpenAI 청구 대시보드는 “얼마를 썼는가”에는 답합니다. 하지만 제품팀과 엔지니어링팀은 “어디에서, 누가, 왜 썼는가”를 알아야 합니다.&lt;/p&gt;

&lt;p&gt;구현 체크리스트는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;모든 요청에 &lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;route&lt;/code&gt;, &lt;code&gt;customer_id&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;를 필수로 붙입니다.&lt;/li&gt;
&lt;li&gt;OpenAI 호출을 단일 래퍼로 통과시킵니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response.usage&lt;/code&gt;에서 토큰 수를 읽고 쓰기 시점에 비용을 계산합니다.&lt;/li&gt;
&lt;li&gt;요청당 구조화된 JSON 로그를 남깁니다.&lt;/li&gt;
&lt;li&gt;웨어하우스에서 기능별, 고객별, 경로별로 집계합니다.&lt;/li&gt;
&lt;li&gt;프로젝트 키별 하드 상한을 설정합니다.&lt;/li&gt;
&lt;li&gt;웨어하우스 기반 알림을 추가합니다.&lt;/li&gt;
&lt;li&gt;배포 전에 Apidog로 로그 스키마와 시나리오를 검증합니다.&lt;/li&gt;
&lt;li&gt;추론 노력, 프롬프트 크기, 캐시 적중률을 정기적으로 감사합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드&lt;/a&gt;하여 비용 귀속 래퍼를 엔드투엔드로 검증할 수 있습니다. 태그가 지정된 요청으로 AI 엔드포인트를 호출하고, 로그 페이로드 형태를 확인하며, 여러 환경에서 시나리오를 재생해 데이터 웨어하우스가 신뢰할 수 있는 데이터를 받고 있는지 확인하십시오.&lt;/p&gt;

&lt;p&gt;관련 비용 관리 자료는 &lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격 분석&lt;/a&gt;과 &lt;a href="http://apidog.com/blog/github-copilot-usage-billing-api-teams?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;API 팀을 위한 GitHub Copilot 사용량 청구&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문 (FAQ)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  추론 토큰은 입력인가요, 출력인가요?
&lt;/h3&gt;

&lt;p&gt;출력 요율로 청구됩니다. OpenAI API는 &lt;code&gt;usage.completion_tokens_details.reasoning_tokens&lt;/code&gt;에 값을 반환합니다. 비용 계산 시 &lt;code&gt;completion_tokens&lt;/code&gt;에 더하십시오. 자세한 내용은 &lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격 분석&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;response.usage&lt;/code&gt;는 OpenAI 대시보드와 얼마나 일치하나요?
&lt;/h3&gt;

&lt;p&gt;토큰 수는 대시보드와 토큰 단위로 일치합니다. 다만 오래된 가격표로 비용을 계산하면 가격 변경 때문에 차이가 생길 수 있습니다. 모델별 요율은 고정하고, OpenAI가 가격 변경을 발표하면 버전을 업데이트하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI 프로젝트 키만으로 귀속할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;부분적으로만 가능합니다. 프로젝트 키는 프로젝트 단위 귀속을 제공합니다. 기능별, 고객별, 경로별 귀속은 애플리케이션 메타데이터가 필요합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  재시도 요청은 비용이 이중 계산되나요?
&lt;/h3&gt;

&lt;p&gt;모델 실행 전에 실패한 요청은 보통 &lt;code&gt;usage&lt;/code&gt;를 반환하지 않으므로 비용이 기록되지 않습니다. 하지만 성공 후 애플리케이션 레이어에서 재시도하면 중복 기록될 수 있습니다. 같은 작업의 재시도는 동일한 &lt;code&gt;request_id&lt;/code&gt;를 사용하고, 저장 또는 집계 단계에서 중복 제거하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI 사용량 API는 실시간인가요?
&lt;/h3&gt;

&lt;p&gt;아니요. 수십 분 정도 지연될 수 있습니다. 실시간 알림, 킬 스위치, 고객별 제한에는 자체 이벤트 로그와 웨어하우스를 사용하십시오. 월별 대사에는 사용량 API가 적합합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  로그 볼륨을 줄이기 위해 샘플링해도 되나요?
&lt;/h3&gt;

&lt;p&gt;권장하지 않습니다. 요청당 JSON 한 줄이면 데이터 볼륨은 작습니다. 샘플링하면 고객별, 경로별 귀속 정확도가 깨집니다. 모든 요청을 기록하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  다른 LLM 공급자에도 같은 방식을 쓸 수 있나요?
&lt;/h3&gt;

&lt;p&gt;가능합니다. 스키마에 &lt;code&gt;provider&lt;/code&gt; 열을 추가하십시오.&lt;/p&gt;

&lt;p&gt;예:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openai
anthropic
google
deepseek
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;공급자별 래퍼와 가격표만 다르고, 웨어하우스와 대시보드는 재사용할 수 있습니다. 비교 자료로 &lt;a href="http://apidog.com/blog/deepseek-v4-api-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;DeepSeek V4 API 가격&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  임베딩과 이미지 생성에도 적용되나요?
&lt;/h3&gt;

&lt;p&gt;예. 비용 계산식만 다릅니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;임베딩: 입력 토큰 기준 과금&lt;/li&gt;
&lt;li&gt;이미지 생성: 이미지 수, 해상도, 품질 기준 과금&lt;/li&gt;
&lt;li&gt;채팅: 입력/캐시/출력/추론 토큰 기준 과금&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;스키마에 &lt;code&gt;endpoint&lt;/code&gt;를 추가하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chat
embeddings
image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그리고 &lt;code&gt;endpoint&lt;/code&gt;별로 비용 계산 함수를 분기하십시오.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>api</category>
      <category>openai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>MCP 서버 테스트 플레이북: Apidog 활용 수동 및 자동화</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Mon, 11 May 2026 08:54:16 +0000</pubDate>
      <link>https://forem.com/rihpig/mcp-seobeo-teseuteu-peulreibug-apidog-hwalyong-sudong-mic-jadonghwa-2ff5</link>
      <guid>https://forem.com/rihpig/mcp-seobeo-teseuteu-peulreibug-apidog-hwalyong-sudong-mic-jadonghwa-2ff5</guid>
      <description>&lt;p&gt;이번 주 초, “Ableton Live MCP” Show HN 게시물이 118점과 78개의 댓글을 받았습니다. 이제 익숙한 패턴입니다. 누군가 예상치 못한 도구를 위한 MCP(Model Context Protocol) 서버를 만들고, Claude Desktop 사용자가 이를 사용하며, 곧바로 “X용 MCP 서버도 만들 수 있나요?”라는 질문이 이어집니다. MCP는 1년도 채 되지 않아 Anthropic 중심의 실험에서 에이전트 통합을 위한 기본 계층으로 빠르게 확산되었습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog 사용해 보기&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;하지만 MCP 서버가 늘어나는 속도에 비해 테스트 방식은 아직 성숙하지 않았습니다. stdio로 JSON-RPC를 직접 입력하며 디버깅하는 방식은 &lt;code&gt;hello-world&lt;/code&gt; 수준에서는 충분하지만, 도구 12개, 프롬프트 3개, 불안정한 업스트림 API가 붙는 순간 유지보수가 어렵습니다. 이 글은 MCP 서버를 수동으로 검증한 뒤 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;로 테스트를 자동화하는 실전 흐름을 정리합니다. 목표는 MCP 서버도 일반 API처럼 계약, 목(mock), 회귀 테스트 스위트를 갖춘 상태로 배포하는 것입니다.&lt;/p&gt;

&lt;p&gt;에이전트 문서화 관점에서 접근하고 있다면 &lt;a href="http://apidog.com/blog/how-to-write-agents-md-files?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;agents.md 가이드&lt;/a&gt;도 함께 참고하세요. 해당 가이드의 규칙은 MCP 서버 계약을 팀에 전달할 때 유용합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  요약: TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt;는 Anthropic의 Model Context Protocol입니다. stdio 또는 HTTP 위에서 JSON-RPC 2.0으로 동작하며 &lt;code&gt;tools&lt;/code&gt;, &lt;code&gt;resources&lt;/code&gt;, &lt;code&gt;prompts&lt;/code&gt;를 노출합니다.&lt;/li&gt;
&lt;li&gt;MCP 서버 테스트는 &lt;code&gt;initialize&lt;/code&gt;, &lt;code&gt;tools/list&lt;/code&gt;, &lt;code&gt;tools/call&lt;/code&gt;, &lt;code&gt;resources/read&lt;/code&gt;, &lt;code&gt;prompts/get&lt;/code&gt; 응답이 계약을 지키는지 검증하는 일입니다.&lt;/li&gt;
&lt;li&gt;먼저 수동으로 시작하세요. stdio 또는 MCP Inspector로 서버를 실행하고, 응답 형태를 확인한 뒤 클라이언트를 붙이기 전에 shape 버그를 제거합니다.&lt;/li&gt;
&lt;li&gt;이후 자동화하세요. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에 JSON-RPC 요청을 저장하고, 응답 shape와 콘텐츠에 대한 assertion을 추가한 뒤 CI에서 실행합니다.&lt;/li&gt;
&lt;li&gt;MCP 서버가 호출하는 외부 API는 Apidog의 목(mock) 서버로 대체해 테스트를 결정론적으로 만듭니다.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog 다운로드&lt;/a&gt;를 통해 요청 컬렉션, 목 서버, CI 실행을 한 곳에서 관리할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  MCP를 2분 안에 이해하기
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://spec.modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol 사양&lt;/a&gt;은 JSON-RPC 2.0 기반의 작은 와이어 프로토콜을 정의합니다. Claude Desktop, Cursor, 자체 에이전트 같은 클라이언트는 MCP 서버를 시작하고 &lt;code&gt;initialize&lt;/code&gt; 핸드셰이크를 수행한 뒤 필요한 호출을 보냅니다.&lt;/p&gt;

&lt;p&gt;테스트에서 가장 많이 다루는 호출은 다음입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initialize&lt;/code&gt;: 프로토콜 버전 협상 및 기능(capabilities) 공개&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools/list&lt;/code&gt;: 서버가 제공하는 도구 목록과 인수 JSON Schema 반환&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools/call&lt;/code&gt;: 도구 이름과 인수를 전달해 도구 실행&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resources/list&lt;/code&gt;, &lt;code&gt;resources/read&lt;/code&gt;: URI로 접근 가능한 리소스 목록 및 읽기&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;prompts/list&lt;/code&gt;, &lt;code&gt;prompts/get&lt;/code&gt;: 클라이언트가 렌더링할 수 있는 프롬프트 템플릿 제공&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;전송 방식은 보통 두 가지입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;stdio&lt;/strong&gt;: stdin/stdout에서 newline-delimited JSON-RPC 프레임 사용&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP&lt;/strong&gt;: 일반적으로 &lt;code&gt;POST /&lt;/code&gt;와 SSE를 사용해 스트리밍 처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;대부분의 로컬 MCP 서버는 stdio를 사용하고, 원격 서버는 HTTP를 사용합니다.&lt;/p&gt;

&lt;p&gt;테스트가 중요한 이유는 단순합니다. &lt;code&gt;tools/list&lt;/code&gt; 응답의 shape가 깨지면 Claude Desktop, Cursor, MCP 지원 IDE가 모두 영향을 받습니다. MCP 서버는 작아 보여도 실제로는 여러 클라이언트가 의존하는 API 계약입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  무엇을 테스트해야 하나
&lt;/h2&gt;

&lt;p&gt;MCP 서버 테스트 스위트는 최소한 다음 여섯 영역을 포함해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 프로토콜 준수
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;initialize&lt;/code&gt; 응답이 올바른 &lt;code&gt;protocolVersion&lt;/code&gt;을 반환하는지 확인합니다. 서버가 실제로 지원하는 capability만 광고하는지도 검증해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 스키마 정확성
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;tools/list&lt;/code&gt;의 각 도구가 유효한 &lt;code&gt;inputSchema&lt;/code&gt;를 제공해야 합니다.&lt;/p&gt;

&lt;p&gt;확인할 항목:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;이 존재하는가&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt;이 비어 있지 않은가&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;inputSchema&lt;/code&gt;가 유효한 JSON Schema인가&lt;/li&gt;
&lt;li&gt;필수 인수가 &lt;code&gt;required&lt;/code&gt;에 포함되어 있는가&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;빈 description은 Claude의 도구 선택 품질을 떨어뜨릴 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 도구 동작
&lt;/h3&gt;

&lt;p&gt;각 &lt;code&gt;tools/call&lt;/code&gt;이 올바른 콘텐츠 블록을 반환하는지 확인합니다.&lt;/p&gt;

&lt;p&gt;예:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Weather in Tokyo: 22°C"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;도구 실행 실패는 JSON-RPC 오류로 던지기보다 &lt;code&gt;isError: true&lt;/code&gt;를 포함한 정상 결과로 반환해야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isError"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missing required argument: city"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. 리소스 접근
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;resources/list&lt;/code&gt;에서 반환한 URI가 &lt;code&gt;resources/read&lt;/code&gt;로 실제 읽히는지 확인합니다. 페이지네이션이 있다면 첫 페이지만이 아니라 다음 페이지도 검증합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 프롬프트 렌더링
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;prompts/get&lt;/code&gt;이 잘 구성된 &lt;code&gt;messages&lt;/code&gt; 배열을 반환하는지 확인합니다. 인수 치환이 예상 위치에 들어가는지도 테스트해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. 실패 모드
&lt;/h3&gt;

&lt;p&gt;다음 상황을 반드시 포함하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;업스트림 API 장애&lt;/li&gt;
&lt;li&gt;필수 인수 누락&lt;/li&gt;
&lt;li&gt;잘못된 타입 전달&lt;/li&gt;
&lt;li&gt;타임아웃&lt;/li&gt;
&lt;li&gt;빈 응답&lt;/li&gt;
&lt;li&gt;동시 &lt;code&gt;tools/call&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 문제들은 로컬 happy path에서는 잘 드러나지 않고, 실제 사용 중에 발견되는 경우가 많습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  stdio로 수동 테스트하기
&lt;/h2&gt;

&lt;p&gt;가장 단순한 테스트 환경은 다음 세 가지입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;터미널&lt;/li&gt;
&lt;li&gt;MCP 서버 실행 파일&lt;/li&gt;
&lt;li&gt;MCP Inspector 또는 직접 작성한 JSON-RPC 요청&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;아직 서버가 없다면 Python 또는 TypeScript용 &lt;a href="https://modelcontextprotocol.io/quickstart" rel="noopener noreferrer"&gt;공식 MCP SDK 퀵스타트&lt;/a&gt;로 스캐폴드를 만드세요. 날씨 예제처럼 도구 1~2개만 있어도 테스트 흐름을 충분히 연습할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. MCP Inspector로 서버 실행
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @modelcontextprotocol/inspector node your-server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspector는 MCP 서버와 통신하는 로컬 웹 UI를 띄우고 요청/응답을 보여줍니다. 먼저 여기서 다음을 확인하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;서버가 정상적으로 시작되는가&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initialize&lt;/code&gt;가 성공하는가&lt;/li&gt;
&lt;li&gt;capability가 예상대로 표시되는가&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools/list&lt;/code&gt;가 도구 목록을 반환하는가&lt;/li&gt;
&lt;li&gt;각 도구를 호출할 수 있는가&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. 원시 stdio 요청 실행
&lt;/h3&gt;

&lt;p&gt;Inspector에서 기본 동작을 확인했다면, 저장 가능한 JSON-RPC 프레임을 직접 실행합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-04-01","capabilities":{}}}'&lt;/span&gt; | node your-server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;stdout으로 JSON-RPC 응답이 출력됩니다. 이 요청과 응답을 저장해 두세요. 이후 다음 호출도 같은 방식으로 캡처합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tools/list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tools/call&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resources/list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resources/read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompts/list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompts/get&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 과정을 마치면 서버의 와이어 레벨 계약을 나타내는 6~12개의 기준 요청/응답 쌍이 생깁니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 콘텐츠 블록 확인
&lt;/h3&gt;

&lt;p&gt;도구 결과는 보통 다음 형태 중 하나입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;또는 이미지 결과일 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"mimeType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;한 응답에서 여러 타입을 섞는 것도 가능하지만, 클라이언트별 렌더링 차이가 있을 수 있으므로 테스트에 포함해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. 오류 처리 방식 확인
&lt;/h3&gt;

&lt;p&gt;MCP에서 도구 실행 실패는 프로토콜 실패와 구분해야 합니다.&lt;/p&gt;

&lt;p&gt;잘못된 방식:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jsonrpc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-32603&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tool failed"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;도구 내부 실패는 보통 다음처럼 반환하는 것이 안전합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jsonrpc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isError"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Upstream API timeout"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JSON-RPC 오류는 프로토콜 수준 실패를 의미합니다. 일부 클라이언트는 프로토콜 오류가 발생하면 연결을 끊을 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  수동 테스트를 Apidog 자동화로 전환하기
&lt;/h2&gt;

&lt;p&gt;수동 테스트는 초기 디버깅에 좋습니다. 하지만 변경할 때마다 10개 이상의 JSON-RPC 요청을 직접 실행하는 방식은 오래가지 못합니다.&lt;/p&gt;

&lt;p&gt;자동화 흐름은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;수동 테스트에서 확보한 JSON-RPC 요청을 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에 저장합니다.&lt;/li&gt;
&lt;li&gt;각 요청에 assertion을 추가합니다.&lt;/li&gt;
&lt;li&gt;업스트림 API를 목(mock)으로 대체합니다.&lt;/li&gt;
&lt;li&gt;CI에서 전체 스위트를 실행합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. MCP 서버용 Apidog 프로젝트 만들기
&lt;/h2&gt;

&lt;p&gt;Apidog에서 새 프로젝트를 생성합니다. 기본 URL은 MCP 서버의 HTTP 엔드포인트로 설정합니다.&lt;/p&gt;

&lt;p&gt;stdio 서버만 있다면 테스트용 HTTP 래퍼를 하나 둡니다.&lt;/p&gt;

&lt;p&gt;구성 예:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apidog request
  -&amp;gt; HTTP wrapper
    -&amp;gt; stdio MCP server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;HTTP 래퍼는 JSON-RPC 요청을 HTTP로 받아 stdio MCP 서버에 전달하고, 응답을 다시 HTTP 응답으로 반환합니다. 공식 Inspector가 비슷한 역할을 하며, 간단한 Node.js 스크립트로도 구현할 수 있습니다.&lt;/p&gt;

&lt;p&gt;비-HTTP 백엔드를 테스트할 때도 같은 패턴을 사용할 수 있습니다. 관련 내용은 &lt;a href="http://apidog.com/blog/api-testing-without-postman-2026?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;2026년 Postman 없이 API 테스트하기&lt;/a&gt;에서 다룹니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 표준 JSON-RPC 요청 저장하기
&lt;/h2&gt;

&lt;p&gt;Apidog에 다음 요청을 각각 저장합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;initialize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tools/list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tools/call&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resources/list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resources/read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompts/list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prompts/get&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;tools/call&lt;/code&gt; 요청 예시는 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"jsonrpc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tools/call"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"get_weather"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"arguments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tokyo"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;같은 도구라도 케이스별로 요청을 분리하세요.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;정상 입력&lt;/li&gt;
&lt;li&gt;필수 인수 누락&lt;/li&gt;
&lt;li&gt;잘못된 타입&lt;/li&gt;
&lt;li&gt;업스트림 API 오류&lt;/li&gt;
&lt;li&gt;빈 결과&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Assertion 추가하기
&lt;/h2&gt;

&lt;p&gt;자동화의 핵심은 요청 전송이 아니라 응답 검증입니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tools/list&lt;/code&gt;에는 최소한 다음 assertion을 추가합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$.result.tools&lt;/code&gt;가 존재한다&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$.result.tools&lt;/code&gt;가 배열이다&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$.result.tools.length&lt;/code&gt;가 0보다 크다&lt;/li&gt;
&lt;li&gt;각 도구에 &lt;code&gt;name&lt;/code&gt;이 있다&lt;/li&gt;
&lt;li&gt;각 도구에 &lt;code&gt;description&lt;/code&gt;이 있다&lt;/li&gt;
&lt;li&gt;각 도구에 &lt;code&gt;inputSchema&lt;/code&gt;가 있다&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;inputSchema&lt;/code&gt;가 유효한 JSON Schema다&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;정상 &lt;code&gt;tools/call&lt;/code&gt;에는 다음을 검증합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$.result.isError&lt;/code&gt;가 &lt;code&gt;false&lt;/code&gt;이거나 존재하지 않는다&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$.result.content&lt;/code&gt;가 배열이다&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$.result.content[0].type&lt;/code&gt;이 예상 타입이다&lt;/li&gt;
&lt;li&gt;텍스트 또는 리소스 값이 예상 패턴과 일치한다&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;잘못된 입력에 대한 &lt;code&gt;tools/call&lt;/code&gt;에는 다음을 검증합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$.result.isError&lt;/code&gt;가 &lt;code&gt;true&lt;/code&gt;다&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$.result.content[0].text&lt;/code&gt;가 오류 내용을 포함한다&lt;/li&gt;
&lt;li&gt;가능하다면 안정적인 오류 코드 또는 정규식으로 검증한다&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;정확한 오류 문자열 전체에 의존하지 마세요. 메시지는 바뀌기 쉽습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. 업스트림 API 목(mock) 처리하기
&lt;/h2&gt;

&lt;p&gt;대부분의 MCP 서버는 외부 API를 감쌉니다.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;날씨 API&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Linear&lt;/li&gt;
&lt;li&gt;Notion&lt;/li&gt;
&lt;li&gt;내부 데이터베이스&lt;/li&gt;
&lt;li&gt;사내 사고 관리 API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CI가 매번 실제 API를 호출하면 다음 문제가 생깁니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;호출 비용 증가&lt;/li&gt;
&lt;li&gt;rate limit&lt;/li&gt;
&lt;li&gt;네트워크 불안정&lt;/li&gt;
&lt;li&gt;외부 장애로 인한 flaky test&lt;/li&gt;
&lt;li&gt;테스트 데이터 변동&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apidog의 목 서버를 사용하면 각 업스트림 엔드포인트를 고정된 응답으로 대체할 수 있습니다.&lt;/p&gt;

&lt;p&gt;테스트 환경에서는 MCP 서버 설정을 목 URL로 지정합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;UPSTREAM_API_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://mock.example.apidog.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;프로덕션에서는 실제 API URL을 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;UPSTREAM_API_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://api.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 방식은 &lt;a href="http://apidog.com/blog/api-tool-contract-first-development?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;계약 우선 API 개발&lt;/a&gt;에서도 다루는 패턴입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. CI에서 테스트 스위트 실행하기
&lt;/h2&gt;

&lt;p&gt;Apidog 프로젝트는 CLI runner로 실행할 수 있습니다. &lt;code&gt;apidog run&lt;/code&gt;은 저장된 요청을 실행하고 assertion을 평가한 뒤 실패 시 non-zero exit code로 종료됩니다.&lt;/p&gt;

&lt;p&gt;GitHub Actions 예시:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MCP server tests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Start MCP HTTP wrapper&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node test/wrapper.js &amp;amp;&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Apidog suite&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx apidog run --project-id $APIDOG_PROJECT --env ci&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;APIDOG_PROJECT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.APIDOG_PROJECT }}&lt;/span&gt;
          &lt;span class="na"&gt;APIDOG_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.APIDOG_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이제 모든 push와 pull request에서 MCP 계약을 검증할 수 있습니다. 특정 도구의 인수 스키마가 깨지면 배포 전에 실패합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  좋은 MCP 테스트 커버리지의 기준
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 MCP 서버 테스트 계획을 구성할 때는 보통 다음 정도를 기준으로 잡습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capability assertion이 포함된 &lt;code&gt;initialize&lt;/code&gt; 요청 1개&lt;/li&gt;
&lt;li&gt;shape 및 JSON Schema assertion이 포함된 &lt;code&gt;tools/list&lt;/code&gt; 요청 1개&lt;/li&gt;
&lt;li&gt;각 도구별 &lt;code&gt;tools/call&lt;/code&gt; 요청 2~4개

&lt;ul&gt;
&lt;li&gt;정상 경로&lt;/li&gt;
&lt;li&gt;필수 인수 누락&lt;/li&gt;
&lt;li&gt;잘못된 타입&lt;/li&gt;
&lt;li&gt;업스트림 오류&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;리소스 그룹별 &lt;code&gt;resources/list&lt;/code&gt; 1개와 &lt;code&gt;resources/read&lt;/code&gt; 1개&lt;/li&gt;

&lt;li&gt;프롬프트 템플릿별 &lt;code&gt;prompts/list&lt;/code&gt; 1개와 &lt;code&gt;prompts/get&lt;/code&gt; 1개&lt;/li&gt;

&lt;li&gt;HTTP MCP 서버라면 SSE 스트리밍 응답 테스트&lt;/li&gt;

&lt;li&gt;공유 상태가 있다면 동시성 테스트&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;예를 들어 도구 10개, 리소스 3개, 프롬프트 4개가 있는 서버라면 전체 스위트는 대략 50~70개 요청이 됩니다. 목 서버가 준비되어 있으면 로컬에서도 빠르게 반복 실행할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP 서버 테스트에서 자주 하는 실수
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;initialize&lt;/code&gt;를 건너뛰는 것
&lt;/h3&gt;

&lt;p&gt;일부 서버는 &lt;code&gt;initialize&lt;/code&gt; 과정에서 도구 레지스트리를 지연 생성합니다. 이 경우 &lt;code&gt;initialize&lt;/code&gt; 없이 &lt;code&gt;tools/list&lt;/code&gt;를 호출하면 실패할 수 있습니다.&lt;/p&gt;

&lt;p&gt;항상 다음 순서를 기본으로 두세요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initialize -&amp;gt; tools/list -&amp;gt; tools/call
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  오류 문자열 전체에 assertion을 거는 것
&lt;/h3&gt;

&lt;p&gt;오류 메시지는 쉽게 바뀝니다. 다음처럼 전체 문자열에 의존하지 마세요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"City is required and must be a valid string"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;대신 다음을 검증하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isError: true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;안정적인 오류 코드&lt;/li&gt;
&lt;li&gt;핵심 단어를 포함하는 정규식&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  목(mock)이 실제 API와 달라지는 것
&lt;/h3&gt;

&lt;p&gt;목 응답이 실제 API와 다르면 테스트는 통과하지만 통합은 깨질 수 있습니다. 릴리스 주기마다 실제 응답을 기반으로 목 fixture를 갱신하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  스트리밍을 테스트하지 않는 것
&lt;/h3&gt;

&lt;p&gt;HTTP MCP 서버는 SSE로 도구 결과를 스트리밍할 수 있습니다. 테스트 runner에서 SSE를 활성화하고, 최종 조립된 스트림에 대해 assertion을 걸어야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  동시성 테스트를 빼는 것
&lt;/h3&gt;

&lt;p&gt;에이전트 루프에서는 여러 &lt;code&gt;tools/call&lt;/code&gt;이 동시에 발생할 수 있습니다. 서버가 공유 상태를 잠금 없이 사용한다면 단일 요청 테스트는 통과해도 프로덕션에서 깨질 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  프로토콜 오류와 도구 오류를 혼동하는 것
&lt;/h3&gt;

&lt;p&gt;도구 내부 실패는 &lt;code&gt;isError: true&lt;/code&gt; 결과로 반환하고, JSON-RPC 오류는 프로토콜 수준 실패에만 사용하세요. 이 구분은 MCP 클라이언트 안정성에 중요합니다. 비슷한 계약 버그는 &lt;a href="http://apidog.com/blog/api-tool-contract-first-development?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;API 플랫폼 계약 우선 개발&lt;/a&gt;에서도 다룹니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  실제 사용 사례
&lt;/h2&gt;

&lt;p&gt;사내 사고 관리 API용 MCP 서버를 만든 한 팀은 Apidog에서 &lt;code&gt;tools/list&lt;/code&gt; shape assertion을 추가한 뒤 일주일 동안 세 가지 회귀를 발견했습니다. 테스트가 없었다면 잘못된 도구 스키마가 Claude Desktop을 사용하는 모든 엔지니어에게 동시에 배포될 수 있었습니다.&lt;/p&gt;

&lt;p&gt;Notion용 오픈소스 MCP 서버를 운영하는 개인 개발자는 CI에서 Notion API rate limit에 걸리지 않도록 Apidog 목 서버를 사용합니다. 테스트 스위트는 모든 PR에서 실행되며, 목 fixture를 저장소에 캐싱해 기여자가 실제 API 접근 권한 없이도 개발할 수 있게 합니다.&lt;/p&gt;

&lt;p&gt;14개의 내부 MCP 서버를 운영하는 플랫폼 팀은 모든 서버 계약을 공유 Apidog 워크스페이스에 저장했습니다. 새 서버는 기본 테스트 스위트를 상속받고, 리뷰어는 병합 전에 스키마 차이를 비교할 수 있습니다. 이 팀은 이름이 변경된 인수가 배포되는 문제를 &lt;code&gt;tools/list&lt;/code&gt; shape assertion으로 사전에 발견했습니다.&lt;/p&gt;

&lt;p&gt;내부 observability 플랫폼용 MCP 서버를 구축한 팀은 Apidog의 환경 전환 기능을 사용해 staging과 production에 같은 스위트를 실행합니다. 각 환경은 다른 목 fixture를 가리키지만, assertion은 동일하게 유지합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;MCP는 빠르게 주류가 되었지만 테스트 방식은 아직 임시적이고 수동적인 경우가 많습니다. MCP 서버도 API입니다. 따라서 REST API와 같은 수준으로 계약을 정의하고, 목을 만들고, CI에서 회귀 테스트를 실행해야 합니다.&lt;/p&gt;

&lt;p&gt;핵심 정리:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP 서버는 JSON-RPC API입니다. API 계약으로 다루세요.&lt;/li&gt;
&lt;li&gt;MCP Inspector로 수동 검증을 시작하고, 표준 요청을 캡처하세요.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 JSON-RPC 요청, assertion, 목 서버, CI 실행을 관리하세요.&lt;/li&gt;
&lt;li&gt;프로토콜 준수, 스키마 정확성, 도구 동작, 리소스 접근, 프롬프트 렌더링, 실패 모드를 모두 테스트하세요.&lt;/li&gt;
&lt;li&gt;업스트림 API는 목(mock)으로 대체해 테스트를 빠르고 결정론적으로 만드세요.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;다음 단계는 간단합니다. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 열고 프로젝트를 만든 뒤, 수동으로 캡처한 &lt;code&gt;initialize&lt;/code&gt;와 &lt;code&gt;tools/list&lt;/code&gt; 요청을 붙여넣으세요. 그런 다음 JSONPath assertion을 추가하고 스위트를 실행하세요. 한 시간 안에 MCP 서버 계약이 배포 가능한 수준인지 확인할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MCP란 무엇인가요?
&lt;/h3&gt;

&lt;p&gt;MCP, 즉 Model Context Protocol은 Claude Desktop 같은 AI 클라이언트가 외부 도구, 리소스, 프롬프트를 호출하는 방식을 정의한 Anthropic의 공개 사양입니다. stdio 또는 스트림 가능한 HTTP 위에서 JSON-RPC 2.0으로 동작합니다. 전체 &lt;a href="https://spec.modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP 사양&lt;/a&gt;은 &lt;a href="http://modelcontextprotocol.io" rel="noopener noreferrer"&gt;modelcontextprotocol.io&lt;/a&gt;에 게시되어 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP 래퍼 없이 MCP 서버를 테스트할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;네. &lt;a href="https://github.com/modelcontextprotocol/inspector" rel="noopener noreferrer"&gt;공식 MCP Inspector&lt;/a&gt;는 stdio를 직접 사용하며 수동 테스트용 UI를 제공합니다. 다만 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;로 자동화하려면 CI에서 stdio 서버를 얇은 HTTP 래퍼 뒤에 두는 방식이 실용적입니다. 프로덕션 트래픽은 계속 stdio를 사용할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP 서버가 호출하는 업스트림 API는 어떻게 목(mock) 처리하나요?
&lt;/h3&gt;

&lt;p&gt;각 업스트림 엔드포인트를 Apidog 프로젝트의 목 서버에 정의하고, 테스트 환경에서는 MCP 서버가 해당 목 URL을 바라보게 설정합니다. 런타임에서는 프로덕션 URL로 전환하면 됩니다. 같은 패턴은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;에서도 설명합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  도구 결과 스트리밍은 어떻게 테스트하나요?
&lt;/h3&gt;

&lt;p&gt;HTTP MCP 서버는 SSE(Server-Sent Events)를 통해 결과를 스트리밍할 수 있습니다. Apidog의 저장된 요청에서 SSE를 활성화하고, 최종 조립된 스트림 또는 이벤트 단위 응답에 대해 assertion을 추가하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  프로토콜 버전도 테스트해야 하나요?
&lt;/h3&gt;

&lt;p&gt;네. &lt;code&gt;initialize&lt;/code&gt; 응답의 &lt;code&gt;protocolVersion&lt;/code&gt;을 고정하고 assertion을 추가하세요. 버전 불일치는 클라이언트와 서버 간 조용한 비호환성을 만들 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  실제 Claude Desktop으로도 테스트해야 하나요?
&lt;/h3&gt;

&lt;p&gt;네. 릴리스 전 최소 한 번은 실제 Claude Desktop으로 smoke test를 수행하는 것이 좋습니다. 하지만 회귀 테스트 루프를 Claude Desktop에 의존하지는 마세요. 느리고 수동적이며 결정론적이지 않습니다. 회귀 테스트는 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;로 자동화하고, Claude Desktop은 최종 확인 용도로 사용하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  실제 MCP 서버 예시는 어디에서 볼 수 있나요?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/servers" rel="noopener noreferrer"&gt;공식 MCP 서버 저장소&lt;/a&gt;에 파일 시스템, GitHub, Slack, Postgres 등을 위한 참조 구현이 있습니다. 도구 정의와 &lt;code&gt;inputSchema&lt;/code&gt;를 읽어보면 좋은 MCP 응답 형태를 빠르게 파악할 수 있습니다.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Maigret: 고장나지 않는 OSINT 스캐너란 무엇인가</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Mon, 11 May 2026 06:09:12 +0000</pubDate>
      <link>https://forem.com/rihpig/maigret-gojangnaji-anhneun-osint-seukaeneoran-mueosinga-19ii</link>
      <guid>https://forem.com/rihpig/maigret-gojangnaji-anhneun-osint-seukaeneoran-mueosinga-19ii</guid>
      <description>&lt;p&gt;대부분의 OSINT 도구는 빠르게 노후화됩니다. 웹 환경이 바뀌고, 사이트 엔드포인트가 이동하며, 캡차가 강화되면 많은 도구가 1~2년 안에 쓸모없어집니다. &lt;a href="https://github.com/soxoj/maigret" rel="noopener noreferrer"&gt;Maigret&lt;/a&gt;은 예외에 가깝습니다. 수년간 유지 관리되어 왔고, 3,000개 이상의 사이트를 지원하며, Python 패키지, Telegram 봇, 웹 UI를 제공합니다. 더 중요한 점은 사이트가 계속 변해도 스캐너를 오래 유지하는 엔지니어링 패턴을 잘 보여준다는 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog 사용해 보기&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;이 글은 단순한 조회 방법이 아니라 엔지니어 관점의 구현 가이드입니다. Maigret이 무엇을 하는지, 합법적인 연구 및 보안 사용 사례는 무엇인지, 수천 개 사이트로 확장할 수 있게 만든 아키텍처는 무엇인지, 그리고 Maigret의 테스트 패턴인 시그니처 데이터베이스, 드리프트 감지, 재귀적 검증을 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt; 기반 API 테스트에 어떻게 적용할 수 있는지 살펴봅니다.&lt;/p&gt;

&lt;p&gt;아직 읽지 않으셨다면, &lt;a href="http://apidog.com/blog/api-testing-without-postman-2026?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;2026년 Postman 없이 API 테스트하기&lt;/a&gt; 글도 함께 참고하세요. API 테스트에서 패턴 매칭과 드리프트 감지를 어떻게 다룰 수 있는지 더 익숙한 맥락에서 설명합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  요약 (TL;DR)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Maigret은 사용자 이름을 입력받아 3,000개 이상의 사이트에서 공개 계정 존재 여부와 공개 프로필 정보를 확인합니다.&lt;/li&gt;
&lt;li&gt;핵심은 코드가 아니라 데이터입니다. 사이트별 URL, 존재 문자열, 부재 문자열, 추출 규칙을 시그니처 데이터베이스로 관리합니다.&lt;/li&gt;
&lt;li&gt;합법적인 사용 사례에는 자기 계정 복구, 브랜드 남용 모니터링, 승인된 레드팀, 실종자 수색 지원, 탐사 저널리즘이 포함됩니다.&lt;/li&gt;
&lt;li&gt;동의 없이 개인을 추적하는 용도로 사용하면 괴롭힘 또는 스토킹에 해당할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Maigret의 아키텍처는 API 테스트에도 그대로 적용됩니다. 엔드포인트별 시그니처, 다중 신호 어설션, 주기적 재생, 드리프트 감지를 설계할 수 있습니다.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 사용하면 이러한 패턴을 API 계약 테스트와 모니터링 워크플로에 적용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Maigret의 정의와 아닌 것
&lt;/h2&gt;

&lt;p&gt;Maigret은 &lt;a href="https://github.com/soxoj" rel="noopener noreferrer"&gt;soxoj&lt;/a&gt;가 유지 관리하는 MIT 라이선스 Python 도구입니다. 핵심 기능은 간단합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;maigret
maigret username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;사용자 이름을 입력하면 Maigret은 데이터베이스에 등록된 사이트들을 조회하고, 공개적으로 접근 가능한 프로필 정보를 수집한 뒤 보고서를 생성합니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-16.png" alt="" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;명확히 구분해야 할 점이 있습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maigret은 공개 데이터만 사용합니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
로그인, 탈취한 자격 증명, 비공개 API 키를 사용하지 않습니다. 익명 방문자에게 공개된 프로필만 읽습니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;합법적인 연구 맥락에서 사용됩니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
조사 언론, 사기 방지, 브랜드 보호, 승인된 레드팀, 실종자 수색 지원 등에서 공개 흔적을 확인하는 데 쓰입니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;오용될 수 있습니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
동의 없이 개인을 추적하거나 데이터를 축적하는 용도로 사용하면 윤리적·법적 문제가 됩니다. 제3자에게 사용하기 전에는 반드시 관할권의 법률과 승인 범위를 확인해야 합니다.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이 글의 초점은 사람을 추적하는 워크플로가 아니라, Maigret이 오래 유지되는 스캐너를 구현한 방식과 그 패턴을 API 테스트에 적용하는 방법입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  사이트 시그니처 데이터베이스
&lt;/h2&gt;

&lt;p&gt;Maigret의 가장 중요한 구현 아이디어는 &lt;strong&gt;사이트 시그니처 데이터베이스&lt;/strong&gt;입니다.&lt;/p&gt;

&lt;p&gt;각 사이트는 코드에 하드코딩되지 않고 JSON 데이터로 정의됩니다. 이 데이터는 스캐너가 다음을 판단하는 데 필요한 정보를 담습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;이 사이트에 특정 사용자 이름이 존재하는가?&lt;/li&gt;
&lt;li&gt;계정이 존재할 때 페이지는 어떤 특징을 갖는가?&lt;/li&gt;
&lt;li&gt;계정이 없을 때 페이지는 어떤 특징을 갖는가?&lt;/li&gt;
&lt;li&gt;공개 프로필에서 어떤 필드를 추출할 수 있는가?&lt;/li&gt;
&lt;li&gt;속도 제한, 캡차, 특수 헤더가 필요한가?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;API 테스트로 바꾸어 생각하면 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Maigret&lt;/th&gt;
&lt;th&gt;API 테스트&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;사이트 URL 템플릿&lt;/td&gt;
&lt;td&gt;엔드포인트 URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;존재 문자열&lt;/td&gt;
&lt;td&gt;성공 응답의 필수 필드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;부재 문자열&lt;/td&gt;
&lt;td&gt;오류 응답의 식별 문자열&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;추출 규칙&lt;/td&gt;
&lt;td&gt;응답 스키마 또는 JSONPath&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사이트별 헤더&lt;/td&gt;
&lt;td&gt;인증 헤더, 버전 헤더&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;드리프트 감지&lt;/td&gt;
&lt;td&gt;계약 테스트 실패&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;예를 들어 API 엔드포인트 시그니처는 다음처럼 데이터로 표현할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GetUserProfile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/users/{id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expectedStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requiredJsonPaths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"$.id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"$.email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"$.createdAt"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"forbiddenJsonPaths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"$.error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"$.stack"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requiredHeaders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"content-type"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 방식의 장점은 분명합니다. 테스트 로직은 공통화하고, 엔드포인트별 기대값은 데이터로 관리할 수 있습니다. 공급업체나 내부 서비스가 늘어나도 테스트 러너를 다시 작성할 필요가 없습니다.&lt;/p&gt;

&lt;p&gt;같은 접근은 &lt;a href="http://apidog.com/blog/api-tool-contract-first-development?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;계약 우선 API 개발&lt;/a&gt;과 &lt;a href="http://apidog.com/blog/mcp-server-testing-apidog?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;MCP 서버 테스트 플레이북&lt;/a&gt;에서도 중요하게 다룬 패턴입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maigret이 “발견”과 “미발견”을 판단하는 방식
&lt;/h2&gt;

&lt;p&gt;단순한 스캐너라면 다음처럼 구현할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/user/alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;하지만 실제 웹에서는 이 방식이 거의 안정적으로 동작하지 않습니다.&lt;/p&gt;

&lt;p&gt;많은 사이트는 존재하지 않는 사용자에게도 &lt;code&gt;200 OK&lt;/code&gt;를 반환합니다. 어떤 사이트는 홈페이지를 반환하고, 어떤 사이트는 “사용자를 찾을 수 없음” 페이지를 &lt;code&gt;200&lt;/code&gt;으로 반환하며, 어떤 사이트는 캡차 페이지를 반환합니다.&lt;/p&gt;

&lt;p&gt;Maigret은 상태 코드 하나에 의존하지 않고 여러 신호를 조합합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;urlMain&lt;/code&gt;, &lt;code&gt;url&lt;/code&gt; 템플릿&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;presenseStrs&lt;/code&gt;: 사용자가 존재할 때 나타나야 하는 문자열&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;absenceStrs&lt;/code&gt;: 사용자가 없을 때 나타나는 문자열&lt;/li&gt;
&lt;li&gt;사용자 이름 또는 프로필 필드 추출용 정규식&lt;/li&gt;
&lt;li&gt;사이트별 헤더&lt;/li&gt;
&lt;li&gt;카테고리 및 국가 태그&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;판단 로직은 다음과 비슷합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;presence_strs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;absence_strs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;has_presence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response_text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;presence_strs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;has_absence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response_text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;absence_strs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;has_presence&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;has_absence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;has_absence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not_found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API 테스트에서도 동일한 원칙이 필요합니다.&lt;/p&gt;

&lt;p&gt;나쁜 테스트:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status is 200&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;더 나은 테스트:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user profile response is valid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;createdAt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;pm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;200 OK&lt;/code&gt;만 확인하면 캐시된 응답, 빈 응답, 일반 오류 페이지를 놓칠 수 있습니다. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서도 상태 코드, 헤더, 본문 필드, JSONPath 기반 검증을 함께 구성하는 방식이 더 안전합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  재귀적 검색과 정보 추출
&lt;/h2&gt;

&lt;p&gt;Maigret은 계정을 찾은 뒤 단순히 “있음”으로 끝내지 않습니다.&lt;/p&gt;

&lt;p&gt;공개 프로필 페이지에서 다음과 같은 추가 식별자를 추출할 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;연결된 이메일 주소&lt;/li&gt;
&lt;li&gt;공개 전화번호&lt;/li&gt;
&lt;li&gt;실명&lt;/li&gt;
&lt;li&gt;다른 사용자 이름&lt;/li&gt;
&lt;li&gt;외부 프로필 링크&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;그다음 새로 발견한 식별자를 다시 검색 루프에 넣습니다. 즉, 하나의 사용자 이름에서 다른 사용자 이름, 다른 사이트, 다른 공개 프로필로 확장됩니다.&lt;/p&gt;

&lt;p&gt;이 패턴을 API 테스트에 적용하면 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;/users/{id}&lt;/code&gt; 응답을 호출합니다.&lt;/li&gt;
&lt;li&gt;응답에서 &lt;code&gt;organizationId&lt;/code&gt;를 추출합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/organizations/{organizationId}&lt;/code&gt;를 호출합니다.&lt;/li&gt;
&lt;li&gt;응답에서 &lt;code&gt;billingAccountId&lt;/code&gt;를 추출합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/billing/accounts/{billingAccountId}&lt;/code&gt; 계약을 검증합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;예시:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Step 1: user response에서 organizationId 저장&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;organizationId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;organizationId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /organizations/{{organizationId}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 방식은 단일 엔드포인트 테스트보다 실제 시스템 흐름에 가깝습니다. 한 응답에서 발견한 필드를 다음 테스트의 입력으로 사용하면, 문서화되지 않은 의존성이나 누락된 계약을 더 빨리 찾을 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  캡차와 속도 제한 처리
&lt;/h2&gt;

&lt;p&gt;Maigret은 자동화 방지 장치를 무력화하려는 도구가 아닙니다. 대신 응답 형태를 읽고 제한 상황을 감지합니다.&lt;/p&gt;

&lt;p&gt;일반적인 대응 전략은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;사용자 에이전트 조정&lt;/li&gt;
&lt;li&gt;사이트별 재시도 헤더 준수&lt;/li&gt;
&lt;li&gt;모바일 또는 간소화된 도메인 사용&lt;/li&gt;
&lt;li&gt;허용되는 경우 Tor 또는 I2P 라우팅&lt;/li&gt;
&lt;li&gt;캡차가 감지되면 자동 판단을 중단하고 수동 확인으로 넘김&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;핵심은 “우회”가 아니라 &lt;strong&gt;감지 후 후퇴&lt;/strong&gt;입니다.&lt;/p&gt;

&lt;p&gt;API 클라이언트와 테스트 러너도 같은 태도를 가져야 합니다. &lt;code&gt;429 Too Many Requests&lt;/code&gt;를 받았는데 계속 요청을 밀어 넣으면 테스트가 아니라 공격처럼 보일 수 있습니다.&lt;/p&gt;

&lt;p&gt;예시 처리:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;retryAfter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Retry-After&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`Rate limited. Retry after: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;retryAfter&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unknown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds`&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CI에서 API 테스트를 실행할 때도 다음을 설정하는 것이 좋습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;테스트 환경별 요청 속도 제한&lt;/li&gt;
&lt;li&gt;재시도 횟수 상한&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Retry-After&lt;/code&gt; 헤더 준수&lt;/li&gt;
&lt;li&gt;실패 시 무한 재시도 금지&lt;/li&gt;
&lt;li&gt;프로덕션 API에 대한 쓰기 테스트 제한&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maigret이 사이트의 제한을 신호로 다루는 것처럼, API 테스트도 제한 응답을 정상적인 테스트 입력으로 다뤄야 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  시그니처 드리프트 문제
&lt;/h2&gt;

&lt;p&gt;3,000개 이상의 사이트 시그니처는 지속적으로 변합니다.&lt;/p&gt;

&lt;p&gt;사이트가 다음을 변경하면 기존 시그니처는 깨집니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;프로필 URL 패턴&lt;/li&gt;
&lt;li&gt;HTML 구조&lt;/li&gt;
&lt;li&gt;오류 메시지&lt;/li&gt;
&lt;li&gt;리디렉션 정책&lt;/li&gt;
&lt;li&gt;캡차 정책&lt;/li&gt;
&lt;li&gt;브랜드 또는 도메인&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 문제를 Maigret은 세 가지 방식으로 완화합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;중앙 GitHub 리포지토리에서 시그니처 자동 업데이트&lt;/li&gt;
&lt;li&gt;커뮤니티 풀 리퀘스트를 통한 사이트별 수정&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--update&lt;/code&gt; 플래그를 통한 수동 업데이트&lt;/li&gt;
&lt;li&gt;알려진 기존 사용자 이름에 대한 테스트 하네스&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;특히 중요한 부분은 &lt;strong&gt;알려진 정상값으로 시그니처를 검증한다는 점&lt;/strong&gt;입니다. 각 사이트에 대해 실제로 존재하는 테스트용 사용자 이름을 두고, 해당 시그니처가 여전히 “발견”을 반환하는지 확인합니다.&lt;/p&gt;

&lt;p&gt;API 테스트에서도 같은 구조가 필요합니다.&lt;/p&gt;

&lt;p&gt;예를 들어 결제 API의 정상 응답 픽스처를 저장해 둡니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pay_123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"succeeded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4900&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;그리고 주기적으로 라이브 또는 스테이징 엔드포인트를 호출해 다음을 비교합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;상태 코드가 그대로인가?&lt;/li&gt;
&lt;li&gt;필수 필드가 사라지지 않았는가?&lt;/li&gt;
&lt;li&gt;타입이 바뀌지 않았는가?&lt;/li&gt;
&lt;li&gt;오류 응답 구조가 변경되지 않았는가?&lt;/li&gt;
&lt;li&gt;새 필드가 추가되었는가?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서는 엔드포인트별 테스트를 저장하고, 반복 실행하고, 응답 차이를 확인하는 방식으로 이 패턴을 구현할 수 있습니다. 특정 공급업체 API의 수동 검증 흐름은 &lt;a href="http://apidog.com/blog/how-to-use-deepseek-v4-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;DeepSeek V4 API 가이드&lt;/a&gt;에서도 참고할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  선택적 AI 요약 모드
&lt;/h2&gt;

&lt;p&gt;Maigret의 &lt;code&gt;--ai&lt;/code&gt; 플래그는 원시 결과를 OpenAI 호환 LLM 엔드포인트로 보내 짧은 조사 요약을 생성합니다. API 키는 사용자가 직접 제공합니다.&lt;/p&gt;

&lt;p&gt;중요한 점은 LLM이 판정을 내리지 않는다는 것입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;계정 존재 여부 판단: 규칙 기반&lt;/li&gt;
&lt;li&gt;문자열 매칭: 규칙 기반&lt;/li&gt;
&lt;li&gt;필드 추출: 규칙 기반&lt;/li&gt;
&lt;li&gt;최종 요약: LLM 후처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 구조가 안전합니다. LLM은 결과를 읽기 쉽게 정리하지만, 테스트의 통과/실패를 결정하지 않습니다.&lt;/p&gt;

&lt;p&gt;API 모니터링에서도 같은 구조를 권장합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API 실행 결과
   ↓
규칙 기반 어설션
   ↓
통과 / 실패 결정
   ↓
LLM 요약
   ↓
Slack 또는 이슈 트래커로 전달
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LLM을 판정자로 쓰면 환각과 비결정성이 테스트 안정성을 해칠 수 있습니다. 반대로 확정적 테스트 결과를 요약하는 후처리기로 쓰면 유용합니다. 이 원칙은 &lt;a href="http://apidog.com/blog/computer-use-vs-structured-apis?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;컴퓨터 사용 대 구조화된 API&lt;/a&gt; 글에서도 다룬 구조화 우선 접근과 맞닿아 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  합법적인 사용 사례
&lt;/h2&gt;

&lt;p&gt;Maigret을 사용할 수 있는 대표적인 합법적 상황은 다음과 같습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 자기 계정 복구
&lt;/h3&gt;

&lt;p&gt;오래전에 사용한 사용자 이름으로 가입했던 계정을 찾을 수 있습니다. 개인정보 정리, 계정 삭제, 디지털 발자국 감사에 유용합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 브랜드 남용 모니터링
&lt;/h3&gt;

&lt;p&gt;기업은 자사 브랜드명, 제품명, 임원 이름 등을 기준으로 사칭 계정을 확인할 수 있습니다. 이 경우에도 내부 정책과 법무 검토를 거치는 것이 좋습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 실종자 수색 지원
&lt;/h3&gt;

&lt;p&gt;가족 동의와 관련 기관 협조가 있는 상황에서 공개 디지털 흔적을 확인하는 데 사용할 수 있습니다. 독자적으로 행동하면 수사를 방해할 수 있으므로 반드시 공식 절차와 협력해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. 승인된 레드팀
&lt;/h3&gt;

&lt;p&gt;계약 범위가 명확한 침투 테스트에서 조직의 공개 공격 표면을 파악하는 데 사용할 수 있습니다. 도구가 합법성을 만드는 것이 아니라, 계약과 승인 범위가 합법성을 만듭니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 탐사 저널리즘
&lt;/h3&gt;

&lt;p&gt;사기, 공익 이슈, 조직 범죄 등을 조사하는 기자가 편집 및 법률 검토 아래 OSINT 도구를 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;반대로 다음은 적절하지 않습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;호기심으로 낯선 사람 검색&lt;/li&gt;
&lt;li&gt;전 배우자 또는 지인 감시&lt;/li&gt;
&lt;li&gt;동의 없는 개인 데이터셋 구축&lt;/li&gt;
&lt;li&gt;괴롭힘, 협박, 신상털이 목적의 사용&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Maigret에서 API 테스트에 적용할 수 있는 패턴
&lt;/h2&gt;

&lt;p&gt;Maigret의 구조에서 API 테스트로 바로 가져올 수 있는 패턴은 다섯 가지입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 수동 코드 대신 시그니처 데이터베이스 사용
&lt;/h3&gt;

&lt;p&gt;엔드포인트별 기대 동작을 코드가 아니라 데이터로 정의합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"endpoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET /v1/orders/{id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expectedStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requiredFields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"forbiddenFields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"stackTrace"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이렇게 하면 테스트 러너는 그대로 두고 시그니처만 업데이트할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 다중 신호 어설션 사용
&lt;/h3&gt;

&lt;p&gt;상태 코드만 보지 말고 다음을 함께 확인합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;상태 코드&lt;/li&gt;
&lt;li&gt;응답 헤더&lt;/li&gt;
&lt;li&gt;JSON 스키마&lt;/li&gt;
&lt;li&gt;필수 필드&lt;/li&gt;
&lt;li&gt;금지 필드&lt;/li&gt;
&lt;li&gt;오류 코드&lt;/li&gt;
&lt;li&gt;응답 시간&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. 시그니처 자동 동기화
&lt;/h3&gt;

&lt;p&gt;팀이 여러 명이면 테스트 정의가 흩어지기 쉽습니다. 중앙 저장소 또는 클라우드 프로젝트로 동기화해야 합니다. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt; 프로젝트 동기화는 이 목적에 맞습니다. 관련 워크플로는 &lt;a href="http://apidog.com/blog/api-testing-without-postman-2026?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Postman 없이 API 테스트하기&lt;/a&gt;에서 더 자세히 다뤘습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-17.png" alt="" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. 드리프트 감지 예약
&lt;/h3&gt;

&lt;p&gt;주기적으로 테스트를 실행하고 결과를 비교합니다.&lt;/p&gt;

&lt;p&gt;예시 CI 흐름:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;API Contract Check&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*/6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contract-test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run API contract tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo "Run Apidog or API test CLI here"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;목표는 사용자가 장애를 발견하기 전에 계약 변경을 감지하는 것입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. LLM은 판정자가 아니라 요약기로 사용
&lt;/h3&gt;

&lt;p&gt;테스트 통과/실패는 규칙으로 결정합니다. LLM은 마지막에 실행 결과를 사람이 읽기 쉽게 요약하는 데만 사용합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maigret 실행 시 흔히 하는 실수
&lt;/h2&gt;

&lt;p&gt;도구 자체를 실험할 때도 몇 가지 실수를 피해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;-a&lt;/code&gt; 없이 실행하고 완전하다고 가정
&lt;/h3&gt;

&lt;p&gt;기본 실행은 전체 사이트가 아니라 우선순위가 높은 일부 사이트를 대상으로 할 수 있습니다. 더 넓은 범위가 필요하면 전체 스캔 옵션을 확인해야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;maigret username &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;전체 스캔은 시간이 더 오래 걸립니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  태그 무시
&lt;/h3&gt;

&lt;p&gt;국가나 카테고리별 사이트를 놓칠 수 있습니다. 특정 지역이나 서비스군이 중요하다면 태그 필터를 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;maigret username &lt;span class="nt"&gt;--tags&lt;/span&gt; us,jp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  업데이트 생략
&lt;/h3&gt;

&lt;p&gt;오래된 시그니처는 오탐과 누락을 만듭니다. 중요한 실행 전에는 업데이트를 확인합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;maigret &lt;span class="nt"&gt;--update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tor 차단을 잘못 해석
&lt;/h3&gt;

&lt;p&gt;일부 사이트는 Tor 출구 노드를 차단합니다. 이것을 대상 사용자에 대한 신호로 해석하면 안 됩니다. 네트워크 조건과 사이트 정책의 결과일 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  추출된 필드를 증거로 단정
&lt;/h3&gt;

&lt;p&gt;Maigret은 페이지에 노출된 문자열을 추출합니다. 페이지는 오래되었거나 조작되었거나 다른 사람의 정보를 포함할 수 있습니다. 결과는 증거가 아니라 단서로 다뤄야 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  실제 사용 사례
&lt;/h2&gt;

&lt;p&gt;보안 컨설팅 회사는 레드팀 범위 설정 단계에서 Maigret을 사용해 고객 조직의 공개 공격 표면을 확인할 수 있습니다. 결과는 초기 보고서에 포함되어 고객이 외부에 노출된 계정과 브랜드 사용 현황을 이해하는 데 도움을 줍니다.&lt;/p&gt;

&lt;p&gt;사기 조사자는 &lt;code&gt;--ai&lt;/code&gt; 플래그를 사용해 긴 스캔 결과를 비기술 고객이 읽을 수 있는 짧은 요약으로 바꿀 수 있습니다. 이때 데이터 수집과 판정은 규칙 기반이고, LLM은 읽기 쉬운 설명 계층입니다.&lt;/p&gt;

&lt;p&gt;엔지니어링 팀은 같은 패턴을 내부 API 테스트에 적용할 수 있습니다. 예를 들어 200개의 마이크로서비스에 대해 엔드포인트 시그니처를 관리하고, 주기적으로 재생하고, 응답 형태가 바뀌면 알림을 보낼 수 있습니다. 이 구조는 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt; 기반 API 계약 테스트와 잘 맞습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;Maigret은 OSINT 도구이지만, 엔지니어링 관점에서는 오래 유지되는 테스트 시스템의 좋은 사례입니다. 핵심은 다음입니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;사이트별 동작을 코드가 아니라 시그니처 데이터로 관리합니다.&lt;/li&gt;
&lt;li&gt;상태 코드 하나가 아니라 여러 신호를 조합해 판단합니다.&lt;/li&gt;
&lt;li&gt;시그니처가 변할 수 있음을 전제로 업데이트와 검증 루프를 둡니다.&lt;/li&gt;
&lt;li&gt;알려진 정상값으로 드리프트를 조기에 감지합니다.&lt;/li&gt;
&lt;li&gt;LLM은 판정자가 아니라 후처리 요약기로 사용합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;API 테스트에도 동일한 원칙을 적용할 수 있습니다. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 열고 프로젝트의 핵심 엔드포인트 하나를 골라 다음처럼 설계해 보세요.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;필수 상태 코드를 정의합니다.&lt;/li&gt;
&lt;li&gt;필수 응답 필드를 정의합니다.&lt;/li&gt;
&lt;li&gt;없어야 하는 오류 필드를 정의합니다.&lt;/li&gt;
&lt;li&gt;정상 응답 픽스처를 저장합니다.&lt;/li&gt;
&lt;li&gt;주기적 재생을 설정합니다.&lt;/li&gt;
&lt;li&gt;응답 형태가 바뀌면 알림을 받도록 구성합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이 규율은 공급업체나 내부 팀이 새벽 2시에 필드 이름을 바꾸었을 때 가치를 발휘합니다. 사용자가 먼저 깨닫기 전에 테스트 스위트가 먼저 알려줘야 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Maigret 사용은 합법적인가요?
&lt;/h3&gt;

&lt;p&gt;관할권과 대상에 따라 다릅니다. 자신, 소유한 계정, 서면 승인을 받은 회사, 승인된 저널리즘 또는 계약 범위 내 보안 테스트에 사용하는 것은 일반적으로 허용될 수 있습니다. 동의 없는 개인을 대상으로 실행하면 EU, 미국, 영국 및 여러 지역에서 스토킹 또는 괴롭힘 법률에 저촉될 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maigret은 Python 없이 작동하나요?
&lt;/h3&gt;

&lt;p&gt;공식 패키지는 Python 3.10+ 기반입니다. 로컬 설치가 어렵다면 &lt;a href="https://t.me/maigret_search_bot" rel="noopener noreferrer"&gt;Telegram 봇&lt;/a&gt; 또는 Cloud Shell 설정을 사용할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3,000개 사이트 지원은 정확한가요?
&lt;/h3&gt;

&lt;p&gt;리포지토리의 사이트 데이터베이스에는 3,000개 이상의 항목이 있습니다. 다만 모든 사이트가 항상 정상 동작하는 것은 아닙니다. 사이트 구조 변경, 캡차, 차단 정책 때문에 일부 시그니처는 업데이트가 필요할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI 모드는 무엇을 하나요?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;--ai&lt;/code&gt; 플래그는 OpenAI 호환 LLM을 사용해 확정적 검색 결과를 읽기 쉬운 보고서로 요약합니다. 검색 판단 자체는 바꾸지 않습니다. API 키는 사용자가 직접 제공해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI에서 Maigret을 사용해도 되나요?
&lt;/h3&gt;

&lt;p&gt;OSINT 조사는 일반적으로 상호작용적이고 승인 범위가 중요한 작업이므로 CI에 무작정 넣는 것은 적절하지 않습니다. 다만 Maigret의 아키텍처 패턴인 시그니처 데이터베이스, 드리프트 감지, 예약된 재생은 API 테스트 CI 파이프라인에 적용하기 좋습니다. &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;는 이런 API 테스트 흐름을 구성하는 데 사용할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sherlock과는 어떻게 다른가요?
&lt;/h3&gt;

&lt;p&gt;Sherlock은 더 오래되고 단순한 사용자 이름 검색 도구입니다. Maigret은 정보 추출, 재귀적 검색, 캡차 처리, AI 요약 모드, 더 풍부한 사이트 데이터베이스로 확장되었습니다. 둘 다 MIT 라이선스이며 OSINT 도구 아키텍처를 이해하는 데 참고할 만합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  오래된 시그니처는 어디에 보고하나요?
&lt;/h3&gt;

&lt;p&gt;Maigret GitHub 리포지토리의 이슈 또는 풀 리퀘스트로 보고하면 됩니다. 오래된 사이트 하나당 하나의 PR로 수정하는 방식이 일반적이며, 커뮤니티 기여가 데이터베이스 품질을 유지하는 핵심입니다.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>클로드 코드 'Invalid custom3p enterprise config' 오류 해결 방법</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Mon, 11 May 2026 03:30:29 +0000</pubDate>
      <link>https://forem.com/rihpig/keulrodeu-kodeu-invalid-custom3p-enterprise-config-oryu-haegyeol-bangbeob-3b9p</link>
      <guid>https://forem.com/rihpig/keulrodeu-kodeu-invalid-custom3p-enterprise-config-oryu-haegyeol-bangbeob-3b9p</guid>
      <description>&lt;p&gt;Claude Code를 DeepSeek V4, OpenRouter 또는 다른 타사 모델 공급자에 연결할 때 &lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt; 오류가 발생했다면, 대부분은 URL, 인증 헤더, &lt;code&gt;settings.json&lt;/code&gt;, 온보딩 상태 중 하나가 잘못된 경우입니다. 이 글에서는 Claude Code의 &lt;code&gt;custom3p&lt;/code&gt; 구성이 무엇인지, 어떤 순서로 확인해야 하는지, OpenRouter·LiteLLM·vLLM에서 바로 적용할 수 있는 설정 예시를 정리합니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog 사용해 보기&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  빠른 체크리스트
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt;는 Claude Code가 타사 공급자 구성을 검증하지 못했다는 뜻입니다.&lt;/p&gt;

&lt;p&gt;먼저 아래 순서대로 확인하세요.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 끝에 &lt;code&gt;/v1&lt;/code&gt;이 붙어 있지 않은지 확인&lt;/li&gt;
&lt;li&gt;공급자가 요구하는 인증 방식에 맞게 &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; 또는 &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; 사용&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.claude/settings.json&lt;/code&gt;이 유효한 JSON인지 검증&lt;/li&gt;
&lt;li&gt;새 설치라면 &lt;code&gt;~/.claude.json&lt;/code&gt;에 온보딩 완료 플래그가 있는지 확인&lt;/li&gt;
&lt;li&gt;프록시·게이트웨이가 &lt;code&gt;anthropic-beta&lt;/code&gt;, &lt;code&gt;anthropic-version&lt;/code&gt; 등 필수 헤더를 전달하는지 확인&lt;/li&gt;
&lt;li&gt;팀/엔터프라이즈 관리 정책이 로컬 설정을 덮어쓰고 있지 않은지 확인&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;가장 흔한 원인은 &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 끝의 &lt;code&gt;/v1&lt;/code&gt;입니다. 이 항목부터 확인하면 상당수의 문제를 바로 해결할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;custom3p&lt;/code&gt;가 의미하는 것
&lt;/h2&gt;

&lt;p&gt;Claude Code는 요청을 다음 모드 중 하나로 라우팅합니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;모드&lt;/th&gt;
&lt;th&gt;트리거 방식&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic API 기본값&lt;/td&gt;
&lt;td&gt;오버라이드 설정 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amazon Bedrock&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE_CODE_USE_BEDROCK=1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google Vertex AI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE_CODE_USE_VERTEX=1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Foundry&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE_CODE_USE_FOUNDRY=1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;커스텀 타사 공급자&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;이 Anthropic이 아닌 엔드포인트를 가리킴&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;여기서 마지막 항목이 Claude Code 내부에서 말하는 &lt;code&gt;custom3p&lt;/code&gt;입니다.&lt;/p&gt;

&lt;p&gt;예를 들어 &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;을 LiteLLM, OpenRouter, 로컬 vLLM 서버, 사내 LLM 게이트웨이로 설정하면 Claude Code는 해당 경로를 &lt;code&gt;custom3p&lt;/code&gt;로 취급하고 첫 API 호출 전에 엔터프라이즈 구성 검사를 수행합니다.&lt;/p&gt;

&lt;p&gt;이 검사가 실패하면 다음 오류가 발생합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invalid custom3p enterprise config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 오류는 정책 차단이 아니라 구성 검증 오류입니다. 따라서 설정을 수정하면 해결할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  왜 이 오류가 자주 발생하는가
&lt;/h2&gt;

&lt;p&gt;2026년 4월 Anthropic은 Claude Code 클라이언트 ID를 위장해 Claude Pro 및 Max 구독에 접근하던 일부 타사 에이전트 도구를 차단했습니다. OpenClaw처럼 Claude Code 세션을 자체 백엔드로 라우팅하던 도구는 이 변경 이후 작동하지 않게 되었습니다.&lt;/p&gt;

&lt;p&gt;하지만 이 글에서 다루는 문제는 그 차단과 별개입니다.&lt;/p&gt;

&lt;p&gt;많은 개발자가 이후 Claude Code의 공식 타사 공급자 지원을 사용해 더 저렴한 모델 백엔드로 라우팅하기 시작했습니다. 예를 들어 한 Reddit 스레드는 Claude Code 에이전트 루프를 &lt;a href="https://openrouter.ai/deepseek/deepseek-v4-pro" rel="noopener noreferrer"&gt;OpenRouter를 통한 DeepSeek V4 Pro&lt;/a&gt;로 전환하면 Anthropic의 백만 출력 토큰당 $15 대비 $0.87 수준으로 사용할 수 있다고 설명했습니다. &lt;a href="https://github.com/aattaran/deepclaude" rel="noopener noreferrer"&gt;DeepClaude&lt;/a&gt; 같은 프로젝트는 이를 단일 명령 설정으로 패키징했습니다.&lt;/p&gt;

&lt;p&gt;문제는 Claude Code의 타사 공급자 지원이 정확한 엔터프라이즈 구성을 요구한다는 점입니다. URL, 인증 변수, JSON 형식, 헤더 중 하나라도 잘못되면 &lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt;가 발생합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  원인 1: &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 끝에 &lt;code&gt;/v1&lt;/code&gt;을 붙임
&lt;/h2&gt;

&lt;p&gt;Claude Code는 설정된 기본 URL 뒤에 자동으로 &lt;code&gt;/v1/messages&lt;/code&gt;를 추가합니다.&lt;/p&gt;

&lt;p&gt;따라서 기본 URL에 이미 &lt;code&gt;/v1&lt;/code&gt;이 포함되어 있으면 실제 요청 경로가 다음처럼 중복됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/v1/v1/messages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 경우 게이트웨이는 보통 &lt;code&gt;404&lt;/code&gt;를 반환합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  잘못된 설정
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.openrouter.ai/api/v1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://litellm.yourcompany.com/v1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  올바른 설정
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://api.openrouter.ai/api"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://litellm.yourcompany.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  URL 확인 방법
&lt;/h3&gt;

&lt;p&gt;Claude Code가 실제로 호출할 엔드포인트를 &lt;code&gt;curl&lt;/code&gt;로 확인합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/v1/messages"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model":"claude-sonnet-4-6","max_tokens":1,"messages":[{"role":"user","content":"hi"}]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;판단 기준은 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;응답 코드&lt;/th&gt;
&lt;th&gt;의미&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;200&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;엔드포인트와 인증이 정상일 가능성이 높음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;400&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;요청 본문은 잘못됐지만 엔드포인트는 존재함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;404&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;기본 URL에 &lt;code&gt;/v1&lt;/code&gt; 중복 가능성 높음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;401&lt;/code&gt; / &lt;code&gt;403&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;인증 변수 또는 키 문제&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  원인 2: 인증 변수를 잘못 사용함
&lt;/h2&gt;

&lt;p&gt;Claude Code는 인증 방식에 따라 서로 다른 환경 변수를 사용합니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;변수&lt;/th&gt;
&lt;th&gt;전송 헤더&lt;/th&gt;
&lt;th&gt;사용 대상&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x-api-key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Anthropic 형식 API 키 인증 게이트웨이&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Authorization: Bearer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OAuth 스타일 게이트웨이, LiteLLM, 대부분의 OpenRouter 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  OpenRouter 예시
&lt;/h3&gt;

&lt;p&gt;OpenRouter는 Bearer 토큰을 기대합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-or-your-openrouter-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://openrouter.ai/api"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenRouter에서 &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;를 사용하면 Claude Code는 &lt;code&gt;x-api-key&lt;/code&gt; 헤더를 보냅니다. OpenRouter가 이 헤더를 사용하지 않으면 인증이 실패하고 Claude Code는 이를 엔터프라이즈 구성 오류로 표시할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  LiteLLM 예시
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-litellm-your-virtual-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://your-litellm-server:4000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  API 키 기반 vLLM 또는 DeepSeek 게이트웨이 예시
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-key-here"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://your-vllm-server"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;게이트웨이 문서에서 어떤 헤더를 요구하는지 먼저 확인하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  원인 3: &lt;code&gt;settings.json&lt;/code&gt; 형식 오류
&lt;/h2&gt;

&lt;p&gt;환경 변수 대신 &lt;code&gt;~/.claude/settings.json&lt;/code&gt;에 설정을 저장할 수 있습니다. 이 파일이 잘못된 JSON이면 Claude Code는 요청을 보내기 전에 구성 검증에서 실패합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  잘못된 예: 끝 쉼표
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://openrouter.ai/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_AUTH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk-or-your-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JSON에서는 마지막 속성 뒤에 쉼표를 붙일 수 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  잘못된 예: 스마트 따옴표
&lt;/h3&gt;

&lt;p&gt;문서나 워드프로세서에서 복사하면 &lt;code&gt;" "&lt;/code&gt; 대신 &lt;code&gt;“ ”&lt;/code&gt;가 들어갈 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;“ANTHROPIC_BASE_URL”:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;“https://openrouter.ai/api”&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  올바른 예
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://openrouter.ai/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_AUTH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk-or-your-openrouter-key"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  JSON 검증
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import json, os; json.load(open(os.path.expanduser('~/.claude/settings.json')))"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Valid JSON"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;또는 &lt;code&gt;jq&lt;/code&gt;를 사용할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="nb"&gt;.&lt;/span&gt; ~/.claude/settings.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;여기서 파싱 오류가 발생하면 Claude Code도 설정을 읽지 못합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  원인 4: 새 설치 후 온보딩이 완료되지 않음
&lt;/h2&gt;

&lt;p&gt;Claude Code는 &lt;code&gt;~/.claude/settings.json&lt;/code&gt;의 엔터프라이즈 구성을 읽기 전에 &lt;code&gt;~/.claude.json&lt;/code&gt;에서 다음 플래그를 확인합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"hasCompletedOnboarding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;새로 설치한 환경에서는 이 값이 없거나 &lt;code&gt;false&lt;/code&gt;일 수 있습니다. 이 경우 Claude Code는 사용자 지정 타사 구성을 건너뛰고 기본 인증 흐름을 시도할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  현재 상태 확인
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.claude.json | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep &lt;/span&gt;hasCompletedOnboarding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;값이 없거나 &lt;code&gt;false&lt;/code&gt;라면 온보딩 플래그를 추가합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hasCompletedOnboarding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"primaryApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk-placeholder"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;primaryApiKey&lt;/code&gt;는 플레이스홀더입니다. 엔터프라이즈 구성에 의해 재정의됩니다. 형식 검사를 통과하려면 &lt;code&gt;sk-&lt;/code&gt;로 시작하는 값을 넣고 Claude Code를 다시 시작하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  원인 5: 게이트웨이가 필수 헤더를 전달하지 않음
&lt;/h2&gt;

&lt;p&gt;Claude Code의 엔터프라이즈 구성 검증에는 기능 핸드셰이크가 포함됩니다. 이 과정에서 게이트웨이에 여러 헤더를 전달합니다.&lt;/p&gt;

&lt;p&gt;게이트웨이가 다음 헤더를 제거하면 Claude Code는 예상과 다른 응답을 받고 &lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt;를 표시할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;anthropic-beta
anthropic-version
X-Claude-Code-Session-Id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LiteLLM은 v1.82.9 이상에서 기본적으로 이 흐름을 처리합니다. 직접 Nginx나 사내 프록시를 구성한다면 헤더 전달을 명시해야 합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/v1/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;anthropic-beta&lt;/span&gt; &lt;span class="nv"&gt;$http_anthropic_beta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;anthropic-version&lt;/span&gt; &lt;span class="nv"&gt;$http_anthropic_version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Claude-Code-Session-Id&lt;/span&gt; &lt;span class="nv"&gt;$http_x_claude_code_session_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;게이트웨이를 수정할 수 없다면 베타 기능 핸드셰이크를 비활성화할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 설정은 일부 실험 기능 접근을 제한할 수 있지만, 핵심 에이전트 루프는 계속 동작할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  원인 6: 엔터프라이즈 정책 충돌
&lt;/h2&gt;

&lt;p&gt;팀 또는 엔터프라이즈 Claude 플랜을 사용 중이고 관리자가 관리 설정을 배포했다면, 해당 설정은 다음보다 우선합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;환경 변수&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;사용자 로컬 설정&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;관리 정책이 &lt;code&gt;availableModels&lt;/code&gt;를 제한하거나 사용자 지정 기본 URL을 차단하면 로컬 설정이 올바르더라도 &lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt;가 발생할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  관리 설정 확인
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; ~/.claude/managed-settings.json 2&amp;gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Managed settings found"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code 내부에서는 다음 명령을 사용할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Managed settings&lt;/code&gt;가 활성화되어 있다면 관리자에게 다음을 요청해야 합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;게이트웨이 도메인을 허용된 기본 URL에 추가&lt;/li&gt;
&lt;li&gt;게이트웨이 모델 ID를 &lt;code&gt;availableModels&lt;/code&gt;에 추가&lt;/li&gt;
&lt;li&gt;사용자 지정 기본 URL 제한에서 예외 처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;사용자가 제어하는 엔터프라이즈 배포에서는 관리 설정이 macOS 기준 다음 경로에 있을 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/Library/Application Support/ClaudeCode/managed-settings.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Windows/Linux에서는 해당 플랫폼의 Claude Code 관리 설정 경로를 확인하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  작동 구성 예시
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code + OpenRouter + DeepSeek V4 Pro
&lt;/h3&gt;

&lt;p&gt;OpenRouter는 Anthropic 호환 API를 제공합니다. 다음 설정은 Claude Code의 에이전트 루프를 DeepSeek V4 Pro로 라우팅합니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://openrouter.ai/api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_AUTH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk-or-your-openrouter-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_DEFAULT_SONNET_MODEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deepseek/deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_DEFAULT_OPUS_MODEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deepseek/deepseek-v4-pro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_DEFAULT_HAIKU_MODEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deepseek/deepseek-v4-pro"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;모델 오버라이드가 필요한 이유는 Claude Code가 기본적으로 &lt;code&gt;claude-sonnet-4-6&lt;/code&gt; 같은 모델명을 사용하기 때문입니다. 기본 URL만 바꾸면 요청이 OpenRouter로 가더라도 모델명은 Claude 모델로 남을 수 있습니다.&lt;/p&gt;

&lt;p&gt;OpenRouter의 Anthropic 스트리밍 및 도구 호출 호환성은 업데이트될 수 있으므로 &lt;a href="https://openrouter.ai/docs/guides/coding-agents/claude-code-integration" rel="noopener noreferrer"&gt;OpenRouter의 Claude Code 통합 문서&lt;/a&gt;를 확인하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code + LiteLLM
&lt;/h3&gt;

&lt;p&gt;LiteLLM은 Claude Code와 함께 쓰기 좋은 게이트웨이입니다. 헤더 전달을 처리하고 여러 공급자 간 모델 라우팅을 지원합니다.&lt;/p&gt;

&lt;p&gt;LiteLLM &lt;code&gt;config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;model_list&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;model_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;
    &lt;span class="na"&gt;litellm_params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deepseek/deepseek-v4&lt;/span&gt;
      &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sk-your-deepseek-key"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;model_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-opus-4-7&lt;/span&gt;
    &lt;span class="na"&gt;litellm_params&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deepseek/deepseek-v4-pro&lt;/span&gt;
      &lt;span class="na"&gt;api_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sk-your-deepseek-key"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_AUTH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sk-litellm-your-key"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 구성에서는 Claude Code가 &lt;code&gt;claude-sonnet-4-6&lt;/code&gt;을 요청하면 LiteLLM이 이를 &lt;code&gt;deepseek/deepseek-v4&lt;/code&gt;로 라우팅합니다. 따라서 Claude Code 쪽에서 모델명을 직접 바꾸지 않아도 됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code + 로컬 vLLM
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.vllm.ai/en/stable/serving/integrations/claude_code/" rel="noopener noreferrer"&gt;vLLM&lt;/a&gt;으로 로컬 모델을 서빙하려면 Anthropic 호환 모드로 서버를 시작합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; vllm.entrypoints.openai.api_server &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--model&lt;/span&gt; deepseek-ai/DeepSeek-V3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dtype&lt;/span&gt; auto &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--api-key&lt;/span&gt; local-key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code 설정:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8000"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"local-key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_DEFAULT_SONNET_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"deepseek-ai/DeepSeek-V3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  디버깅 절차
&lt;/h2&gt;

&lt;p&gt;위 설정을 적용해도 실패한다면 Claude Code를 디버그 모드로 실행합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--debug&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;출력에서 다음 항목을 확인하세요.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;로그 항목&lt;/th&gt;
&lt;th&gt;확인할 내용&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Sending request to:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;실제 호출 URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Response status:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;게이트웨이 HTTP 응답 코드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enterprise config error:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;내부 검증 실패 메시지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;게이트웨이 측에서 동일 요청을 재현하려면 다음 &lt;code&gt;curl&lt;/code&gt;을 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/v1/messages"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_AUTH_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"anthropic-version: 2023-06-01"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"anthropic-beta: max-tokens-3-5-sonnet-2024-07-15"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "claude-sonnet-4-6",
    "max_tokens": 10,
    "messages": [{"role": "user", "content": "hi"}]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;응답 해석:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;200&lt;/code&gt;: 게이트웨이와 인증이 정상&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;401&lt;/code&gt; / &lt;code&gt;403&lt;/code&gt;: 인증 문제&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;404&lt;/code&gt;: 기본 URL 문제&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;422&lt;/code&gt;: 요청 형식 또는 모델 매핑 문제&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl&lt;/code&gt;은 성공하지만 Claude Code가 실패한다면, Claude Code가 보내는 preflight 요청과 헤더가 &lt;code&gt;curl&lt;/code&gt;과 다를 가능성이 높습니다. &lt;code&gt;--debug&lt;/code&gt; 로그를 기준으로 비교하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog로 API 요청 검사하기
&lt;/h2&gt;

&lt;p&gt;타사 공급자 통합을 디버깅할 때 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 사용하면 LLM 게이트웨이로 전달되는 요청과 응답을 쉽게 검사할 수 있습니다.&lt;/p&gt;

&lt;p&gt;게이트웨이의 &lt;code&gt;/v1/messages&lt;/code&gt; 엔드포인트에 대한 컬렉션을 만들고 다음 값을 컬렉션 변수로 저장하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Authorization&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;anthropic-version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;anthropic-beta&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;모델명&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이렇게 하면 Claude Code를 매번 재실행하지 않고도 OpenRouter, LiteLLM, vLLM 같은 공급자별 응답을 비교할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-30.png" alt="헤더가 있는 API 요청 구성을 보여주는 Apidog 스크린샷" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;특히 &lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt;가 헤더 전달 문제인지 확인할 때 유용합니다. Claude Code 설정을 계속 바꾸기 전에 게이트웨이가 어떤 헤더를 실제로 받고 전달하는지 먼저 검증할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  알아두면 좋은 Claude Code 설정
&lt;/h2&gt;

&lt;h3&gt;
  
  
  베타 헤더 의존성 비활성화
&lt;/h3&gt;

&lt;p&gt;일부 엔터프라이즈 게이트웨이는 사용자 지정 헤더를 전달하지 못합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 설정은 엔터프라이즈 구성 검증에서 베타 기능 핸드셰이크를 제거합니다. 단, 베타 헤더에 의해 활성화되는 일부 기능은 사용할 수 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  게이트웨이 모델 자동 검색
&lt;/h3&gt;

&lt;p&gt;Claude Code v2.1.129부터 게이트웨이의 &lt;code&gt;/v1/models&lt;/code&gt;를 사용해 &lt;code&gt;/model&lt;/code&gt; 선택기를 채울 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code는 시작 시 게이트웨이의 모델 목록을 조회합니다. 단, &lt;code&gt;claude&lt;/code&gt; 또는 &lt;code&gt;anthropic&lt;/code&gt;으로 시작하는 모델 ID만 자동 추가됩니다. DeepSeek 같은 모델은 여전히 다음처럼 수동 지정이 필요할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_DEFAULT_SONNET_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"deepseek/deepseek-v4-pro"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  사용자 지정 모델 선택기 항목 추가
&lt;/h3&gt;

&lt;p&gt;세션 중 &lt;code&gt;/model&lt;/code&gt; 선택기에서 사용자 지정 모델을 고르고 싶다면 다음 변수를 사용할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_CUSTOM_MODEL_OPTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"deepseek/deepseek-v4-pro"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_CUSTOM_MODEL_OPTION_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"DeepSeek V4 Pro"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Claude Opus보다 17배 저렴"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 항목은 &lt;code&gt;/model&lt;/code&gt; 선택기에 표시되어 기본 Claude 모델과 게이트웨이 모델을 쉽게 전환할 수 있게 해줍니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  관련 가이드
&lt;/h2&gt;

&lt;p&gt;사용자 지정 모델 백엔드로 Claude Code 에이전트 기능을 실험하고 있다면 다음 글도 참고하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://apidog.com/blog/how-to-write-agents-md-files?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;API 개발 팀을 위한 AGENTS.md 파일 작성 방법&lt;/a&gt; — 특정 스택에 맞게 Claude Code 동작 구성&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://apidog.com/blog/ruflo-multi-agent-claude-code?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Ruflo: Claude Code를 위한 다중 에이전트 오케스트레이션&lt;/a&gt; — Claude Code에 스웜, 영구 메모리, 100개 이상의 MCP 도구 추가&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://apidog.com/blog/get-free-unlimited-claude-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Puter.js를 통해 무료 무제한 Claude API 이용하기&lt;/a&gt; — 클라이언트 앱을 구축하는 경우 브라우저 기반 대안&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://apidog.com/blog/best-local-llms-2026?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;최고의 로컬 LLM 2026&lt;/a&gt; — vLLM으로 로컬 추론을 실행하려는 경우&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code에서 타사 공급자를 사용하는 것이 Anthropic 약관 위반인가요?
&lt;/h3&gt;

&lt;p&gt;아닙니다. Anthropic은 Bedrock, Vertex AI, Foundry 및 사용자 지정 게이트웨이를 통한 라우팅을 위해 &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; 패턴을 지원합니다.&lt;/p&gt;

&lt;p&gt;2026년 4월 차단된 것은 Claude Code 클라이언트 ID를 위장해 구독 가격으로 Anthropic 자체 API에 접근하던 일부 타사 도구입니다. 자체 게이트웨이나 OpenRouter 같은 공급자를 자신의 API 키로 사용하는 것은 별개의 문제입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code의 에이전트 루프가 DeepSeek V4 Pro와 작동하나요?
&lt;/h3&gt;

&lt;p&gt;핵심 루프는 작동합니다.&lt;/p&gt;

&lt;p&gt;예를 들어 다음 작업은 가능합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;파일 편집&lt;/li&gt;
&lt;li&gt;셸 명령 실행&lt;/li&gt;
&lt;li&gt;다단계 작업 수행&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;다만 타사 공급자에서는 다음 기능이 제한될 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP 서버 도구&lt;/li&gt;
&lt;li&gt;이미지/시각 입력&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 기능이 필요하다면 Anthropic API, Bedrock 또는 Vertex를 계속 사용해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  엔터프라이즈 플랜이 아닌데 왜 &lt;code&gt;enterprise config&lt;/code&gt;라고 나오나요?
&lt;/h3&gt;

&lt;p&gt;Claude Code는 타사 공급자 설정을 내부적으로 &lt;code&gt;enterprise config&lt;/code&gt;라고 부릅니다. 이는 플랜 등급을 의미하는 것이 아니라 코드 수준의 레이블입니다.&lt;/p&gt;

&lt;p&gt;개별 개발자도 사용자 지정 타사 공급자를 구성할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  세션 중 Anthropic과 타사 공급자를 전환할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;단일 세션 내에서는 어렵습니다. 기본 URL은 Claude Code 시작 시 읽힙니다.&lt;/p&gt;

&lt;p&gt;전환하려면 다음 순서로 진행하세요.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Claude Code 종료&lt;/li&gt;
&lt;li&gt;환경 변수 또는 &lt;code&gt;settings.json&lt;/code&gt; 변경&lt;/li&gt;
&lt;li&gt;새 세션 시작&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/aattaran/deepclaude" rel="noopener noreferrer"&gt;DeepClaude&lt;/a&gt;는 이 전환을 &lt;code&gt;--backend ds&lt;/code&gt;, &lt;code&gt;--backend anthropic&lt;/code&gt; 같은 CLI 플래그로 감싸서 처리합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  기업 방화벽 뒤의 게이트웨이를 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;가능합니다. 실행 전에 프록시를 설정하세요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://your-proxy:8080"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://your-internal-gateway"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;기업 프록시가 TLS를 가로채는 경우 CA 인증서를 추가합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NODE_EXTRA_CA_CERTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/corporate-ca-bundle.pem"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;curl&lt;/code&gt; 테스트는 성공하는데 Claude Code는 실패합니다. 무엇이 다른가요?
&lt;/h3&gt;

&lt;p&gt;Claude Code는 일반 &lt;code&gt;curl&lt;/code&gt; 요청 외에도 사전 검증 요청을 보냅니다. 이 요청에는 다음이 포함될 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;anthropic-beta&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;anthropic-version&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;X-Claude-Code-Session-Id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;검증용 JSON 본문&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;claude --debug&lt;/code&gt;로 실제 preflight 요청을 확인한 뒤, 해당 헤더와 본문을 &lt;code&gt;curl&lt;/code&gt; 테스트에 반영해 비교하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  결론
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Invalid custom3p enterprise config&lt;/code&gt;는 대부분 정책 차단이 아니라 구성 검증 실패입니다.&lt;/p&gt;

&lt;p&gt;해결 순서는 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt;에서 &lt;code&gt;/v1&lt;/code&gt; 제거&lt;/li&gt;
&lt;li&gt;공급자에 맞는 인증 변수 사용

&lt;ul&gt;
&lt;li&gt;Bearer 토큰: &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;API 키 헤더: &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.claude/settings.json&lt;/code&gt; JSON 검증&lt;/li&gt;
&lt;li&gt;새 설치 환경에서 온보딩 플래그 확인&lt;/li&gt;
&lt;li&gt;게이트웨이 헤더 전달 확인&lt;/li&gt;
&lt;li&gt;관리 정책 충돌 확인&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;구성이 정상적으로 검증되면 Claude Code의 에이전트 루프를 OpenRouter, LiteLLM, vLLM 같은 백엔드로 라우팅할 수 있습니다. DeepSeek V4 Pro를 OpenRouter 또는 LiteLLM을 통해 사용하는 구성은 많은 Claude Code 워크플로우에서 비용을 줄이는 대안이 될 수 있습니다. 단, MCP 도구와 시각 입력처럼 Anthropic API가 필요한 기능은 제한될 수 있습니다.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>무료 무제한 Gemini API 받기</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Sat, 09 May 2026 07:00:08 +0000</pubDate>
      <link>https://forem.com/rihpig/muryo-mujehan-gemini-api-badgi-47p1</link>
      <guid>https://forem.com/rihpig/muryo-mujehan-gemini-api-badgi-47p1</guid>
      <description>&lt;p&gt;Google의 Gemini 제품군은 대용량 워크로드에 적합한 최신 모델 라인업입니다. Gemini 2.5 Pro는 백만 토큰당 $1.25 / $10 수준이고, Flash 계열은 더 저렴합니다. 하지만 무료 공개 앱, 사이드 프로젝트, 해커톤 프로젝트처럼 사용자가 많아지면 비용은 빠르게 누적됩니다. Puter.js는 이 과금 구조를 다르게 처리합니다. 개발자가 Google API 키를 관리하지 않고도 Gemini 2.5 Pro, 2.5 Flash, 2.0 Flash, 3 Flash Preview, Gemma 2/3/4 계열을 사용할 수 있으며, 사용량은 최종 사용자의 Puter 계정에 귀속됩니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;오늘 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Puter.js&lt;/strong&gt;를 사용하면 Google API 키, Google Cloud 프로젝트, 서버 없이 Gemini 및 Gemma 모델을 브라우저에서 호출할 수 있습니다.&lt;/li&gt;
&lt;li&gt;지원 Gemini 모델: &lt;strong&gt;2.5 Pro, 2.5 Flash, 2.5 Flash Lite, 2.0 Flash, 2.0 Flash Lite, 3 Flash Preview&lt;/strong&gt; 및 일부 이전 프리뷰 버전.&lt;/li&gt;
&lt;li&gt;지원 Gemma 모델: 여러 크기의 &lt;strong&gt;Gemma 2, 3, 4&lt;/strong&gt; 계열.&lt;/li&gt;
&lt;li&gt;설치는 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 태그 하나로 끝납니다.&lt;/li&gt;
&lt;li&gt;채팅, 스트리밍, 이미지 입력, 온도 조절을 브라우저에서 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;사용량은 최종 사용자의 Puter 계정에 연결되므로 개발자는 Google API 비용을 직접 부담하지 않습니다.&lt;/li&gt;
&lt;li&gt;Puter 기반 프로토타입과 공식 Gemini API를 비교하거나 마이그레이션 계획을 세울 때는 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  “무료 무제한”이 작동하는 방식
&lt;/h2&gt;

&lt;p&gt;Puter.js는 개발자가 Google AI Studio 키를 발급받고 모든 토큰 비용을 부담하는 방식이 아닙니다. 대신 사용자가 Puter에 로그인하고, 해당 사용자의 Puter 계정 잔액에서 호출 비용이 처리됩니다. 새 Puter 계정에는 초기 크레딧이 제공되며, 사용자는 필요하면 추가로 충전할 수 있습니다.&lt;/p&gt;

&lt;p&gt;개발자 입장에서 얻는 이점은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google Cloud 프로젝트가 필요 없습니다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google AI Studio 키를 저장하거나 노출할 필요가 없습니다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;서버 없이 정적 웹앱에서도 Gemini를 호출할 수 있습니다.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;개발자 계정 기준의 토큰 비용 부담이 없습니다.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;주의할 점도 있습니다. Puter.js는 브라우저 우선 방식입니다. 로그인한 사용자 세션을 전제로 하므로, 백엔드 cron 작업, 배치 처리, 서버 간 호출에는 적합하지 않습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  1단계: 설치
&lt;/h2&gt;

&lt;p&gt;정적 HTML에서는 CDN 스크립트 하나만 추가하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;번들러 기반 앱에서는 패키지로 설치할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @heyputer/puter.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@heyputer/puter.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2단계: 모델 선택
&lt;/h2&gt;

&lt;p&gt;Puter에서 사용할 수 있는 주요 Gemini 및 Gemma 모델은 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;모델 ID&lt;/th&gt;
&lt;th&gt;사용 시점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemini-2.5-pro&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;복잡한 추론, 긴 컨텍스트 분석, 고품질 응답이 필요한 작업&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemini-2.5-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;대부분의 일반 채팅, Q&amp;amp;A, 콘텐츠 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemini-2.5-flash-lite&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;대량 분류, 태깅, 짧은 응답 중심 작업&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemini-2.0-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;안정적인 기준선이 필요한 경우&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemini-3-flash-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;최신 Flash 프리뷰 모델을 테스트할 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemma-3-27b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;오픈 Gemma 기반 지시 튜닝 모델이 필요한 경우&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;google/gemma-4-31b-it&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;더 큰 오픈 Gemma 계열을 테스트할 때&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;대부분의 앱에서는 &lt;code&gt;google/gemini-2.5-flash&lt;/code&gt;를 기본값으로 두는 것이 좋습니다. 복잡한 추론 작업만 &lt;code&gt;google/gemini-2.5-pro&lt;/code&gt;로 올리고, 대량 분류나 단순 태깅은 &lt;code&gt;google/gemini-2.5-flash-lite&lt;/code&gt;로 낮추면 됩니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  3단계: Gemini 호출하기
&lt;/h2&gt;

&lt;p&gt;가장 작은 예제는 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;머신러닝을 세 문장으로 설명해 주세요.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;실행 흐름은 간단합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;브라우저에서 HTML 파일을 엽니다.&lt;/li&gt;
&lt;li&gt;사용자가 Puter에 로그인합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;puter.ai.chat()&lt;/code&gt;이 Gemini 모델을 호출합니다.&lt;/li&gt;
&lt;li&gt;응답이 페이지에 출력됩니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;API 키, 환경 변수, 백엔드 서버가 필요 없습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  4단계: 응답 스트리밍하기
&lt;/h2&gt;

&lt;p&gt;채팅 UI나 긴 답변을 다룰 때는 스트리밍을 사용하는 편이 좋습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;광합성에 대해 자세히 설명해 주세요.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;outputDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;part.text&lt;/code&gt;는 응답의 일부 청크입니다. 이를 UI에 순차적으로 추가하면 사용자는 답변이 실시간으로 생성되는 것처럼 볼 수 있습니다.&lt;/p&gt;

&lt;p&gt;간단한 UI 예시는 다음과 같이 구성할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"output"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Next.js API Route와 Server Action의 차이를 설명해 주세요.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;outputDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5단계: 이미지 입력 사용하기
&lt;/h2&gt;

&lt;p&gt;Gemini는 텍스트뿐 아니라 이미지 입력도 처리할 수 있습니다. Puter에서는 두 번째 인수로 이미지 URL을 전달합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;이 이미지에서 무엇을 보시나요? 색상, 사물, 분위기를 설명해 주세요.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://assets.puter.site/doge.jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;적용 가능한 사용 사례는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;이미지 대체 텍스트 생성&lt;/li&gt;
&lt;li&gt;제품 이미지 태그 지정&lt;/li&gt;
&lt;li&gt;스크린샷 분석&lt;/li&gt;
&lt;li&gt;시각적 Q&amp;amp;A&lt;/li&gt;
&lt;li&gt;OCR 보조 작업&lt;/li&gt;
&lt;li&gt;접근성 도구&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;자연 이미지와 다이어그램에는 잘 맞지만, 텍스트가 매우 많은 스크린샷에서는 다른 모델이 더 나은 결과를 줄 수도 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  6단계: 온도 조절하기
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;temperature&lt;/code&gt;는 응답의 다양성과 창의성을 조절합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;로봇 요리사에 대한 창의적인 단편 소설을 써 주세요.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;실무에서는 다음 기준으로 시작하면 됩니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;목적&lt;/th&gt;
&lt;th&gt;권장 temperature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;사실 기반 Q&amp;amp;A&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.0&lt;/code&gt; ~ &lt;code&gt;0.3&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON, 분류, 태깅&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.0&lt;/code&gt; ~ &lt;code&gt;0.2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;일반 채팅&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.5&lt;/code&gt; ~ &lt;code&gt;0.7&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;창의적 글쓰기&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.7&lt;/code&gt; ~ &lt;code&gt;1.0&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;구조화된 출력이 필요하면 낮게 설정하고, 아이디어 생성이나 스토리 작성에는 높게 설정하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  7단계: 다중 턴 대화 만들기
&lt;/h2&gt;

&lt;p&gt;이전 대화 맥락을 유지하려면 메시지 배열을 전달합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;저는 Postgres와 함께 Next.js 앱을 만들고 있습니다.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;알겠습니다. 무엇을 도와드릴까요?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;마이그레이션 구조를 어떻게 잡아야 할까요?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;채팅 앱에서는 새 메시지가 생길 때마다 배열에 추가하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;중요한 점은 다음 호출 전에 이전 사용자 메시지와 어시스턴트 응답을 모두 배열에 보존하는 것입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  동일한 프롬프트로 Gemini와 다른 모델 비교하기
&lt;/h2&gt;

&lt;p&gt;Puter는 하나의 인터페이스로 여러 LLM을 호출할 수 있습니다. 같은 프롬프트를 여러 모델에 보내면 지연 시간과 응답 품질을 비교할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-ai/grok-4.3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;이 React 컴포넌트를 훅을 사용하도록 리팩토링하세요: ...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;---&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;비교할 때는 최소한 다음 항목을 기록하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;첫 토큰까지의 체감 지연 시간&lt;/li&gt;
&lt;li&gt;전체 응답 시간&lt;/li&gt;
&lt;li&gt;코드 정확도&lt;/li&gt;
&lt;li&gt;포맷 준수 여부&lt;/li&gt;
&lt;li&gt;재시도 필요 여부&lt;/li&gt;
&lt;li&gt;사용자가 실제로 선호하는 응답&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;한 번의 실행 결과만으로 결정하지 말고, 실제 앱에서 자주 쓰는 프롬프트 세트를 기준으로 반복 테스트하는 것이 좋습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  얻는 것과 얻지 못하는 것
&lt;/h2&gt;

&lt;h3&gt;
  
  
  얻는 것
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Gemini 2.5 / 2.0 / 3 Flash 계열 및 2.5 Pro&lt;/li&gt;
&lt;li&gt;Gemma 2 / 3 / 4 계열&lt;/li&gt;
&lt;li&gt;다중 턴 대화&lt;/li&gt;
&lt;li&gt;스트리밍 응답&lt;/li&gt;
&lt;li&gt;이미지 URL 기반 비전 입력&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;temperature&lt;/code&gt;, &lt;code&gt;max_tokens&lt;/code&gt;, 시스템 프롬프트 등 기본 옵션&lt;/li&gt;
&lt;li&gt;브라우저 기반 앱에서 사용할 수 있는 간단한 통합 방식&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  얻지 못할 수 있는 것
&lt;/h3&gt;

&lt;p&gt;Puter 버전과 모델 지원 상태에 따라 다음 기능은 제한될 수 있습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gemini의 네이티브 함수 호출&lt;/li&gt;
&lt;li&gt;코드 실행 도구&lt;/li&gt;
&lt;li&gt;Google 검색 기반 기능&lt;/li&gt;
&lt;li&gt;Gemini의 전체 2M 토큰 컨텍스트 상한&lt;/li&gt;
&lt;li&gt;브라우저 세션 없는 서버 측 사용&lt;/li&gt;
&lt;li&gt;Google API의 직접적인 비율 제한 정보&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;코드 실행, 검색 기반 에이전트, 매우 긴 컨텍스트, 서버 측 자동화가 핵심이면 공식 Google AI Studio API가 더 적합합니다. 일반적인 채팅, Q&amp;amp;A, 콘텐츠 생성, 이미지 설명 작업이라면 Puter로 충분한 경우가 많습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Puter와 공식 Gemini API 선택 기준
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Puter를 선택할 때
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;무료 공개 앱을 출시하지만 API 비용 노출을 피하고 싶을 때&lt;/li&gt;
&lt;li&gt;해커톤이나 프로토타입을 빠르게 만들 때&lt;/li&gt;
&lt;li&gt;Google Cloud 프로젝트를 만들고 싶지 않을 때&lt;/li&gt;
&lt;li&gt;정적 사이트나 브라우저 확장 프로그램에서 Gemini를 쓰고 싶을 때&lt;/li&gt;
&lt;li&gt;사용자가 Puter 로그인 단계를 받아들일 수 있을 때&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  공식 Gemini API를 선택할 때
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;서버 측 호출이 필요할 때&lt;/li&gt;
&lt;li&gt;cron, 배치, 웹훅에서 모델을 호출해야 할 때&lt;/li&gt;
&lt;li&gt;코드 실행이나 검색 기반 기능이 필요할 때&lt;/li&gt;
&lt;li&gt;전체 2M 컨텍스트 상한이 필요한 워크로드일 때&lt;/li&gt;
&lt;li&gt;Google과의 직접 계약 관계가 필요한 규정 준수 환경일 때&lt;/li&gt;
&lt;li&gt;사용자가 Puter 로그인을 허용하지 않을 때&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gemini 3 Flash를 직접 사용하는 방법은 &lt;a href="http://apidog.com/blog/how-to-use-gemini-3-flash-preview-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Gemini 3 Flash Preview API 사용 방법&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog에서 통합 테스트하기
&lt;/h2&gt;

&lt;p&gt;Puter 호출은 브라우저에서 발생하므로 일반적인 백엔드 테스트 러너에서 그대로 실행하기 어렵습니다. 대신 다음 구조로 테스트 환경을 나누는 것이 좋습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Puter 스크립트를 포함한 작은 정적 테스트 페이지를 만듭니다.&lt;/li&gt;
&lt;li&gt;프롬프트를 쿼리 파라미터나 입력 폼으로 전달합니다.&lt;/li&gt;
&lt;li&gt;공식 Gemini API로 마이그레이션할 가능성이 있다면 Apidog에서 별도 컬렉션을 구성합니다.&lt;/li&gt;
&lt;li&gt;Puter 프로토타입 환경과 Gemini API 환경을 분리해 둡니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;예시 환경 구성:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;환경&lt;/th&gt;
&lt;th&gt;용도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;puter-prototype&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Puter 페이지를 호스팅하는 localhost 또는 정적 URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gemini-prod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;https://generativelanguage.googleapis.com/v1&lt;/code&gt; 기반 공식 API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드&lt;/a&gt;한 뒤 두 환경을 만들어 두면, Puter 기반 프로토타입에서 공식 Gemini API로 전환할 때 요청 구조를 더 쉽게 비교할 수 있습니다.&lt;/p&gt;

&lt;p&gt;API 테스트 패턴은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;도 참고할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Puter를 통한 기타 무료 LLM 경로
&lt;/h2&gt;

&lt;p&gt;같은 사용자 지불 모델은 다른 주요 LLM에도 적용됩니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://apidog.com/blog/get-free-unlimited-claude-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 무제한 Claude API 얻기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://apidog.com/blog/get-free-unlimited-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 무제한 GPT-5.5 API 얻기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://apidog.com/blog/how-to-use-grok-4-3-api-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 Grok 4.3 사용 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://apidog.com/blog/get-free-unlimited-deepseek-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 무제한 DeepSeek API 얻기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Puter에서는 &lt;code&gt;model&lt;/code&gt; 문자열을 바꾸는 방식으로 공급자를 전환할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;API 설계를 리뷰해 주세요.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google/gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;다른 모델을 테스트하려면 &lt;code&gt;model&lt;/code&gt; 값만 변경합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;API 설계를 리뷰해 주세요.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-sonnet-4-6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  정말 무제한인가요?
&lt;/h3&gt;

&lt;p&gt;개발자 계정 기준으로는 사용량을 직접 부담하지 않습니다. 최종 사용자의 Puter 계정 잔액에서 호출이 처리됩니다. 새 계정에는 초기 크레딧이 제공되며, 사용자가 더 필요하면 충전할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Google 계정이나 Google Cloud 프로젝트가 필요한가요?
&lt;/h3&gt;

&lt;p&gt;아니요. Puter가 Google API 호출을 처리하므로 개발자는 Google API 키를 직접 관리하지 않아도 됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  프로덕션에서 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;브라우저 기반 앱이라면 사용할 수 있습니다. 다만 사용자에게 Puter 로그인 단계가 필요하다는 점을 제품 흐름에서 고려해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puter를 통한 Gemini가 공식 API와 동일하게 동작하나요?
&lt;/h3&gt;

&lt;p&gt;Puter는 사용자를 대신해 모델 호출을 처리합니다. 모델 출력은 같은 모델을 기준으로 하지만, Puter 계층이 추가되므로 지연 시간이 달라질 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gemini의 2M 토큰 컨텍스트도 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;Puter가 모든 모델 변형에서 전체 2M 토큰 상한을 노출한다고 가정하면 안 됩니다. 극단적으로 긴 컨텍스트가 필요하면 공식 Google AI Studio API를 사용하는 편이 안전합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discord 봇이나 백엔드 서비스에서 Puter Gemini를 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;권장되지 않습니다. Puter는 브라우저 우선이며 사용자 세션을 전제로 합니다. Discord 봇, cron, 백엔드 서비스는 공식 Gemini API를 직접 사용하는 것이 적합합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  기본 모델은 무엇을 쓰면 되나요?
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;google/gemini-2.5-flash&lt;/code&gt;를 기본값으로 시작하세요. 대부분의 프롬프트에서 속도와 품질의 균형이 좋습니다. 복잡한 추론은 &lt;code&gt;google/gemini-2.5-pro&lt;/code&gt;, 대량 분류는 &lt;code&gt;google/gemini-2.5-flash-lite&lt;/code&gt;로 분기하면 됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  이미지 생성도 지원되나요?
&lt;/h3&gt;

&lt;p&gt;Puter는 현재 OpenAI의 &lt;code&gt;gpt-image-2&lt;/code&gt; 및 DALL-E 변형을 통해 이미지 생성을 노출하며, Imagen은 아닙니다. 이미지 생성 경로는 &lt;a href="http://apidog.com/blog/get-free-unlimited-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;무료 무제한 GPT-5.5 API 얻기&lt;/a&gt;를 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  마무리
&lt;/h2&gt;

&lt;p&gt;Puter.js를 사용하면 Google Cloud 설정 없이 브라우저 기반 앱에서 Gemini를 빠르게 통합할 수 있습니다. 스크립트를 추가하고, &lt;code&gt;google/gemini-2.5-flash&lt;/code&gt;를 기본 모델로 선택한 뒤, 필요한 프롬프트를 호출하면 됩니다.&lt;/p&gt;

&lt;p&gt;서버 측 Gemini 호출, 미세 조정, 코드 실행 도구, 전체 2M 토큰 컨텍스트가 필요하다면 공식 Google AI Studio API가 더 적합합니다. 반대로 프로토타입, 해커톤, 무료 공개 앱, 정적 사이트라면 Puter가 훨씬 빠른 시작점이 될 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 요청을 구성하고, Puter 기반 프로토타입과 공식 Gemini API를 비교해 보세요. 실제 프롬프트, 응답 품질, 지연 시간 기준으로 앱에 맞는 경로를 선택하는 것이 가장 안전합니다.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>무료 GPT-5.5 API 및 모든 OpenAI 모델 무제한 사용</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Sat, 09 May 2026 02:36:30 +0000</pubDate>
      <link>https://forem.com/rihpig/muryo-gpt-55-api-mic-modeun-openai-model-mujehan-sayong-2ebg</link>
      <guid>https://forem.com/rihpig/muryo-gpt-55-api-mic-modeun-openai-model-mujehan-sayong-2ebg</guid>
      <description>&lt;p&gt;OpenAI의 GPT-5.5는 유료 API와 함께 제공됩니다. 입력 토큰 100만 개당 5달러, 출력 토큰 100만 개당 30달러가 필요합니다. 사이드 프로젝트, 해커톤 빌드, 무료 공개 앱에서는 이 비용이 시작 장벽이 될 수 있습니다. Puter.js는 OpenAI 키 없이 GPT-5.5, GPT-5.5 Pro, GPT-5.x 변형, GPT-Image-2, DALL-E, OpenAI TTS를 브라우저에서 사용할 수 있게 하며, 비용은 개발자가 아니라 최종 사용자의 Puter 계정에 귀속됩니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;오늘 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Puter.js&lt;/strong&gt;는 OpenAI API 키, OpenAI 계정, 서버 없이 브라우저에서 OpenAI 모델을 호출할 수 있게 합니다.&lt;/li&gt;
&lt;li&gt;지원 텍스트 모델에는 &lt;strong&gt;gpt-5.5, gpt-5.5-pro, gpt-5.4, gpt-5, gpt-5-mini, o1, o3, gpt-4.1, gpt-4o&lt;/strong&gt;가 포함됩니다.&lt;/li&gt;
&lt;li&gt;이미지 모델: &lt;strong&gt;gpt-image-2, gpt-image-1.5, dall-e-3&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;TTS 모델: &lt;strong&gt;gpt-4o-mini-tts, tts-1, tts-1-hd&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;기본 사용법은 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 태그 추가 후 &lt;code&gt;puter.ai.chat()&lt;/code&gt; 호출입니다.&lt;/li&gt;
&lt;li&gt;스트리밍, 함수 호출, 비전 입력, 이미지 생성, 텍스트 음성 변환을 브라우저에서 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;사용량은 최종 사용자의 Puter 계정에서 차감됩니다.&lt;/li&gt;
&lt;li&gt;마이그레이션 전에는 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 사용해 Puter 호출과 공식 OpenAI API 호출을 같은 프롬프트로 비교하세요.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Puter.js의 “무료 무제한” 구조
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.puter.com/tutorials/free-unlimited-openai-api/" rel="noopener noreferrer"&gt;Puter.js&lt;/a&gt;는 일반적인 LLM 과금 흐름을 바꿉니다.&lt;/p&gt;

&lt;p&gt;보통은 개발자가 OpenAI API 키를 만들고, 모든 사용자 요청의 토큰 비용을 부담합니다. Puter.js에서는 사용자가 Puter에 로그인하고, 해당 사용자의 Puter 계정에서 사용량이 차감됩니다.&lt;/p&gt;

&lt;p&gt;개발자 입장에서 얻는 이점은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;OpenAI API 키를 저장하지 않아도 됩니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;.env&lt;/code&gt;, 서버 시크릿, 키 로테이션, 키 유출 대응이 필요 없습니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;서버 없이 브라우저에서 바로 호출할 수 있습니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
정적 HTML, Vite/React 앱, 브라우저 확장 프로그램, 해커톤 데모에 적합합니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;개발자 계정 기준 사용량 제한을 직접 부담하지 않습니다.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
각 사용자가 자신의 Puter 계정으로 사용량을 처리합니다.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;단점도 명확합니다.&lt;/p&gt;

&lt;p&gt;Puter.js는 브라우저 우선 방식입니다. 로그인된 사용자 세션을 전제로 하므로 백엔드 Node.js 배치 작업, 크론 작업, 웹훅 핸들러 같은 서버 측 워크로드에는 공식 OpenAI API가 더 적합합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  1단계: Puter.js 설치
&lt;/h2&gt;

&lt;p&gt;가장 빠른 방법은 CDN 스크립트를 추가하는 것입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;정적 HTML 파일이라면 이것만으로 충분합니다.&lt;/p&gt;

&lt;p&gt;번들러 기반 앱에서는 NPM 패키지를 사용할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @heyputer/puter.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@heyputer/puter.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;선택 기준은 간단합니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;환경&lt;/th&gt;
&lt;th&gt;권장 방식&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;단일 HTML 파일&lt;/td&gt;
&lt;td&gt;CDN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;해커톤 프로토타입&lt;/td&gt;
&lt;td&gt;CDN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;정적 사이트&lt;/td&gt;
&lt;td&gt;CDN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React/Vue/Svelte 앱&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript 타입이 필요한 앱&lt;/td&gt;
&lt;td&gt;NPM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2단계: 사용할 모델 선택
&lt;/h2&gt;

&lt;p&gt;Puter는 GPT-5.x 라인업과 이전 OpenAI 모델을 노출합니다. 작업 유형에 따라 모델을 선택하세요.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;모델 ID&lt;/th&gt;
&lt;th&gt;사용 시기&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.5-pro&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;복잡한 추론, 코딩 에이전트, 긴 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;일반 채팅, 기본 추론, 대부분의 앱 기본값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.4-nano&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;빠른 분류, 대량 텍스트 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.4-mini&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;채팅 UI, 중간 난이도 작업&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gpt-5.3-codex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;코드 생성 및 코드 설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;복잡한 추론 체인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o1-pro&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;에이전트식 다단계 계획&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;gpt-4.1&lt;/code&gt;, &lt;code&gt;gpt-4o&lt;/code&gt;, &lt;code&gt;gpt-4o-mini&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;안정적인 기준 모델&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;이미지 생성 모델:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gpt-image-2&lt;/code&gt;: 최신 이미지 생성 모델&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpt-image-1.5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gpt-image-1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dall-e-3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dall-e-2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;텍스트 음성 변환 모델:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gpt-4o-mini-tts&lt;/code&gt;: 최신 TTS 모델&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tts-1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tts-1-hd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3단계: GPT-5.5 호출하기
&lt;/h2&gt;

&lt;p&gt;최소 예제는 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Explain WebSockets in three sentences&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 파일을 브라우저에서 열면 다음 흐름으로 동작합니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Puter.js가 로드됩니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;puter.ai.chat()&lt;/code&gt;이 GPT-5.5 호출을 생성합니다.&lt;/li&gt;
&lt;li&gt;사용자가 Puter에 로그인하거나 계정을 생성합니다.&lt;/li&gt;
&lt;li&gt;응답이 페이지에 출력됩니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;API 키, 서버, 환경 변수 없이 실행할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  4단계: 채팅 UI에 스트리밍 적용하기
&lt;/h2&gt;

&lt;p&gt;긴 답변이나 챗봇 UI에서는 전체 응답을 기다리는 것보다 스트리밍이 더 자연스럽습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Explain the theory of relativity in detail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;실제 UI에서는 &lt;code&gt;puter.print()&lt;/code&gt; 대신 DOM 요소에 이어 붙이면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;React Server Components를 실무 관점에서 설명해줘&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;part&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"output"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5단계: 이미지 입력으로 비전 기능 사용하기
&lt;/h2&gt;

&lt;p&gt;이미지 URL을 함께 전달하면 모델이 이미지를 읽고 답변할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What do you see in this image? Describe colors, objects, and mood.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://assets.puter.site/doge.jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;활용 예시는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;이미지 대체 텍스트 생성&lt;/li&gt;
&lt;li&gt;스크린샷 분석&lt;/li&gt;
&lt;li&gt;OCR 기반 텍스트 추출&lt;/li&gt;
&lt;li&gt;UI 버그 리포트 자동 요약&lt;/li&gt;
&lt;li&gt;접근성 도구&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6단계: 이미지 생성하기
&lt;/h2&gt;

&lt;p&gt;이미지 생성은 &lt;code&gt;puter.ai.txt2img()&lt;/code&gt;를 사용합니다. 이 함수는 생성된 이미지가 포함된 &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; 요소를 반환합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;txt2img&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A futuristic cityscape at night, cinematic, neon, rain&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-image-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageElement&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;컨테이너에 렌더링하려면 다음처럼 작성할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"image-result"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#image-result&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;txt2img&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A clean developer workspace with multiple monitors, flat illustration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-image-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageElement&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이미지 생성 비용은 사용자의 Puter 계정에서 처리됩니다. 공개 이미지 생성기를 만들 때 개발자가 직접 OpenAI 이미지 생성 비용을 부담하지 않아도 되는 구조입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  7단계: 텍스트를 음성으로 변환하기
&lt;/h2&gt;

&lt;p&gt;OpenAI TTS 모델은 &lt;code&gt;puter.ai.txt2speech()&lt;/code&gt;로 호출할 수 있습니다. 반환값은 생성된 음성을 포함하는 &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; 요소입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;txt2speech&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome back. Your account balance is $1,247.50.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4o-mini-tts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;controls&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;사용 예시는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;앱 온보딩 음성 안내&lt;/li&gt;
&lt;li&gt;접근성 내레이션&lt;/li&gt;
&lt;li&gt;대시보드 알림 음성&lt;/li&gt;
&lt;li&gt;짧은 팟캐스트 인트로&lt;/li&gt;
&lt;li&gt;학습용 문장 읽기&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8단계: 함수 호출 사용하기
&lt;/h2&gt;

&lt;p&gt;Puter의 함수 호출 형식은 OpenAI의 도구 호출 형식과 유사합니다. 먼저 도구를 선언합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_weather&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get the current weather for a city.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;모델에 도구를 전달합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What's the weather in Tokyo right now?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tools&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;모델이 도구 호출을 반환하면 애플리케이션 쪽에서 실행합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 여기에서 실제 get_weather 구현을 호출합니다.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;프로덕션에서 도구 기반 흐름을 검증하려면 &lt;a href="http://apidog.com/blog/mcp-server-testing-apidog?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog에서 MCP 서버 테스트&lt;/a&gt;를 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  9단계: &lt;code&gt;temperature&lt;/code&gt;와 &lt;code&gt;max_tokens&lt;/code&gt; 조정하기
&lt;/h2&gt;

&lt;p&gt;Puter 호출에서도 표준 OpenAI 스타일의 옵션을 전달할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tell me about Mars&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;실무에서는 다음 기준으로 설정하세요.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;옵션&lt;/th&gt;
&lt;th&gt;추천 값&lt;/th&gt;
&lt;th&gt;사용 상황&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;temperature: 0.0-0.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;td&gt;사실 기반 답변, 요약, 분류&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;temperature: 0.7-1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;높음&lt;/td&gt;
&lt;td&gt;창의적 글쓰기, 아이디어 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;제한 권장&lt;/td&gt;
&lt;td&gt;호출당 비용과 응답 길이 제어&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;공개 앱에서는 &lt;code&gt;max_tokens&lt;/code&gt;를 반드시 설정하는 편이 좋습니다. 사용자의 Puter 잔액을 과도하게 소모하는 긴 응답을 줄일 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  Puter에서 가능한 것과 제한되는 것
&lt;/h2&gt;

&lt;p&gt;Puter.js는 브라우저 앱에 적합한 OpenAI 접근 경로를 제공합니다. 다만 공식 OpenAI API 전체를 완전히 대체하는 것은 아닙니다.&lt;/p&gt;

&lt;p&gt;Puter에서 사용할 수 있는 기능:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPT-5.5, GPT-5.5 Pro, GPT-5.4 계열&lt;/li&gt;
&lt;li&gt;GPT-4.1, GPT-4o, o1, o3 등 이전 OpenAI 모델&lt;/li&gt;
&lt;li&gt;GPT-Image-2 및 DALL-E 기반 이미지 생성&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpt-4o-mini-tts&lt;/code&gt;를 포함한 OpenAI TTS&lt;/li&gt;
&lt;li&gt;스트리밍&lt;/li&gt;
&lt;li&gt;비전 입력&lt;/li&gt;
&lt;li&gt;함수 호출&lt;/li&gt;
&lt;li&gt;&lt;code&gt;temperature&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max_tokens&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;제한될 수 있는 기능:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responses API&lt;/li&gt;
&lt;li&gt;프롬프트 캐싱 비용 절감&lt;/li&gt;
&lt;li&gt;Files API&lt;/li&gt;
&lt;li&gt;브라우저 세션 없는 서버 측 호출&lt;/li&gt;
&lt;li&gt;OpenAI에서 직접 제공하는 rate limit 헤더&lt;/li&gt;
&lt;li&gt;OpenAI의 구조화된 출력 모드 및 JSON 스키마 강제 적용&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;브라우저 기반 프로토타입, 무료 공개 도구, 정적 사이트에는 Puter가 적합합니다. 서버 중심 워크로드나 엔터프라이즈 요구사항이 있다면 공식 OpenAI API를 사용하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  Puter와 공식 OpenAI API 선택 기준
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Puter를 선택하기 좋은 경우
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;무료 공개 앱을 만들고 있고 개발자가 API 비용을 부담하고 싶지 않을 때&lt;/li&gt;
&lt;li&gt;해커톤 또는 사이드 프로젝트를 빠르게 만들 때&lt;/li&gt;
&lt;li&gt;OpenAI 계정과 결제 설정 없이 프로토타입을 만들고 싶을 때&lt;/li&gt;
&lt;li&gt;정적 사이트 또는 브라우저 확장 프로그램에서 바로 LLM을 호출하고 싶을 때&lt;/li&gt;
&lt;li&gt;사용자가 Puter 로그인 흐름을 수용할 수 있을 때&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  공식 OpenAI API를 선택해야 하는 경우
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;서버 측 호출이 필요할 때&lt;/li&gt;
&lt;li&gt;크론 작업, 웹훅, 배치 처리가 필요할 때&lt;/li&gt;
&lt;li&gt;프롬프트 캐싱 비용 절감이 중요할 때&lt;/li&gt;
&lt;li&gt;Responses API, Files API, 구조화된 출력이 필요할 때&lt;/li&gt;
&lt;li&gt;BAA, SOC 2, 데이터 상주 같은 계약 및 컴플라이언스 요구가 있을 때&lt;/li&gt;
&lt;li&gt;사용자가 Puter 로그인 단계를 거치면 안 될 때&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;일반적인 전략은 Puter로 빠르게 프로토타입을 만들고, 서버 측 요구사항이나 API 표면 제약이 생기면 공식 OpenAI API로 마이그레이션하는 것입니다.&lt;/p&gt;

&lt;p&gt;유료 프로덕션 설정은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API 사용 방법&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog에서 마이그레이션 테스트하기
&lt;/h2&gt;

&lt;p&gt;Puter 호출은 브라우저에서 실행됩니다. 따라서 일반적인 백엔드 API 테스트 러너에서 Puter 호출 자체를 그대로 실행하기는 어렵습니다.&lt;/p&gt;

&lt;p&gt;대신 다음 방식으로 정리하면 마이그레이션이 쉬워집니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Puter 호출을 포함한 작은 정적 테스트 페이지를 만듭니다.&lt;/li&gt;
&lt;li&gt;프롬프트를 쿼리 파라미터로 받을 수 있게 구성합니다.&lt;/li&gt;
&lt;li&gt;공식 OpenAI API로 전환할 때 사용할 요청을 Apidog에 컬렉션으로 만듭니다.&lt;/li&gt;
&lt;li&gt;Puter 프로토타입과 OpenAI 프로덕션 환경을 별도 환경으로 관리합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96pq8yfcm9zepoxri4x9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96pq8yfcm9zepoxri4x9.png" alt="서로 다른 환경과 API 요청을 보여주는 Apidog 인터페이스 스크린샷." width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드&lt;/a&gt;한 뒤 환경을 두 개로 나누세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;puter-prototype&lt;/code&gt;: Puter 테스트 페이지를 호스팅하는 localhost URL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;openai-prod&lt;/code&gt;: &lt;code&gt;https://api.openai.com/v1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이렇게 구성하면 같은 프롬프트와 메시지 구조를 기준으로 Puter 결과와 공식 OpenAI API 결과를 비교할 수 있습니다.&lt;/p&gt;

&lt;p&gt;더 넓은 API 테스트 패턴은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;를 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;h3&gt;
  
  
  정말 무제한인가요?
&lt;/h3&gt;

&lt;p&gt;개발자 기준으로는 무제한입니다. 사용량은 최종 사용자의 Puter 계정에서 처리됩니다. 새 Puter 계정은 시작 크레딧을 받고, 더 많은 사용량이 필요하면 사용자가 충전할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenAI 계정이 필요한가요?
&lt;/h3&gt;

&lt;p&gt;아니요. 개발자는 OpenAI API 키를 만들 필요가 없습니다. Puter가 OpenAI와의 연결을 처리합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  프로덕션에서 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;브라우저 기반 앱이라면 사용할 수 있습니다. 핵심 판단 기준은 사용자가 Puter 로그인 흐름을 받아들일 수 있는지입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puter를 통한 GPT-5.5 출력은 공식 API와 동일한가요?
&lt;/h3&gt;

&lt;p&gt;Puter는 사용자 대신 공식 OpenAI API를 호출합니다. 모델 동작은 동일한 모델을 기준으로 하지만, 추가 통신 단계 때문에 지연 시간이 약간 늘어날 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  프롬프트 캐싱 비용 절감도 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;Puter는 현재 OpenAI의 프롬프트 캐싱 요금 제어를 노출하지 않습니다. 긴 고정 시스템 프롬프트를 자주 재사용하고 캐시 할인이 중요하다면 공식 OpenAI API를 사용하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  백엔드 서비스에서 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;권장되지 않습니다. Puter는 브라우저 우선이며 사용자 세션을 전제로 합니다. 백엔드 서비스에는 공식 OpenAI API가 더 적합합니다.&lt;/p&gt;

&lt;p&gt;무료 서버 측 옵션은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API를 무료로 사용하는 방법&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  기본 모델은 무엇을 쓰면 되나요?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;일반 추론: &lt;code&gt;gpt-5.5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;대량 분류: &lt;code&gt;gpt-5.4-nano&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;어려운 추론: &lt;code&gt;gpt-5.5-pro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;긴 추론 체인: &lt;code&gt;o3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  사용자에게 비용이 많이 청구되나요?
&lt;/h3&gt;

&lt;p&gt;대부분의 채팅형 사용은 세션당 몇 센트 수준입니다. 다만 긴 응답이나 이미지 생성은 더 많은 잔액을 사용할 수 있습니다. 공개 앱에서는 &lt;code&gt;max_tokens&lt;/code&gt;를 제한하고 불필요한 생성 호출을 줄이세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puter로 이미지도 생성할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;네. &lt;code&gt;txt2img()&lt;/code&gt;와 &lt;code&gt;gpt-image-2&lt;/code&gt; 또는 DALL-E 계열 모델을 사용하면 됩니다. 이미지 생성 비용은 사용자의 Puter 잔액에서 처리됩니다.&lt;/p&gt;

&lt;p&gt;공식 유료 API 가이드는 &lt;a href="http://apidog.com/blog/how-to-use-gpt-image-2-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-Image-2 API 사용 방법&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  마무리
&lt;/h2&gt;

&lt;p&gt;Puter.js는 브라우저 기반 앱에서 OpenAI 모델을 빠르게 붙이는 실용적인 방법입니다. 스크립트를 추가하고, 모델을 선택하고, &lt;code&gt;puter.ai.chat()&lt;/code&gt;을 호출하면 됩니다. API 키를 저장하지 않아도 되고, 개발자가 직접 토큰 비용을 부담하지 않아도 됩니다.&lt;/p&gt;

&lt;p&gt;다만 서버 측 워크로드, 프롬프트 캐싱, Responses API, Files API, 구조화된 출력이 필요하다면 공식 OpenAI API를 선택해야 합니다.&lt;/p&gt;

&lt;p&gt;프로토타입은 Puter로 빠르게 만들고, 프로덕션 전환 시점에는 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 요청을 정리해 공식 API와 비교하세요.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>2026년 그록 4.3 무료 사용법: 4가지 가능한 방법</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Sat, 09 May 2026 02:25:56 +0000</pubDate>
      <link>https://forem.com/rihpig/2026nyeon-geurog-43-muryo-sayongbeob-4gaji-ganeunghan-bangbeob-32ob</link>
      <guid>https://forem.com/rihpig/2026nyeon-geurog-43-muryo-sayongbeob-4gaji-ganeunghan-bangbeob-32ob</guid>
      <description>&lt;p&gt;Grok 4.3은 2026년 5월 현재 xAI의 주력 모델입니다. 100만 토큰 컨텍스트 윈도우와 기본 비디오 입력을 제공하며, 가격은 백만 토큰당 $1.25 / $2.50입니다. 유료 API 가격도 경쟁력이 있지만, 프로토타입, 학습, 사이드 프로젝트 단계라면 비용 없이 Grok 4.3을 테스트할 수 있는 경로가 있습니다: xAI Console 프로모션 크레딧, Puter.js의 사용자 지불 모델, 그리고 grok.com 및 X의 무료 채팅 UI입니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;이 글에서는 각 경로를 실제로 설정하고 호출하는 방법을 코드 중심으로 정리합니다. 유료 API 전체 가이드는 &lt;a href="http://apidog.com/blog/how-to-use-grok-4-3-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok 4.3 API 사용 방법&lt;/a&gt;을 참고하십시오. 음성 버전은 &lt;a href="http://apidog.com/blog/how-to-use-grok-voice-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok Voice 무료 사용 방법&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grok 4.3을 무료로 이용하는 세 가지 경로&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;xAI Console: 프로모션 크레딧 사용&lt;/li&gt;
&lt;li&gt;Puter.js: 최종 사용자가 사용료 지불&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://grok.com" rel="noopener noreferrer"&gt;grok.com&lt;/a&gt; 및 X: 코드 없는 채팅 UI&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;개발자에게 가장 실용적인 경로:&lt;/strong&gt; Puter.js. API 키와 결제 키를 앱에 넣지 않아도 됩니다.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;개인 프로토타이핑에 적합한 경로:&lt;/strong&gt; xAI Console. 신규 계정의 프로모션 크레딧으로 실제 API 통합을 검증할 수 있습니다.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;비개발자에게 적합한 경로:&lt;/strong&gt; &lt;a href="http://grok.com" rel="noopener noreferrer"&gt;grok.com&lt;/a&gt; 또는 X 앱. 일일 메시지 제한은 있지만 코드가 필요 없습니다.&lt;/li&gt;

&lt;li&gt;Puter.js의 Grok 4.3 모델 ID: &lt;code&gt;x-ai/grok-4.3&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;xAI 직접 호출 시 모델 ID: &lt;code&gt;grok-4.3&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 사용하면 xAI, OpenRouter 등 여러 제공업체에 동일한 요청을 보내고 응답, 지연 시간, 토큰 사용량을 비교할 수 있습니다.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  경로 1: xAI Console 프로모션 크레딧
&lt;/h2&gt;

&lt;p&gt;실제 프로덕션 API와 동일한 표면을 테스트하려면 xAI Console이 가장 직접적인 경로입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  단계 1: 계정 만들기
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;console.x.ai&lt;/code&gt;로 이동해 계정을 생성합니다.&lt;/p&gt;

&lt;p&gt;로그인은 X 계정을 통해 진행됩니다. X에서 요구하는 인증 외에 별도의 이메일 인증은 필요하지 않습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  단계 2: 프로모션 크레딧 확인하기
&lt;/h3&gt;

&lt;p&gt;xAI는 신규 계정에 무료 크레딧을 제공하는 프로모션을 운영합니다. 금액과 자격 기간은 변경될 수 있으므로 가입 후 &lt;strong&gt;Billing&lt;/strong&gt; 탭에서 현재 제공되는 크레딧을 확인하십시오.&lt;/p&gt;

&lt;p&gt;일반적인 사용 패턴은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;신규 계정 생성&lt;/li&gt;
&lt;li&gt;자동 갱신되지 않는 무료 크레딧 수령&lt;/li&gt;
&lt;li&gt;크레딧으로 API 통합 검증&lt;/li&gt;
&lt;li&gt;이후 유료 API로 전환하거나 Puter.js / 채팅 UI 경로로 이동&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;xAI는 과거에 특정 모델, 예를 들어 Grok 4.1 Fast 및 Agent Tools API에 대해 프로모션 기간 중 무료 액세스를 제공한 적도 있습니다. 다만 프로모션 조건은 항상 변경될 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  단계 3: API 키 설정하기
&lt;/h3&gt;

&lt;p&gt;API 키를 환경 변수로 저장합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;XAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"xai-..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  단계 4: Grok 4.3 호출하기
&lt;/h3&gt;

&lt;p&gt;xAI API는 OpenAI Chat Completions 형식과 호환됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.x.ai/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$XAI_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "grok-4.3",
    "messages": [
      {
        "role": "user",
        "content": "Explain prompt caching in three sentences."
      }
    ],
    "reasoning_effort": "low"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;프로토타입 단계에서는 &lt;code&gt;reasoning_effort&lt;/code&gt;를 &lt;code&gt;low&lt;/code&gt;로 두는 것이 좋습니다. &lt;code&gt;medium&lt;/code&gt; 또는 &lt;code&gt;high&lt;/code&gt;는 더 깊은 추론을 제공하지만 크레딧을 더 빠르게 소모합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node.js 예시
&lt;/h3&gt;

&lt;p&gt;OpenAI 호환 클라이언트를 사용하는 경우 기본 URL만 xAI로 바꾸면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;XAI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.x.ai/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grok-4.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Summarize prompt caching for API developers.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;reasoning_effort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  장점과 단점
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;장점&lt;/th&gt;
&lt;th&gt;단점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;실제 프로덕션 API 표면을 그대로 테스트 가능&lt;/td&gt;
&lt;td&gt;크레딧은 유한함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok 4.3 기능 사용 가능: 100만 컨텍스트, 비디오, 함수 호출&lt;/td&gt;
&lt;td&gt;프로모션 조건은 변경될 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;유료 전환 시 코드 변경이 거의 없음&lt;/td&gt;
&lt;td&gt;크레딧 범위 안에서만 무료 사용 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;백엔드, CLI, 자동화 테스트에 적합&lt;/td&gt;
&lt;td&gt;속도 제한은 별도로 적용될 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;권장 사용 사례:&lt;/strong&gt; 프로덕션 API가 실제로 어떻게 동작하는지 확인하려면 Console에서 시작하십시오. 전체 요청 스키마는 &lt;a href="http://apidog.com/blog/how-to-use-grok-4-3-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok 4.3 API 사용 방법&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  경로 2: Puter.js — 사용자 지불, 개발자 무료
&lt;/h2&gt;

&lt;p&gt;Puter.js는 공개 웹 앱이나 무료 도구를 만들 때 가장 실용적인 선택지입니다. 개발자가 API 비용을 부담하지 않고 Grok 4.3 기능을 사용자에게 제공할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48utw9k2o2vpe8zkl3kx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F48utw9k2o2vpe8zkl3kx.png" alt="Puter.js 예시" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  작동 방식
&lt;/h3&gt;

&lt;p&gt;Puter.js는 Grok, GPT, Claude, Gemini, DeepSeek 등 여러 LLM을 호출할 수 있는 JavaScript 클라이언트입니다.&lt;/p&gt;

&lt;p&gt;핵심은 결제 모델입니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;최종 사용자가 자신의 Puter 계정으로 사용료를 지불하고, 개발자는 지불하지 않습니다.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;개발자는 웹 페이지에 스크립트를 추가하고 &lt;code&gt;puter.ai.chat()&lt;/code&gt;을 호출합니다. 사용자가 기능을 실행하면 Puter가 로그인 또는 계정 생성을 요청하고, 이후 사용자의 세션과 잔액을 기준으로 AI 사용량이 처리됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  단계 1: HTML에 Puter.js 추가하기
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API 키, 서버 설정, 개발자 계정 생성이 필요 없습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  단계 2: Grok 4.3 호출하기
&lt;/h3&gt;

&lt;p&gt;Puter.js에서는 모델 ID로 &lt;code&gt;x-ai/grok-4.3&lt;/code&gt;을 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Summarize the trade-offs between SQLite and Postgres in three bullets.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-ai/grok-4.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;사용자가 처음 실행하면 Puter 로그인 또는 무료 계정 생성을 요청받습니다. 가입 시 소량의 무료 크레딧을 받을 수 있으며, 더 많은 사용량이 필요하면 사용자가 직접 충전합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  단계 3: UI에 연결하기
&lt;/h3&gt;

&lt;p&gt;간단한 입력 폼과 연결하면 다음처럼 사용할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://js.puter.com/v2/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"prompt"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"질문을 입력하세요"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"run"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Grok 4.3 실행&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;pre&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"output"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/pre&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promptInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prompt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;실행 중...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promptInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-ai/grok-4.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`오류: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  단계 4: 스트리밍 사용하기
&lt;/h3&gt;

&lt;p&gt;긴 응답을 표시할 때는 스트리밍이 더 적합합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Walk me through migrating a React app to Next.js.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-ai/grok-4.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;reasoning_effort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;브라우저 UI에서는 &lt;code&gt;process.stdout.write&lt;/code&gt; 대신 DOM에 누적해서 렌더링하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;puter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;React 앱을 Next.js로 마이그레이션하는 단계를 설명해줘.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-ai/grok-4.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;reasoning_effort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  장점과 단점
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;장점&lt;/th&gt;
&lt;th&gt;단점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;개발자 비용 $0&lt;/td&gt;
&lt;td&gt;사용자는 Puter에 로그인해야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API 키를 프론트엔드나 리포지토리에 넣지 않아도 됨&lt;/td&gt;
&lt;td&gt;백엔드 전용 시스템에는 적합하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;여러 LLM을 비슷한 방식으로 호출 가능&lt;/td&gt;
&lt;td&gt;xAI 직접 호출보다 지연 시간이 길 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공개 웹 앱, 무료 도구, 사이드 프로젝트에 적합&lt;/td&gt;
&lt;td&gt;브라우저 컨텍스트가 필요함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;권장 사용 사례:&lt;/strong&gt; 공개 웹 앱, 무료 도구, 사이드 프로젝트처럼 사용자가 직접 쿼리를 실행하는 앱이라면 Puter.js가 가장 깔끔합니다. 반대로 내부 자동화, Discord 봇, 서버 사이드 배치 작업처럼 사용자가 직접 호출하지 않는 시스템에는 적합하지 않습니다.&lt;/p&gt;

&lt;p&gt;비슷한 패턴은 &lt;a href="http://apidog.com/blog/how-to-use-deepseek-v4-api-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;DeepSeek V4 API를 무료로 사용하는 방법&lt;/a&gt;과 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API를 무료로 사용하는 방법&lt;/a&gt;에서도 확인할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  경로 3: grok.com 및 X 앱
&lt;/h2&gt;

&lt;p&gt;코드에서 호출할 필요 없이 Grok 4.3과 대화만 하면 된다면 채팅 UI를 사용하면 됩니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://grok.com" rel="noopener noreferrer"&gt;grok.com&lt;/a&gt;: 웹 채팅 UI입니다. X 계정으로 로그인합니다. 무료 사용자는 일일 메시지 할당량을 받으며, 할당량은 24시간마다 재설정됩니다.&lt;/li&gt;
&lt;li&gt;X 앱: 모바일 및 웹 X 앱의 Grok 탭에서 사용할 수 있습니다. 동일한 할당량 정책이 적용됩니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 경로는 API가 아니므로 자동화할 수 없습니다. 다음 작업에 적합합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;일회성 리서치 질문&lt;/li&gt;
&lt;li&gt;API 호출 전에 프롬프트 초안 검증&lt;/li&gt;
&lt;li&gt;모델 응답 스타일 확인&lt;/li&gt;
&lt;li&gt;Grok이 해당 작업에 적합한지 빠르게 테스트&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://grok.com" rel="noopener noreferrer"&gt;grok.com&lt;/a&gt;의 무료 티어는 기본적으로 더 작은 Grok 변형, 현재 Grok 4.1을 사용합니다. X의 프리미엄 구독은 더 높은 할당량으로 채팅 UI에서 Grok 4.3을 사용할 수 있게 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  경로 4: OpenRouter — 저렴하지만 Grok 4.3은 무료가 아님
&lt;/h2&gt;

&lt;p&gt;OpenRouter는 여러 모델 제공업체를 하나의 API 키와 가격 체계 뒤에 통합합니다.&lt;/p&gt;

&lt;p&gt;OpenRouter의 Grok 4.3은 xAI 직접 사용과 동일하게 백만 토큰당 $1.25 / $2.50이므로 무료는 아닙니다. 다만 OpenRouter는 일부 Grok 모델에 대해 완전히 무료인 모델 변형을 제공합니다. 예를 들어 &lt;code&gt;grok-4-fast:free&lt;/code&gt;는 Grok 4.3의 전체 추론 깊이가 필요하지 않을 때 사용할 수 있는 대체 옵션입니다.&lt;/p&gt;

&lt;p&gt;비용 없이 Grok 계열 출력을 테스트하고 싶다면 OpenRouter에서 &lt;code&gt;grok-4-fast:free&lt;/code&gt;를 사용할 수 있습니다. 반드시 Grok 4.3이 필요하다면 앞의 세 가지 경로 중 하나를 선택하십시오.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://openrouter.ai/api/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$OPENROUTER_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "x-ai/grok-4-fast:free",
    "messages": [
      {
        "role": "user",
        "content": "Hello!"
      }
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenRouter를 사용하면 동일한 API 키로 무료 DeepSeek 및 다른 오픈 모델도 테스트할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  네 가지 경로 비교
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;경로&lt;/th&gt;
&lt;th&gt;개발자 비용&lt;/th&gt;
&lt;th&gt;최종 사용자 비용&lt;/th&gt;
&lt;th&gt;최적의 용도&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;xAI Console 크레딧&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0, 크레딧 내에서&lt;/td&gt;
&lt;td&gt;해당 없음&lt;/td&gt;
&lt;td&gt;프로토타이핑, 프로덕션 API 학습&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Puter.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;영구적으로 $0&lt;/td&gt;
&lt;td&gt;세션당 몇 센트 가능&lt;/td&gt;
&lt;td&gt;공개 웹 앱, 사이드 프로젝트, 무료 도구&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;a href="http://grok.com" rel="noopener noreferrer"&gt;grok.com&lt;/a&gt; / X&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0, 할당량 내에서&lt;/td&gt;
&lt;td&gt;비개발자, 일회성 질문&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenRouter 무료 모델&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;해당 없음&lt;/td&gt;
&lt;td&gt;Grok 4.3이 아닌 Grok 계열 무료 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Apidog에서 여러 경로 테스트하기
&lt;/h2&gt;

&lt;p&gt;여러 제공업체가 동일하거나 유사한 모델을 제공할 때는 동일한 요청을 각각에 보내고 결과를 비교하는 방식이 가장 빠릅니다.&lt;/p&gt;

&lt;p&gt;권장 설정은 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apidog에서 새 환경을 만듭니다.&lt;/li&gt;
&lt;li&gt;환경 변수로 다음 값을 추가합니다.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;XAI_API_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BASE_URL&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;xAI 직접 호출용 요청을 만듭니다.&lt;/li&gt;
&lt;li&gt;OpenRouter 호출용 요청을 복제합니다.&lt;/li&gt;
&lt;li&gt;동일한 프롬프트를 실행합니다.&lt;/li&gt;
&lt;li&gt;응답 품질, 토큰 사용량, 지연 시간을 비교합니다.&lt;/li&gt;
&lt;li&gt;크레딧이 소진되면 환경만 전환합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Puter.js는 브라우저 전용 흐름이므로 이 API 테스트 루프에서는 제외하는 것이 일반적입니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드&lt;/a&gt;하고 새 컬렉션을 생성하십시오.&lt;/p&gt;

&lt;p&gt;xAI 기본 URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.x.ai/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenRouter 기본 URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://openrouter.ai/api/v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;두 제공업체 모두 OpenAI Chat Completions와 유사한 스키마를 사용하므로 &lt;code&gt;model&lt;/code&gt; 문자열을 제외하면 요청 본문을 거의 동일하게 유지할 수 있습니다.&lt;/p&gt;

&lt;p&gt;xAI 요청 본문 예시:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"grok-4.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Explain the trade-offs of using Redis as a cache."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenRouter 요청 본문 예시:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"x-ai/grok-4-fast:free"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Explain the trade-offs of using Redis as a cache."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;교차 제공업체 테스트에 대한 자세한 내용은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;를 참고하십시오.&lt;/p&gt;

&lt;h2&gt;
  
  
  무료 사용 시 주의할 점
&lt;/h2&gt;

&lt;p&gt;무료 경로는 프로토타이핑에는 충분하지만, 운영 단계에서는 다음 제약을 고려해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 속도 제한
&lt;/h3&gt;

&lt;p&gt;Console 크레딧이 있다고 해서 분당 요청 제한이 없어지는 것은 아닙니다. 대량 테스트를 실행하면 크레딧을 모두 쓰기 전에 &lt;code&gt;429&lt;/code&gt; 오류를 만날 수 있습니다.&lt;/p&gt;

&lt;p&gt;테스트 스크립트에는 간단한 재시도 및 지연 로직을 넣는 것이 좋습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callWithRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 프롬프트 캐싱 효과 제한
&lt;/h3&gt;

&lt;p&gt;Grok 4.3의 유료 API에서는 100만 캐시 토큰당 $0.20의 프롬프트 캐싱이 핵심 비용 최적화 기능입니다.&lt;/p&gt;

&lt;p&gt;하지만 50회 정도 호출하는 프로토타입에서는 캐싱 절감 효과가 크게 체감되지 않을 수 있습니다. 캐싱 최적화는 반복 호출이 많고 시스템 프롬프트가 큰 워크로드에서 더 중요합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 지원 범위
&lt;/h3&gt;

&lt;p&gt;무료 Console 계정은 일반적으로 커뮤니티 지원 수준에 가깝습니다. 프로덕션 장애, 규정 준수, 보안 감사가 필요한 경우에는 유료 티어를 검토해야 합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  유료 전환 시점
&lt;/h2&gt;

&lt;p&gt;다음 중 하나에 해당하면 무료 경로에서 유료 경로로 전환할 시점입니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;지속적인 처리량이 필요함&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
일주일에 여러 번 Console 속도 제한에 도달한다면 무료 크레딧 기반 테스트를 넘어선 상태입니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;큰 시스템 프롬프트를 반복 사용함&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
50K+ 토큰 규모의 안정적인 시스템 프롬프트가 있고 반복 호출이 많다면 캐싱 비용 절감 효과를 고려할 수 있습니다.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;규정 준수가 필요함&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
SOC 2 감사 추적, BAA, 지역 데이터 상주 등이 필요하다면 무료 티어만으로는 충분하지 않습니다.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;마이그레이션 자체는 단순합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;xAI Console 유료 전환: API 키 또는 과금 설정 변경&lt;/li&gt;
&lt;li&gt;OpenRouter 전환: 기본 URL 및 모델 ID 변경&lt;/li&gt;
&lt;li&gt;OpenAI 호환 클라이언트 사용 시: 코드 구조는 대부분 유지&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Grok 4.3은 정말 무료인가요, 아니면 체험판인가요?
&lt;/h3&gt;

&lt;p&gt;경로에 따라 다릅니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;xAI Console: 자동 갱신되지 않는 크레딧 기반 체험판&lt;/li&gt;
&lt;li&gt;Puter.js: 개발자에게 구조적으로 무료, 사용자가 지불&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://grok.com" rel="noopener noreferrer"&gt;grok.com&lt;/a&gt;: 일일 메시지 할당량 기반 무료 사용&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  백엔드에서 Grok 4.3을 비용 없이 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;예. xAI Console 크레딧이 남아 있는 동안은 가능합니다.&lt;/p&gt;

&lt;p&gt;크레딧을 모두 사용한 뒤에는 유료 API로 전환하거나, 사용자가 사용량을 부담하는 Puter.js 같은 브라우저 기반 경로로 이동해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puter.js는 Node.js에서 작동하나요?
&lt;/h3&gt;

&lt;p&gt;Puter.js는 브라우저 우선입니다. 서버 SDK가 개발 중이지만, 사용자 지불 모델은 브라우저 핸드오프를 중심으로 설계되어 있습니다.&lt;/p&gt;

&lt;p&gt;백엔드에서 무료로 테스트하려면 xAI Console 크레딧을 사용하는 것이 더 적합합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puter에서 Grok 4.3 모델 ID는 무엇인가요?
&lt;/h3&gt;

&lt;p&gt;다음 모델 ID를 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x-ai/grok-4.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Puter의 LLM 카탈로그에서는 일반적으로 &lt;code&gt;provider/model&lt;/code&gt; 형식의 모델 ID를 사용합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  무료 크레딧으로 함수 호출과 비디오 입력도 사용할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;예. Console 크레딧은 Grok 4.3 기능에 적용됩니다.&lt;/p&gt;

&lt;p&gt;여기에는 다음이 포함됩니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100만 토큰 컨텍스트&lt;/li&gt;
&lt;li&gt;함수 호출&lt;/li&gt;
&lt;li&gt;비디오 입력&lt;/li&gt;
&lt;li&gt;추론 노력 설정&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;다만 비디오는 컨텍스트를 빠르게 소모할 수 있으므로 토큰 사용량을 주의해야 합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grok Voice 무료 티어와는 어떻게 다른가요?
&lt;/h3&gt;

&lt;p&gt;Grok Voice는 Console에서 구조적으로 무료입니다. 분당 요금이 없습니다.&lt;/p&gt;

&lt;p&gt;반면 Grok 4.3 텍스트 API는 크레딧 기반입니다. 자세한 내용은 &lt;a href="http://apidog.com/blog/how-to-use-grok-voice-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok Voice 무료 사용 방법&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;h3&gt;
  
  
  무료 Grok 4.3 mini가 있나요?
&lt;/h3&gt;

&lt;p&gt;아직 없습니다. xAI는 4.3 라인에 대해 별도의 mini SKU를 출시하지 않았습니다.&lt;/p&gt;

&lt;p&gt;가장 가까운 무료 대안은 OpenRouter의 &lt;code&gt;grok-4-fast:free&lt;/code&gt;입니다. 이는 더 작고 빠른 Grok 4 변형입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  정리
&lt;/h2&gt;

&lt;p&gt;Grok 4.3을 무료로 사용할 수 있는 합법적인 경로는 프로젝트 유형에 따라 다릅니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;실제 API 통합을 검증하려면 &lt;strong&gt;xAI Console&lt;/strong&gt;을 사용하십시오.&lt;/li&gt;
&lt;li&gt;공개 웹 앱에서 개발자 비용 없이 AI 기능을 제공하려면 &lt;strong&gt;Puter.js&lt;/strong&gt;를 사용하십시오.&lt;/li&gt;
&lt;li&gt;코드 없이 일회성 질문을 하려면 &lt;strong&gt;grok.com&lt;/strong&gt; 또는 X 앱을 사용하십시오.&lt;/li&gt;
&lt;li&gt;Grok 4.3이 꼭 필요하지 않고 Grok 계열 무료 출력을 원한다면 &lt;strong&gt;OpenRouter의 무료 모델&lt;/strong&gt;을 검토하십시오.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;프로젝트가 이 경로들에 맞지 않는다면 유료 API 사용도 현실적인 선택입니다. Grok 4.3은 백만 토큰당 $1.25 / $2.50 수준이므로 많은 사이드 프로젝트에서 감당 가능한 범위입니다.&lt;/p&gt;

&lt;p&gt;전체 유료 API 가이드는 &lt;a href="http://apidog.com/blog/how-to-use-grok-4-3-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok 4.3 API 사용 방법&lt;/a&gt;을 참고하십시오. OpenAI와의 직접 비교는 &lt;a href="http://apidog.com/blog/grok-voice-vs-gpt-realtime-best-voice-model?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok Voice vs GPT-Realtime&lt;/a&gt;을 참고하십시오.&lt;/p&gt;

&lt;p&gt;Apidog에서 요청을 한 번 구성하고 기본 URL과 모델 ID만 바꾸면, xAI Console, OpenRouter, 기타 OpenAI 호환 제공업체를 같은 방식으로 비교할 수 있습니다. 이렇게 하면 무료 크레딧 단계에서 시작해 유료 운영 단계로 넘어갈 때 코드 변경을 최소화할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1j3kymdmi5tzgtqoo07.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1j3kymdmi5tzgtqoo07.png" alt="Apidog 테스트 화면" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Grok 4.3 API 사용법</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Fri, 08 May 2026 07:41:46 +0000</pubDate>
      <link>https://forem.com/rihpig/grok-43-api-sayongbeob-2gj7</link>
      <guid>https://forem.com/rihpig/grok-43-api-sayongbeob-2gj7</guid>
      <description>&lt;p&gt;xAI는 Grok 4.3을 단계적으로 출시했습니다. 베타는 2026년 4월 17일, API 접근은 4월 30일, 정식 출시는 5월 6일입니다. 핵심 변경 사항은 1,000,000 토큰 컨텍스트 창, Grok 라인 최초의 기본 비디오 입력, 상시 추론(always-on reasoning), Grok 4.20 대비 약 40% 가격 인하입니다. 기존 Grok 모델 8개는 5월 15일 서비스 종료 예정이므로, &lt;code&gt;grok-3&lt;/code&gt; 또는 &lt;code&gt;grok-4&lt;/code&gt; 시리즈를 사용하는 팀은 즉시 마이그레이션을 준비해야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;오늘 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;이 가이드에서는 코드에서 Grok 4.3을 호출하는 방법을 구현 중심으로 정리합니다. 다루는 내용은 엔드포인트, 인증, OpenAI 호환 &lt;code&gt;base_url&lt;/code&gt;, &lt;code&gt;reasoning_effort&lt;/code&gt;, 비디오 입력, 함수 호출, 그리고 &lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 재현 가능한 테스트 설정입니다.&lt;/p&gt;

&lt;p&gt;동일한 릴리스의 음성 기능은 &lt;a href="http://apidog.com/blog/how-to-use-grok-voice-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok Voice를 무료로 사용하는 방법&lt;/a&gt;을 참고하세요. OpenAI의 주력 음성 모델과 비교하려면 &lt;a href="http://apidog.com/blog/grok-voice-vs-gpt-realtime-best-voice-model?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok Voice 대 GPT-Realtime&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Grok 4.3은 &lt;strong&gt;2026년 5월 6일&lt;/strong&gt; 정식 출시되었습니다.&lt;/li&gt;
&lt;li&gt;기존 Grok 모델 8개는 &lt;strong&gt;2026년 5월 15일&lt;/strong&gt; 서비스 종료 예정입니다.&lt;/li&gt;
&lt;li&gt;가격:

&lt;ul&gt;
&lt;li&gt;입력 토큰 100만 개당 &lt;strong&gt;$1.25&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;출력 토큰 100만 개당 &lt;strong&gt;$2.50&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;캐시된 입력 100만 개당 &lt;strong&gt;$0.20&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Grok 4.20 대비 약 40% 저렴합니다.&lt;/li&gt;

&lt;li&gt;컨텍스트 창은 &lt;strong&gt;100만 토큰&lt;/strong&gt;입니다.&lt;/li&gt;

&lt;li&gt;기본 &lt;strong&gt;비디오 입력&lt;/strong&gt;을 지원합니다.&lt;/li&gt;

&lt;li&gt;추론은 항상 활성화되어 있으며, &lt;code&gt;reasoning_effort&lt;/code&gt;로 깊이를 조정합니다.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;reasoning_effort&lt;/code&gt; 값은 &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt;입니다. 기본값은 &lt;code&gt;medium&lt;/code&gt;입니다.&lt;/li&gt;

&lt;li&gt;엔드포인트는 OpenAI 호환 Chat Completions 형태입니다.
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.x.ai/v1/chat/completions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;표준 티어 기준 처리량은 초당 약 159 토큰입니다.&lt;/li&gt;
&lt;li&gt;Artificial Analysis 기준 지능 지수는 53이며, 추적 모델 146개 중 10위입니다.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;를 사용하면 요청, 환경 변수, 추론 설정, OpenAI 호환 모드 테스트를 한 곳에서 재현할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Grok 4.3의 주요 변경 사항
&lt;/h2&gt;

&lt;p&gt;팀에서 바로 확인해야 할 변경 사항은 다음과 같습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 가격 인하
&lt;/h3&gt;

&lt;p&gt;Grok 4.3은 Grok 4.20 대비 약 40% 저렴합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;입력: Grok 4.20 대비 37.5% 인하&lt;/li&gt;
&lt;li&gt;출력: Grok 4.20 대비 58.3% 인하&lt;/li&gt;
&lt;li&gt;캐시된 입력: $0.20 / 1M tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;긴 시스템 프롬프트를 반복적으로 사용하는 에이전트 워크로드라면 캐시된 입력 비용 절감 효과가 큽니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 100만 토큰 컨텍스트
&lt;/h3&gt;

&lt;p&gt;Grok 4.20의 256k 컨텍스트에서 100만 토큰으로 확장되었습니다.&lt;/p&gt;

&lt;p&gt;활용 예시는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;중간 규모 코드베이스 전체 리뷰&lt;/li&gt;
&lt;li&gt;긴 실적 발표 자료 분석&lt;/li&gt;
&lt;li&gt;전체 법률 계약서 기반 질의응답&lt;/li&gt;
&lt;li&gt;장기 대화 이력 기반 에이전트 메모리&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. 기본 비디오 입력
&lt;/h3&gt;

&lt;p&gt;Grok 4.3은 Grok 라인에서 처음으로 기본 비디오 입력을 지원합니다.&lt;/p&gt;

&lt;p&gt;비디오 URL을 콘텐츠 블록에 전달하면 모델이 프레임을 직접 추론합니다. 별도로 키프레임을 추출하지 않아도 됩니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. 상시 추론
&lt;/h3&gt;

&lt;p&gt;Grok 4.3은 모든 요청에서 추론 단계를 수행합니다.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;reasoning_effort&lt;/code&gt;는 추론을 켜고 끄는 옵션이 아니라 깊이를 조절하는 옵션입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;low&lt;/code&gt;를 사용해도 추론이 완전히 비활성화되지는 않습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 에이전트 워크플로 개선
&lt;/h3&gt;

&lt;p&gt;Grok 4.3은 Grok 4.20 대비 GDPval-AA에서 Elo 점수가 300점 향상되었습니다. 도구 선택, 함수 호출, 다단계 워크플로에서 개선 효과가 나타납니다.&lt;/p&gt;

&lt;p&gt;Artificial Analysis 기준 지능 지수 53은 동일 가격대 평균인 35보다 높으며, 추적 중인 146개 모델 중 10위입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  준비 사항
&lt;/h2&gt;

&lt;p&gt;첫 요청을 보내기 전에 다음을 준비하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;console.x.ai&lt;/code&gt;의 xAI 콘솔 계정&lt;/li&gt;
&lt;li&gt;API 키가 포함된 유료 티어&lt;/li&gt;
&lt;li&gt;프로덕션용 프로젝트 범위 API 키&lt;/li&gt;
&lt;li&gt;OpenAI SDK 또는 xAI SDK&lt;/li&gt;
&lt;li&gt;요청을 재현할 API 클라이언트&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-24.png" alt="" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;환경 변수로 API 키를 설정합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;XAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"xai-..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  엔드포인트 및 인증
&lt;/h2&gt;

&lt;p&gt;Grok 4.3은 OpenAI 호환 Chat Completions 인터페이스를 사용합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://api.x.ai/v1/chat/completions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;인증은 Bearer 토큰 방식입니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Authorization: Bearer $XAI_API_KEY
Content-Type: application/json
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OpenAI SDK를 이미 사용 중이라면 &lt;code&gt;base_url&lt;/code&gt;만 xAI로 바꾸면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;XAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.x.ai/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GraphQL과 REST의 장단점을 세 가지 핵심으로 요약하세요.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;reasoning_effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;xAI SDK를 사용해도 호출 구조는 동일합니다. 달라지는 부분은 SDK import와 클라이언트 생성 방식입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  요청 매개변수
&lt;/h2&gt;

&lt;p&gt;Grok 4.3에서 주로 사용하는 매개변수는 다음과 같습니다.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;매개변수&lt;/th&gt;
&lt;th&gt;유형&lt;/th&gt;
&lt;th&gt;값&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;model&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;&lt;code&gt;grok-4.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;필수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;messages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;OpenAI 메시지 형태&lt;/td&gt;
&lt;td&gt;필수. &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt;, &lt;code&gt;assistant&lt;/code&gt; 역할 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reasoning_effort&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;선택 사항. 기본값은 &lt;code&gt;medium&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max_tokens&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1–32768&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;출력 토큰 제한&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;temperature&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0.0–2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;기본값 1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;top_p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0.0–1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;핵 샘플링&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stream&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;true&lt;/code&gt;이면 서버 전송 이벤트 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tools&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;OpenAI tools 형태&lt;/td&gt;
&lt;td&gt;함수 호출&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tool_choice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string / object&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;, 특정 도구&lt;/td&gt;
&lt;td&gt;표준 OpenAI 시맨틱&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;response_format&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "json_object" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;구조화된 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;seed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;temperature: 0&lt;/code&gt;일 때 재현성 확보&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;기본 &lt;code&gt;curl&lt;/code&gt; 요청은 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.x.ai/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$XAI_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "grok-4.3",
    "messages": [
      {
        "role": "system",
        "content": "당신은 선임 백엔드 엔지니어입니다."
      },
      {
        "role": "user",
        "content": "이 쿼리 계획을 검토하고 병목 현상을 표시하세요."
      }
    ],
    "reasoning_effort": "high"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;응답은 표준 OpenAI Chat Completions 형태를 따릅니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"choices"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prompt_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"completion_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;657&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;reasoning_effort&lt;/code&gt; 선택 기준
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;reasoning_effort&lt;/code&gt;는 비용, 지연 시간, 답변 품질에 영향을 줍니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;low&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;다음 작업에 적합합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;분류&lt;/li&gt;
&lt;li&gt;짧은 요약&lt;/li&gt;
&lt;li&gt;규칙 추출&lt;/li&gt;
&lt;li&gt;간단한 Q&amp;amp;A&lt;/li&gt;
&lt;li&gt;라우팅 판단
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;응답은 빠르고 직접적입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;medium&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;기본값입니다. 대부분의 프로덕션 트래픽에 적합합니다.&lt;/p&gt;

&lt;p&gt;사용 예시는 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;고객 지원 응답&lt;/li&gt;
&lt;li&gt;함수 호출&lt;/li&gt;
&lt;li&gt;데이터 분석&lt;/li&gt;
&lt;li&gt;단일 단계 도구 사용&lt;/li&gt;
&lt;li&gt;일반적인 코드 설명
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;high&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;복잡한 작업에 사용하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;다단계 에이전트&lt;/li&gt;
&lt;li&gt;긴 코드 리뷰&lt;/li&gt;
&lt;li&gt;복잡한 수학 문제&lt;/li&gt;
&lt;li&gt;사전 계획이 필요한 분석&lt;/li&gt;
&lt;li&gt;여러 도구를 순차적으로 호출하는 워크플로
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;high&lt;/code&gt;는 지연 시간과 출력 토큰 사용량을 증가시킬 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  함수 호출 구현
&lt;/h2&gt;

&lt;p&gt;Grok 4.3은 OpenAI 호환 함수 호출 형태를 지원합니다.&lt;/p&gt;

&lt;p&gt;도구를 선언하면 모델은 &lt;code&gt;tool_calls&lt;/code&gt; 배열을 포함한 assistant 메시지를 반환합니다. 애플리케이션은 해당 함수를 실행한 뒤 &lt;code&gt;tool&lt;/code&gt; 역할 메시지로 결과를 다시 전달하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;function&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lookup_user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ID로 사용자를 찾습니다.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;사용자 u_42를 찾아 마지막 로그인 시간을 알려주세요.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reasoning_effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;tool_calls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;도구 호출 결과를 모델에 다시 전달하는 흐름은 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;사용자 u_42를 찾아 마지막 로그인 시간을 알려주세요.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;first_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reasoning_effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;assistant_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assistant_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 실제 애플리케이션에서는 여기서 tool_calls를 순회하며 함수를 실행합니다.
&lt;/span&gt;&lt;span class="n"&gt;tool_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;u_42&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_login&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-05-06T10:30:00Z&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_call_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;assistant_message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_result&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;final_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;final_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;도구 흐름을 테스트하는 경우 &lt;a href="http://apidog.com/blog/mcp-server-testing-apidog?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog의 MCP 서버 테스트&lt;/a&gt;를 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  비디오 입력 사용하기
&lt;/h2&gt;

&lt;p&gt;Grok 4.3은 기본 비디오 입력을 지원합니다.&lt;/p&gt;

&lt;p&gt;비디오 URL은 메시지의 콘텐츠 블록에 포함합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;이 클립에서 무슨 일이 일어나는지 설명하고 이상 징후를 표시하세요.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;video_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com/clip.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;주의할 점은 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;비디오 입력은 입력 토큰으로 계산됩니다.&lt;/li&gt;
&lt;li&gt;긴 클립은 컨텍스트와 비용을 빠르게 소모합니다.&lt;/li&gt;
&lt;li&gt;비용이 중요하면 전송 전에 클립을 자르거나 다운샘플링하세요.&lt;/li&gt;
&lt;li&gt;모델이 프레임을 직접 추론하므로 수동 키프레임 추출은 필수가 아닙니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  100만 토큰 컨텍스트 활용 패턴
&lt;/h2&gt;

&lt;p&gt;100만 토큰 컨텍스트는 실제 프로덕션 워크플로에 사용할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  전체 코드베이스 리뷰
&lt;/h3&gt;

&lt;p&gt;수정된 파일, diff, lint 결과를 함께 전달하고 리뷰를 요청할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;다음 diff와 lint 출력을 기준으로 보안 문제, 성능 병목, 유지보수 위험을 분류하세요.
각 항목에는 파일명, 라인, 심각도, 수정 제안을 포함하세요.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  장문 문서 Q&amp;amp;A
&lt;/h3&gt;

&lt;p&gt;계약서, 정책 문서, 실적 발표 자료처럼 긴 문서를 한 번에 넣고 특정 질문을 할 수 있습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;다음 계약서에서 자동 갱신, 해지 조건, 책임 제한 조항을 찾아 요약하세요.
리스크가 큰 조항은 별도로 표시하세요.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  장기 대화 메모리
&lt;/h3&gt;

&lt;p&gt;에이전트가 장기간의 대화 이력을 기반으로 개인화 응답을 생성해야 할 때 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;캐시된 입력 가격은 100만 토큰당 $0.20입니다. 예를 들어 안정적인 40만 토큰 시스템 프롬프트를 반복 호출한다면, 새 입력으로 처리할 때보다 캐시를 활용하는 편이 훨씬 저렴합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  기존 Grok 모델에서 마이그레이션하기
&lt;/h2&gt;

&lt;p&gt;기존 Grok 모델 8개는 &lt;strong&gt;2026년 5월 15일 오후 12시(태평양 표준시)&lt;/strong&gt;에 서비스가 종료됩니다.&lt;/p&gt;

&lt;p&gt;대부분의 경우 &lt;code&gt;model&lt;/code&gt; 값만 변경하면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- "model": "grok-4"
&lt;/span&gt;&lt;span class="gi"&gt;+ "model": "grok-4.3"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;또는 다음과 같이 Python 코드에서 변경합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;마이그레이션 시 확인할 항목은 두 가지입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 추론 동작
&lt;/h3&gt;

&lt;p&gt;일부 기존 모델은 &lt;code&gt;reasoning_effort&lt;/code&gt;를 사용하지 않았습니다.&lt;/p&gt;

&lt;p&gt;Grok 4.3은 항상 추론을 수행합니다. 이전 코드가 빠른 비추론 경로에 의존했다면 &lt;code&gt;reasoning_effort&lt;/code&gt;를 &lt;code&gt;low&lt;/code&gt;로 설정하고 지연 시간을 측정하세요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 출력 형식
&lt;/h3&gt;

&lt;p&gt;Grok 4.3은 Grok 4.20보다 더 구조화된 응답을 반환하는 경향이 있습니다.&lt;/p&gt;

&lt;p&gt;기존 파이프라인이 정규 표현식 기반 후처리에 의존한다면, 다음 항목을 다시 테스트하세요.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON 파싱&lt;/li&gt;
&lt;li&gt;마크다운 테이블 파싱&lt;/li&gt;
&lt;li&gt;코드 블록 추출&lt;/li&gt;
&lt;li&gt;함수 호출 결과 처리&lt;/li&gt;
&lt;li&gt;스트리밍 응답 처리&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenAI 라인 전체의 가격 비교는 &lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격&lt;/a&gt;을 참고하세요. 직접 비교할 추론 모델은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-5-5-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 API 사용 방법&lt;/a&gt;을 참고하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apidog에서 Grok 4.3 테스트하기
&lt;/h2&gt;

&lt;p&gt;Grok 4.3을 실제 워크로드로 검증하려면 요청을 반복 가능하게 만들어야 합니다.&lt;/p&gt;

&lt;p&gt;권장 절차는 다음과 같습니다.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apidog에서 새 환경을 만듭니다.&lt;/li&gt;
&lt;li&gt;환경 변수에 &lt;code&gt;XAI_API_KEY&lt;/code&gt;를 추가합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BASE_URL&lt;/code&gt;을 &lt;code&gt;https://api.x.ai/v1&lt;/code&gt;로 설정합니다.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /chat/completions&lt;/code&gt; 요청을 생성합니다.&lt;/li&gt;
&lt;li&gt;동일한 프롬프트로 &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt; 세 가지 요청을 저장합니다.&lt;/li&gt;
&lt;li&gt;세 요청의 응답 품질, 지연 시간, &lt;code&gt;usage.reasoning_tokens&lt;/code&gt;를 비교합니다.&lt;/li&gt;
&lt;li&gt;OpenAI 호환 베이스 URL을 사용하는 네 번째 요청을 추가해 동일 입력으로 모델별 결과를 비교합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;예시 요청 본문은 다음과 같습니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"grok-4.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"당신은 API 설계 리뷰어입니다."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"다음 API 응답 스키마의 문제점을 찾고 개선안을 제안하세요."&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reasoning_effort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;비교 테스트를 실행하려면 &lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드&lt;/a&gt;하세요. 공급자를 바꿔도 컬렉션을 유지할 수 있으므로, OpenAI 호환 API를 비교 테스트하기 좋습니다.&lt;/p&gt;

&lt;p&gt;더 넓은 API 테스트 전략은 &lt;a href="http://apidog.com/blog/api-testing-tool-qa-engineers?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;QA 엔지니어를 위한 API 테스트 도구&lt;/a&gt;를 참고하세요.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.apidog.com%2Fblog-next%2F2026%2F05%2Fimage-23.png" alt="" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  속도 제한 처리
&lt;/h2&gt;

&lt;p&gt;xAI 콘솔의 티어 제한은 계정 티어에 따라 다릅니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;티어 1: 분당 수천 요청 기준&lt;/li&gt;
&lt;li&gt;엔터프라이즈 티어: 수십만 요청까지 확장 가능&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;정확한 숫자는 변경될 수 있으므로 콘솔 대시보드에서 확인하세요.&lt;/p&gt;

&lt;p&gt;xAI가 광고하는 초당 159 토큰 처리량은 스트림당 출력 속도입니다. 전체 계정 처리량이 아닙니다. 동시 요청 수는 티어 상한 내에서 확장됩니다.&lt;/p&gt;

&lt;p&gt;429 응답을 받으면 &lt;code&gt;retry-after&lt;/code&gt; 헤더를 확인하고 지수 백오프를 적용하세요.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RateLimitError&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;reasoning_effort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;RateLimitError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;sleep_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sleep_seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Grok 4.3은 OpenAI와 호환됩니까?
&lt;/h3&gt;

&lt;p&gt;Chat Completions 기준으로는 호환됩니다.&lt;/p&gt;

&lt;p&gt;OpenAI SDK를 설치하고 다음 두 값만 바꾸면 됩니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.x.ai/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grok-4.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;함수 호출, 구조화된 출력, 스트리밍도 OpenAI Chat Completions 형태로 사용할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Responses API를 지원합니까?
&lt;/h3&gt;

&lt;p&gt;현재 xAI 인터페이스는 Chat Completions입니다. Responses API는 OpenAI 전용입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  실제 컨텍스트 제한은 얼마입니까?
&lt;/h3&gt;

&lt;p&gt;1,000,000 토큰입니다.&lt;/p&gt;

&lt;p&gt;다만 긴 입력은 비용이 발생합니다. 입력 가격이 100만 토큰당 $1.25라고 해도 대규모 요청을 반복하면 비용이 빠르게 증가합니다. 안정적인 프롬프트는 캐시를 활용하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  상시 추론은 지연 시간에 어떤 영향을 줍니까?
&lt;/h3&gt;

&lt;p&gt;첫 토큰 지연 시간은 비추론 모델보다 높을 수 있습니다. 하지만 Grok 4.3은 초당 약 159 토큰으로 출력을 스트리밍하므로 전체 응답 시간은 경쟁력 있습니다.&lt;/p&gt;

&lt;p&gt;정확도가 중요한 워크로드에서는 이 절충이 유효합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grok 4.3을 Grok Voice와 함께 사용할 수 있습니까?
&lt;/h3&gt;

&lt;p&gt;예. 음성 에이전트인 &lt;code&gt;grok-voice-think-fast-1.0&lt;/code&gt;은 추론 시 내부적으로 Grok 4.3을 호출합니다.&lt;/p&gt;

&lt;p&gt;또한 TTS 및 STT 프리미티브 위에 직접 음성 루프를 구축하고, 중간 추론 단계에서 Grok 4.3을 호출할 수도 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  5월 15일 이후 이전 Grok 3 / Grok 4 호출은 어떻게 됩니까?
&lt;/h3&gt;

&lt;p&gt;410 오류로 실패합니다.&lt;/p&gt;

&lt;p&gt;서비스 종료 전에 &lt;code&gt;model&lt;/code&gt; 값을 &lt;code&gt;grok-4.3&lt;/code&gt;으로 변경하고 회귀 테스트를 완료하세요.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grok 4.3은 이미지 입력을 지원합니까?
&lt;/h3&gt;

&lt;p&gt;예. 비디오 입력과 함께 이미지 입력도 지원합니다.&lt;/p&gt;

&lt;p&gt;OpenAI와 동일한 방식으로 콘텐츠 블록에 이미지 URL을 전달합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  마무리
&lt;/h2&gt;

&lt;p&gt;Grok 4.3은 xAI의 가격 대비 성능 개선이 큰 릴리스입니다. 40% 가격 인하, 100만 토큰 컨텍스트, 상시 추론, 기본 비디오 입력은 에이전트 워크로드에서 바로 테스트할 만한 조합입니다.&lt;/p&gt;

&lt;p&gt;마이그레이션 경로도 단순합니다. OpenAI SDK를 사용 중이라면 &lt;code&gt;base_url&lt;/code&gt;과 &lt;code&gt;model&lt;/code&gt;을 바꾸고, &lt;code&gt;reasoning_effort&lt;/code&gt;별로 지연 시간과 품질을 측정하세요.&lt;/p&gt;

&lt;p&gt;가장 빠른 검증 방법은 Apidog에서 동일 프롬프트를 &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt; 세 가지 설정으로 저장한 뒤 응답 품질, 지연 시간, &lt;code&gt;reasoning_tokens&lt;/code&gt;를 비교하는 것입니다. 기존 Grok 모델을 사용 중이라면 5월 15일 전에 마이그레이션하세요.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>2026년 최고 음성 모델: Grok Voice vs GPT-Realtime 전격 비교</title>
      <dc:creator>Rihpig</dc:creator>
      <pubDate>Fri, 08 May 2026 07:35:29 +0000</pubDate>
      <link>https://forem.com/rihpig/2026nyeon-coego-eumseong-model-grok-voice-vs-gpt-realtime-jeongyeog-bigyo-2fca</link>
      <guid>https://forem.com/rihpig/2026nyeon-coego-eumseong-model-grok-voice-vs-gpt-realtime-jeongyeog-bigyo-2fca</guid>
      <description>&lt;p&gt;xAI는 OpenAI가 GPT-Realtime-2를 출시한 같은 주에 Grok Voice를 출시했습니다. 2026년에 음성 모델을 선택하는 개발자는 이제 두 가지 플래그십 옵션을 비교해야 합니다. 두 모델 모두 추론 기능을 갖춘 음성-음성 모델이고, WebSocket으로 실행되며, 도구 사용을 지원하고, 사람에 가까운 억양으로 응답합니다. 선택 기준은 지연 시간, 가격, 음성 카탈로그, 추론 깊이, 그리고 SIP, 이미지 입력, 음성 복제 필요 여부입니다.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://apidog.com/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation" class="crayons-btn crayons-btn--primary"&gt;지금 Apidog를 사용해 보세요&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;이 글에서는 Grok Voice와 GPT-Realtime-2를 API 관점에서 비교하고, 일반적인 음성 에이전트 유형별로 어떤 모델을 선택해야 하는지 정리합니다.&lt;/p&gt;

&lt;p&gt;단독 구현 가이드는 &lt;a href="http://apidog.com/blog/gpt-realtime-2-api/?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-Realtime-2 사용 방법&lt;/a&gt; 및 &lt;a href="http://apidog.com/blog/how-to-use-grok-voice-for-free?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok Voice 무료 사용 방법&lt;/a&gt;을 참조하세요. 부하 상태에서 두 모델을 스트레스 테스트하려면 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;가 WebSocket 세션을 기본적으로 처리합니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  요약
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grok Voice (&lt;code&gt;grok-voice-think-fast-1.0&lt;/code&gt;)&lt;/strong&gt;는 지연 시간, 무료 콘솔 액세스, 80개 이상의 음성 카탈로그, 28개 언어 TTS, 음성 복제에서 강점이 있습니다.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPT-Realtime-2&lt;/strong&gt;는 GPT-5급 추론, 128k 컨텍스트, 이미지 입력, 네이티브 SIP, MCP 지원에서 강점이 있습니다.&lt;/li&gt;
&lt;li&gt;유료 사용 기준으로 GPT-Realtime-2는 오디오 토큰 1백만 개당 입력 $32, 출력 $64입니다.&lt;/li&gt;
&lt;li&gt;Grok Voice는 콘솔에서 음성 기능에 대한 분당 오디오 요금이 없고, Grok 4.3 추론에 대해 입력 $1.25/출력 $2.50 per 1M tokens를 지불합니다.&lt;/li&gt;
&lt;li&gt;대용량, 저지연 소비자 앱 또는 음성 복제가 필요하면 &lt;strong&gt;Grok Voice&lt;/strong&gt;를 우선 검토하세요.&lt;/li&gt;
&lt;li&gt;복잡한 추론, 멀티모달 음성 에이전트, SIP 기반 콜센터 배포에는 &lt;strong&gt;GPT-Realtime-2&lt;/strong&gt;가 더 적합합니다.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 WebSocket 테스트를 한 번 구성한 뒤 URL만 바꿔 두 모델을 비교할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  한 표로 보는 두 모델
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기능&lt;/th&gt;
&lt;th&gt;Grok Voice (&lt;code&gt;grok-voice-think-fast-1.0&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;GPT-Realtime-2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;첫 오디오까지의 시간&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;1초 미만&lt;/strong&gt;. xAI 주장: 가장 가까운 경쟁자보다 약 5배 빠름&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;low&lt;/code&gt; 추론 시 1초 미만, &lt;code&gt;high&lt;/code&gt;/&lt;code&gt;xhigh&lt;/code&gt;에서는 더 느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;추론 수준&lt;/td&gt;
&lt;td&gt;낮음 / 중간 / 높음. 기반: Grok 4.3&lt;/td&gt;
&lt;td&gt;최소 / 낮음 / 중간 / 높음 / 최고&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;기반 지능&lt;/td&gt;
&lt;td&gt;Grok 4.3. 지능 지수 53&lt;/td&gt;
&lt;td&gt;GPT-5급&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;컨텍스트 창&lt;/td&gt;
&lt;td&gt;1,000,000 토큰. Grok 4.3 기준&lt;/td&gt;
&lt;td&gt;128,000 토큰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사전 설정 음성&lt;/td&gt;
&lt;td&gt;80개 이상. 음성 에이전트 페르소나: Eve, Ara, Rex, Sal, Leo&lt;/td&gt;
&lt;td&gt;10개. Cedar, Marin 및 재조정된 8개 음성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;언어, TTS&lt;/td&gt;
&lt;td&gt;28개&lt;/td&gt;
&lt;td&gt;공식적으로 집계되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;언어, STT&lt;/td&gt;
&lt;td&gt;25개&lt;/td&gt;
&lt;td&gt;GPT-Realtime에서 상속&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;음성 복제&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;예&lt;/strong&gt;. 1분 샘플, 2분 미만 훈련&lt;/td&gt;
&lt;td&gt;아니요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이미지 입력&lt;/td&gt;
&lt;td&gt;아니요. 텍스트 + 오디오&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;예&lt;/strong&gt;. 사진, 스크린샷&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;원격 MCP 서버&lt;/td&gt;
&lt;td&gt;도구 사용 가능. 네이티브 MCP는 아직 홍보되지 않음&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;예&lt;/strong&gt;. API를 통해 MCP 도구 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네이티브 SIP / 전화 통화&lt;/td&gt;
&lt;td&gt;자체 SIP 공급자 필요&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;예&lt;/strong&gt;. &lt;code&gt;?call_id={call_id}&lt;/code&gt; 엔드포인트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;오디오 형식&lt;/td&gt;
&lt;td&gt;PCM16, MP3, μ-law&lt;/td&gt;
&lt;td&gt;PCM16, G.711 μ-law, A-law&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;가격 모델&lt;/td&gt;
&lt;td&gt;콘솔에서 음성 기능은 &lt;strong&gt;무료&lt;/strong&gt;. Grok 4.3 추론에 대해서만 입력 $1.25/출력 $2.50 per 1M tokens&lt;/td&gt;
&lt;td&gt;오디오 입력 $32/1M, 오디오 출력 $64/1M, 텍스트 입력 $4/출력 $24 per 1M tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;규정 준수&lt;/td&gt;
&lt;td&gt;SOC 2 Type II, HIPAA 적격 BAA, GDPR&lt;/td&gt;
&lt;td&gt;SOC 2, GDPR. OpenAI Enterprise 기준&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  지연 시간: Grok Voice가 유리
&lt;/h2&gt;

&lt;p&gt;xAI는 &lt;code&gt;grok-voice-think-fast-1.0&lt;/code&gt;이 “가장 가까운 경쟁자보다 거의 5배 빠르다”고 주장합니다. 자체 벤치마크이므로 배율 자체는 보수적으로 봐야 하지만, 경향은 명확합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grok Voice: 첫 오디오까지 1초 미만으로 안정적&lt;/li&gt;
&lt;li&gt;GPT-Realtime-2: 추론 수준에 따라 약 800ms–1500ms 범위&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;전화 통화에서는 600ms와 1200ms의 차이가 큽니다. 사용자는 “사람처럼 대화한다”와 “봇이 기다렸다가 답한다”를 지연 시간으로 판단합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;선택 기준&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;모바일 앱, 소비자 앱, 인터랙티브 캐릭터처럼 반응 속도가 핵심이면 Grok Voice를 먼저 테스트하세요.&lt;/li&gt;
&lt;li&gt;응답 품질과 복잡한 추론이 더 중요하면 GPT-Realtime-2의 높은 추론 설정을 함께 측정하세요.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  가격: 단위가 다르므로 같은 방식으로 환산해야 함
&lt;/h2&gt;

&lt;p&gt;두 모델은 가격 구조가 다릅니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT-Realtime-2
&lt;/h3&gt;

&lt;p&gt;GPT-Realtime-2는 음성을 토큰 단위로 과금합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;오디오 입력: $32 / 1M tokens&lt;/li&gt;
&lt;li&gt;오디오 출력: $64 / 1M tokens&lt;/li&gt;
&lt;li&gt;텍스트 입력: $4 / 1M tokens&lt;/li&gt;
&lt;li&gt;텍스트 출력: $24 / 1M tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1초 오디오는 약 50토큰입니다. 균형 잡힌 턴 교환이 있는 5분 대화는 약 30,000 오디오 토큰이 될 수 있으며, 오디오 입출력 비용은 약 $1.50 수준입니다. 안정적인 시스템 프롬프트는 캐시 입력으로 비용을 줄일 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grok Voice
&lt;/h3&gt;

&lt;p&gt;Grok Voice는 xAI 콘솔에서 TTS, STT, 음성 에이전트, 사용자 지정 음성에 대한 분당 또는 토큰당 음성 요금이 없습니다. Grok 4.3 추론에 대해서만 과금됩니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;입력: $1.25 / 1M tokens&lt;/li&gt;
&lt;li&gt;출력: $2.50 / 1M tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;동일한 5분 통화에서 추론 토큰은 오디오 토큰보다 대략 한 자릿수 적기 때문에 비용이 $0.10 미만으로 나올 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;선택 기준&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;하루 10,000분 이상 통화하는 대용량 소비자 앱이면 Grok Voice가 비용 면에서 유리합니다.&lt;/li&gt;
&lt;li&gt;소량이지만 중요도가 높은 영업, 규제 지원, 복잡한 고객 상담이면 가격보다 추론 품질을 우선해서 비교하세요.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;관련 가격 자료:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://apidog.com/blog/how-to-use-grok-4-3-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Grok 4.3 API 사용 방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://apidog.com/blog/gpt-5-5-pricing?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-5.5 가격 책정&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  추론 깊이: GPT-Realtime-2가 유리
&lt;/h2&gt;

&lt;p&gt;GPT-Realtime-2는 OpenAI가 “GPT-5급”이라고 설명하는 음성-음성 모델입니다.&lt;/p&gt;

&lt;p&gt;발표된 벤치마크 기준:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Big Bench Audio: 96.6%&lt;/li&gt;
&lt;li&gt;이전 모델: 81.4%&lt;/li&gt;
&lt;li&gt;Audio MultiChallenge: 48.5%&lt;/li&gt;
&lt;li&gt;이전 모델: 34.7%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;또한 &lt;code&gt;minimal&lt;/code&gt;부터 &lt;code&gt;xhigh&lt;/code&gt;까지 5가지 추론 수준을 제공하므로 요청별로 품질과 지연 시간을 조절할 수 있습니다.&lt;/p&gt;

&lt;p&gt;Grok Voice는 Grok 4.3을 기반으로 합니다. Grok 4.3은 Artificial Analysis에서 지능 지수 53을 기록했고, 146개 모델 중 10위에 해당합니다. 특히 에이전트 작업에서 강력하지만, 공개된 음성-음성 추론 벤치마크에서는 GPT-Realtime-2가 더 앞서 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;선택 기준&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;사용자의 의도를 명확히 해야 함&lt;/li&gt;
&lt;li&gt;여러 도구를 순서대로 호출해야 함&lt;/li&gt;
&lt;li&gt;긴 대화 기록을 바탕으로 판단해야 함&lt;/li&gt;
&lt;li&gt;실패한 도구 호출에서 복구해야 함&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이런 패턴이 많으면 GPT-Realtime-2가 더 안전합니다.&lt;/p&gt;

&lt;p&gt;FAQ 응답, 간단한 예약, 리드 수집처럼 흐름이 단순하면 Grok Voice의 지연 시간과 비용 이점이 더 중요할 수 있습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  음성 카탈로그: Grok은 개수, OpenAI는 일관성
&lt;/h2&gt;

&lt;p&gt;Grok은 28개 언어에 걸쳐 80개 이상의 사전 설정 음성을 제공합니다. 음성 에이전트에는 Eve, Ara, Rex, Sal, Leo의 5가지 페르소나가 있으며, 더 넓은 TTS 표면에서는 더 큰 음성 라이브러리를 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;GPT-Realtime-2는 총 10개 음성을 제공합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;신규 Realtime API 전용 음성: Cedar, Marin&lt;/li&gt;
&lt;li&gt;재조정된 기존 음성: alloy, ash, ballad, coral, echo, sage, shimmer, verse&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenAI의 라이브러리는 작지만, 음성 간 일관성이 높습니다. 모든 음성이 동일한 오디오 스택을 사용하고 억양 제어가 비슷하게 동작합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;선택 기준&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;특정 지역 억양, 브랜드 음성, 캐릭터 음성, 음성 복제가 필요하면 Grok Voice&lt;/li&gt;
&lt;li&gt;적은 수의 고품질 음성과 예측 가능한 동작이 중요하면 GPT-Realtime-2&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  음성 복제: Grok Voice만 제공
&lt;/h2&gt;

&lt;p&gt;xAI의 Custom Voices는 약 1분 분량의 깨끗한 음성 샘플에서 음성을 복제하고, 2분 이내에 &lt;code&gt;voice_id&lt;/code&gt;를 반환합니다. 동일한 &lt;code&gt;voice_id&lt;/code&gt;는 TTS 엔드포인트와 음성 에이전트에서 사용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;OpenAI는 현재 Realtime API에서 음성 복제 기능을 노출하지 않습니다.&lt;/p&gt;

&lt;p&gt;따라서 음성 복제가 필수 요구사항이면 선택지는 Grok Voice입니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  이미지 입력: GPT-Realtime-2만 제공
&lt;/h2&gt;

&lt;p&gt;GPT-Realtime-2는 텍스트, 오디오, 이미지를 입력으로 받을 수 있습니다. 예를 들어 사용자 턴에 스크린샷이나 사진을 첨부하고, 에이전트에게 설명을 요청한 뒤 계속 음성 대화를 이어갈 수 있습니다.&lt;/p&gt;

&lt;p&gt;적합한 사용 사례:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;현장 지원&lt;/li&gt;
&lt;li&gt;음성 기반 QA&lt;/li&gt;
&lt;li&gt;접근성 내레이션&lt;/li&gt;
&lt;li&gt;화면을 보며 진행하는 고객 지원&lt;/li&gt;
&lt;li&gt;사진 기반 문제 진단&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grok Voice는 현재 이 패턴을 지원하지 않습니다.&lt;/p&gt;

&lt;p&gt;OpenAI의 비전 스택은 &lt;a href="http://apidog.com/blog/how-to-use-gpt-image-2-api?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;GPT-Image-2 API 사용 방법&lt;/a&gt;을 참조하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  SIP 및 전화 통합: GPT-Realtime-2는 네이티브, Grok은 브리지 필요
&lt;/h2&gt;

&lt;p&gt;OpenAI Realtime API는 네이티브 SIP를 지원합니다. SIP 트렁크를 OpenAI 게이트웨이로 연결하면 수신 전화가 다음 형태의 WebSocket 세션을 엽니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wss://api.openai.com/v1/realtime?call_id={call_id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 방식은 별도의 SIP-to-WebSocket 브리지 레이어를 줄일 수 있습니다.&lt;/p&gt;

&lt;p&gt;Grok Voice는 전화 통화에 필요한 μ-law 출력을 지원하지만, 자체 SIP 공급자를 사용해야 합니다.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Twilio&lt;/li&gt;
&lt;li&gt;Telnyx&lt;/li&gt;
&lt;li&gt;Plivo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;이 경우 SIP 공급자와 Grok Voice 사이의 브리지를 직접 운영해야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;선택 기준&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;콜센터 에이전트를 빠르게 배포해야 하면 GPT-Realtime-2&lt;/li&gt;
&lt;li&gt;이미 SIP 브리지를 운영 중이고 비용과 지연 시간이 더 중요하면 Grok Voice도 검토 가능&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  MCP 및 도구 사용
&lt;/h2&gt;

&lt;p&gt;두 모델 모두 함수 호출을 지원합니다. 차이는 도구 실행 방식입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT-Realtime-2
&lt;/h3&gt;

&lt;p&gt;GPT-Realtime-2는 원격 MCP 서버를 기본적으로 지원합니다. 서버 URL과 도구 허용 목록을 구성하면 Realtime API가 MCP 도구를 실행합니다. 애플리케이션 서버가 모든 함수 호출 이벤트를 직접 중계하지 않아도 됩니다.&lt;/p&gt;

&lt;p&gt;도구가 많은 에이전트에 적합합니다.&lt;/p&gt;

&lt;p&gt;예:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;은행 상담 에이전트&lt;/li&gt;
&lt;li&gt;CRM 기반 영업 에이전트&lt;/li&gt;
&lt;li&gt;내부 운영 자동화 에이전트&lt;/li&gt;
&lt;li&gt;50개 이상의 API 엔드포인트를 다루는 음성 에이전트&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Grok Voice
&lt;/h3&gt;

&lt;p&gt;Grok Voice는 함수 호출을 지원하고 내장 &lt;code&gt;web_search&lt;/code&gt; 도구를 제공합니다. 다만 MCP가 아직 일급 프리미티브로 홍보되지는 않았습니다.&lt;/p&gt;

&lt;p&gt;도구 수가 5개 이하이고 이벤트 루프를 직접 구현해도 된다면 Grok Voice에서도 충분히 구현할 수 있습니다.&lt;/p&gt;

&lt;p&gt;MCP 서버 자체를 테스트하려면 &lt;a href="http://apidog.com/blog/mcp-server-testing-apidog?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog에서 MCP 서버 테스트&lt;/a&gt;를 참조하세요.&lt;/p&gt;

&lt;h2&gt;
  
  
  한 줄 선택 가이드
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;소비자 음성 앱, 대용량, 지연 시간 중요:&lt;/strong&gt; Grok Voice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;음성 복제 필요:&lt;/strong&gt; Grok Voice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;맞춤형 브랜드 음성 또는 캐릭터 음성:&lt;/strong&gt; Grok Voice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;10개 이상 언어의 대규모 TTS:&lt;/strong&gt; Grok Voice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;스크린샷을 이해해야 하는 음성 에이전트:&lt;/strong&gt; GPT-Realtime-2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SIP 기반 콜센터 배포:&lt;/strong&gt; GPT-Realtime-2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;50개 이상의 도구를 사용하는 다단계 에이전트:&lt;/strong&gt; GPT-Realtime-2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP 기반 도구 실행:&lt;/strong&gt; GPT-Realtime-2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;긴 컨텍스트 대화:&lt;/strong&gt; GPT-Realtime-2. 단, 오디오 토큰 비용을 감당할 수 있다면 Grok 4.3의 1M 컨텍스트도 검토 가능&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;가장 저렴한 프로덕션 음성 에이전트:&lt;/strong&gt; 콘솔의 Grok Voice&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;벤치마크 중심의 고난도 추론:&lt;/strong&gt; &lt;code&gt;xhigh&lt;/code&gt; 추론을 사용하는 GPT-Realtime-2&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  커밋 전에 두 모델을 모두 테스트하는 방법
&lt;/h2&gt;

&lt;p&gt;처음부터 한 모델에 고정하지 말고, 같은 시나리오를 두 모델에서 실행해 측정하세요.&lt;/p&gt;

&lt;p&gt;권장 절차는 다음과 같습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. 고정 대화 시나리오 만들기
&lt;/h3&gt;

&lt;p&gt;10턴 정도의 대화를 준비합니다.&lt;/p&gt;

&lt;p&gt;포함할 항목:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;일반 질문 2~3개&lt;/li&gt;
&lt;li&gt;모호한 사용자 요청 1개&lt;/li&gt;
&lt;li&gt;도구 호출 1개&lt;/li&gt;
&lt;li&gt;긴 답변 1개&lt;/li&gt;
&lt;li&gt;사용자 중단 또는 정정 1개&lt;/li&gt;
&lt;li&gt;실제 사용자 음성 녹음&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. WebSocket 요청을 한 번 구성하기
&lt;/h3&gt;

&lt;p&gt;Apidog에서 WebSocket 요청을 만들고, API 키를 환경 변수로 분리합니다.&lt;/p&gt;

&lt;p&gt;예:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;XAI_API_KEY=...
OPENAI_API_KEY=...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;테스트 URL은 실행마다 교체합니다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wss://api.x.ai/v1/realtime?model=grok-voice-think-fast-1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wss://api.openai.com/v1/realtime?model=gpt-realtime-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 동일한 메시지 시퀀스 실행하기
&lt;/h3&gt;

&lt;p&gt;각 모델에 동일한 사용자 오디오와 동일한 대화 흐름을 보냅니다.&lt;/p&gt;

&lt;p&gt;측정할 값:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;첫 오디오까지의 시간&lt;/li&gt;
&lt;li&gt;전체 응답 완료 시간&lt;/li&gt;
&lt;li&gt;중단 처리 품질&lt;/li&gt;
&lt;li&gt;도구 호출 성공률&lt;/li&gt;
&lt;li&gt;답변 품질&lt;/li&gt;
&lt;li&gt;토큰 사용량&lt;/li&gt;
&lt;li&gt;실행당 예상 비용&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. 결과를 버전 관리하기
&lt;/h3&gt;

&lt;p&gt;응답 오디오, 이벤트 로그, 비용 계산 결과를 저장합니다. 모델 선택은 감이 아니라 실제 워크로드 기준 데이터로 결정해야 합니다.&lt;/p&gt;

&lt;p&gt;나란히 비교하려면 &lt;a href="https://apidog.com/download?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog를 다운로드하세요&lt;/a&gt;. 컬렉션 형식은 이식성이 높기 때문에 비교 아티팩트를 버전 제어 시스템에 보관하기 쉽습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  자주 묻는 질문
&lt;/h2&gt;

&lt;h3&gt;
  
  
  동일한 앱에서 두 모델을 모두 사용하고 런타임에 라우팅할 수 있나요?
&lt;/h3&gt;

&lt;p&gt;가능합니다. 두 모델 모두 유사한 이벤트 형태를 사용합니다. 예를 들어 저렴한 의도 분류기를 앞단에 두고, 캐주얼한 요청은 Grok Voice로, 복잡한 요청은 GPT-Realtime-2로 라우팅할 수 있습니다.&lt;/p&gt;

&lt;p&gt;언어 기준 라우팅도 가능합니다. 대규모 비영어권 TTS가 필요하면 Grok Voice를 우선 라우팅하는 방식입니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  어떤 모델의 비영어권 음성 품질이 더 좋나요?
&lt;/h3&gt;

&lt;p&gt;언어 커버리지는 Grok Voice가 유리합니다. 80개 이상의 음성과 TTS 28개 언어를 제공합니다.&lt;/p&gt;

&lt;p&gt;다만 두 모델이 모두 지원하는 언어에서는 실제 품질 차이가 사용 사례별로 달라질 수 있습니다. 필요한 언어, 억양, 도메인 문장을 직접 녹음해 비교하는 것이 안전합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  GPT-Realtime-2가 일반 워크로드에서 10배 가격을 지불할 가치가 있나요?
&lt;/h3&gt;

&lt;p&gt;워크로드에 따라 다릅니다.&lt;/p&gt;

&lt;p&gt;FAQ에 답변하는 단순 고객 지원 에이전트라면 가격 차이를 정당화하기 어렵습니다. 반대로 CRM을 읽고, 도구를 디스패치하고, 사용자 중단에서 복구해야 하는 영업 에이전트라면 추론 격차가 비용보다 중요할 수 있습니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  두 모델 모두 유명인의 실제 음성 복제를 지원하나요?
&lt;/h3&gt;

&lt;p&gt;아니요. 두 공급업체 모두 동의된 샘플에 한해 복제를 허용하도록 필터링합니다. 허가 없이 유명인의 음성을 복제하는 것은 양쪽 플랫폼의 서비스 약관을 위반합니다.&lt;/p&gt;

&lt;h3&gt;
  
  
  나중에 한 모델에서 다른 모델로 마이그레이션하려면 얼마나 걸리나요?
&lt;/h3&gt;

&lt;p&gt;이벤트 이름은 다르지만 대화 구조는 비슷합니다. 보통 &lt;code&gt;session.update&lt;/code&gt; 페이로드, 이벤트 핸들러 이름, 오디오 포맷 처리 부분을 수정해야 합니다.&lt;/p&gt;

&lt;p&gt;테스트용 요청 컬렉션을 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 관리하면 모델 교체 시 비교와 포팅이 더 쉽습니다.&lt;/p&gt;

&lt;h2&gt;
  
  
  마무리
&lt;/h2&gt;

&lt;p&gt;Grok Voice와 GPT-Realtime-2 사이에 보편적으로 정답인 모델은 없습니다. 선택은 사용 사례가 결정합니다.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;빠른 소비자 음성 앱을 만들고 모든 밀리초가 중요하면 Grok Voice를 먼저 테스트하세요.&lt;/li&gt;
&lt;li&gt;화면을 이해하고, 많은 도구를 호출하고, SIP 브리지 없이 전화 통화를 처리해야 한다면 GPT-Realtime-2가 더 적합합니다.&lt;/li&gt;
&lt;li&gt;그 외의 경우에는 &lt;a href="https://apidog.com?utm_source=dev.to&amp;amp;utm_medium=wanda&amp;amp;utm_content=n8n-post-automation"&gt;Apidog&lt;/a&gt;에서 동일한 WebSocket 테스트를 구성하고, 일주일 동안 두 모델을 같은 시나리오로 측정한 뒤 선택하세요.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
