OpenAIAPILLMAIJavaScriptResponses APIStructured Outputs

OpenAI API: Responses API 및 Structured Outputs 사양 및 구현 가이드

Sloth255
Sloth255
·2 min read·368 words

소개

2025년에 접어들어 OpenAI API가 큰 전환점을 맞이했습니다. 2025년 3월 Responses API가 정식 출시(GA)되어, Chat Completions API의 대화 기능과 Assistants API의 도구 연동 기능을 단일 엔드포인트로 통합했습니다. 레거시 Assistants API는 2026년 8월 26일에 서비스 종료 예정입니다.

또한 개발자가 지정한 JSON 스키마에 모델 출력이 엄격하게 준수하도록 보장하는 Structured Outputs는 Responses API와의 조합에서 진가를 발휘합니다. 2024년 8월 출시 이후, 에이전틱 워크플로우와 데이터 추출 파이프라인의 신뢰성을 크게 향상시켰습니다.

이 글에서는 먼저 2025년 기준 전체 OpenAI API 현황을 정리하고, 이 두 가지 핵심 주제의 사양과 구현 세부사항을 살펴봅니다.

출처 정보
이 글의 사양과 성능 데이터는 OpenAI 공식 문서(developers.openai.com/api), 공식 마이그레이션 가이드(developers.openai.com/api/docs/guides/migrate-to-responses), 공식 블로그(openai.com/index/introducing-structured-outputs-in-the-api)를 참조합니다.


1. API 현황 개요

2025년 기준 OpenAI API의 주요 카테고리는 다음과 같이 정리됩니다:

카테고리 엔드포인트 포지셔닝
Responses API POST /v1/responses 신규 프로젝트에 권장. 에이전트용 통합 인터페이스.
Chat Completions API POST /v1/chat/completions 계속 지원(서비스 종료 예정 없음).
Realtime API WebRTC / WebSocket / SIP 실시간 양방향 음성 및 텍스트.
Embeddings POST /v1/embeddings 벡터 검색 및 RAG.
Images POST /v1/images/generations 이미지 생성 및 편집.
Audio POST /v1/audio/transcriptions 음성 인식 및 TTS.

OpenAI는 Responses API를 새로운 기능의 주요 목적지로 포지셔닝하고 있으며, 2026년 8월 26일 Assistants API 서비스 종료가 공식 확정되었습니다(출처: 공식 마이그레이션 가이드). Chat Completions API는 서비스 종료 날짜 없이 계속 지원되지만, 신규 프로젝트에는 Responses API가 현재 권장됩니다.

Structured Outputs는 위 표의 엔드포인트처럼 독립적인 엔드포인트가 아니라, Responses API와 Chat Completions API 양쪽에서 사용 가능한 출력 형식 제어 옵션입니다. 전자에서는 text.format 파라미터, 후자에서는 response_format 파라미터로 지정합니다. 이 글에서는 특히 Responses API와의 조합을 중점적으로 다룹니다.


2. Responses API

2.1 개요

Responses API는 Chat Completions API의 후계이자 Assistants API의 기능을 통합한 새로운 프리미티브입니다. 2025년 3월 일반 제공(GA)에 도달했습니다.

가장 큰 변화는 서버 사이드에서 대화 상태를 유지할 수 있다는 점입니다. 기존 Chat Completions에서는 모든 요청에 대화 이력 전체를 포함해야 했지만, Responses API에서는 previous_response_id를 전달하는 것만으로 대화를 이어갈 수 있습니다.

2.2 기본 요청

import OpenAI from "openai";

const client = new OpenAI();

const response = await client.responses.create({
  model: "gpt-4o",
  input: "도쿄의 날씨를 알려주세요.",
});

console.log(response.output_text); // output_text 헬퍼로 텍스트 직접 취득

2.3 output_text 헬퍼

output_text는 API 사양 자체가 아닌 OpenAI SDK가 제공하는 편의 속성입니다.

Responses API의 원시 응답에서 텍스트는 다음 구조 안에 중첩되어 있습니다:

response.output[0].content[0].text

output_text는 이 경로를 탐색하는 과정을 요약합니다. 내부적으로 output 배열에서 type: "message"이고 type: "output_text"content 블록을 가진 첫 번째 요소의 텍스트를 반환합니다.

// 둘 다 같은 출력 결과
console.log(response.output_text);
console.log(response.output[0].content[0].text);

단, output 배열의 첫 번째 항목이 텍스트 메시지가 아닌 경우(예: 도구 호출이 발생한 경우)에는 예상대로 동작하지 않을 수 있습니다. 도구를 사용하는 강건한 에이전틱 코드에서는 output 배열을 루프로 순회하고 type을 확인하는 것이 좋습니다.

for (const item of response.output) {
  if (item.type === "message") {
    for (const block of item.content) {
      if (block.type === "output_text") {
        console.log(block.text);
      }
    }
  }
}

2.4 입력 메시지의 role

input에 배열을 전달할 때 각 메시지에 role을 지정할 수 있습니다. role은 모델에게 "누가 이 발언을 하는가"를 알려주며, 세 가지 종류가 있습니다.

role 의미 일반적인 사용
system 시스템(개발자)으로부터의 지시 모델의 동작, 어조, 제약을 정의합니다. 일반적으로 대화 시작 시 한 번 배치됩니다.
user 최종 사용자로부터의 입력 사용자의 발언이나 질문을 나타냅니다.
assistant 모델 자신의 과거 발언 멀티턴 대화에서 이전 응답을 이력으로 제공할 때 사용합니다.
const response = await client.responses.create({
  model: "gpt-4o",
  input: [
    {
      role: "system",
      content: "당신은 도움이 되는 일본어 어시스턴트입니다. 간결하게 답해주세요.",
    },
    {
      role: "user",
      content: "JavaScript 배열 메서드에 대해 알려주세요.",
    },
  ],
});

input에 문자열을 직접 전달하면(2.2의 샘플처럼) 그 문자열은 role: "user"인 메시지로 처리됩니다. 모델 동작에 대한 세밀한 제어가 필요하거나 system 지시를 제공하고 싶은 경우에는 배열 형식을 사용합니다.

2.5 응답 구조

Chat Completions의 choices와 달리 결과는 output 배열로 반환됩니다.

{
  "id": "resp_68af4030...",
  "object": "response",
  "created_at": 1756315696,
  "model": "gpt-4o",
  "output": [
    {
      "id": "msg_68af4033...",
      "type": "message",
      "status": "completed",
      "role": "assistant",
      "content": [
        {
          "type": "output_text",
          "text": "도쿄의 날씨는 맑습니다."
        }
      ]
    }
  ],
  "usage": {
    "input_tokens": 15,
    "output_tokens": 12,
    "total_tokens": 27
  }
}

2.6 멀티턴 대화

Responses API에서 멀티턴 대화를 실현하는 방법은 두 가지입니다.

1. input에 이력을 배열로 전달

Chat Completions API의 기존 방법입니다. 클라이언트 측에서 대화 이력을 유지하고 관리하며 모든 요청에 모든 메시지를 포함합니다.

const history = [
  { role: "system", content: "You are a helpful assistant." },
  { role: "user", content: "도쿄의 날씨를 알려주세요." },
  { role: "assistant", content: "오늘 도쿄는 맑습니다." },
];

const response = await client.responses.create({
  model: "gpt-4o",
  input: [...history, { role: "user", content: "내일은요?" }],
});

서버에서 상태를 유지하지 않으므로 특정 메시지를 삭제하거나 요약하는 등 이력을 자유롭게 조작할 수 있다는 장점이 있습니다. 단, 대화가 길어질수록 입력 토큰 수가 증가해 비용과 레이턴시에 영향을 미칩니다.

2. previous_response_id 전달 (Responses API 전용)

Responses API에서 새롭게 도입된 서버 사이드 상태 관리 방법입니다. 이전 응답 ID를 전달하기만 하면 OpenAI 서버가 대화 이력을 이어받습니다.

// 첫 번째 턴
const response1 = await client.responses.create({
  model: "gpt-4o",
  input: "도쿄의 날씨를 알려주세요.",
});

// 두 번째 턴: previous_response_id만으로 문맥 이어받기
const response2 = await client.responses.create({
  model: "gpt-4o",
  input: "내일은요?",
  previous_response_id: response1.id,
});

클라이언트가 이력 전체를 유지하거나 전송할 필요가 없어 요청 크기가 작게 유지됩니다. 또한 o1이나 o3 같은 추론 모델을 사용할 때 사고 토큰이 턴 사이에 유지되어, 연속적인 추론이 필요한 작업의 정확도가 향상되는 큰 장점이 있습니다.

이 방법을 사용하려면 서버에 응답이 저장되어야 합니다. store 파라미터의 기본값은 true이지만, store: false로 설정하면 ID로 참조할 수 없게 됩니다.

선택 기준

상황 권장 방법
이력을 중간에 수정/편집이 필요한 경우 (RAG 주입, 오래된 메시지 삭제 등) ① 배열 기반
추론 모델(o1, o3 등)로 복잡한 멀티턴 문제 해결 previous_response_id
수동 이력 관리를 피하고 싶은 간단한 채팅 previous_response_id
Chat Completions API 사용 ① 배열 기반(previous_response_id는 Responses API 전용)

지속적인 대화 관리가 필요한 경우 Conversations API와의 연동도 가능합니다.

2.7 내장 도구

Responses API의 가장 큰 장점 중 하나는 추가 인프라 없이 사용 가능한 내장 도구 세트입니다.

const response = await client.responses.create({
  model: "gpt-4o",
  input: "최신 OpenAI 뉴스를 검색해 요약해주세요.",
  tools: [
    { type: "web_search_preview" },
    { type: "file_search" },
    { type: "code_interpreter" },
  ],
});
도구 용도
web_search_preview ChatGPT에 상당하는 웹 검색.
file_search 업로드된 파일에 대한 RAG 검색.
code_interpreter 코드 실행 및 데이터 분석.
computer_use 컴퓨터 조작 에이전트.
mcp 서드파티 MCP 서버에 연결.

MCP (Model Context Protocol) 연동

Connectors는 Google Workspace나 Dropbox 같은 주요 서비스에 대한 OpenAI 관리 MCP 래퍼이며, 원격 MCP 서버는 원격 MCP 프로토콜(Streamable HTTP 또는 HTTP/SSE 전송 프로토콜)을 구현한 인터넷상의 모든 서버입니다(출처: OpenAI Connectors and MCP Guide).

Responses API는 Streamable HTTP 또는 HTTP/SSE 전송 프로토콜을 지원하는 원격 MCP 서버와 연동할 수 있습니다. 도구가 지정되면 API는 먼저 서버에서 사용 가능한 도구 목록을 가져오고(mcp_list_tools), 모델은 그 목록에서 필요한 도구를 호출합니다.

기본 연결 예시 (출처: OpenAI Using tools Guide)

const response = await client.responses.create({
  model: "gpt-4o",
  input: "2d6를 굴려서 결과를 알려주세요.",
  tools: [
    {
      type: "mcp",
      server_label: "dice_server",           // 서버 식별자 (임의)
      server_url: "https://example.com/mcp", // MCP 서버의 URL
      require_approval: "never",             // 도구 호출을 자동으로 승인
    },
  ],
});

console.log(response.output_text);

require_approval로 승인 제어

기본적으로 모든 도구 호출은 개발자의 명시적 승인이 필요합니다. require_approval로 이 동작을 제어할 수 있습니다(출처: OpenAI Connectors and MCP Guide).

const response = await client.responses.create({
  model: "gpt-4o",
  input: "MCP 사양의 전송 프로토콜에 대해 알려주세요.",
  tools: [
    {
      type: "mcp",
      server_label: "deepwiki",
      server_url: "https://mcp.deepwiki.com/mcp",
      require_approval: {
        never: {
          // 이 두 도구는 승인 불필요; 나머지는 승인 필요
          tool_names: ["ask_question", "read_wiki_structure"],
        },
      },
    },
  ],
});
require_approval 동작
"never" 모든 도구 호출을 자동으로 승인.
{ never: { tool_names: [...] } } 지정한 도구를 자동으로 승인; 나머지는 승인 필요.
생략(기본값) 모든 도구 호출에 승인 필요.

인증이 필요한 서버에 연결

MCP 서버가 인증을 요구하는 경우 headers 파라미터로 토큰을 전달합니다.

const response = await client.responses.create({
  model: "gpt-4o",
  input: "데이터를 가져와주세요.",
  tools: [
    {
      type: "mcp",
      server_label: "my_server",
      server_url: "https://my-mcp-server.example.com/mcp",
      require_approval: "never",
      headers: {
        Authorization: `Bearer ${process.env.MCP_ACCESS_TOKEN}`,
      },
    },
  ],
});

도구 목록 캐싱: MCP 서버에서 도구 목록을 가져오는(mcp_list_tools) 것은 요청별로 발생하지만, previous_response_id를 사용한 멀티턴 대화에서는 이전 응답에 도구 목록이 포함되어 있으므로 재취득이 생략됩니다(출처: OpenAI Cookbook: MCP Tool Guide).

2.8 주요 요청 파라미터

파라미터 타입 설명
model string 모델명(예: gpt-4o).
input string / array 텍스트 또는 멀티모달 입력.
previous_response_id string 멀티턴용 이전 응답 ID.
tools array 사용할 도구 정의.
text.format object Structured Outputs 사양(아래 참조).
stream boolean 스트리밍 활성화.
store boolean 서버에 응답 저장 여부(기본값: true).
reasoning_effort string 추론 깊이 조정(low / medium / high).
background boolean 백그라운드 모드에서 비동기 실행.

2.9 Chat Completions와의 비교

기능 Chat Completions Responses API
대화 상태 클라이언트 측(전체 이력 필요) 서버 측(previous_response_id)
웹 검색 수동 구현 필요 내장(web_search_preview)
파일 검색 / RAG 수동 구현 필요 내장(file_search)
코드 실행 수동 구현 필요 내장(code_interpreter)
MCP 연결 미지원 원격 MCP 네이티브 지원
추론 토큰 유지 턴 사이에 폐기 유지 가능
output_text 헬퍼 없음 있음
형식 지정 response_format text.format
새로운 기능 제공 제한적 주요 목적지

2.10 추론 모델 (o 시리즈)

GPT 시리즈와 구별되는 추론 모델이라 불리는 모델 그룹입니다. 이 모델들은 답을 내기 전에 내부에서 단계별 사고 과정(Chain-of-Thought)을 실행합니다. 이 내부 사고는 추론 토큰으로 계산되며 최종 출력에는 포함되지 않습니다.

수학, 코딩, 논리적 추론, 복잡한 분석 등 다단계 추론이 필요한 작업에서 GPT-4o보다 훨씬 높은 정확도를 보여줍니다. 반면 사고에 시간이 걸리므로 레이턴시와 비용이 높아집니다.

2025년 기준 주요 모델:

모델 특징
o1 / o1-mini 첫 세대 추론 모델.
o3 / o3-mini 고정밀·고성능 후계 시리즈.
o4-mini 비용과 성능을 균형 있게 제공하는 모델.

추론 깊이는 reasoning_effort 파라미터로 조정할 수 있습니다(2.8 참조). low는 레이턴시와 비용을 줄이는 경량 추론이며, high는 최대 정밀도를 위한 심층 추론입니다.

const response = await client.responses.create({
  model: "o3",
  input: "이 수열의 일반항을 구하세요: 1, 1, 2, 3, 5, 8, 13, ...",
  reasoning_effort: "high",
});

또한 previous_response_id를 사용한 멀티턴 대화(2.6, 방법 2 참조)에서 추론 토큰이 턴 사이에 유지됩니다. 여러 턴에 걸쳐 같은 문제를 깊이 파고들 때, 모델이 처음부터 시작하는 것이 아니라 이전 턴의 추론을 이어받아 정확도와 효율성이 향상됩니다.


3. Structured Outputs

3.1 개요와 배경

LLM 출력을 JSON 형식으로 안정적으로 강제하는 것은 애플리케이션 연동의 핵심 과제였습니다. OpenAI는 이를 점진적으로 해결해 왔습니다:

JSON 모드 (레거시 기능) 는 구문적으로 올바른 JSON을 보장하지만, 스키마 준수는 보장하지 않습니다. 필수 필드가 누락되거나 불필요한 필드가 추가될 위험이 있었습니다.

Structured Outputs는 2024년 8월에 출시되어, 개발자가 지정한 JSON 스키마에 100% 준수를 보장합니다(출처: OpenAI 공식 블로그).

OpenAI 내부 평가(evals)에서 Structured Outputs를 사용한 gpt-4o-2024-08-06은 복잡한 JSON 스키마에 대해 100% 준수를 달성했으며, 이는 gpt-4-0613의 40% 미만에서 엄청난 도약입니다(출처: OpenAI 공식 블로그).

3.2 동작 원리

OpenAI API는 지정된 JSON Schema를 문맥 자유 문법(CFG)으로 변환해 구조화 출력을 실현합니다. 이 문법은 샘플링 중 생성 가능한 토큰을 제한해 스키마 준수를 강제합니다. 새로운 스키마가 처음 전송될 때는 문법 전처리에 추가 레이턴시가 발생하지만, 같은 스키마로의 후속 요청에서는 이 페널티가 없습니다.

참고 (파인튜닝 모델): 파인튜닝된 모델의 경우 새로운 스키마를 사용하는 첫 번째 요청에서 추가 레이턴시가 발생합니다. 같은 스키마로의 후속 요청에서는 없습니다. 다른 모델에는 이 제한이 없습니다. (출처: Structured Outputs Guide)

3.3 두 가지 사용 방법

Structured Outputs는 API에서 두 가지 형태로 제공됩니다.

첫 번째는 Function calling (tools) 을 통한 방법으로, 함수 정의 내에 strict: true를 설정해 활성화합니다. gpt-4-0613 이상의 모든 모델에서 사용 가능하며, 모델 기능과 애플리케이션을 연결하는 데(예: 데이터베이스 쿼리 함수 접근) 적합합니다.

두 번째는 response_format / text.format 파라미터 를 통한 방법으로, json_schema를 지정하면 모델이 구조화된 형식으로 사용자에게 응답하는 데 적합합니다(예: 수학 튜토리얼 UI에서 다른 부분을 분리해서 표시).

3.4 구현 예시 (Responses API)

Responses API에서 파라미터는 response_format에서 text.format으로 이동했습니다(출처: 공식 마이그레이션 가이드).

스키마 description에 대해

JSON Schema의 각 필드에 description을 포함할 것을 강력히 권장합니다. description은 모델에 대한 지시 역할을 하며, 해당 필드에 무엇이 들어가야 하는지 모델이 올바르게 판단하는 데 도움을 줍니다. explanation이나 output 같은 일반적인 필드명은 특히 description 없이는 모델이 오해할 가능성이 높습니다.

Zod를 사용할 때는 .describe("...")를 사용합니다. JSON Schema를 직접 작성할 때는 속성 객체 내의 "description" 키로 지정합니다.

Zod를 사용한 스키마 정의 (권장)

import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const client = new OpenAI();

const Step = z.object({
  explanation: z.string().describe("이 계산 단계에서 수행하는 내용의 설명."),
  output: z.string().describe("이 단계의 계산 결과 (수식 또는 수치)."),
});

const MathResponse = z.object({
  steps: z.array(Step).describe("풀이 단계 목록."),
  final_answer: z.string().describe("방정식의 최종 답 (예: x = -3.75)."),
});

const response = await client.responses.parse({
  model: "gpt-4o",
  input: [
    { role: "system", content: "당신은 수학 튜터입니다. 단계별로 설명해주세요." },
    { role: "user", content: "8x + 7 = -23을 풀어주세요" },
  ],
  text: { format: zodResponseFormat(MathResponse, "math_response") },
});

const result = response.output_parsed;
console.log(result.final_answer);
for (const step of result.steps) {
  console.log(step.explanation, "->", step.output);
}

JSON Schema 직접 지정

const response = await client.responses.create({
  model: "gpt-4o",
  input: [
    { role: "system", content: "당신은 수학 튜터입니다." },
    { role: "user", content: "8x + 7 = -23을 풀어주세요" },
  ],
  text: {
    format: {
      type: "json_schema",
      name: "math_response",
      strict: true,
      schema: {
        type: "object",
        description: "방정식의 단계별 풀이를 보여주는 응답.",
        properties: {
          steps: {
            type: "array",
            description: "풀이 단계 목록.",
            items: {
              type: "object",
              properties: {
                explanation: {
                  type: "string",
                  description: "이 계산 단계에서 수행하는 내용의 설명.",
                },
                output: {
                  type: "string",
                  description: "이 단계의 계산 결과 (수식 또는 수치).",
                },
              },
              required: ["explanation", "output"],
              additionalProperties: false,
            },
          },
          final_answer: {
            type: "string",
            description: "방정식의 최종 답 (예: x = -3.75).",
          },
        },
        required: ["steps", "final_answer"],
        additionalProperties: false,
      },
    },
  },
});

참고: Responses API에서 올바른 필드는 text.format입니다. 구 response_format 키는 Responses API에서 비권장(deprecated)입니다(출처: OpenAI Developer Community).

3.5 Function Calling에서의 Structured Outputs

도구 호출에 Structured Outputs를 적용하려면 함수 정의에 strict: true를 추가합니다.

const response = await client.responses.create({
  model: "gpt-4o",
  input: "주문 번호 #12345의 배송일을 알려주세요",
  tools: [
    {
      type: "function",
      name: "get_delivery_date",
      description: "주문의 예정 배송일을 가져옵니다.",
      strict: true,
      parameters: {
        type: "object",
        properties: {
          order_id: { type: "string" },
        },
        required: ["order_id"],
        additionalProperties: false,
      },
    },
  ],
});

제한사항: Function Calling에 Structured Outputs를 사용할 때는 parallel_tool_callsfalse로 설정해야 합니다.

3.6 Structured Outputs가 보장하는 것 (보장하지 않는 것)

항목 상태 보충
올바른 JSON 구문 ✅ 보장
지정된 스키마 준수 ✅ 보장(strict: true인 경우)
필수 필드 존재 ✅ 보장
enum에 지정된 값 사용 ✅ 보장
사실적 정확성 ❌ 보장 안 됨 스키마와 관계없는 입력에 대해 할루시네이션이 발생할 수 있습니다.
안전 정책 면제 ❌ 보장 안 됨 안전상의 이유로 모델이 refusal을 반환할 수 있습니다.

refusal 처리 예시:

const response = await client.responses.parse({
  model: "gpt-4o",
  input: [/* ... */],
  text: { format: zodResponseFormat(MathResponse, "math_response") },
});

if (response.output[0].content[0].type === "refusal") {
  console.log("Model refused:", response.output[0].content[0].refusal);
} else {
  const result = response.output_parsed;
}

3.7 strict 모드에서의 스키마 제약

strict: true 모드에서는 일부 JSON Schema 기능이 제한됩니다(출처: Structured Outputs Guide).

  • additionalProperties: false가 필수입니다.
  • 모든 속성이 required 배열에 포함되어야 합니다.
  • 루트 객체에서 anyOf를 직접 사용할 수 없습니다.
  • oneOf, anyOf 등의 조합에 제한이 있습니다.

스키마와 타입 정의 간의 불일치를 방지하기 위해 OpenAI는 공식적으로 네이티브 Zod 지원이 있는 SDK 사용을 강력히 권장합니다.


4. Realtime API

2025년에 일반 제공(GA)에 도달한 Realtime API는 WebRTC, WebSocket, SIP를 통한 저레이턴시 양방향 음성 및 텍스트 스트리밍을 위한 전용 API입니다. 브라우저에서 직접 연결되는 음성 에이전트나 전화 시스템(PBX)과의 연동 같은 실시간 상호작용 사용 사례를 위해 설계되어, Responses API와는 용도가 명확히 구분됩니다. 자세한 내용은 공식 Realtime API 가이드를 참조하세요.


5. 스트리밍

Responses API는 Server-Sent Events (SSE) 형식의 스트리밍을 지원해 긴 응답을 점진적으로 수신할 수 있습니다.

const stream = await client.responses.stream({
  model: "gpt-4o",
  input: "우주의 시작에 대해 자세히 알려주세요.",
});

for await (const event of stream) {
  if (
    event.type === "response.output_text.delta" &&
    event.delta
  ) {
    process.stdout.write(event.delta);
  }
}

Structured Outputs도 스트리밍과 결합할 수 있으며, 이 경우 끝에 스키마를 완전히 준수하는 JSON이 반환됩니다.


6. HTTP 응답 헤더

API 응답에는 디버깅 및 레이트 모니터링에 유용한 헤더가 포함됩니다.

헤더 내용
x-request-id 요청의 고유 ID(지원 문의 시 필요).
x-ratelimit-limit-requests 현재 적용된 RPM 제한.
x-ratelimit-limit-tokens 현재 적용된 TPM 제한.
x-ratelimit-remaining-requests 남은 요청 수.
x-ratelimit-remaining-tokens 남은 토큰 수.
x-ratelimit-reset-requests RPM 리셋까지의 시간.
x-ratelimit-reset-tokens TPM 리셋까지의 시간.

클라이언트 측에서 요청 ID를 지정하려면 X-Client-Request-Id 헤더를 추가합니다.


7. 레이트 리밋

레이트 리밋은 조직 및 프로젝트 단위로 적용됩니다(사용자 단위가 아님).

  • RPM (Requests Per Minute): 분당 요청 수.
  • TPM (Tokens Per Minute): 분당 토큰 수.

사용 티어는 누적 결제와 사용 이력에 따라 자동으로 상향됩니다. 429 Too Many Requests가 반환되면 지수 백오프로 재시도할 것을 권장합니다(출처: Rate Limits Guide).

import retry from "async-retry";

async function callApiWithBackoff(params) {
  return retry(
    async () => {
      return await client.responses.create(params);
    },
    {
      retries: 6,
      minTimeout: 1000,
      maxTimeout: 60000,
      randomize: true,
    }
  );
}

8. 버전 안정성과 모델 피닝

gpt-4o 같은 별칭은 주기적으로 새 스냅샷으로 업데이트되어 같은 프롬프트라도 출력이 변경될 수 있습니다. 프로덕션에서는 gpt-4o-2024-08-06 같은 스냅샷 이름을 피닝하고, 업데이트 시에는 항상 평가(eval)를 수행할 것을 권장합니다.


정리

포인트 내용
신규 프로젝트 Responses API (POST /v1/responses) 사용.
Chat Completions 계속 지원. 즉시 마이그레이션 불필요.
Assistants API 2026년 8월 26일 서비스 종료. Responses API로의 마이그레이션 권장.
Structured Outputs strict: true + additionalProperties: false로 100% 스키마 준수.
Responses API 사용 response_format 대신 text.format 사용.
실시간 음성 Realtime API (WebRTC / WebSocket / SIP) 참조.
레이트 리밋 헤더 모니터링 및 지수 백오프로 재시도.
모델 버전 관리 프로덕션에서 스냅샷 피닝 및 eval 수행.

유용한 링크