개발

ChatGPT API 파이썬 연동

ilboard 2026. 5. 30. 15:45

ChatGPT API 파이썬으로 연동하기 — 처음부터 실제 사용까지

API 키 발급받고 나서 "이제 뭘 하지?" 하는 단계가 생각보다 헷갈린다. 문서는 영어고, 예제는 단순하고, 실제로 쓰려면 어디서부터 손대야 할지 막막한 경우가 많다.

이 글에서는 ChatGPT API를 파이썬으로 연동하는 전체 흐름을 정리한다. 단순 Hello World가 아니라, 실제로 쓸 수 있는 구조까지 다룬다.

A developer working at a clean desk with a dark monitor showing Python code and the OpenAI API documentation side by side, modern minimal workspace, soft warm desk lamp lighting, professional tech blog atmosphere, realistic photo, cinematic lighting, dark mode code editor visible on screen


API 키 발급과 환경 설정

먼저 platform.openai.com에서 계정을 만들고 API 키를 발급받아야 한다. 발급 후에는 키를 코드에 직접 넣지 말고 반드시 환경 변수로 관리한다.

pip install openai python-dotenv

프로젝트 루트에 .env 파일을 만들고 키를 저장한다.

OPENAI_API_KEY=sk-...

.gitignore.env를 추가하는 건 기본 중의 기본이다. 실수로 올라가면 키를 즉시 폐기해야 한다.


기본 호출 구조 잡기

openai 라이브러리는 1.x 버전부터 인터페이스가 바뀌었다. 구버전 코드가 많이 돌아다니니 버전 확인이 필요하다.

import os
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv()

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

def ask(prompt: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "user", "content": prompt}
        ]
    )
    return response.choices[0].message.content

gpt-4o-mini는 비용 대비 성능이 괜찮은 편이라 테스트나 단순 자동화에 많이 사용하는 방식이다. 응답 품질이 더 중요하면 gpt-4o로 바꾸면 된다.

호출 결과는 response.choices[0].message.content로 꺼낸다. 처음에는 구조가 낯설지만 한 번 익히면 패턴이 반복된다.


실무에서 자주 쓰는 패턴 3가지

시스템 프롬프트 분리

사용 목적에 따라 AI의 역할을 고정할 수 있다. 이 방식이 관리하기 편했다.

def ask_with_role(system: str, user: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": system},
            {"role": "user", "content": user}
        ]
    )
    return response.choices[0].message.content

result = ask_with_role(
    system="당신은 파이썬 코드 리뷰 전문가입니다. 간결하게 핵심만 설명하세요.",
    user="이 코드의 문제점이 뭔가요? ..."
)

시스템 프롬프트를 잘 잡으면 응답 일관성이 확실히 달라진다.

대화 맥락 유지

단발 질문이 아닌 대화 흐름이 필요하면 messages 배열을 직접 관리한다.

history = []

def chat(user_message: str) -> str:
    history.append({"role": "user", "content": user_message})

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=history
    )

    reply = response.choices[0].message.content
    history.append({"role": "assistant", "content": reply})
    return reply

히스토리가 길어질수록 토큰 비용이 올라가니 적당히 자르거나 요약하는 로직을 붙이는 게 좋다.

스트리밍 응답

긴 답변을 기다리지 않고 실시간으로 출력하려면 stream=True를 쓴다.

def ask_stream(prompt: str) -> None:
    stream = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        stream=True
    )

    for chunk in stream:
        delta = chunk.choices[0].delta.content
        if delta:
            print(delta, end="", flush=True)
    print()

CLI 도구나 터미널 앱에서 쓸 때 체감 속도가 많이 달라진다.

Terminal window showing real-time streaming output from a Python script calling the OpenAI API, dark terminal background with green text output, developer environment, realistic screenshot style, tech blog aesthetic, clean composition


비용과 에러 처리

API는 토큰 단위로 과금되니 실제 서비스에 붙이기 전에 응답 길이를 제어하는 게 필요하다.

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": prompt}],
    max_tokens=500,       # 응답 최대 길이 제한
    temperature=0.7       # 창의성 수준 (0~2, 낮을수록 일관적)
)

에러 처리도 빠뜨리기 쉬운 부분이다.

from openai import RateLimitError, APIConnectionError

try:
    result = ask(prompt)
except RateLimitError:
    print("요청 한도 초과. 잠시 후 재시도하세요.")
except APIConnectionError:
    print("API 연결 실패. 네트워크를 확인하세요.")

처음에는 그냥 돌리다가 rate limit 에러 한 번 맞고 나면 자연스럽게 추가하게 된다.


마무리

처음에는 헷갈릴 수 있지만 구조 자체는 단순하다. client 만들고 → messages 구성하고 → create() 호출하고 → .content 꺼내는 흐름이 반복된다.

실무에서 쓰다 보면 시스템 프롬프트 관리, 토큰 비용 추적, 응답 캐싱 같은 부분이 추가로 필요해지는데, 그건 기본 연동이 익숙해진 다음 단계에서 하나씩 붙이는 게 낫다.

일단 이 구조로 작은 자동화 하나 만들어보는 게 제일 빠른 방법이다.