LLM에서 프롬프트 캐싱을 왜 신경 써야 할까?
Source: Towards Data Science
위의 링크에 포함된 전체 텍스트를 제공해 주시면, 해당 내용을 한국어로 번역해 드리겠습니다. 현재는 원문이 없으므로 번역을 진행할 수 없습니다. 텍스트를 복사해서 보내 주세요.
Source: …
RAG 및 AI 에이전트의 비용과 지연 시간 확장
우리는 RAG가 맞춤 데이터에서 AI의 힘을 활용하는 데 얼마나 놀라운 도구인지에 대해 많이 이야기했습니다. 일반적인 LLM API 요청이든, RAG 애플리케이션이든, 혹은 더 복잡한 AI 에이전트이든, 한 가지 질문은 언제나 동일합니다:
이 시스템들은 어떻게 확장될까?
구체적으로, 요청 수가 증가함에 따라 비용과 지연 시간은 어떻게 변할까?
단일 사용자 질의에 대해 여러 번의 LLM 호출을 포함할 수 있는 고급 AI 에이전트의 경우, 이러한 고민이 특히 중요해집니다.
캐싱이 중요한 이유
실제로, 많은 입력 토큰이 여러 요청에 걸쳐 반복됩니다:
- 사용자는 동일한 구체적인 질문을 반복해서 묻는 경우가 많습니다.
- 시스템 프롬프트와 지시문이 모든 질의에 포함됩니다.
- 단일 프롬프트라도 토큰‑단위로 재귀적으로 생성되면서 같은 컨텍스트가 여러 번 반복됩니다.
캐싱 개념을 적용하면 비용과 지연 시간을 크게 줄일 수 있습니다. OpenAI Prompt Caching 문서에 따르면:
- 지연 시간을 최대 **80 %**까지 단축할 수 있습니다.
- 입력 토큰 비용을 최대 **90 %**까지 절감할 수 있습니다.
요약
반복되는 프롬프트 구성 요소를 캐시하고 OpenAI의 프롬프트‑캐싱 기능을 활용하면, RAG 파이프라인과 AI 에이전트를 확장하면서 훨씬 더 효율적으로 만들 수 있습니다. 이 최적화는 프로덕션 수준 AI 애플리케이션에서 성능을 유지하고 비용을 통제하는 데 필수적입니다.
Source: …
캐싱은 어떨까?
일반적으로, 캐싱은 컴퓨팅에서 새로운 개념이 아니다. 캐시의 핵심은 데이터를 일시적으로 저장해 두어 동일한 데이터에 대한 향후 요청을 더 빠르게 처리할 수 있게 하는 것이다. 이는 두 가지 기본 결과를 만든다:
- 캐시 히트 – 요청한 데이터가 캐시 안에 있어 빠르고 저렴하게 가져올 수 있다.
- 캐시 미스 – 데이터가 캐시 안에 없어 애플리케이션이 원본 소스에 접근해야 하며, 이는 더 비용이 많이 들고 시간이 오래 걸린다.
전형적인 예: 웹 브라우저
- 첫 방문 – 브라우저가 해당 URL에 대한 캐시를 확인한다.
- 결과: 캐시 미스 → 브라우저는 원격 서버에 페이지를 요청해야 한다.
- 페이지 로드 후 – 브라우저는 가져온 리소스를 로컬 캐시에 저장한다.
- 다음 방문 (예: 5분 후) – 브라우저가 다시 캐시에서 페이지를 찾는다.
- 결과: 캐시 히트 → 서버에 연락하지 않고 페이지가 즉시 로드된다.
이 메커니즘은 브라우징 속도를 높이고 네트워크 트래픽을 감소시킨다.
캐싱이 이렇게 효과적인 이유
대부분의 시스템은 데이터를 균등하게 접근하지 않는다. 대신, 소수의 데이터가 대부분의 요청을 차지하는 왜곡된 분포를 따른다. 많은 실제 애플리케이션이 파레토 원칙을 따르는데, 이는 대략 전체 요청의 80 %가 데이터의 20 %에 집중된다는 의미이다.
요청이 균등하게 분포한다면, 캐시 메모리는 주 메모리만큼 커야 하므로 비용이 너무 많이 든다. 이 왜곡을 활용하면 비교적 작은 캐시만으로도 많은 접근을 만족시킬 수 있어 성능이 크게 향상되고 비용이 절감된다.
Source:
프롬프트 캐싱 및 LLM 추론에 대한 간단한 소개
캐싱 개념 – 자주 사용되는 데이터를 어딘가에 저장하고, 원본 소스에서 다시 가져오는 대신 그곳에서 불러오는 것 – 은 LLM 호출의 효율성을 높이는 데 사용되며, 비용과 지연 시간을 크게 줄여줍니다.
캐싱은 AI 애플리케이션의 여러 부분에 적용될 수 있는데, 가장 중요한 것은 프롬프트 캐싱입니다. RAG 검색이나 질의‑응답 캐싱과 같은 다른 측면에도 유용할 수 있지만, 이 글에서는 프롬프트 캐싱에만 초점을 맞춥니다.
LLM 추론은 어떻게 작동하는가
LLM 추론(학습된 모델을 사용해 텍스트를 생성하는 과정)은 두 개의 뚜렷한 단계로 나뉩니다:
| 단계 | 수행 내용 | 주요 병목 현상 |
|---|---|---|
| Pre‑fill | 전체 프롬프트를 한 번에 처리해 첫 토큰을 생성합니다. | Compute‑bound – 무거운 행렬 곱셈 |
| Decoding | 마지막으로 생성된 토큰을 시퀀스에 추가하고, 다음 토큰을 자동 회귀 방식으로 생성합니다. | Memory‑bound – 매 토큰마다 전체 컨텍스트를 메모리에서 로드해야 함 |
예시
프롬프트:
What should I cook for dinner?첫 토큰 (Pre‑fill 후):
Here디코딩 반복:
Here
Here are
Here are 5
Here are 5 easy
Here are 5 easy dinner
Here are 5 easy dinner ideas디코딩 과정에서 모델은 이전 토큰들을 반복적으로 다시 처리하는데, 이는 매우 비효율적입니다.
KV (Key‑Value) 캐싱
KV caching 은 위의 비효율성을 해결하기 위해 프롬프트와 이미 생성된 토큰에 대한 중간 키와 값 텐서를 저장합니다. 각 디코딩 단계에서 모델은:
- 기존 컨텍스트에 대한 캐시된 KV 텐서를 가져옵니다.
- 새로운 토큰에 대한 KV 텐서만 계산합니다.
- 새로운 KV 쌍을 캐시에 추가합니다.
이렇게 모델은 매 새로운 토큰에 대해 필요 최소 연산만 수행합니다.
하지만 KV 캐싱은 단일 프롬프트와 단일 응답에만 적용됩니다.
프롬프트 캐싱
프롬프트 캐싱은 KV 캐싱을 다양한 프롬프트, 사용자, 세션에 걸쳐 확장합니다. 아이디어는 간단합니다:
- 프롬프트의 반복되는 접두사(예: 시스템 프롬프트, 지시문, 검색된 컨텍스트)를 식별한다.
- 해당 접두사의 KV 텐서를 한 번 계산해 저장한다.
- 새로운 요청에 동일한 접두사가 포함될 경우 저장된 KV 텐서를 재사용한다.
장점
- 비용 절감 – 동일한 토큰을 다시 계산할 필요가 없습니다.
- 지연 시간 감소 – 이미 수행된 작업을 건너뛰게 됩니다.
- 특히 RAG 파이프라인이나 큰 반복 지시문을 갖는 애플리케이션에 유용합니다.
토큰‑레벨 동작
캐싱은 토큰 수준에서 작동합니다. 두 프롬프트가 동일한 토큰 접두사를 공유하면, 접미사가 달라도 공유된 부분을 캐시에서 제공받을 수 있습니다. 공유 토큰은 프롬프트의 시작 부분에 있어야 하며, 그렇지 않으면 캐시 미스가 발생합니다.
예시 – 캐시 히트
Prompt 1
What should I cook for dinner?
Prompt 2
What should I cook for lunch?공통 접두사 “What should I cook”가 캐시 히트를 일으켜 Prompt 2의 연산을 절감합니다.
예시 – 캐시 미스
Prompt 1
Dinner time! What should I cook?
Prompt 2
Launch time! What should I cook?첫 토큰이 (“Dinner” vs. “Launch”) 다르기 때문에 캐시를 재사용할 수 없으며, 의미가 비슷하더라도 캐시 미스가 발생합니다.
실용적인 경험 법칙
- 정적 정보(시스템 프롬프트, 지시문, 검색된 컨텍스트) → 모델 입력의 앞부분에 배치한다.
- 동적 정보(타임스탬프, 사용자 ID, 사용자‑특정 질의) → 프롬프트의 뒤부분에 배치한다.
이 순서를 따르면 캐시 히트 가능성을 최대화하고 프롬프트 캐싱의 전체적인 이점을 누릴 수 있습니다.
OpenAI API와 직접 손을 더럽히기
최신 프론티어 기반 모델—예: GPT (OpenAI docs) 및 Claude (Claude cookbook)—은 API에서 바로 Prompt Caching을 제공합니다. 이 API에서는 캐시가 동일한 API 키를 사용하는 조직의 모든 사용자에게 공유됩니다.
- 요청이 들어오면 모델이 프롬프트 접두사를 캐시에 저장합니다.
- 동일한 접두사를 포함하는 이후 요청은 캐시를 활용해 사전 계산된 결과를 재사용합니다.
- 이를 통해 토큰 사용량을 줄이고 응답 생성 속도를 높일 수 있으며, 특히 많은 사용자가 반복적으로 유사한 프롬프트를 보내는 엔터프라이즈 규모 AI 애플리케이션에 유용합니다.
캐시 유지 옵션
| 유지 유형 | 일반적인 지속 시간 | 제공 여부 |
|---|---|---|
| In‑memory 프롬프트 캐시 | ~5 – 10 분 (최대 1 시간) | 캐시를 지원하는 모든 모델 |
| Extended 프롬프트 캐시 | 최대 24 시간 | 특정 모델에만 적용 (예: GPT‑5.2) |
Note: 대부분의 최신 모델에서는 Prompt Caching이 기본적으로 활성화되어 있지만, 유지 설정을 여전히 조정할 수 있습니다.
Source: …
최소 파이썬 예제
아래는 OpenAI API를 사용한 프롬프트 캐싱을 보여주는 짧은 스크립트입니다. 예제는 매우 큰 공유 프리픽스를 사용하여 캐싱 효과가 눈에 띄게 합니다.
from openai import OpenAI
api_key = "your_api_key"
client = OpenAI(api_key=api_key)
# ----------------------------------------------------------------------
# 캐싱에 필요한 1 024 토큰 임계값을 넘기기 위해 80번 반복된 거대한 프롬프트 프리픽스.
# ----------------------------------------------------------------------
prefix = """
You are a helpful cooking assistant.
Your task is to suggest simple, practical dinner ideas for busy people.
Follow these guidelines carefully when generating suggestions:
General cooking rules:
- Meals should take less than 30 minutes to prepare.
- Ingredients should be easy to find in a regular supermarket.
- Recipes should avoid overly complex techniques.
- Prefer balanced meals including vegetables, protein, and carbohydrates.
Formatting rules:
- Always return a numbered list.
- Provide 5 suggestions.
- Each suggestion should include a short explanation.
Ingredient guidelines:
- Prefer seasonal vegetables.
- Avoid exotic ingredients.
- Assume the user has basic pantry staples such as olive oil, salt, pepper, garlic, onions, and pasta.
Cooking philosophy:
- Favor simple home cooking.
- Avoid restaurant‑level complexity.
- Focus on meals that people realistically cook on weeknights.
Example meal styles:
- pasta dishes
- rice bowls
- stir fry
- roasted vegetables with protein
- simple soups
- wraps and sandwiches
- sheet‑pan meals
Diet considerations:
- Default to healthy meals.
- Avoid deep frying.
- Prefer balanced macronutrients.
Additional instructions:
- Keep explanations concise.
- Avoid repeating the same ingredients in every suggestion.
- Provide variety across the meal suggestions.
""" * 80 # repeat to exceed the caching threshold
# --------------------------------------------------------------
# Prompt 1 – 첫 번째 요청 (캐시를 채움)
# --------------------------------------------------------------
prompt1 = prefix + "What should I cook for dinner?"
response1 = client.responses.create(
model="gpt-5.2",
input=prompt1
)
print("\nResponse 1:")
print(response1.output_text)
print("\nUsage stats:")
print(response1.usage)
# --------------------------------------------------------------
# Prompt 2 – 두 번째 요청 (캐시된 프리픽스 재사용)
# --------------------------------------------------------------
prompt2 = prefix + "What should I cook for lunch?"
response2 = client.responses.create(
model="gpt-5.2",
input=prompt2
)
print("\nResponse 2:")
print(response2.output_text)
print("\nUsage stats:")
print(response2.usage)내부에서 무슨 일이 일어나나요?
- Prompt 1은 전체 토큰 수(≈ 20 014 토큰)를 사용합니다.
- Prompt 2는 캐시된 프리픽스를 재사용하므로 다른 부분만 청구됩니다.
- 청구된 토큰 ≈ 20 014 – 19 840 = 174 토큰 (≈ 99 % 절감).
프롬프트 캐싱이 언제 효과적인가?
OpenAI는 1 024 토큰 최소에 도달했을 때만 캐싱을 활성화하며, 캐시는 최대 24시간(연장 모드) 동안 유지될 수 있습니다. 따라서 가장 큰 비용 및 지연 시간 절감 효과는 다음과 같은 대규모 배포 상황에서 나타납니다:
- 많은 사용자가 매일 동일한 애플리케이션을 이용한다.
- 프롬프트 프리픽스가 길고 자주 반복된다.
이러한 시나리오에서는 프롬프트 캐싱이 토큰 사용량을 크게 줄이고 LLM 기반 애플리케이션의 응답 시간을 개선할 수 있습니다.
내 생각
프롬프트 캐싱은 LLM에 대한 강력한 최적화 기법으로, 비용과 시간 측면에서 AI 애플리케이션의 효율성을 크게 향상시킬 수 있습니다. 동일한 프롬프트 접두사를 재사용함으로써 모델은 중복 계산을 건너뛰고 동일한 입력 토큰을 반복적으로 처리하는 일을 피할 수 있습니다. 그 결과 응답 속도가 빨라지고 비용이 낮아지며, 특히 프롬프트의 큰 부분(예: 시스템 지시문이나 검색된 컨텍스트)이 여러 요청에 걸쳐 일정하게 유지되는 경우에 효과적입니다.
AI 시스템이 확장되고 LLM 호출 횟수가 증가함에 따라 이러한 최적화는 점점 더 중요해집니다.
나와 연결하기
모든 이미지는 별도 표기가 없는 한 저자에 의해 제공됩니다.