본문으로 건너뛰기
Koding
Claude Certified Architect – Foundations (CCA-F) 자격시험 교재
무료

Claude Certified Architect – Foundations (CCA-F) 자격시험 교재

한국 SI·컨설팅 실무자와 AI 엔지니어를 위한 CCA-F 합격 교재예요. 원문 61회 연재 원고를 내용 손실 없이 32개 장으로 재구성했어요. 각 세션의 이론·연습문제·해설은 한 장에 묶어 학습 흐름이 끊기지 않게 했고, 프로젝트와 모의고사는 문제편과 해설편을 분리해 실전처럼 풀 수 있게 했어요.

클로드claudeanthropicCCACCAF

5.제4장. 세션 2: Anthropic API 기초 (이론·연습문제·해설)

출제 도메인: 전 도메인 공통 기초 · 작성자: 김재우 (jaewoo@claudcode.to)


① Anthropic API 기초 완벽 정리 (CCA-F 세션 2): Messages API·주요 파라미터·Batch 처리

지난 장 돌아보기

지난 장에서는 Claude의 설계 철학과 모델 패밀리를 배웠어요. 이번 장에서는 그 모델들을 API에서 호출하기 위한 기본기를 배웁니다. CCA-F 시험에서는 Tool Use나 MCP 문제에서 API 파라미터 지식을 꼭 묻기 때문에, 여기를 확실히 다져 둡시다.

주제 개요

Anthropic API는 HTTP REST API로 제공되고, 그 중심에 messages 엔드포인트가 있어요. 구조 자체는 '메시지 리스트를 보내면 Claude의 어시스턴트 응답이 돌아온다'가 전부인 단순한 형태죠. 하지만 그 위에 system 프롬프트, 각종 파라미터, 툴 호출처럼 시험에서 묻는 개념이 여럿 얹혀 있습니다.

비유하자면 API는 'Claude라는 레스토랑의 웨이터' 같은 존재죠. 주문서(요청)를 건네면 요리(응답)가 나오는 단순한 구조지만, 주문서를 어떻게 쓰느냐에 따라 요리의 질이 크게 달라집니다.

습득 포인트

  • Messages API의 요청/응답 구조를 설명할 수 있다
  • 주요 파라미터(model·max_tokens·temperature·top_p·stop_sequences·system)의 의미를 말할 수 있다
  • role과 content의 역할을 이해하고 있다(user / assistant / system)
  • 에러 응답과 재시도의 기본 개념을 파악하고 있다
  • Message Batches API의 특징과 적용 판단을 설명할 수 있다
  • (참고) 스트리밍·요금 체계·레이트 리밋의 개요를 배경지식으로 이해하고 있다(모두 시험 범위 밖)

1. Messages API 요청 구조

1.1 최소 요청

basic_request.py

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "파이썬으로 피보나치 수열을 계산하는 함수 짜 줘."}
    ],
)

print(response.content[0].text)

1.2 요청의 주요 필드

필드필수용도
model사용할 모델의 ID
max_tokens생성할 최대 토큰 수
messages대화 이력(리스트)
system-시스템 프롬프트(Claude의 역할이나 제약을 지시)
temperature-0~1.0 부동소수점. 출력의 무작위성을 제어
top_p-확률 누적에 따른 샘플링 임곗값
top_k-상위 K개 토큰에서 샘플링
stop_sequences-이 문자열이 나타나면 생성 중단
stream-True면 스트리밍 응답
tools-툴 정의(Tool Use 기능, 세션 5에서 상세히)
metadata-로깅용 메타데이터(user_id 등)

1.3 메시지 구조

messages는 user / assistant 발화가 번갈아 늘어선 리스트예요.

conversation.py

messages = [
    {"role": "user", "content": "사과는 영어로 뭐야?"},
    {"role": "assistant", "content": "apple이에요."},
    {"role": "user", "content": "그럼 '귤'은?"},
]

규칙:

  • 첫 메시지는 반드시 user
  • user와 assistant는 번갈아 배치
  • system은 messages 안이 아니라 최상위 system 필드에 작성

Bad(가독성·비용 문제): system 역할을 messages에 넣기

bad.py

messages = [
    {"role": "system", "content": "당신은 정중한 한국어 어시스턴트입니다."},  # ❌ 여기에 쓰는 API가 아님
    {"role": "user", "content": "안녕하세요."},
]

Good(가독성): system은 최상위에서 지정

good.py

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system="당신은 정중한 한국어 어시스턴트입니다.",  # ✓ 최상위
    messages=[
        {"role": "user", "content": "안녕하세요."},
    ],
)

왜 Good일까요: Anthropic API에서 system은 최상위 지정이 정식 사양이에요. OpenAI API와 사양이 다른 지점이라 시험에 자주 나옵니다.

content를 쓰는 두 가지 방법: 문자열과 콘텐츠 블록

content는 두 가지 방식으로 쓸 수 있어요. 둘 다 유효하고, API는 같은 것으로 처리합니다.

  • 문자열(축약형): "content": "Hi"
  • 콘텐츠 블록 리스트: "content": [{"type": "text", "text": "Hi"}]

content_forms.py

# 아래 두 가지는 동등하다(둘 다 에러가 나지 않음)
{"role": "user", "content": "Hi"}
{"role": "user", "content": [{"type": "text", "text": "Hi"}]}

리스트 형식에서는 각 블록에 type(text / image 등)을 명시하고, 텍스트 블록이면 text 필드에 본문을 넣어요. 단순한 텍스트뿐이라면 문자열로 충분하지만, 이미지와 텍스트를 섞거나 여러 블록을 나열할 때는 리스트 형식이 필수입니다.

참고: 응답의 content가 항상 블록 리스트(response.content[0].text)인 것과 같은 구조를 요청 쪽에서도 쓸 수 있다고 생각하면 외우기 쉬워요. 응답 쪽 블록 종류는 '3.1 content 블록의 종류'를 참고하세요.

2. 주요 파라미터 상세

2.1 temperature(온도)

동작용도 예시
0.0결정적(같은 입력에 같은 출력)추출·분류·코드 생성
0.3~0.5다소 다양성 있음일반적인 대화
0.7~1.0창의적·다양소설·브레인스토밍

비유하자면 temperature는 '요리사의 기분'이에요. 0일 때는 정해진 레시피 그대로, 1일 때는 기분에 따라 변화를 줍니다.

주의: Tool Use나 JSON 출력처럼 구조가 엄격하게 요구되는 작업은 반드시 저온도(0~0.3)로 설정하세요. 고온도로 두면 포맷 위반이 늘어납니다.

2.2 top_p / top_k

  • top_p(뉴클리어스 샘플링): 누적 확률이 P%에 도달할 때까지의 토큰 집합에서 샘플링
  • top_k: 상위 K개 토큰에서 샘플링

사용법과 주의점

  • 기본적으로 temperature만 조정하면 OK
  • 여러 개를 동시에 바꾸면 동작을 예측하기 어려우니, 한 번에 하나씩 조정하는 게 철칙

2.3 max_tokens

생성할 최대 토큰 수예요. 입력이 아니라 출력 쪽 상한입니다.

  • 크게 설정해도 실제 사용량만 과금 대상
  • 다만 극단적으로 큰 값은 응답 시간에 영향을 줄 수 있음
  • 모델마다 상한이 다름(Haiku는 8K, Sonnet은 64K 등)

[최신 정보] 'Haiku는 8K'는 구세대(Claude 3.5 Haiku) 수치입니다. 이 책이 예제에서 쓰는 현행 Claude Haiku 4.5(claude-haiku-4-5-20251001)의 최대 출력은 64K 토큰이에요. Sonnet 4.6도 64K로, 원문의 Sonnet 값은 그대로 맞습니다. '모델마다 상한이 다르다'는 원칙은 유효하되, 최신 Haiku 상한은 64K로 읽어 주세요.

2.4 stop_sequences

특정 문자열이 나타나면 생성을 중단합니다.

stop_example.py

response = client.messages.create(
    model="claude-haiku-4-5-20251001",
    max_tokens=1024,
    stop_sequences=["</done>", "STOP"],
    messages=[{"role": "user", "content": "..."}],
)
print(response.stop_reason)  # "stop_sequence" 같은 값

3. 응답 구조

response_structure.py

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "..."}],
)

print(response.id)              # 메시지 ID
print(response.type)            # "message"
print(response.role)            # "assistant"
print(response.content)         # [TextBlock(text="...", type="text")]
print(response.model)           # "claude-sonnet-4-6"
print(response.stop_reason)     # "end_turn" / "max_tokens" / "stop_sequence" / "tool_use"
print(response.usage)           # Usage(input_tokens=..., output_tokens=...)

3.1 content 블록의 종류

content는 여러 블록의 리스트예요.

블록 타입용도
text텍스트 출력
tool_use툴 호출(세션 5에서 상세히)
image이미지(입력 시에만)
thinkingExtended Thinking의 사고 과정

3.2 stop_reason의 의미

의미
end_turn통상 종료(모델이 자연스럽게 멈춤)
max_tokensmax_tokens 상한에 도달
stop_sequencestop_sequences 중 하나와 일치
tool_use툴 호출을 요구

사용법과 주의점

  • 툴 에이전트 루프에서는 stop_reason == "tool_use"를 보고 툴 실행으로 분기한다
  • max_tokens로 끝난 경우에는 출력이 도중에 잘렸을 가능성이 높으니 이어받기 처리를 검토한다

4. 스트리밍 응답 (참고·시험 범위 밖)

참고: 스트리밍은 CCA-F 출제 범위 밖이에요. 이 절은 구현 이미지를 참고로 보여줄 뿐이라, 시험 대비로 외울 필요는 없습니다.

긴 응답에서는 토큰을 하나씩 받아 가며 표시하고 싶을 때가 있어요.

streaming_example.py

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "내일 아침 식사로 추천할 메뉴 알려 줘."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    print()

    # 완료 후 최종 메시지 가져오기
    final = stream.get_final_message()
    print(f"\n(사용 토큰: {final.usage.input_tokens} in / {final.usage.output_tokens} out)")

사용법과 주의점

  • 채팅 UI에서는 필수급 기능
  • 배치 처리처럼 UI가 필요 없는 경우엔 비스트리밍으로 충분
  • 에러가 스트리밍 도중에 발생할 수 있으니 예외 처리를 잊지 말 것

5. 에러 핸들링과 레이트 리밋

5.1 주요 에러

HTTP 상태에러 종류대처
400invalid_request_error요청 구조가 잘못됨(파라미터 확인)
401authentication_errorAPI 키 무효
403permission_error모델 접근 권한 없음
404not_found_error엔드포인트가 잘못됨
429rate_limit_error레이트 리밋 도달. 지수 백오프로 재시도
500api_error서버 측 에러
529overloaded_error서버 과부하

5.2 재시도 전략

retry_example.py

import anthropic
import time

client = anthropic.Anthropic(max_retries=3)  # SDK의 자동 재시도 기능

# 수동 재시도(지수 백오프)
def call_with_retry(prompt, max_attempts=5):
    for attempt in range(max_attempts):
        try:
            return client.messages.create(
                model="claude-haiku-4-5-20251001",
                max_tokens=512,
                messages=[{"role": "user", "content": prompt}],
            )
        except anthropic.RateLimitError:
            wait = 2 ** attempt
            print(f"rate limit, sleeping {wait}s")
            time.sleep(wait)
    raise RuntimeError("max retries exceeded")

사용법과 주의점

  • SDK에는 자동 재시도 기능이 있음(max_retries)
  • 대량 병렬 처리에서는 클라이언트 쪽에서도 적절한 백오프를 구현하는 게 필수
  • 429는 '지금 당장 전면 중단'이 아니라 '조금 기다리라'는 신호

6. 토큰 과금과 Pricing

Anthropic API는 토큰 기반 과금이죠. 1 토큰은 영어로 약 4자이고, 한국어는 더 잘게 나뉩니다.

과금 종류설명
Input Tokens요청에 포함된 토큰
Output Tokens모델이 생성한 토큰
Cache Write프롬프트 캐시에 쓰기
Cache Read프롬프트 캐시에서 읽기(할인 가격)

요금 구조의 특징:

  • Output Tokens는 Input Tokens보다 단가가 높음(모델에 따라 다르지만 약 3~5배)
  • Cache Read는 통상 가격의 10~20% 정도로 크게 할인(프롬프트 캐시, 세션 3에서 상세히)
  • 모델 패밀리에 따라 단가가 크게 다름(Opus > Sonnet > Haiku)

Bad(비용 효율 문제): 매번 같은 시스템 프롬프트를 보내기

bad.py

# 매번 system prompt를 10K 토큰씩 보내면 비용이 불어난다
for question in questions:
    client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=256,
        system=very_long_system_prompt,  # 10K 토큰
        messages=[{"role": "user", "content": question}],
    )

Good(비용 효율): 프롬프트 캐시 사용

good.py

for question in questions:
    client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=256,
        system=[
            {
                "type": "text",
                "text": very_long_system_prompt,
                "cache_control": {"type": "ephemeral"},  # ✓ 캐시 활성화
            }
        ],
        messages=[{"role": "user", "content": question}],
    )

왜 Good일까요: 프롬프트 캐시 덕분에, 두 번째부터 같은 시스템 프롬프트는 크게 할인된 가격으로 재사용할 수 있어요. 자세한 내용은 세션 3에서 다룹니다.

7. Message Batches API (비동기 배치 처리)

지금까지 본 messages.create()는 요청을 보내면 그 자리에서 응답이 돌아오는 동기(즉시 응답) API였어요. 그런데 '즉시 응답은 필요 없지만, 아무튼 대량의 요청을 한꺼번에 싸게 처리하고 싶다'는 상황도 있죠. 그럴 때 쓰라고 준비된 게 Message Batches API입니다.

비유하자면 동기 API가 '창구에서 주문해 그 자리에서 받는 패스트푸드'라면, Message Batches API는 '서류를 잔뜩 모아 한 번에 부쳐 두고 나중에 결과를 한꺼번에 받는 우편 신청' 같은 거예요. 바로 오지는 않지만, 몰아서 처리하는 만큼 값이 쌉니다.

7.1 구조와 특징

Message Batches API는 비동기 배치 처리 API죠. 여러 요청을 하나의 배치로 묶어 보내고, 처리가 끝난 뒤 결과를 한꺼번에 가져옵니다. 주요 특징은 다음과 같아요.

항목내용
처리 방식비동기(요청을 묶어 투입하고 나중에 결과를 가져옴)
비용표준(동기) Messages API의 약 50%
처리 시간각 배치는 최대 24시간 이내에 처리됨(대부분은 더 빠름)
즉시성즉시 응답이 아님. SLA(응답 시간) 보장도 없음
결과 대응각 요청에 붙인 custom_id로 결과와 대조

batch_create.py

import anthropic

client = anthropic.Anthropic()

# 여러 요청을 하나의 배치로 묶어 투입한다
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": "review-1",  # ✓ 반환된 결과와 대조하는 데 사용
            "params": {
                "model": "claude-haiku-4-5-20251001",
                "max_tokens": 50,
                "messages": [
                    {"role": "user", "content": "다음 리뷰를 긍정/부정으로 분류: 최고였어요!"}
                ],
            },
        },
        {
            "custom_id": "review-2",
            "params": {
                "model": "claude-haiku-4-5-20251001",
                "max_tokens": 50,
                "messages": [
                    {"role": "user", "content": "다음 리뷰를 긍정/부정으로 분류: 두 번 다시 안 살 거예요."}
                ],
            },
        },
    ]
)

print(batch.id)                 # 배치 ID(나중에 상태 확인·결과 취득에 사용)
print(batch.processing_status)  # "in_progress" 등

custom_id는 결과를 대조할 때 쓰는 식별자죠. 배치는 병렬·비동기로 처리되니, 돌아온 결과가 어느 요청에 대응하는지는 순서로는 알 수 없습니다. 요청마다 붙인 custom_id에 기대어 맞춰 봅니다.

7.2 적용 판단 (언제 써야 하나)

시험에서는 '동기 Messages API와 Message Batches API 중 무엇을 골라야 하나'라는 적용 판단을 묻습니다. 판단 기준은 단순해요.

상황골라야 할 API
즉시 응답이 필요 없고, 대량이며, 비용을 약 50% 낮추고 싶다Message Batches API
실시간 응답·대화·멀티턴 툴 호출이 필요하다일반 Messages API

가장 잘 맞는 유스케이스는 대량 데이터의 일괄 분류·요약·추출이나 평가 데이터셋 일괄 처리처럼 즉시성이 필요 없는 대량 배치예요. 반면 멀티턴 툴 호출(에이전트 같은 대화)에는 맞지 않습니다. 배치는 '1턴으로 끝나는 독립적인 요청을 대량 처리'하는 구조라서, 앞 턴의 결과를 보고 다음 요청을 짜는 대화형 처리에는 어울리지 않거든요.

: 판단의 요령은 '사용자를 기다리게 하는가?'를 떠올리는 거예요. 화면 너머에서 사람이 응답을 기다린다면 동기 API, 야간 배치처럼 사람이 기다리지 않는 대량 처리라면 Message Batches API가 후보입니다.

Bad(비용 문제): 즉시성이 필요 없는 대량 처리를 한 건씩 동기 호출

bad.py

# 야간에 100만 건의 리뷰를 분류하는데, 즉시성이 필요 없는데도
# 한 건씩 동기 API를 호출 → 표준 가격을 그대로 다 지불하게 된다
for review in one_million_reviews:
    client.messages.create(
        model="claude-haiku-4-5-20251001",
        max_tokens=50,
        messages=[{"role": "user", "content": f"긍정/부정으로 분류: {review}"}],
    )

Good(비용 개선): Message Batches API로 몰아서 약 50% 싸게 처리

good.py

# 즉시 응답은 필요 없으니, 한꺼번에 배치로 투입 → 약 50% 비용으로 처리할 수 있다
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"review-{i}",
            "params": {
                "model": "claude-haiku-4-5-20251001",
                "max_tokens": 50,
                "messages": [{"role": "user", "content": f"긍정/부정으로 분류: {review}"}],
            },
        }
        for i, review in enumerate(one_million_reviews)
    ]
)

왜 Good일까요: 즉시성이 필요 없는 대량 처리라면 Message Batches API로 표준 가격의 약 50%까지 낮출 수 있어요. 응답은 최대 24시간 이내에 한꺼번에 돌아오니, 야간 배치 같은 용도와 잘 맞습니다.

사용법과 주의점

  • 즉시 응답이 필요한 경우엔 쓰지 않기: 결과는 최대 24시간 이내에 몰아서 돌아오므로, 사용자를 그 자리에서 기다리게 하는 용도엔 부적합
  • custom_id는 반드시 붙이기: 결과 대조에 필수. 중복되지 않는 고유 ID로
  • 대화·멀티턴 툴 호출에는 부적합: 1턴으로 끝나는 독립적인 요청의 대량 처리에 사용

자주 하는 오해와 개념 정리

❌ 자주 하는 오해: 'max_tokens는 입력 토큰의 상한'

  • 오해: max_tokens를 키우면 긴 입력을 넣을 수 있다고 착각하기 쉬움
  • 실제: max_tokens는 출력 토큰의 상한. 입력 쪽은 컨텍스트 윈도우로 제한됨
  • 확인 방법: 응답의 usage.output_tokens가 max_tokens에 가까우면 출력이 잘렸을 가능성

❌ 자주 하는 오해: 'temperature는 0~2까지 지정할 수 있다'

  • 오해: OpenAI API와 같은 감각으로 temperature를 0~2 범위로 지정할 수 있다고 착각하기 쉬움
  • 실제: Anthropic API의 temperature는 01이 범위. 1.0이 지정 가능한 최댓값이고, OpenAI 같은 02가 아님
  • 확인 방법: 1.0보다 큰 값(예: 1.5)을 넘기면 invalid_request_error

❌ 자주 하는 오해: 'system 메시지는 role: "system"으로 넘긴다'

  • 오해: OpenAI 스타일로 messages 안에 role: "system"을 넣음
  • 실제: Anthropic은 최상위 system 필드로 지정
  • 확인 방법: messages에 system을 넣으면 invalid_request_error

자주 나는 에러와 대처법

  • 에러 예시: messages: at least one message is required
    • 원인: messages가 비었거나 구조가 잘못됨
    • 대처법: 최소 1건의 user 메시지가 필요
  • 에러 예시: messages: roles must alternate
    • 원인: user와 assistant가 번갈아 배치되지 않음
    • 대처법: 이력을 정리해 번갈아 배치하도록
  • 에러 예시: max_tokens: must be at most X
    • 원인: 모델의 최대 출력 토큰 수 초과
    • 대처법: 모델별 상한을 확인하고 값을 낮춤

정리와 다음 한 걸음

  • Messages API는 messages 리스트와 주요 파라미터로 간단히 호출할 수 있다
  • system은 최상위에서 지정(OpenAI 형식과 다른 점에 주의)
  • temperature는 0~1. 구조화 출력은 저온도가 원칙
  • 스트리밍은 client.messages.stream(...)으로 사용 가능
  • 레이트 리밋에는 지수 백오프로 대처
  • 프롬프트 캐시는 비용 절감의 가장 중요한 기술

이 장의 연습문제와 해설을 마친 뒤, 다음 장(제5장)에서는 이 API들을 사용한 프롬프트 엔지니어링의 기본 테크닉을 배웁니다.


② CCA-F 세션 2 연습문제 9선: Anthropic API 파라미터·Batch·프롬프트 캐시 완전 대비

연습 진행 방법

API 파라미터 암기와 동작 이해는 CCA-F 시험에 자주 나와요. 고급 문제는 입문자라면 건너뛰고 진행하세요.

습득 포인트와 문제 매칭

습득 포인트해당 문제
Messages API의 요청 구조문제 1, 문제 2
주요 파라미터의 의미문제 3, 문제 4
스트리밍 처리문제 5
레이트 리밋·에러 처리문제 6
과금 구조(프롬프트 캐시)문제 7
Message Batches API의 적용 판단문제 8

문제 1: system 프롬프트 지정 위치

  • 카테고리: 기초
  • 난이도: ★☆☆☆☆
  • 예상 소요 시간: 5분

문제 내용: Anthropic API에서 system 프롬프트를 지정하는 위치로 올바른 것은 무엇인가요?

  • (A) messages의 첫 요소에 {"role": "system", "content": "..."}를 넣는다
  • (B) messages.create()의 최상위 인자 system="..."로 지정한다
  • (C) messages의 마지막에 {"role": "system", "content": "..."}를 넣는다
  • (D) URL 쿼리 파라미터로 지정한다

문제 2: messages의 role 규칙

  • 카테고리: 기초
  • 난이도: ★☆☆☆☆
  • 예상 소요 시간: 5분

문제 내용: 다음 메시지 리스트 중 Anthropic API가 에러를 반환할 가능성이 가장 높은 것은 무엇인가요?

(A)

[{"role": "user", "content": "Hi"}]

(B)

[{"role": "user", "content": "Hi"}, {"role": "assistant", "content": "Hello"}, {"role": "user", "content": "How are you?"}]

(C)

[{"role": "user", "content": "Hi"}, {"role": "user", "content": "Are you there?"}]

(D)

[{"role": "user", "content": [{"type": "text", "text": "Hi"}]}]

문제 3: temperature 구분 사용

  • 카테고리: 응용
  • 난이도: ★★☆☆☆
  • 예상 소요 시간: 5분

문제 내용: JSON 스키마로 엄격하게 포맷된 구조화 출력을 생성하는 작업에서 가장 적절한 temperature는 무엇인가요?

  • (A) 0.0
  • (B) 0.5
  • (C) 0.9
  • (D) 1.0

문제 4: max_tokens의 동작

  • 카테고리: 기초
  • 난이도: ★★☆☆☆
  • 예상 소요 시간: 5분

문제 내용: max_tokens 설명으로 올바른 것은 무엇인가요?

  • (A) 요청에 포함할 수 있는 입력 토큰의 최댓값
  • (B) 모델이 생성하는 출력 토큰의 최댓값
  • (C) 입력과 출력의 합계 토큰 수의 최댓값
  • (D) 컨텍스트 윈도우 크기와 같다

문제 5: 스트리밍의 이점

  • 카테고리: 응용
  • 난이도: ★★☆☆☆
  • 예상 소요 시간: 5분

문제 내용: 스트리밍 모드(client.messages.stream)를 채택해야 하는 유스케이스로 가장 적절한 것은 무엇인가요?

  • (A) 배치로 100만 건의 리뷰를 분류하는 처리
  • (B) 채팅 UI에서 실시간으로 응답을 표시하는 처리
  • (C) 전체 응답을 집계해 합계를 계산하는 처리
  • (D) JSON 스키마에 따라 구조화 데이터를 추출하는 처리

문제 6: 레이트 리밋 대처

  • 카테고리: 응용
  • 난이도: ★★☆☆☆
  • 예상 소요 시간: 10분

문제 내용: API가 429 rate_limit_error를 반환했을 때의 대처로 가장 적절한 것은 무엇인가요?

  • (A) 같은 요청을 연속으로 10회 재시도한다
  • (B) 실패한 요청을 버리고, 이후의 요청도 중단한다
  • (C) 지수 백오프(대기 시간을 점점 늘림)로 재시도한다
  • (D) 다른 API 키로 바꿔 즉시 재시도한다

문제 7: 프롬프트 캐시

  • 카테고리: 응용
  • 난이도: ★★★☆☆
  • 예상 소요 시간: 10분

문제 내용: 같은 10K 토큰의 System 프롬프트를 하루 100만 번 쓰는 앱에서, 가장 비용 효율이 좋은 설계는 무엇인가요?

  • (A) 매번 그대로 system 프롬프트를 보낸다
  • (B) system 프롬프트를 100 토큰으로 압축한다
  • (C) 프롬프트 캐시(cache_control: ephemeral)를 활성화해 보낸다
  • (D) System 프롬프트를 포기하고 user 프롬프트에 매번 넣는다

문제 8: 대량 배치 처리의 API 선택

  • 카테고리: 응용
  • 난이도: ★★☆☆☆
  • 예상 소요 시간: 5분

문제 내용: 야간에 대량(약 100만 건)의 상품 리뷰를 긍정/부정으로 분류하는 배치 처리를 설계합니다. 즉시 응답은 필요 없고, 결과는 다음 날 아침까지 모여 있으면 되며, 비용은 최대한 낮추고 싶어요. 가장 적절한 선택지는 무엇인가요?

  • (A) 일반 Messages API를 쓰고, 리뷰를 한 건씩 동기적으로 호출한다
  • (B) 스트리밍(client.messages.stream)을 써서 토큰을 순차적으로 받는다
  • (C) 일반 Messages API를 호출하고, temperature를 올려 다양한 분류를 얻는다
  • (D) Message Batches API로 요청을 묶어 투입한다(비동기·표준 가격의 약 50%)

문제 9 (고급): 토큰 사용량 최적화

  • 카테고리: 고급
  • 난이도: ★★★★☆
  • 예상 소요 시간: 15분

문제 내용: 다음 시나리오에서 가장 비용 효율이 좋은 설계 판단은 무엇인가요?

시나리오:

  • 사내 1000페이지 문서에서, 사용자가 질문할 때마다 관련 부분을 검색해 답변한다

  • 하루 1만 건의 질문이 예상된다

  • 질문 내용은 다양하고, 매번 다른 부분이 참조된다

  • 응답 품질을 유지하면서 비용을 최적화하고 싶다

  • (A) 모든 문서를 매번 system 프롬프트에 넣어 Opus로 처리한다

  • (B) 문서를 통째로 프롬프트 캐시에 넣어 Opus로 처리한다

  • (C) RAG(벡터 검색으로 관련 부분만 추출)로 관련 청크만 매번 입력하고, Sonnet으로 처리한다

  • (D) 문서를 매번 요약한 뒤 Haiku로 처리한다


정답은 이 장 후반의 정답·해설편에서 확인하세요.

[참고] 한국 환경에서 위 문항들을 실제로 구현할 때, 한국어는 영어보다 글자당 토큰이 더 잘게 쪼개지는 경향이 있어 같은 분량이라도 토큰 수와 비용이 늘어납니다. 그래서 max_tokens 산정이나 프롬프트 캐시·배치의 비용 효과를 가늠할 때 이 점을 감안하는 게 좋아요. 사내 문서 검색(RAG)을 한국어로 구성한다면 형태소 특성을 고려한 청킹과 한국어 임베딩 모델 선택이 검색 품질을 좌우합니다. 또 사내 데이터가 민감하다면 개인정보보호법(PIPA)상 처리 근거, 망분리 환경에서의 API 호출 경로도 함께 검토해 두면 좋습니다.


③ CCA-F 세션 2 연습문제 정답·해설: Anthropic API 파라미터·Batch·RAG 완전 풀이

목차

  • 정답 일람
  • 문제별 해설 (문제 1 ~ 문제 9)
  • 이 세션 돌아보기

정답 일람

문제정답
문제 1(B)
문제 2(C)
문제 3(A)
문제 4(B)
문제 5(B)
문제 6(C)
문제 7(C)
문제 8(D)
문제 9(C)

문제 1: system 프롬프트 지정 위치 — 정답 (B)

해설

Anthropic API에서 system 프롬프트는 최상위 system 인자로 지정해요. 이건 OpenAI API(messages 안에 role: "system"을 넣는다)와 다른 점이라, 시험에 자주 나오죠.

client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system="당신은 정중한 한국어 어시스턴트입니다.",  # ✓
    messages=[{"role": "user", "content": "..."}],
)

◆ 설계와 운용 포인트

  • 설계 사상: system 프롬프트를 별도 필드로 분리하면 프롬프트 캐시와 궁합이 좋은 구조가 돼요.
  • 운용 시 주의점: OpenAI 호환 코드를 이식할 때 가장 큰 함정이에요.

문제 2: messages의 role 규칙 — 정답 (C)

해설

user와 assistant는 번갈아 배치되어야 해요. user가 연속되면 에러가 나요.

수정 예:

# Bad
[{"role": "user", "content": "Hi"}, {"role": "user", "content": "Are you there?"}]

# Good(결합한다)
[{"role": "user", "content": "Hi. Are you there?"}]

오답 선택지

  • (A): 단일 user 메시지. 첫 메시지가 user이므로 유효
  • (B): user → assistant → user로 올바르게 번갈아 배치되어 유효
  • (D): content를 콘텐츠 블록 리스트([{"type": "text", "text": "Hi"}])로 쓴 형태. 문자열 "Hi"와 등가인 올바른 표기라 에러가 나지 않는다(content의 2형식은 본문 '1.3 메시지 구조' 참고)

◆ 설계와 운용 포인트

  • 운용 시 주의점: 채팅 이력을 쌓을 때는 API 전송 전에 연속된 같은 role을 결합하는 헬퍼를 마련하는 게 정석이에요.

문제 3: temperature 구분 사용 — 정답 (A)

해설

JSON 스키마처럼 엄격한 구조가 필요한 작업에서는 temperature=0.0이 원칙이에요. 고온도에서는 포맷 위반(콤마 누락, 키 이름 흔들림 등)이 늘어나요.

유스케이스권장 temperature
구조화 출력·분류·추출0.0
FAQ·요약0.0~0.3
일반적인 대화0.5~0.7
창작·브레인스토밍0.7~1.0

◆ 설계와 운용 포인트

  • 설계 사상: 온도는 '출력의 무작위성'을 제어하지만, 무작위성 ≠ 다양성이에요. 다양한 출력이 필요하면 top_p 조정도 검토해 보세요.
  • 다른 답: Tool Use로 JSON을 출력한다면, 온도를 0으로 둔 다음 schema validation + retry를 구현하는 게 견고해요.

문제 4: max_tokens의 동작 — 정답 (B)

해설

max_tokens는 출력(생성) 쪽 상한이에요. 입력 쪽은 컨텍스트 윈도우로 제한돼요.

오답 선택지

  • (A)(C)(D): 입력이 아니라 출력의 상한이므로 틀림

◆ 설계와 운용 포인트

  • 설계 사상: max_tokens를 크게 잡아도 실제 사용분만 과금해요. 다만 극단적으로 큰 값은 응답 시간에 영향을 줄 때가 있어요.
  • 운용 시 주의점: stop_reason == "max_tokens"를 보고 출력 잘림을 감지하는 로직은 필수예요.

문제 5: 스트리밍의 이점 — 정답 (B)

해설

스트리밍의 가장 큰 가치는 '사용자가 응답 시작까지의 대기 시간을 짧게 느낀다'는 점이에요. 채팅 UI 같은 실시간 표시에서 위력을 발휘해요.

오답 선택지

  • (A)(C)(D): 전체 결과만 얻으면 충분한 배치 처리에서는 스트리밍이 불필요. 오히려 일반 모드가 더 단순

◆ 설계와 운용 포인트

  • 운용 시 주의점: 스트리밍 중 예외 처리를 잊지 말고 구현하세요. SSE(Server-Sent Events) 연결이 도중에 끊길 가능성에 대비해요.
  • 계산량과 리소스 사용: 스트리밍 자체에 추가 과금은 없지만, 장시간 연결을 유지하는 만큼 서버 리소스는 늘어나요.

문제 6: 레이트 리밋 대처 — 정답 (C)

해설

429 rate_limit_error는 '일시적으로 너무 많다'는 신호라, 지수 백오프(1초, 2초, 4초, 8초…)로 재시도하는 게 정석이에요.

오답 선택지

  • (A): 연속 재시도는 상황을 악화시킨다
  • (B): 전면 중단은 과잉 반응
  • (D): 여러 키 남용은 계정 정책 위반 가능성 있음

◆ 설계와 운용 포인트

  • 설계 사상: Anthropic SDK는 max_retries 파라미터로 자동 재시도를 제공해요. 수동으로 구현할 때는 jitter(랜덤 흔들림)를 더하면, 여러 클라이언트가 동시에 재시도하는 '썬더링 허드(thundering herd) 문제'를 피할 수 있어요.
  • 운용 시 주의점: 레이트 리밋은 Tier 상향으로 상한을 올릴 수 있는 경우가 있어요.

문제 7: 프롬프트 캐시 — 정답 (C)

해설

10K × 100만 회 = 100억 토큰 분량의 system 프롬프트를 매번 보내면 비용이 막대해요. 프롬프트 캐시를 활성화하면 두 번째부터는 할인 가격(보통 10~20%)으로 재사용할 수 있어요.

system=[
    {
        "type": "text",
        "text": very_long_system_prompt,
        "cache_control": {"type": "ephemeral"},
    }
]

오답 선택지

  • (A): 그대로 보내면 비용 최대
  • (B): 압축하면 품질이 떨어질 가능성
  • (D): user 프롬프트에 넣어도 캐시 효과 없음

◆ 설계와 운용 포인트

  • 설계 사상: 캐시는 5분간의 TTL을 가져요. 지속적으로 쓰는 유스케이스에서 유효해요.
  • 운용 시 주의점: 캐시 첫 쓰기는 통상 가격의 1.25배 등 다소 비싸요. 짧은 기간에 다 쓰는 경우엔 오히려 비싸질 수도 있어요.

[추가 내용] 최신 정보를 덧붙입니다. 캐시 TTL은 기본값(ephemeral)이 5분이지만, Anthropic은 1시간 지속 옵션도 제공합니다. 사고 시간이 길거나 여러 단계에 걸친 워크플로처럼 5분을 넘기기 쉬운 경우에는 1시간 캐시로 캐시 적중을 유지할 수 있어요.

문제 8: 대량 배치 처리의 API 선택 — 정답 (D)

해설

즉시 응답이 필요 없고, 대량의 요청을 비용을 낮춰 처리하고 싶다. 바로 이럴 때가 Message Batches API(비동기 배치 처리 API)의 전형적인 유스케이스예요. 요청을 하나의 배치로 묶어 투입하고, 결과를 나중에 한꺼번에 가져와요. 비용은 표준(동기) Messages API의 약 50%이고, 각 배치는 최대 24시간 이내에 처리되니 '다음 날 아침까지 모여 있으면 된다'는 이번 요건에 딱 맞아요.

오답 선택지

  • (A): 즉시성이 필요 없는데 한 건씩 동기 호출하면 표준 가격을 그대로 다 지불하게 되어 비용 효율이 나쁘다. 약 50% 할인 기회를 놓친다
  • (B): 스트리밍은 '응답을 순차 표시해 사용자 체감 대기 시간을 줄이는' 기능이라 채팅 UI용. 집계만이 목적인 배치 처리에서는 비용 절감이 안 된다
  • (C): temperature를 올리면 분류의 흔들림(포맷 위반이나 판정 흔들림)이 늘어난다. 분류 작업에서는 오히려 저온도가 바람직하고, 비용 절감과도 무관

◆ 설계와 운용 포인트

  • 설계 사상: API 선택의 판단 축은 '사용자를 기다리게 하는가'예요. 사람이 그 자리에서 기다리지 않는 대량 처리는 Message Batches API, 실시간 응답·대화·멀티턴 툴 호출이 필요하면 일반 Messages API를 골라요.
  • 운용 시 주의점: 배치는 병렬·비동기로 처리되니, 각 요청에 고유한 custom_id를 붙여 돌아온 결과와 대조하는 데 써요. SLA(응답 시간) 보장은 없으니, 즉시성이 필요한 처리에는 쓰지 않아요.

문제 9 (고급): 토큰 사용량 최적화 — 정답 (C)

해설

RAG(Retrieval-Augmented Generation)를 쓰는 게 최적이에요. 1000페이지를 매번 입력하는 건 캐시를 쓰더라도 오버스펙이고, Lost in the Middle 위험도 있어요.

설계대략적인 월간 비용품질
(A) 매번 전량 + Opus매우 높음높지만 장황
(B) 전량 캐시 + Opus높음위와 같음
(C) RAG + Sonnet낮음충분히 높음
(D) 요약 + Haiku가장 낮음품질이 불안정

◆ 설계와 운용 포인트

  • 설계 사상: '필요한 정보만 필요한 만큼 넘긴다'가 LLM 운용의 비용 최적화 기본이에요.
  • 계산량과 리소스 사용: RAG는 벡터 DB 인프라 비용이 따로 들지만, 토큰 과금 절감 효과가 그걸 웃도는 경우가 많아요.
  • 운용 시 주의점: 벡터 검색 정확도가 낮으면 품질이 떨어지니, Recall 평가를 제대로 해야 해요.

이 세션 돌아보기

  • Messages API의 요청/응답 구조를 이해했어요.
  • 주요 파라미터(model·max_tokens·temperature·system)의 의미와 쓰임새를 파악했어요.
  • 스트리밍·에러 처리·레이트 리밋 대처를 배웠어요.
  • 프롬프트 캐시로 하는 비용 최적화를 이해했어요.

다음 세션(제5장)에서는 도메인 4(프롬프트 엔지니어링과 구조화 출력)의 핵심인 프롬프트 설계 테크닉을 배웁니다.


©2024-2026 ClaudeCode.to, Hand-crafted & made with Jaewoo Kim.

  • 이메일문의: jaewoo@claudecode.to
  • AI 에이전트 만드는 사람
  • 기업 AI 강의 · 에이전트 개발 · 기술자문
  • "AI한테 일 시키는 법, 제대로 알려드립니다"