한 줄 요약: API 호출 자체는 함수 하나다. 실력은 구조화된 출력, 캐싱, 배치, 모델 라우팅으로 "안정적이고 싼" 기능을 만드는 데서 나온다. 이 네 가지를 적용하면 비용은 흔히 한 자릿수 배율로 줄어든다.
가장 작은 호출
// npm i @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic(); // ANTHROPIC_API_KEY 환경변수, 일시적 오류는 SDK가 자동 재시도
const res = await client.messages.create({
model: "claude-haiku-5-5",
max_tokens: 300,
system: "너는 한국어로 답하는 시니어 백엔드 개발자다. 답은 3문장 이내.",
messages: [{ role: "user", content: "N+1 쿼리 문제가 뭐야?" }],
});
console.log(res.content[0].type === "text" ? res.content[0].text : "");
console.log(res.usage); // input_tokens, output_tokens, cache_* — 비용 계산의 근거이것이 전부입니다. 나머지는 이 호출을 어떻게 감싸고 반복하느냐의 문제입니다. 비밀키는 반드시 환경변수나 시크릿 매니저에 두고, 프론트엔드 코드에는 절대 넣지 않습니다.
실전 예제: 커밋 메시지 생성기
git diff --staged를 읽어 Conventional Commits 형식의 메시지를 만드는 CLI입니다. 핵심은 스키마로 고정한 구조화된 출력입니다. 자유 텍스트 대신 정해진 JSON을 받으므로 파싱 오류가 없습니다.
// npm i @anthropic-ai/sdk zod (ANTHROPIC_API_KEY 환경변수 필요)
import Anthropic from "@anthropic-ai/sdk";
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";
import { z } from "zod";
import { execSync } from "node:child_process";
const CommitMessage = z.object({
type: z.enum(["feat", "fix", "refactor", "test", "docs", "chore"]),
scope: z.string().describe("변경 모듈, 없으면 빈 문자열"),
subject: z.string().describe("명령형 한국어, 50자 이내"),
body: z.string().describe("무엇을, 왜 바꿨는지. 없으면 빈 문자열"),
});
const client = new Anthropic();
const diff = execSync("git diff --staged", { encoding: "utf8" }).slice(0, 40_000);
if (!diff) { console.error("staged 변경이 없습니다"); process.exit(1); }
const res = await client.messages.parse({
model: "claude-haiku-5-5", // 단순한 요약 작업 → 가장 저렴한 모델
max_tokens: 400,
thinking: { type: "disabled" }, // 요약에 긴 생각은 필요 없다. 켜 두면 생각 토큰이 400 안에서 답을 밀어낸다
output_config: { format: zodOutputFormat(CommitMessage) }, // 응답을 이 스키마의 JSON으로 고정
messages: [{ role: "user", content: `<diff>\n${diff}\n</diff>\n위 변경의 커밋 메시지를 작성해줘.` }],
});
const m = res.parsed_output;
if (!m) { console.error("형식에 맞는 응답을 받지 못했습니다"); process.exit(1); }
console.log(`${m.type}${m.scope ? `(${m.scope})` : ""}: ${m.subject}${m.body ? `\n\n${m.body}` : ""}`);비용 감각: diff 5,000토큰 + 출력 150토큰이면 Haiku 5.5 기준 약 $0.0006, 하루 커밋 20번에도 한 달에 몇백 원 수준입니다. 같은 일을 Fable 5.1로 하면 약 100배($0.0575)가 듭니다. 작업 난이도에 맞는 모델 선택이 첫 번째 최적화입니다.
비용 최적화 기법 다섯 가지
| 기법 | 효과 | 맞는 상황 |
|---|---|---|
| 모델 라우팅 | 작업별로 단가 수 배~수십 배 차이 | 분류·추출은 작은 모델, 어려운 추론만 큰 모델 |
| 프롬프트 캐싱 | 캐시된 입력은 기본가의 2.5~10% | 긴 시스템 프롬프트, 반복 참조 문서, 대화·에이전트 |
| 배치 API | 입력·출력 50% 할인 | 즉시 응답이 필요 없는 대량 작업 |
| 출력 줄이기 | 출력은 입력의 5배 단가 | "코드만", "diff만", 구조화된 출력, 적절한 max_tokens |
| 입력 줄이기 | 매 호출마다 비례해서 절감 | 로그·파일 잘라 넣기, 긴 대화 요약 후 재시작 |
프롬프트 캐싱 적용하기
아래처럼 바뀌지 않는 긴 블록 끝에 cache_control을 달면, 그 지점까지의 입력이 캐시됩니다. 이후 5분 안에 같은 앞부분으로 호출하면 캐시 읽기 단가가 적용됩니다. 요청 최상위에 cache_control을 하나만 두는 자동 캐싱 방식도 있으니 공식 문서에서 확인하세요.
// client와 diff는 앞의 커밋 메시지 생성기와 같다
import { readFileSync } from "node:fs";
const manual = readFileSync("docs/coding-guide.md", "utf8"); // 수만 토큰짜리 사내 가이드
const res = await client.messages.create({
model: "claude-sonnet-5-5",
max_tokens: 1024,
system: [
{ type: "text", text: "너는 사내 코딩 가이드에 따라 코드를 리뷰한다." },
{ type: "text", text: manual, cache_control: { type: "ephemeral" } }, // 여기까지 캐시
],
messages: [{ role: "user", content: `이 diff를 리뷰해줘:\n${diff}` }],
});
console.log(res.usage.cache_creation_input_tokens, res.usage.cache_read_input_tokens);첫 호출은 cache_creation_input_tokens가, 두 번째부터는 cache_read_input_tokens가 채워지면 성공입니다. 캐시되려면 앞부분이 한 글자도 달라지면 안 됩니다. 시스템 프롬프트에 현재 시각을 넣는 실수가 캐시를 무력화하는 대표적인 예입니다. 모델별 최소 캐시 길이 조건도 있으니 문서를 확인하세요.
배치로 대량 처리하기
파일 200개에 JSDoc을 달거나, 레거시 함수 300개의 테스트 초안을 만드는 일은 몇 시간 기다려도 괜찮습니다. 이런 작업은 배치 API로 보내면 반값입니다.
// files: { content: string }[] — 처리할 파일 목록
const batch = await client.messages.batches.create({
requests: files.map((f, i) => ({
custom_id: `doc-${i}`,
params: {
model: "claude-sonnet-5-5",
max_tokens: 2000,
messages: [{ role: "user", content: `다음 파일의 export 함수에 JSDoc을 추가해줘:\n${f.content}` }],
},
})),
});
console.log(batch.id, batch.processing_status); // 나중에 상태를 조회해 결과를 받는다운영에서 챙길 것
- 사용량 로깅: 모든 호출의
usage와 모델 이름을 기록해야 어디서 돈이 새는지 보입니다. - 스트리밍: 사용자가 기다리는 UI라면
client.messages.stream()으로 토큰을 받는 대로 표시합니다. 비용은 같고 체감 속도만 빨라집니다. - 속도 제한(rate limit): 계정 등급별 분당 토큰·요청 한도가 있습니다. 대량 처리는 동시성을 제한하거나 배치로 보냅니다.
- 평가 세트: 프롬프트나 모델을 바꿀 때 비교할 입력 20~50개와 기대 결과를 만들어 둡니다. "싼 모델로 바꿔도 되나?"를 느낌이 아니라 수치로 답할 수 있게 됩니다.
- 토큰 예산: 사용자별·기능별 일일 한도를 두어 버그나 악용으로 비용이 폭주하는 것을 막습니다.
코딩 실습 (1시간)
- 위 커밋 메시지 생성기를
~/bin/aicommit.ts로 저장하고 git alias(git config alias.aicommit '!npx tsx ~/bin/aicommit.ts')로 등록해 일주일간 써 본다. - 사내 코딩 가이드나 README를 시스템 프롬프트에 넣고 캐싱을 건 리뷰 봇을 만들어, 같은 요청 3번의
usage를 비교한다. - 두 작업의 호출당 비용을 4편 가격표로 직접 계산해 본다.
정리
- API 호출은 단순하다. 구조화된 출력(
output_config.format스키마)으로 안정성을 확보한다. - 비용은 모델 라우팅 → 캐싱 → 배치 → 출력·입력 다이어트 순으로 줄인다.
- 로깅과 평가 세트 없이는 최적화도 추측일 뿐이다.
다음 편: 마지막 편입니다. AI를 쓸 때 반드시 알아야 할 한계와 보안, 그리고 앞으로의 학습 방향을 다룹니다.
출처: Anthropic — Pricing (2026-10-13 확인)