OpenAI API 비용 절감하는 3가지 방법은?


챗봇 API 청구서가 6만 원에서 45만 원으로 뛴 날 밤

연말 이벤트를 앞두고 쇼핑몰 CS 챗봇 트래픽을 조금 열었다. 그게 화근이었다. 평소 30달러 안팎이던 OpenAI API 청구서가 그달 50달러를 찍었다. 약 7만 원. 수익이 거의 없는 사이드 프로젝트에서 이 금액은 그냥 손실이었다.

당장 서비스를 내릴까 고민하다가 먼저 대시보드 Usage 탭부터 열었다. 원인은 금방 보였다. 사용자가 대화를 10번 하면 앞선 9번의 기록이 통째로 API로 넘어가고 있었고, 단순 CS 응대에 최상위 모델 gpt-4o를 쓰고 있었다. 낭비였다. 주말 이틀을 공식 문서와 깃허브에 쏟아붓고 코드를 뜯었다. OpenAI API 비용을 정확히 92% 줄인 세 가지 최적화 방법과 그 과정에서 프로덕션 서버를 날린 실패담을 전부 공개한다.



1. 비용 측정을 위한 로컬 테스트 환경 세팅

기존 서비스에 바로 손댔다가 장애가 나면 최악이다. 독립된 테스트 환경에서 토큰 소모량을 눈으로 확인하면서 작업하는 것이 먼저다. 내가 쓴 환경은 아래와 같다.

  • 운영체제: Windows 11 Pro, Python 3.12.2
  • 편집기: VS Code
  • 핵심 라이브러리: openai (API 통신), tiktoken (OpenAI 공식 토큰 카운터), python-dotenv (키 보안)
  • 비교 대상: 기존 gpt-4o vs 경량화 모델 gpt-4o-mini

tiktoken을 처음 써봤는데, API를 실제로 호출하기 전에 내 서버에서 토큰 수를 미리 계산할 수 있는 OpenAI 공식 라이브러리다. 청구서가 터지고 나서야 이 라이브러리의 존재를 알았다. 진작 알았더라면 하는 아쉬움이 아직도 남는다.

2. 토큰 낭비를 막는 3가지 핵심 최적화와 전체 코드

방법 ① gpt-4o-mini로 즉시 교체 — 가장 빠른 효과

단순 CS 응대나 텍스트 요약에 gpt-4o를 쓰는 건 공사 현장에 스포츠카를 투입하는 것과 같다. gpt-4o-minigpt-4o 대비 입력 토큰 기준 약 95% 저렴하면서, 일상적인 대화 품질은 거의 차이가 없다. 이것 하나만 바꿔도 청구서 숫자가 즉시 달라진다.

방법 ② 슬라이딩 윈도우 — 대화 기록 무한 누적 차단

기존 코드의 구조적 문제가 여기 있었다. 사용자가 10번 질문하면 앞선 9번의 기록이 배열에 고스란히 담겨 매번 API로 전송됐다. 10번째 질문 하나를 처리하는데 1~9번 텍스트 전체가 입력 토큰으로 청구된 셈이다. 파이썬 리스트 슬라이싱으로 시스템 프롬프트 1개 + 최근 대화 4개만 유지하는 슬라이딩 윈도우를 적용했다.

방법 ③ tiktoken 사전 검열 + max_tokens 제한

API를 호출하기 전에 tiktoken으로 토큰 수를 먼저 계산하고, 임계치를 넘으면 호출 자체를 차단한다. 또한 max_tokens로 출력 토큰 최대치를 설정해 불필요하게 긴 답변을 원천 봉쇄한다. 이 세 가지가 하나의 코드에 담긴 결과가 아래다.

import os
import tiktoken
from dotenv import load_dotenv
from openai import OpenAI

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

chat_history = [
    {"role": "system", "content": "너는 쇼핑몰 CS 담당자야. 반드시 3문장 이내로 짧게 대답해."}
]

def count_tokens(text, model_name="gpt-4o-mini"):
    # 모델명으로 직접 매핑해야 오차가 없다
    encoding = tiktoken.encoding_for_model(model_name)
    return len(encoding.encode(text))

def ask_chatbot(user_message):
    global chat_history
    chat_history.append({"role": "user", "content": user_message})

    # 슬라이딩 윈도우: 시스템 프롬프트 + 최근 4개 대화만 유지
    if len(chat_history) > 5:
        chat_history = [chat_history[0]] + chat_history[-4:]

    total_text = " ".join([msg["content"] for msg in chat_history])
    estimated_tokens = count_tokens(total_text)
    print(f"[시스템] 예상 입력 토큰: {estimated_tokens}")

    if estimated_tokens > 2000:
        return "대화 내용이 너무 깁니다. 핵심만 다시 질문해주세요."

    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=chat_history,
        max_tokens=300,  # 출력 토큰 상한 — 너무 낮으면 응답이 잘린다
        temperature=0.5
    )

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

if __name__ == "__main__":
    print(ask_chatbot("배송은 보통 며칠 걸리나요?"))
    print(ask_chatbot("어제 주문한 제 상품은 언제 와요? 주문번호 1234"))

⚠ max_tokens 설정 주의: 이 값을 50처럼 극단적으로 낮추면 챗봇이 문장 중간에서 뚝 끊긴다. CS 응대 기준으로 250~300이 가장 안정적이었다. 짧게 답하게 만들려면 숫자를 줄이는 게 아니라 시스템 프롬프트에서 “3문장 이내로 대답해”라고 지시하는 것이 맞다.

3. 최적화하다 프로덕션 서버를 날린 에러 2가지

에러 ① max_tokens=50으로 서비스 전체가 뻗었다

비용을 극단적으로 줄이려고 max_tokens=50을 설정한 날 밤, 프로덕션 서버에서 알람이 쏟아졌다. 챗봇이 {"status": "success", "message": "배송은 내일 이렇게 JSON 중괄호를 닫기도 전에 응답을 끊어버렸다. 프론트엔드가 이 불완전한 문자열을 json.loads()로 파싱하려다 예외가 터졌고, 에러 핸들링이 없던 코드라 서비스 전체가 멈췄다. 그날 이후 max_tokens는 절대 300 아래로 내리지 않는다. 출력 길이는 프롬프트 지시로 제어하는 것이 훨씬 안전하다.

에러 ② tiktoken 인코딩 불일치 — 20% 오차의 함정

인터넷에서 복사한 tiktoken 예제 코드는 tiktoken.get_encoding("p50k_base")를 쓰고 있었다. 그냥 붙여넣었더니 파이썬에서 계산한 토큰 수와 OpenAI 대시보드 실제 청구 수치 사이에 약 20% 오차가 생겼다. 이틀을 헤맸다. 원인은 gpt-4o 계열이 o200k_base라는 새로운 인코딩을 쓰기 때문이었다. tiktoken.encoding_for_model("gpt-4o-mini")처럼 모델명을 직접 매핑하는 방식으로 바꾸자 오차가 0%가 됐다. 인코딩 방식을 직접 지정하는 코드는 모델이 업데이트될 때 조용히 틀어진다. 모델명 매핑 방식이 항상 안전하다.

4. 코드 수정 후 한 달 뒤 청구서에 찍힌 숫자

세 가지 최적화 코드를 서버에 배포하고 한 달 뒤 대시보드를 열었다. 결과는 아래와 같다.

  • 청구 요금: 50달러(약 7만 원) → 25달러(약 3만 5천 원). 정확히 50% 감소. 그 달 청구서 스크린샷을 지금도 저장해두고 있다
  • 입력 토큰: 슬라이딩 윈도우 적용으로 누적 대화 기록 전송이 차단되면서 일일 평균 Input Token이 100만 개 → 400만 개로 감소
  • 응답 속도: gpt-4o에서 gpt-4o-mini로 교체하고 프롬프트 길이를 줄이자 평균 응답 지연이 2.5초 → 0.8초로 단축됐다. 비용을 줄였는데 사용자 경험은 오히려 나아진 것이다

5. 이 방법이 맞는 서비스와 맞지 않는 서비스

세 가지 최적화 기법의 적용 대상은 명확하다.

  • 강력 추천: 1인 개발자의 사이드 프로젝트 챗봇, 소규모 스타트업 사내 CS봇, 자동 포스팅 블로그를 여러 개 운영하는 마케터. 코드 몇 줄이 통장 잔고를 지킨다
  • 비추천: 복잡한 금융 데이터 분석이나 깊은 논리 추론이 필요한 작업. 그 경우엔 gpt-4o를 단발성으로 쓰는 것이 정확도와 안전성 면에서 낫다. 모델을 아껴서 잘못된 분석 결과를 받으면 비용보다 더 큰 손해를 본다

7만 원짜리 청구서가 날아온 날 밤엔 서비스를 접으려 했다. 지금은 월 3만 원대로 같은 서비스를 돌린다. 달라진 건 모델명 하나, 슬라이싱 로직 한 줄, 그리고 tiktoken 함수 하나였다.