키 관리와 비용 감 — .env, 토큰이 곧 돈
Article
2강 끝에서 찜찜한 게 하나 있었다. .env 에 키를 넣어뒀다고 했는데, 코드 어디에도 그 파일을 읽는 줄이 없었다. process.env.ANTHROPIC_API_KEY 를 SDK 가 "자동으로 읽는다"고만 하고 넘어갔다. 자동으로 읽는다는 게 대체 무슨 뜻일까. 진짜로 그런지, 지금 확인해본다.
안 되는 걸 먼저 본다
2강에서 쓴 index.ts 를 그대로, 이번엔 다르게 실행해본다.
npx tsx index.ts
- Error: Could not resolve authentication method. Expected one of apiKey,
- authToken, credentials, config, or profile to be set. Or for one of the
- "X-Api-Key" or "Authorization" headers to be explicitly omitted
- at Anthropic.validateHeaders (.../node_modules/@anthropic-ai/sdk/...)
터진다. .env 파일에 키를 분명히 적어뒀는데도 이 에러가 난다. .env 파일은 그냥 텍스트 파일이기 때문이다. Node 가 프로그램을 시작할 때 이 파일을 알아서 읽어 환경변수로 올려주지 않는다. 누군가 명시적으로 "이 파일 읽어서 환경변수로 만들어줘"라고 시켜야 한다.
--env-file 로 진짜 불러온다
Node 에 내장된 플래그를 쓴다. node -v 로 확인했던 그 Node 다.
node --env-file=.env --help
tsx 도 이 플래그를 그대로 전달받는다. 다시 실행해본다.
npx tsx --env-file=.env index.ts
- # TypeScript 한 문장 설명
- TypeScript는 JavaScript에 정적 타입 시스템을 추가하여 개발 중 오류를 미리 발견하고 코드의 안정성을 높이는 언어입니다.
- 입력 토큰: 29, 출력 토큰: 75
- 이번 호출 비용: 약 $0.000404
이번엔 성공한다. --env-file=.env 가 .env 파일의 각 줄(ANTHROPIC_API_KEY=...)을 읽어 실제 환경변수로 만들어 프로세스에 올린다. 그 다음에야 new Anthropic() 이 process.env.ANTHROPIC_API_KEY 를 찾아낼 수 있다.
- .env 파일그냥 텍스트. ANTHROPIC_API_KEY=sk-ant-...
- --env-file=.envNode 가 이 파일을 읽어 환경변수로 만든다
- process.env.ANTHROPIC_API_KEY이제 프로세스 안에서 값을 꺼낼 수 있다
- new Anthropic()SDK 가 이 이름의 환경변수를 자동으로 찾아 쓴다
매번 --env-file=.env 를 타이핑하기 귀찮으니 package.json 의 scripts 에 등록해둔다.
{
"scripts": {
"dev": "tsx --env-file=.env index.ts"
}
}
이제부터는 이렇게 실행하면 된다.
npm run dev
토큰이 곧 돈이다
2강에서 response.usage 에 input_tokens 와 output_tokens 가 있는 걸 봤다. 이 두 숫자가 정확히 이번 호출의 가격을 정한다. Claude 는 모델마다 1백만 토큰당 가격이 다르게 매겨져 있다.
| claude-haiku-4-5 | $1.00 | $5.00 | 가장 저렴하고 빠르다. 지금 실습에 쓰는 모델 |
| claude-sonnet-5 | $3.00 | $15.00 | 속도와 성능의 균형 |
| claude-opus-4-8 | $5.00 | $25.00 | 가장 똑똑하지만 가장 비싸다 |
input_tokens 는 우리가 보낸 질문(대략 한글 한 글자가 1~2토큰), output_tokens 는 Claude 가 만든 답변의 길이다. 계산은 간단한 곱셈이다.
이 계산을 코드에 직접 넣어서, 호출할 때마다 비용이 얼마였는지 바로 보이게 한다. index.ts 를 이렇게 바꾼다.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-haiku-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "타입스크립트를 한 문장으로 설명해줘." }],
});
console.log(response.content[0].text);
const { input_tokens, output_tokens } = response.usage;
const inputCostPerMTok = 1.0;
const outputCostPerMTok = 5.0;
const cost =
(input_tokens / 1_000_000) * inputCostPerMTok +
(output_tokens / 1_000_000) * outputCostPerMTok;
console.log(`\n입력 토큰: ${input_tokens}, 출력 토큰: ${output_tokens}`);
console.log(`이번 호출 비용: 약 $${cost.toFixed(6)}`);
위 dg:output 에서 이미 실행 결과를 봤다. $0.000404 다. 이 정도면 하루에 수백 번을 불러도 1달러가 안 된다. 다만 이건 Haiku 로 짧은 질문 하나를 날렸을 때 이야기다. 모델을 Opus 로 바꾸거나, 문서 전체를 프롬프트에 욱여넣거나, 대화 기록이 계속 쌓이는 채팅 앱을 만들면 이 숫자는 순식간에 커진다. 그 감각은 6강(토큰과 비용)에서 대화가 길어질 때를 놓고 다시 잡는다.
정리하면
.env 파일은 값을 적어두는 곳일 뿐, --env-file 같은 명시적인 로딩 과정을 거쳐야 코드에 도달한다. 그리고 usage 의 토큰 수는 곱셈 두 번이면 실제 달러로 바뀐다.
- 01
.env 만으로는 부족하다는 걸 확인했다
플래그 없이 실행하면 인증 에러가 난다. 파일이 자동으로 로드되지 않기 때문이다.
- 02
--env-file 로 진짜 불러왔다
Node 내장 기능으로 .env 의 내용을 환경변수로 올렸다. package.json 의 dev 스크립트에 등록해뒀다.
npm run dev - 03
모델별 가격표를 확인했다
Haiku · Sonnet · Opus 순서로 비싸진다. 지금은 가장 저렴한 Haiku 로 연습한다.
- 04
usage 로 실제 비용을 계산했다
input_tokens · output_tokens 에 각각의 단가를 곱하면 이번 호출이 정확히 얼마였는지 나온다.
Part 1이 끝났다. 프로젝트를 세팅하고, 첫 호출을 하고, 그 비용까지 셀 수 있게 됐다. Part 2 부터는 한 번 묻고 끝나는 대화가 아니라, Claude 가 이전 대화를 기억하며 이어가는 진짜 대화를 만든다. 그러려면 지금까지 한 번도 안 건드린 role 필드, system·user·assistant 세 가지의 차이부터 짚어야 한다. 다음 강의에서 시작한다.