프롬프트 캐시(Prompt cache)의 타입 정의 완료: llm-ports 0.1.0-alpha.19 출시
요약
@llm-ports 0.1.0-alpha.19 버전은 Anthropic, OpenAI, Gemini 등 다양한 LLM 공급자의 프롬프트 캐싱 방식을 통합하는 공급자 중립적 인터페이스를 제공합니다. 이를 통해 개발자는 각 모델별로 상이한 캐싱 메커니즘을 일관된 타입 정의로 관리할 수 있습니다.
핵심 포인트
- Anthropic, OpenAI, Gemini의 서로 다른 캐싱 방식을 통합하는 인터페이스 제공
- 공급자 변경 시 코드 재작성 부담을 줄이는 ports-and-adapters 패턴 적용
- cacheControl 필드를 통한 네 가지 캐싱 모드 지원
- 비용 계산 필드명 변경(cacheDiscountUSD → cacheSavingsUSD)에 따른 마이그레이션 필요
요약 (TL;DR). @llm-ports 0.1.0-alpha.19 버전은 Anthropic, OpenAI, Gemini 전반에 걸쳐 프롬프트 캐싱 (prompt caching)을 위한 타입이 지정된, 공급자 중립적인 인터페이스를 제공합니다. 모든 요청에 하나의 선택적 cacheControl 필드가 포함되며, 네 가지 모드를 지원합니다. 또한, 파괴적 변경 사항(BREAKING change)으로 필드 이름이 변경되었습니다: cost.cacheDiscountUSD → cost.cacheSavingsUSD. 이는 2026-06-30에 예정된 beta.0 출시 전까지 진행되는 네 번의 형태 고정 (shape-locks) 중 세 번째 단계입니다.
설치: 이제 npm install @llm-ports/core@alpha를 통해 설치할 수 있습니다.
애초에 프롬프트 캐시에 포트 인터페이스가 필요했던 이유
세 명의 공급자, 세 가지의 완전히 다른 메커니즘.
Anthropic은 메시지 콘텐츠 (message-content) 블록에 배치되는 명시적인 cache_control: { type: "ephemeral" } 마커를 사용합니다. 사용자는 어떤 블록을 캐싱할지 직접 결정합니다. 공급자의 캐시 조회 (cache lookup)는 캐싱된 블록의 접두사 (prefix)를 기준으로 이루어집니다. 첫 번째 호출 시에는 쓰기 비용 (write rate)을 지불하고, 이후 호출 시에는 읽기 비용 (read rate)을 지불합니다.
OpenAI는 항상 켜져 있는 암시적 (implicit) 캐싱을 수행합니다. 사용 여부를 선택할 수 있는 API는 없습니다. 시스템이 알아서 캐싱하며, 캐시가 적중 (hit)할 때 할인율 (discount rate)을 적용받습니다. 제어 인터페이스 (control surface)나 API 계약 (API contract)이 없습니다.
Gemini는 핸들 (handle)을 반환하는 createCachedContent를 사용합니다. 캐싱하려는 콘텐츠와 함께 캐시 생성 API를 한 번 호출하여 불투명한 핸들 (opaque handle)을 받은 다음, 이후 요청 시 원래 콘텐츠 대신 해당 핸들을 전달합니다.
만약 이 세 가지를 모두 사용하는 애플리케이션을 작성한다면, 완전히 다른 세 가지 캐싱 코드 경로를 작성해야 합니다. 공급자를 변경하려면 해당 코드 경로를 다시 작성해야 합니다. 네 번째 공급자를 추가하려면 네 번째 경로를 추가해야 합니다.
이것이 바로 ports-and-adapters 패턴이 해결하고자 하는 상황입니다. 다만 우리가 아직 해결하지 못했을 뿐입니다.
고정된 형태 (The locked shape)
import type { CacheControl } from "@llm-ports/core";
interface CacheControl {
...
GenerateTextOptions, GenerateStructuredOptions, StreamTextOptions, StreamStructuredOptions, RunAgentOptions에서 cacheControl?이 이제 선택 사항(optional)입니다. 이를 생략하는 것은 `{ mode:
TypeScript가 모든 읽기 사이트(read site)를 포착합니다. 이전 필드 이름을 수동으로 작성한 런타임 코드는 조용히 undefined로 해결되므로, 대시보드 쿼리도 함께 확인하십시오. 전체 차이점(diff)과 몇 가지 주의 사항이 포함된 마이그레이션 가이드는 다음과 같습니다: docs/migration/alpha-18-to-alpha-19.md.
작동 예시 (Worked example)
길고 안정적인 시스템 프롬프트(system prompt)와 짧은 턴별 사용자 메시지가 포함된 Anthropic 멀티 턴 대화 예시입니다:
import { createAnthropicAdapter } from "@llm-ports/adapter-anthropic";
const adapter = createAnthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY! });
...
동일한 호출 사이트(call sites)가 OpenAI 및 Gemini에서도 작동합니다. cacheControl 필드는 어디에서나 허용됩니다. 제공업체(provider)에 상응하는 기능이 없는 경우 이는 아무런 동작도 수행하지 않는 no-op이 됩니다. 제공업체를 전환하더라도 캐시 경로를 다시 작성할 필요가 없습니다.
형태(Shape)는 고정되었습니다. 동작(Behaviors)은 그렇지 않습니다.
이 부분이 이해할 가치가 있는 계약(contract)의 핵심입니다.
CacheControl의 **형태(shape)**는 alpha.19에서 고정되었습니다. 모든 필드, 모든 리터럴(literal), 모든 유니온 멤버(union member)가 확정되었습니다. beta.0 버전에서도 이는 변경되지 않은 채 출시됩니다.
모드별 어댑터 동작은 형태를 깨뜨리지 않으면서 beta 마이너 버전 업데이트를 통해 성숙해집니다:
- Anthropic의
mode: "auto"를 위한 더 나은 정적 블록(static-block) 탐지. namespace를 위한 Helicone 프록시 헤더 전달.@llm-ports/capabilities하위의 GeminicreateCachedContent생명주기 헬퍼(생성, 갱신, 만료) 처리.
오늘 이 형태를 기준으로 호출 사이트를 작성한다면, Anthropic이 beta.1에서 수행하는 중단점(breakpoint) 배치는 귀하의 코드가 이미 지정한 동일한 마커를
- alpha.20 (2026-06-17, 화).
BudgetScope. 테넌트(tenant) → 고객(customer) → 사용자(user) → 에이전트(agent) → 세션(session)의 5단계 계층. 일부 제공업체(Cerebras의 30 RPM, 특정 모델에 대한 Groq의 10 RPM)는 아무리 수학적으로 기발하게 계산하려 해도cost:N/day로 표현할 수 없는 속도 제한(rate limits)을 가지고 있기 때문에 미세한 단위의 윈도우(minute-grain windows)를 제공합니다. - alpha.21 (2026-06-20, 금). OpenTelemetry의
gen_ai.*시맨틱 컨벤션(semantic conventions)에 맞춘 관측성(Observability) 훅 시그니처(hook signatures).onCost,onTokenUsage,onFallback,onValidationRetry,onCacheHit. Langfuse / Phoenix / OpenLLMetry / Datadog과의 즉시 연결(Drop-in wire-up) 지원. 사용자 측면에서의 어댑터 코드 작성 불필요. - beta.0 (2026-06-30, 화). 범위 확정(Scope-closed). 계약(Contract)이 하중을 견디는 구조(load-bearing)가 됩니다. 표면적인 변화가 멈춥니다.
그 후 beta 마이너 버전들은 잠금(locking)을 해제하고, 이미 존재했어야 할 기능들을 전달하기 시작합니다:
- beta.1 (2026-07-28, 화). 탄력적인 폴백(Resilient fallback) 프리셋 (
runtimeFallback.shouldFallback주변에 직접 회로 차단기(circuit breaker)를 구현할 필요가 없음).adapter-anthropic은 숨겨진 추론(hidden reasoning)에 전체 출력 예산(output budget)을 소비하는 확장 사고(extended-thinking) 모델에 비용을 낭비하는 것을 방지합니다. 안정적인 시스템 프롬프트를 위한 자동 멀티 턴(multi-turn)cache_control배치. 귀하가 직접 작성해 왔던 네 가지 기능 팩토리(capability factories):createDetector,createTagger,createAnswerer,createResponder. - beta.2 (2026-08-11, 화). 지속 가능한 예산 백엔드(Persistent budget backend). 비용 게이트(cost gates)가 프로세스 재시작 후에도 유지됩니다.
"테넌트당 100만 토큰당 $X"와 같은 토큰 단위 모드 지원. 플러그형CacheBackend를 통해 정확한 프롬프트 응답 캐시(exact-prompt response cache)를 원하는 곳(Redis, 파일, 자체 KV)에 저장할 수 있습니다. 세 가지 추가 팩토리:createRewriter,createDecider,createExpander. - beta.3 (2026-08-25, 화).
RerankPort에 첫 번째 어댑터 추가. 세 가지 더 난이도 높은 팩토리: PII(개인정보) 안전 프롬프트를 위한createRedactor, 멀티 턴 도구 사용(tool-use)이 설명서 없는 IKEA 가구 조립처럼 느껴지지 않게 하는createAgent인체공학(ergonomics),RerankPort를 둘러싼 기능 래퍼(capability-wrapper). - 1.0.0 (2026-09-08, 월). 계약(Contract)이 하중을 견디는 구조(load-bearing)가 됩니다.
테스트 통계
7개 패키지에 걸쳐 626개가 통과되었으며, 이는 alpha.18의 약 615개에서 증가한 수치입니다. packages/core/tests/cache-control.test.ts에 추가된 11개의 새로운 테스트가 형태 잠금(shape lock)과 이름 변경(rename)을 다룹니다. 기존의 비용(cost) 테스트 2개가 업데이트되었습니다. 동작 회귀(behavioral regressions)는 없습니다.
링크 (Links)
- GitHub 릴리스:
@llm-ports/core@0.1.0-alpha.19 - 캐시 개념 문서: docs/concepts/cache.md
- 마이그레이션 가이드: docs/migration/alpha-18-to-alpha-19.md
- 토론 스레드: #42
- 리포지토리: github.com/baabakk/llm-ports
beta.0 이전에 네 가지 모드에서 실제 간극을 발견하셨나요? 이슈(issue)를 등록해 주세요. 추가적인 필드(Additive fields)는 여전히 논의 가능하지만, 구조적 변경(structural changes)은 허용되지 않습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기