OpenAI 프롬프트 캐싱 최적화, 고정 prefix·브레이크포인트·비용 측정법
AI를 활용하여 생성한 이미지입니다.
프롬프트 캐싱은 긴 지시문을 매번 새로 처리하지 않고, 반복되는 앞부분을 재사용해 입력 비용과 지연을 줄이는 기능이에요. OpenAI 문서 기준으로 캐시 대상은 개발자 지시문만이 아니라 도구 정의와 대화 이력까지 포함한 렌더링된 전체 문맥이에요.[1] 그래서 캐시 적중률을 높이려면 모델 호출 횟수보다 요청 앞부분의 모양을 먼저 설계해야 해요.
캐시가 깨지는 지점부터 찾아요
캐시 가능한 prefix는 요청마다 완전히 같은 순서와 내용으로 앞에 놓여야 해요. 모델, 도구 이름과 설명, 스키마, 도구 순서, 구조화 출력 형식이 바뀌면 캐시 prefix가 달라질 수 있어요.[1] 사용자의 질문이나 현재 문서처럼 매번 달라지는 내용은 뒤쪽에 두는 편이 낫습니다.
| 구성 요소 | 고정 영역에 둘 것 | 뒤로 미룰 것 |
|---|---|---|
| 개발자 지시 | 역할, 규칙, 출력 예시 | 실행마다 달라지는 작업 번호 |
| 도구 | 도구 이름·설명·스키마·순서 | 이번 요청에서만 필요한 도구 결과 |
| 사용자 입력 | 공통 업무 규칙이나 고정 기준 | 질문, 파일 내용, 검색 결과 |
| 출력 형식 | 같은 구조화 스키마 | 없음. 스키마를 매번 바꾸면 prefix도 바뀌어요. |
OpenAI 문서는 모델별 최소 캐시 길이를 안내해요. GPT-5.6 이상은 1,024토큰, 그보다 오래된 모델은 2,048토큰이 기준이에요.[1] 짧은 프롬프트를 억지로 늘리는 것보다, 반복되는 시스템 지시와 도구 정의가 실제로 이 기준을 넘는지 확인하는 편이 좋아요.
암묵적 캐시와 명시적 브레이크포인트
기본 동작만으로도 반복 prefix가 캐시될 수 있지만, 고정된 지시문과 가변 대화의 경계를 분명히 해야 한다면 명시적 브레이크포인트를 사용할 수 있어요. 문서에 따르면 prompt_cache_options.mode를 explicit로 두고 지원되는 입력 블록에 prompt_cache_breakpoint를 지정할 수 있어요.[1] 이 방식은 뒤의 동적 내용까지 캐시에 쓰지 않도록 경계를 잡을 때 유용해요.
prompt_cache_options: {
mode: "explicit",
ttl: "30m"
}
// 개념적 배치
개발자 지시 + 도구 정의 + 고정 예시 [브레이크포인트]
사용자 질문 + 현재 문서 + 도구 결과
30m은 현재 지원되는 캐시 수명 옵션이자 기본값이에요. 최근 쓰기 또는 재사용 뒤 30분 동안 재사용 대상이 될 수 있지만, 서버가 그보다 오래 보관할 수도 있어요.[1] 따라서 다음 날까지 반드시 적중한다고 가정하지 말고, 실제 요청의 사용량을 기록해야 해요.
cached_tokens를 비용 지표로 써요
캐싱 최적화는 체감 속도만으로 판단하면 안 돼요. 요청별 입력 토큰 중 캐시 읽기가 얼마나 발생했는지, 캐시 쓰기와 일반 입력이 각각 얼마인지, 응답 지연과 총비용이 어떻게 변했는지를 같은 기간에 비교해야 해요.[1] 문서도 모델을 옮길 때 cached_tokens, cache write 토큰, 지연, 전체 비용을 전후로 비교하라고 안내해요.
- 먼저 같은 모델과 같은 도구 정의로 20~30건 정도의 대표 요청을 기록해요.
- 고정 prefix와 가변 suffix를 분리한 뒤 같은 요청군을 다시 실행해요.
- 첫 요청의 쓰기 비용과 뒤 요청의 읽기 비중을 구분해요.
- 캐시가 적중해도 답변 품질, 도구 오류, 재시도 횟수가 나빠지지 않았는지 함께 봐요.
캐시가 읽혔다고 해서 결과가 완전히 같아지는 것은 아니에요. 캐시는 입력 처리 경로를 줄이는 기능이지 출력 토큰을 고정하는 기능이 아니에요.[1] 동일한 prefix라도 모델은 새로운 응답을 생성하므로 품질 검사는 별도로 남겨야 해요.
도구 호출과 구조화 출력을 함께 쓸 때
도구를 연결한 애플리케이션에서는 함수 호출을 사용하고, 모델이 최종 답변으로 구조화된 데이터를 내보내게 할 때는 구조화 출력 형식을 선택하는 식으로 역할을 나누면 돼요.[2] 함수 호출 결과를 다음 요청에 넣을 때는 해당 호출의 call_id를 정확히 연결해야 하고, 도구 결과는 구조화 JSON이나 일반 텍스트로 보낼 수 있어요.[3]
함수 스키마에는 가능하면 strict: true를 적용하는 편이 좋아요. OpenAI 문서는 strict 모드가 함수 호출이 스키마를 따르도록 돕고, 항상 활성화하는 것을 권장한다고 설명해요.[3] 다만 지원하지 않는 JSON Schema 키워드가 있으면 오류가 날 수 있으므로 스키마를 단순하게 만들고 실제 호출에서 검증하세요.[2]
Responses API로 옮기는 경우에는 Chat Completions의 messages 배열을 곧바로 복사하기보다 input, instructions, output 구조와 함수 호출 결과 전달 방식을 다시 확인해야 해요. Responses API에서는 구조화 출력이 text.format을 사용하고, 응답의 출력 구조도 달라져요.[4] 마이그레이션 중 모델·도구·스키마를 동시에 바꾸면 캐시 적중률 변화와 API 형식 변화가 섞이므로 한 단계씩 옮기는 것이 안전해요.
캐시를 포기하는 편이 나은 경우
요청마다 시스템 지시, 도구 목록, 스키마가 크게 달라지거나 긴 prefix가 한 번만 쓰인다면 캐시 설계에 들인 복잡성이 이득보다 클 수 있어요. 보안상 사용자별 문맥을 섞으면 안 되는 서비스라면 공통 prefix에 개인 정보나 테넌트 전용 자료를 넣지 말고, 캐시 키와 데이터 경계를 분리해요. 캐시 적중률만 올리려고 오래된 정책이나 불필요한 예시를 계속 붙이는 것도 좋은 최적화가 아니에요.
이전에 도구 호출의 멱등성과 재시도를 다룬 AI 에이전트 도구 호출 설계 글과 함께 보면, 비용 최적화와 실행 안전성을 같은 설계표에서 관리하기 좋아요.