02. Chat Completions API와 Responses API 비교 v2
이 노트북은 같은 질문을 Responses API와 Chat Completions API에 각각 보내며 두 API의 요청 구조를 비교합니다.
# Colab 또는 로컬 노트북 실행 환경을 구분하기 위해 sys를 가져옵니다.
import sys
# 패키지 설치 명령을 현재 Python 커널에서 실행하기 위해 subprocess를 가져옵니다.
import subprocess
# 패키지 설치 여부를 확인하기 위해 importlib.util을 가져옵니다.
import importlib.util
# 환경 변수에서 API 키를 읽고 설정하기 위해 os를 가져옵니다.
import os
# API 키를 화면에 노출하지 않고 입력받기 위해 getpass를 가져옵니다.
import getpass
# .env 파일 위치를 다루기 위해 pathlib의 Path를 가져옵니다.
from pathlib import Path
# google.colab 모듈이 있으면 현재 런타임이 Google Colab이라고 판단합니다.
IN_COLAB = "google.colab" in sys.modules
# 노트북에서 사용하는 import 이름과 pip 패키지 이름을 짝지어 둡니다.
REQUIRED_PACKAGES = {
"openai": "openai>=2.26.0",
"dotenv": "python-dotenv>=1.2.2",
"pydantic": "pydantic>=2.11.0",
"PIL": "pillow>=12.1.1",
"requests": "requests>=2.32.5",
"numpy": "numpy>=2.3.3",
"websockets": "websockets>=15.0.1",
"websocket": "websocket-client>=1.8.0",
"nest_asyncio": "nest-asyncio>=1.6.0",
}
# 현재 커널에서 import할 수 없는 패키지만 설치하는 함수입니다.
def ensure_package(import_name: str, package_name: str) -> None:
# 이미 import 가능한 패키지는 설치를 건너뜁니다.
if importlib.util.find_spec(import_name) is not None:
# 설치가 필요 없음을 호출자에게 조용히 알리고 돌아갑니다.
return
# Colab에서는 현재 노트북 커널의 Python에 패키지를 설치해야 합니다.
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", package_name])
# Colab 기본 런타임에는 일부 OpenAI 실습 패키지가 없을 수 있으므로 먼저 준비합니다.
if IN_COLAB:
# 실습 전체에서 필요한 패키지를 하나씩 확인하고 부족한 것만 설치합니다.
for import_name, package_name in REQUIRED_PACKAGES.items():
# 누락된 패키지를 현재 Colab 런타임에 설치합니다.
ensure_package(import_name, package_name)
# 패키지 설치 이후 .env 로딩 기능을 사용할 수 있도록 load_dotenv를 가져옵니다.
from dotenv import load_dotenv
# 현재 작업 폴더의 .env 파일이 있으면 로컬 실행처럼 환경 변수로 올립니다.
load_dotenv(Path.cwd() / ".env")
# OPENAI_API_KEY가 이미 있으면 그대로 사용하고, 없으면 Colab Secrets 또는 입력으로 보완합니다.
if not os.getenv("OPENAI_API_KEY"):
# Colab Secrets에서 OPENAI_API_KEY를 읽어 볼 변수를 준비합니다.
secret_key = None
# Colab이 아닌 로컬 환경에서는 google.colab import가 실패할 수 있으므로 예외를 허용합니다.
try:
# Colab Secrets의 userdata API를 가져옵니다.
from google.colab import userdata
# Secrets에 저장된 OPENAI_API_KEY 값을 읽습니다.
secret_key = userdata.get("OPENAI_API_KEY")
except Exception:
# Colab Secrets를 사용할 수 없으면 이후 수동 입력 단계로 넘어갑니다.
secret_key = None
# Secrets에서 키를 찾았다면 현재 런타임 환경 변수로 설정합니다.
if secret_key:
# OpenAI SDK가 자동으로 읽을 수 있도록 표준 환경 변수 이름에 저장합니다.
os.environ["OPENAI_API_KEY"] = secret_key
else:
# 키가 없으면 노트북 실행자가 직접 입력하도록 요청합니다.
entered_key = getpass.getpass("OPENAI_API_KEY를 입력하세요: ").strip()
# 빈 문자열이 아닌 값을 입력한 경우에만 환경 변수로 등록합니다.
if entered_key:
# OpenAI SDK가 자동으로 읽을 수 있도록 표준 환경 변수 이름에 저장합니다.
os.environ["OPENAI_API_KEY"] = entered_key
# API 키가 끝까지 없으면 다음 OpenAI API 호출이 실패하므로 명확한 오류를 냅니다.
if not os.getenv("OPENAI_API_KEY"):
# Colab에서는 Secrets 또는 입력, 로컬에서는 .env 또는 환경 변수를 설정해야 함을 알려 줍니다.
raise RuntimeError("OPENAI_API_KEY가 없습니다. Colab Secrets, 수동 입력, 또는 .env 파일로 설정해 주세요.")
# 이후 셀에서 Colab 여부를 참고할 수 있도록 간단히 출력합니다.
print(f"개발환경: {'Colab' if IN_COLAB else '로컬'}")
# API 키를 직접 출력하지 않고 준비 완료 여부만 알려 줍니다.
print("OPENAI_API_KEY 준비 완료")
1단계. 최소 실행 환경 준비
이 단계에서는 API 호출에 필요한 기본 준비를 합니다. import, .env 로드, OpenAI() 클라이언트 생성, output 폴더 생성을 차례대로 확인합니다.
아래 셀에서 특히 client = OpenAI() 줄을 확인하세요. 이후 모든 API 호출은 이 client 객체에서 시작됩니다.
# 운영체제 환경 변수와 .env 값을 읽기 위해 os를 사용합니다.
import os
# JSON 메타데이터를 파일로 저장하기 위해 json을 사용합니다.
import json
# 실행 시간을 비교하는 예제에서 사용할 시간 측정 모듈입니다.
import time
# 노트북 실행 위치와 output 폴더 경로를 안전하게 다루기 위한 Path입니다.
from pathlib import Path
# .env 파일에 저장된 OPENAI_API_KEY를 현재 Python 환경으로 불러옵니다.
from dotenv import load_dotenv
# OpenAI API를 직접 호출하기 위한 공식 SDK 클라이언트입니다.
from openai import OpenAI
# 현재 노트북이 워크스페이스 루트에서 실행되는지, 01.text_generation 폴더에서 실행되는지 확인합니다.
CURRENT_DIR = Path.cwd().resolve()
# 워크스페이스 루트에서 실행 중이면 01.text_generation 폴더를 실습 루트로 사용합니다.
if (CURRENT_DIR / "01.text_generation").exists():
TEXT_GENERATION_DIR = CURRENT_DIR / "01.text_generation"
# 이미 01.text_generation 폴더 안에서 실행 중이면 현재 폴더를 실습 루트로 사용합니다.
else:
TEXT_GENERATION_DIR = CURRENT_DIR
# 워크스페이스 루트는 01.text_generation 폴더의 부모 폴더입니다.
WORKSPACE_ROOT = TEXT_GENERATION_DIR.parent
# 실행 결과를 저장할 output 폴더 경로입니다.
OUTPUT_DIR = TEXT_GENERATION_DIR / "output"
# output 폴더가 없으면 새로 만들고, 이미 있으면 그대로 둡니다.
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
# 워크스페이스 루트의 .env 파일을 읽습니다.
load_dotenv(WORKSPACE_ROOT / ".env")
# OpenAI API 키가 설정되어 있는지 먼저 확인합니다.
if not os.getenv("OPENAI_API_KEY"):
raise RuntimeError("OPENAI_API_KEY가 없습니다. 워크스페이스 루트의 .env 파일을 확인해 주세요.")
# OpenAI API를 호출할 클라이언트를 생성합니다. 이 줄이 모든 API 호출의 출발점입니다.
client = OpenAI()
# 이후 셀에서 저장 경로를 확인할 수 있도록 출력합니다.
print(f"실습 폴더: {TEXT_GENERATION_DIR}")
print(f"결과 저장 폴더: {OUTPUT_DIR}")
실습 폴더: C:\Users\ai4nu\2026-ai-tech\AS.1.1_0601\01.text_generation
결과 저장 폴더: C:\Users\ai4nu\2026-ai-tech\AS.1.1_0601\01.text_generation\output
2단계. 공통 프롬프트 준비하기
두 API를 비교하려면 같은 지시문과 같은 사용자 요청을 보내야 합니다.
# Responses API 요청 모델입니다.
RESPONSES_MODEL = os.getenv("OPENAI_RESPONSES_MODEL", "gpt-4.1-mini")
# Chat Completions API 요청 모델입니다.
CHAT_MODEL = os.getenv("OPENAI_CHAT_MODEL", "gpt-4.1-mini")
# 두 API에 공통으로 사용할 상위 지시문입니다.
INSTRUCTIONS = "당신은 교육용 튜터입니다. 짧고 쉬운 한국어로 답변하세요."
# 두 API에 공통으로 보낼 사용자 요청입니다.
PROMPT = "입사 첫 주에 꼭 해야 할 4가지 행동을 번호 목록으로 정리해 주세요."
print(f"Responses 모델: {RESPONSES_MODEL}")
print(f"Chat 모델: {CHAT_MODEL}")
print(PROMPT)
Responses 모델: gpt-4.1-mini
Chat 모델: gpt-4.1-mini
입사 첫 주에 꼭 해야 할 4가지 행동을 번호 목록으로 정리해 주세요.
3단계. Responses API 직접 호출하기
Responses API는 instructions와 input을 분리해서 전달합니다.
# Responses API 호출 시작 시간을 기록합니다.
responses_started = time.perf_counter()
# Responses API를 직접 호출합니다.
responses_response = client.responses.create(
# Responses API에 사용할 모델입니다.
model=RESPONSES_MODEL,
# 모델 역할과 답변 스타일입니다.
instructions=INSTRUCTIONS,
# 실제 사용자 요청입니다.
input=PROMPT,
# 최대 출력 토큰 수입니다.
max_output_tokens=240,
)
# 실행 시간을 계산합니다.
responses_elapsed = time.perf_counter() - responses_started
# Responses API의 최종 텍스트를 읽습니다.
responses_text = responses_response.output_text
print("[Responses API 결과]")
print(responses_text)
print(f"모델: {responses_response.model}")
print(f"실행 시간: {responses_elapsed:.4f}초")
print(f"사용량: {responses_response.usage}")
[Responses API 결과]
1. 인사 잘 하기
2. 회사 규칙 배우기
3. 동료와 친해지기
4. 적극적으로 질문하기
모델: gpt-4.1-mini-2025-04-14
실행 시간: 3.3258초
사용량: ResponseUsage(input_tokens=54, input_tokens_details=InputTokensDetails(cached_tokens=0), output_tokens=32, output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=86)
4단계. Chat Completions API 직접 호출하기
Chat Completions API는 messages 배열에 역할별 메시지를 넣습니다. 이 배열 구조가 Responses API와 가장 큰 차이입니다.
# Chat Completions API에 전달할 messages 배열입니다.
messages = [
# system 메시지는 모델의 역할과 규칙을 지정합니다.
{"role": "system", "content": INSTRUCTIONS},
# user 메시지는 실제 사용자 요청입니다.
{"role": "user", "content": PROMPT},
]
# Chat Completions API 호출 시작 시간을 기록합니다.
chat_started = time.perf_counter()
# Chat Completions API를 직접 호출합니다.
chat_response = client.chat.completions.create(
# Chat API에 사용할 모델입니다.
model=CHAT_MODEL,
# 대화 메시지 배열입니다.
messages=messages,
)
# 실행 시간을 계산합니다.
chat_elapsed = time.perf_counter() - chat_started
# Chat 응답은 choices[0].message.content에서 텍스트를 읽습니다.
chat_text = chat_response.choices[0].message.content
print("[Chat Completions API 결과]")
print(chat_text)
print(f"모델: {chat_response.model}")
print(f"실행 시간: {chat_elapsed:.4f}초")
print(f"사용량: {chat_response.usage}")
[Chat Completions API 결과]
1. 인사 잘 하기
2. 회사 규칙 배우기
3. 동료와 친해지기
4. 맡은 일 열심히 하기
모델: gpt-4.1-mini-2025-04-14
실행 시간: 1.2857초
사용량: CompletionUsage(completion_tokens=34, prompt_tokens=54, total_tokens=88, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=0, audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), prompt_tokens_details=PromptTokensDetails(audio_tokens=0, cached_tokens=0))
5단계. 비교 결과 저장하기
두 API의 결과와 사용량을 저장합니다.
# 저장할 파일 경로를 정합니다.
responses_path = OUTPUT_DIR / "02_responses_v2_output.txt"
chat_path = OUTPUT_DIR / "02_chat_v2_output.txt"
metadata_path = OUTPUT_DIR / "02_chatcompletions_api_v2_meta.json"
# 각 API의 텍스트 결과를 저장합니다.
responses_path.write_text(responses_text + "\\n", encoding="utf-8")
chat_path.write_text(chat_text + "\\n", encoding="utf-8")
# 사용량 객체를 JSON 저장 가능한 형태로 바꿉니다.
responses_usage = responses_response.usage.model_dump() if responses_response.usage else {}
chat_usage = chat_response.usage.model_dump() if chat_response.usage else {}
# 비교 메타데이터를 구성합니다.
metadata = {
"example": "02.chatcompletions_api_v2",
"responses_model": responses_response.model,
"chat_model": chat_response.model,
"responses_elapsed_seconds": round(responses_elapsed, 4),
"chat_elapsed_seconds": round(chat_elapsed, 4),
"responses_usage": responses_usage,
"chat_usage": chat_usage,
"responses_output_path": str(responses_path),
"chat_output_path": str(chat_path),
}
# JSON 메타데이터를 저장합니다.
metadata_path.write_text(json.dumps(metadata, ensure_ascii=False, indent=2) + "\\n", encoding="utf-8")
print(f"Responses 결과 저장: {responses_path}")
print(f"Chat 결과 저장: {chat_path}")
print(f"메타데이터 저장: {metadata_path}")
Responses 결과 저장: C:\Users\ai4nu\2026-ai-tech\AS.1.1_0601\01.text_generation\output\02_responses_v2_output.txt
Chat 결과 저장: C:\Users\ai4nu\2026-ai-tech\AS.1.1_0601\01.text_generation\output\02_chat_v2_output.txt
메타데이터 저장: C:\Users\ai4nu\2026-ai-tech\AS.1.1_0601\01.text_generation\output\02_chatcompletions_api_v2_meta.json
'AI System > OpenAI API와 바이브 코딩으로 배우는 AI 서비스 개발' 카테고리의 다른 글
| d01 - 01. text_generation - 05. reasoning_vs_general_response_v2 (0) | 2026.06.01 |
|---|---|
| d01 - 01. text_generation - 04. Streaming_v2 (1) | 2026.06.01 |
| d01 - 01. text_generation - 03. 다중 턴 문맥 비교_v2 (0) | 2026.06.01 |
| d01 - 01. text_generation - 01. responses_api_v2 (0) | 2026.06.01 |
| README.md (1) | 2026.06.01 |