DEV Community

jidong
jidong

Posted on

LLM API 비용을 70% 줄이는 프로의 스킬 트리

AI 사이드 프로젝트를 시작하면서 가장 먼저 든 생각이 “이거 비용 구조가 어떻게 되는 거지?”였다.

나는 사주 앱이랑 부동산 분석 서비스를 만들어보고 있는 개발자다. 둘 다 LLM API를 쓸 계획인데, 서비스를 설계하기 전에 비용 구조를 먼저 이해하고 싶었다.

그래서 파봤다.

프로와 아마추어의 차이는 프롬프트를 잘 쓰느냐가 아니다.

비용 구조를 설계하느냐다.


토큰 경제학부터 이해하자

모든 것의 기본이다.

LLM API는 토큰 단위로 과금된다. 한국어 기준 1토큰은 대략 1~2글자. 영어는 0.75단어쯤 된다.

여기서 가장 중요한 건 이거다.

Output 토큰이 Input보다 훨씬 비싸다.

“친절하고 상세하게 설명해줘”라고 시키면 모델이 장문을 쏟아낸다. 그게 다 output 토큰이고, 다 돈이다.

max_tokens를 안 걸면 모델은 알아서 가능한 한 많이 쓴다.

“50자 이내로 답해”라고 시키는 것 자체가 비용 최적화다.

사주 서비스에서 “오늘의 운세 한줄”에 500토큰짜리 답변이 나온다고 치자.

max_tokens: 100을 걸고 프롬프트에 “20자 이내 한줄”을 명시하면 output 비용이 5분의 1로 줄어든다.


모든 요청을 Opus에 보내는 건 모든 이메일을 등기로 보내는 거다

모델 라우팅.

이걸 아느냐 모르느냐가 진짜 큰 차이다.

대충 가격만 봐도 감이 온다. Gemini Flash input이 $0.15/1M 토큰, Haiku가 $1, Sonnet이 $3, Opus가 $15다.

Opus는 Flash 대비 100배 비싸다.

“오늘 운세 알려줘” 같은 단순 요청을 Opus가 처리할 이유가 없다.

사주 서비스를 설계한다면 “오늘의 운세 한줄”은 Haiku면 충분하고, “사주팔자 심층 해석”만 Sonnet을 쓰면 된다.

요청의 대부분이 단순 운세일 텐데, 그걸 전부 Sonnet에 보내면 돈이 새는 거다.

# 이렇게 하면 안 된다 — 전부 Sonnet
result = await call_sonnet(prompt)  # 매 요청 $0.01+

# 이렇게 해야 한다 — 라우팅
if request_type == "daily_fortune":
    result = await call_haiku(prompt)  # $0.001
elif request_type == "deep_analysis":
    result = await call_sonnet(prompt)  # $0.01
Enter fullscreen mode Exit fullscreen mode

이것만으로 비용 70%가 줄어드는 서비스도 많다.


프롬프트 캐싱 — Anthropic의 숨은 무기

아는 사람이 의외로 적다.

Anthropic API에서 시스템 프롬프트에 cache_control을 붙이면, 반복되는 시스템 프롬프트를 매번 재처리하지 않는다.

{
  "system": [
    {
      "type": "text",
      "text": "너는 20년 경력의 명리학 전문가...(2000토큰)",
      "cache_control": {"type": "ephemeral"}
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

첫 호출에는 정상 비용이 나간다.

두 번째부터는 캐시 히트로 input 토큰 비용이 크게 줄어든다.

시스템 프롬프트가 2000토큰이고 하루 1,000명이 쓴다고 치면, 캐싱 없으면 200만 input 토큰이다.

캐싱이 걸리면 그게 20만 토큰 수준으로 내려간다.

코드 한 줄이 월 비용을 갈라놓는다.

OpenAI에는 이 수준의 명시적 캐싱이 아직 없다.

가격표만 보면 비슷해 보이는데, 캐싱까지 계산하면 Anthropic이 실질적으로 더 싸지는 순간이 온다.


대화가 길어지면 비용이 제곱으로 폭증한다

LLM API 구조상 대화가 이어지면 이전 메시지가 전부 input 토큰으로 다시 들어간다.

10턴 대화면 1턴부터 9턴까지의 모든 메시지가 매번 재전송된다.

대화가 길어질수록 비용이 누적합 형태로 폭증한다.

여기서 해결은 요약이다. 어느 시점에서든 대화 이력을 압축해서 다시 넣어야 한다.

슬라이딩 윈도우로 최근 N턴만 유지하는 것도 좋다.

RAG를 써서 필요한 정보만 벡터 검색으로 꺼내서 주입하는 것도 있다.

사주 서비스라면 대부분 1~2턴으로 끝날 거다.

근데 부동산 분석에서 “이 아파트 분석해줘” 다음에 “근처 다른 아파트는?” “둘 다 비교해줘” 같은 흐름이 나오면, 설계할 때부터 요약 삽입을 넣어둬야 한다.


시맨틱 캐싱 — 같은 질문에 두 번 돈 내지 마라

“1990년 3월 15일생 남자 운세”를 100명이 물어보면 100번 API를 호출할 이유가 없다.

임베딩으로 유사 쿼리를 감지해서 캐시된 응답을 반환하는 게 시맨틱 캐싱이다.

Redis와 벡터 DB를 조합하면 구현할 수 있다.

사주 서비스는 같은 생년월일 조합이 반복될 확률이 높으니까, 설계에 넣어둘 가치가 있다.

추가로 30~50% 비용을 더 깎을 수 있다.


모델 라우팅으로 70%.

프롬프트 캐싱으로 input 비용 90%.

시맨틱 캐싱으로 30~50%.

이론적으로 전체 비용 60~80% 절감이 가능하다.

서비스를 만들고 나서 비용을 깎는 게 아니라, 설계 단계에서 비용 구조를 잡는 게 맞다.

"비용 구조가 곧 해자다. 같은 서비스인데 네가 70% 싸게 돌리면, 그게 경쟁력이다."

Top comments (0)