> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apimart.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude 컨텍스트 캐시 사용 가이드

> Claude Messages API 또는 OpenAI 호환 Chat Completions API를 통해 반복해서 사용하는 프롬프트 접두부를 캐시하여 긴 콘텐츠를 반복 처리할 때 발생하는 token 비용을 줄입니다.

Claude 컨텍스트 캐시(Context Cache)는 system prompt, 문서, 코드베이스, 대화 기록 등의 긴 접두부를 반복해서 사용할 때 적합합니다. 안정적인 접두부에 `cache_control`을 추가하면 첫 번째 요청에서 캐시를 생성하고 이후 요청에서는 만료되지 않은 캐시를 읽을 수 있습니다.

사용 전에 API 키를 설정하세요.

```bash theme={null}
export API_KEY="API 키를 입력하세요"
```

<Note>이 가이드의 예제에서는 `claude-sonnet-5`를 사용합니다. 다른 모델의 컨텍스트 캐시 지원 여부는 플랫폼의 모델 설명을 참조하세요.</Note>

## 적합한 사용 사례

여러 요청에서 동일한 긴 콘텐츠를 반복해서 전송하는 경우 다음과 같은 안정적인 접두부를 캐시할 수 있습니다.

* 긴 system prompt
* 고정된 지식 베이스 또는 제품 문서
* 멀티턴 대화에서 변경되지 않는 이전 메시지
* 반복해서 사용하는 코드베이스, 도구 정의 및 설명

컨텍스트 캐시는 “앞부분의 콘텐츠는 그대로 유지되고 마지막 질문만 계속 바뀌는” 요청에 적합합니다.

## Claude Messages API

### 5분 캐시

캐시할 content block에 `cache_control`을 추가합니다.

```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "여기에 반복해서 사용할 긴 접두부를 입력합니다……",
        "cache_control": {
          "type": "ephemeral"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "위 내용에 따라 질문에 답변하세요."
      }
    ]
  }'
```

<Warning>`system`은 content block 배열로 작성해야 합니다. 문자열 형식의 `system`에는 `cache_control`을 추가할 수 없습니다.</Warning>

`ttl`을 생략하면 캐시 유효 기간은 기본적으로 5분입니다.

### 1시간 캐시

1시간 캐시를 사용하려면 `anthropic-beta` 요청 헤더를 추가하고 `ttl`을 `1h`로 설정해야 합니다.

```bash theme={null}
curl "https://api.apimart.ai/v1/messages" \
  -H "x-api-key: $API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: extended-cache-ttl-2025-04-11" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "system": [
      {
        "type": "text",
        "text": "여기에 반복해서 사용할 긴 접두부를 입력합니다……",
        "cache_control": {
          "type": "ephemeral",
          "ttl": "1h"
        }
      }
    ],
    "messages": [
      {
        "role": "user",
        "content": "위 내용에 따라 질문에 답변하세요."
      }
    ]
  }'
```

지원되는 TTL:

| TTL  | 의미                                            |
| ---- | --------------------------------------------- |
| `5m` | 5분 동안 캐시하며, `ttl`을 생략하면 이 값을 사용               |
| `1h` | 1시간 동안 캐시하며, 해당 `anthropic-beta` 요청 헤더도 함께 필요 |

### 응답 사용량 필드

Claude Messages API는 일반 입력, 캐시 쓰기 및 캐시 읽기 token을 `usage`에 각각 반환합니다.

```json theme={null}
{
  "usage": {
    "input_tokens": 23,
    "cache_creation_input_tokens": 2619,
    "cache_read_input_tokens": 0,
    "cache_creation": {
      "ephemeral_5m_input_tokens": 2619,
      "ephemeral_1h_input_tokens": 0
    },
    "output_tokens": 24
  }
}
```

총 입력 token은 다음과 같이 계산합니다.

```text theme={null}
input_tokens
+ cache_creation_input_tokens
+ cache_read_input_tokens
```

이 세 항목은 서로 겹치지 않습니다. 첫 번째 요청에서는 일반적으로 `cache_creation_input_tokens > 0`이 표시됩니다. 동일한 안정적인 접두부를 다시 전송하면 `cache_read_input_tokens > 0`이 표시되어야 합니다.

## OpenAI 호환 API

### 요청 예제

`/v1/chat/completions`를 통해 캐시를 사용할 때 `cache_control` 형식은 Claude Messages API와 유사합니다.

```bash theme={null}
curl "https://api.apimart.ai/v1/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "system",
        "content": [
          {
            "type": "text",
            "text": "여기에 반복해서 사용할 긴 접두부를 입력합니다……",
            "cache_control": {
              "type": "ephemeral"
            }
          }
        ]
      },
      {
        "role": "user",
        "content": "위 내용에 따라 질문에 답변하세요."
      }
    ]
  }'
```

### 1시간 캐시

OpenAI 호환 형식도 1시간 캐시를 지원합니다. 요청에 `anthropic-beta` 헤더를 추가하고 `cache_control`에서 `ttl: "1h"`를 설정하세요.

```bash theme={null}
-H "anthropic-beta: extended-cache-ttl-2025-04-11"
```

```json theme={null}
"cache_control": {
  "type": "ephemeral",
  "ttl": "1h"
}
```

### `content`는 배열로 지정

OpenAI 호환 형식에서는 `cache_control`을 구체적인 content block 안에 배치해야 하며 문자열 형식의 메시지에 추가할 수 없습니다.

```json theme={null}
{
  "role": "system",
  "content": "여기에 긴 접두부를 입력합니다……",
  "cache_control": {
    "type": "ephemeral"
  }
}
```

위 형식은 캐시를 활성화하지 않으며 요청도 오류를 반환하지 않습니다. 올바른 형식은 다음과 같습니다.

```json theme={null}
{
  "role": "system",
  "content": [
    {
      "type": "text",
      "text": "여기에 긴 접두부를 입력합니다……",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ]
}
```

<Warning>`content`가 문자열이면 캐시 표시가 무시되고 입력 콘텐츠는 일반 입력으로 처리됩니다. 응답의 캐시 사용량 필드를 확인하여 캐시 적중 여부를 판단하세요.</Warning>

### user 또는 assistant content block 캐시

`user` 또는 `assistant` 메시지의 content block에도 `cache_control`을 추가하여 긴 문서나 멀티턴 대화 접두부를 캐시할 수 있습니다.

```json theme={null}
{
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": "여기에 반복해서 사용할 긴 문서를 입력합니다……",
      "cache_control": {
        "type": "ephemeral"
      }
    },
    {
      "type": "text",
      "text": "위 문서의 핵심 내용을 세 가지로 요약하세요."
    }
  ]
}
```

안정적인 콘텐츠와 현재 질문을 서로 다른 content block으로 나누고 안정적인 content block에만 `cache_control`을 추가하세요.

### 응답 사용량 필드

OpenAI 호환 형식은 다른 필드를 사용하여 캐시 사용량을 보고합니다.

```json theme={null}
{
  "usage": {
    "prompt_tokens": 1942,
    "completion_tokens": 22,
    "prompt_tokens_details": {
      "cached_tokens": 1921,
      "cache_write_tokens": 0
    },
    "claude_cache_creation_5_m_tokens": 0,
    "claude_cache_creation_1_h_tokens": 0
  }
}
```

필드 대응:

| 의미          | Claude Messages API                        | OpenAI 호환 API                                                     |
| ----------- | ------------------------------------------ | ----------------------------------------------------------------- |
| 총 입력        | 세 입력 필드의 합계                                | `prompt_tokens`                                                   |
| 캐시 읽기       | `cache_read_input_tokens`                  | `prompt_tokens_details.cached_tokens`                             |
| 일반 캐시 쓰기 필드 | `cache_creation_input_tokens`              | `prompt_tokens_details.cache_write_tokens`(TTL 세부 항목이 없을 때만 값 반환) |
| 5분 캐시 쓰기    | `cache_creation.ephemeral_5m_input_tokens` | `claude_cache_creation_5_m_tokens`                                |
| 1시간 캐시 쓰기   | `cache_creation.ephemeral_1h_input_tokens` | `claude_cache_creation_1_h_tokens`                                |
| 출력          | `output_tokens`                            | `completion_tokens`                                               |

<Note>`prompt_tokens_details.cache_write_tokens`가 `0`이어도 `claude_cache_creation_5_m_tokens`와 `claude_cache_creation_1_h_tokens`를 확인하세요. TTL 세부 필드가 있는 경우 캐시 쓰기 양은 해당 필드에 반환됩니다.</Note>

<Note>`claude_cache_creation_5_m_tokens`와 `claude_cache_creation_1_h_tokens`에서 숫자와 단위 사이에는 밑줄이 있습니다. 응답에 반환된 필드 이름을 그대로 사용하세요.</Note>

<Warning>OpenAI 호환 인터페이스는 `stream: true`를 명시적으로 전달하지 않아도 SSE 스트리밍 응답을 반환할 수 있습니다. 클라이언트는 `chat.completion.chunk`를 파싱할 수 있어야 하며, 사용량은 `usage`가 포함된 마지막 데이터 블록에 있습니다.</Warning>

## 캐시 적중 조건

### 접두부가 최소 길이를 충족

이 가이드에서 사용하는 모델의 캐시 접두부에는 일반적으로 약 1024 token 이상이 필요합니다. 접두부가 너무 짧으면 오류 없이 캐시 표시가 무시될 수 있습니다.

### 접두부가 바이트 단위로 동일하게 유지

캐시 접두부의 텍스트, 공백, 줄바꿈 및 content block 순서는 모두 동일하게 유지해야 합니다. 안정적인 접두부에 타임스탬프, 임의 ID, 요청 횟수 등의 동적 콘텐츠를 추가하지 마세요.

### 요청이 모델 거부를 유발하지 않음

요청이 모델 거부를 유발하면 응답에 캐시 생성 token이 보고되더라도 다음 요청에서 해당 캐시를 읽지 못합니다. 캐시 미스를 해결할 때는 `stop_reason`이 `refusal`인지도 확인하세요.

### 캐시가 아직 유효함

캐시 유효 기간은 5분 또는 1시간이며 마지막으로 액세스한 시점부터 계산됩니다. 캐시에 적중하면 유효 기간이 갱신됩니다.

## 과금 사용량

캐시 관련 사용량은 세 가지로 나뉩니다.

| 사용량   | 발생 시점             |
| ----- | ----------------- |
| 캐시 쓰기 | 캐시를 처음 생성할 때      |
| 캐시 읽기 | 이후 요청에서 캐시에 적중할 때 |
| 일반 입력 | 캐시 접두부 이외의 입력     |

세 가지 사용량은 서로 겹치지 않습니다. 캐시 쓰기 비용은 일반적으로 일반 입력보다 높고 캐시 읽기 비용은 일반 입력보다 낮으므로, 컨텍스트 캐시는 TTL 내에 반복해서 사용하는 안정적인 접두부에 적합합니다.

## 최소 재현 예제

아래 스크립트는 충분히 긴 안정적인 접두부를 생성하고 동일한 요청을 연속해서 두 번 전송합니다. 두 번째 응답에는 `cache_read_input_tokens > 0`이 표시되어야 합니다.

```bash theme={null}
python3 - <<'PY' > /tmp/claude-cache-request.json
import json

paragraph = (
    "프롬프트 캐싱은 요청의 접두부를 저장하므로 이후 요청에서 "
    "바이트 단위로 동일한 접두부를 다시 처리하지 않고 재사용할 수 있습니다. "
)

system_text = (
    "당신은 문서 작성 도우미입니다. 참고 자료는 다음과 같습니다.\n\n"
    + paragraph * 40
)

print(json.dumps({
    "model": "claude-sonnet-5",
    "max_tokens": 32,
    "system": [{
        "type": "text",
        "text": system_text,
        "cache_control": {"type": "ephemeral"}
    }],
    "messages": [{
        "role": "user",
        "content": "변경하지 않고 유지해야 하는 항목을 한 문장으로 답하세요."
    }]
}))
PY

for request_number in 1 2; do
  echo "${request_number}번째 요청"
  curl -s "https://api.apimart.ai/v1/messages" \
    -H "x-api-key: $API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "Content-Type: application/json" \
    --data @/tmp/claude-cache-request.json \
  | python3 -c "import json, sys; print(json.load(sys.stdin)['usage'])"
done
```

예상 결과:

```text theme={null}
요청 1: cache_creation_input_tokens > 0, cache_read_input_tokens = 0
요청 2: cache_creation_input_tokens = 0, cache_read_input_tokens > 0
```

## 문제 해결 체크리스트

캐시에 적중하지 않으면 다음 항목을 순서대로 확인하세요.

* `stop_reason`이 `refusal`인지
* 캐시 접두부가 모델의 최소 token 수를 충족하는지
* 두 요청의 안정적인 접두부가 바이트 단위로 동일한지
* OpenAI 호환 형식의 `content`가 배열인지
* `cache_control`이 구체적인 content block 안에 있는지
* 1시간 캐시에 `ttl: "1h"`와 해당 `anthropic-beta` 요청 헤더가 모두 설정되어 있는지
* 캐시가 TTL을 초과했는지
* 현재 사용 중인 인터페이스에 해당하는 캐시 사용량 필드를 읽고 있는지
