핵심 요약
AI 요약
기사 목차 펼치기 / 접기
1편에서는 오픈라우터(OpenRouter)에 가입하고 크레딧을 충전했다. 이번에는 API 키를 만들어 내 PC에서 모델을 직접 부르는데, 키 하나만 있으면 프로그램이나 업무 도구에서도 같은 모델을 쓸 수 있다.
본지는 10월 24일 윈도우 기본 파워셸(PowerShell) 5.1과 파이썬(Python)으로 아래 명령을 직접 실행했다. 실행 결과도 그날 화면에 나온 그대로 옮겼다. 파워셸 기본 명령으로 부른 답은 한글이 깨졌고, curl.exe와 파이썬은 멀쩡했다.
키를 만들 때 한도부터 건다
왼쪽 위 메뉴에서 API Keys를 누르면 키 목록이 나오고, 오른쪽 위 New Key가 새 키를 만드는 버튼이다.
| 순서 | 누를 곳 | 고를 값 |
|---|---|---|
| 1 | New Key | 키 생성 창이 뜬다 |
| 2 | Name * | 식별용 이름. 예시 문구는 “Chatbot Key”다 |
| 3 | Expiration * | 1 hour·1 day·7 days·30 days·90 days·180 days·1 year·No expiration 중 하나 |
| 4 | Credit limit * | $50·$250·$1000·Custom amount·No limit 중 하나 |
| 5 | Reset limit every... | N/A·Daily·Weekly·Monthly 주기 선택 |
| 6 | Create | 키가 화면에 한 번만 표시된다 |
처음이면 만료는 30 days, 한도는 Custom amount로 5달러쯤을 권한다. $50을 고르면 “Requests are rejected once this key has used $50 in total, until you raise its credit limit.”라는 안내가 뜬다. 정한 금액을 다 쓰면, 그 키로 보낸 요청은 한도를 올릴 때까지 거절된다.
Create를 누르면 키가 한 번만 보인다는 경고가 뜬다. 키는 sk-or-v1-로 시작하는 긴 문자열이고, 창을 닫으면 다시 볼 수 없으니 바로 복사해 둔다.
오픈라우터는 모든 키에 한도를 설정하라고 권하며, 공개 저장소에 키를 올리지 말 것을 인증(Authentication) 공식 가이드에서 강조한다. 화면 캡처에 키가 찍히지 않게 조심하는 것도 같은 이유다.
키를 환경변수에 넣는다
키를 명령마다 붙여 넣지 않으려면 환경변수에 담는다. 시작 메뉴에서 Windows PowerShell(파란 창)을 열고 아래 둘 중 하나를 입력한다. 따옴표 안에는 sk-or-v1-부터 끝까지 키 값을 통째로 넣는다.
키가 살아 있는지부터 확인한다
비용이 발생하지 않는 엔드포인트부터 조회해 보면, 키의 잔여 한도와 무료 모델 사용 횟수가 반환된다.
Invoke-RestMethod -Uri "https://openrouter.ai/api/v1/key" ` -Headers @{ Authorization = "Bearer $env:OPENROUTER_API_KEY" } ` | ConvertTo-Json -Depth 5
본지 화면에 반환된 응답 값 가운데 핵심 메트릭을 추려 정리했다.
"limit": 10,"limit_remaining": 9.484032194,"is_free_tier": false,"free_model_daily_requests": { "used": 118, "limit": 1000, "remaining": 882}
키 한도 10달러 가운데 9.48달러가 남았고, 무료 모델은 하루 1000회 가운데 118회를 소진했다. 10달러를 충전한 계정이라 하루 한도가 1000회로 확장돼 있다. 이 조회 주소와 항목 구조는 공식 문서의 키 한도 규정에 상세히 설명돼 있다.
파워셸 기본 명령으로 부르면 답이 깨진다
첫 관문은 curl이다. 인터넷 글의 예제 대부분이 curl로 시작하지만, 파란 창에서는 그대로 쓰면 안 된다.
$PSVersionTable.PSVersion # 본지 실측: 5.1.26100.9711Get-Alias curl # 본지 실측: Invoke-WebRequest
마이크로소프트(Microsoft) 공식 기술문서는 윈도우 파워셸에서 curl이 Invoke-WebRequest의 별칭(Alias)이라고 설명한다.
이름만 같은 다른 명령이라 맥이나 리눅스용 예제를 붙여 넣으면 옵션이 충돌한다.
파워셸 자체 명령인 Invoke-RestMethod로 질문을 보내 봤다. 질문의 한글이 깨지지 않도록 본문을 UTF-8 바이트로 바꿔 보냈다.
$body = @{ model = "anthropic/claude-haiku-5.5" messages = @(@{ role = "user" content = "오픈라우터를 처음 쓰는 사람이 조심할 점 두 가지를 한 줄씩 알려 줘." })} | ConvertTo-Json -Depth 5$bytes = [System.Text.Encoding]::UTF8.GetBytes($body)$res = Invoke-RestMethod ` -Uri "https://openrouter.ai/api/v1/chat/completions" ` -Method Post ` -Headers @{ Authorization = "Bearer $env:OPENROUTER_API_KEY" } ` -ContentType "application/json; charset=utf-8" ` -Body $bytes$res.choices[0].message.content
질문은 제대로 갔다. 클로드 하이쿠(Claude Haiku) 5.5가 질문에 맞춰 두 줄로 답했고, 영문 단어 API와 깃허브(GitHub)는 읽혔다. 하지만 한글은 ë…í…처럼 알아볼 수 없는 문자로 바뀌어 화면에 찍혔다. “안녕이라고 한 단어만 답해 달라”는 질문에도 같은 명령은 깨진 문자열을 돌려줬다. 원인은 응답 쪽에 있다. 본지가 받은 응답의 Content-Type 머리글은 application/json이었고, 글자 인코딩(charset) 표시가 없었다. 이런 JSON 응답을 UTF-8로 자동 해석하는 동작은 파워셸 6.2부터 개선되었다고 파워셸 릴리스 노트는 명시한다. 구형 5.1은 UTF-8이 아닌 시스템 기본 인코딩으로 해석해 한글을 깨뜨린다.
curl.exe로 받으면 한글이 산다
진짜 curl은 curl.exe로 부른다. 질문을 body.json 파일로 만들고, 답도 out.json 파일로 받은 뒤 UTF-8로 읽었다.
$body = @{ model = "openrouter/free" messages = @(@{ role = "user" content = "안녕이라고 한국어로 한 단어만 답해 줘." })} | ConvertTo-Json -Depth 5$utf8NoBom = New-Object System.Text.UTF8Encoding($false)[System.IO.File]::WriteAllText("$PWD\body.json", $body, $utf8NoBom)curl.exe -s https://openrouter.ai/api/v1/chat/completions ` -H "Authorization: Bearer $env:OPENROUTER_API_KEY" ` -H "Content-Type: application/json" ` -d "@body.json" ` -o out.json$json = Get-Content out.json -Raw -Encoding UTF8 | ConvertFrom-Json$json.choices[0].message.content
본지 화면에는 안녕 두 글자가 그대로 찍혔다. 모델 칸의 openrouter/free는 무료 모델 가운데 하나를 자동으로 고르라는 뜻이다. 매번 같은 모델을 쓰려면 google/gemma-4-31b-it:free처럼 이름을 적는다. 이유는 다음 절에 있다.
파이썬은 주소 한 줄만 바꾸면 된다
파이썬 환경에서는 오픈AI 라이브러리의 접속 주소 한 줄만 바꾸면 즉시 연동된다.
파이썬이 설치돼 있다면 오픈AI(OpenAI) 공식 라이브러리를 그대로 쓰고, 주소만 오픈라우터로 교체하면 된다. 라이브러리를 설치한 뒤 아래 코드를 or_test.py로 저장하고 실행한다.
import osfrom openai import OpenAI# 오픈라우터 주소로 교체하는 것이 핵심client = OpenAI( base_url="https://openrouter.ai/api/v1", api_key=os.environ["OPENROUTER_API_KEY"],)res = client.chat.completions.create( model="anthropic/claude-haiku-5.5", messages=[ { "role": "user", "content": "오픈라우터를 한 문장으로 설명해 줘.", } ],)print(res.choices[0].message.content)print("모델:", res.model)print(res.usage)
같은 파란 창에서 실행했지만, 본지 화면에 나온 답은 한글이 깨지지 않았다.
OpenRouter는 OpenAI, Anthropic, Google 등 여러 회사의다양한 AI 모델을 하나의 API 키와 통합된 인터페이스로사용할 수 있게 해 주는 서비스입니다.모델: anthropic/claude-haiku-5.5CompletionUsage(completion_tokens=86, prompt_tokens=30, total_tokens=116, ... cost=4.6e-05, ...)
질문 30토큰, 답 86토큰에 0.000046달러(약 0.06원)가 들었다. 클로드 하이쿠 5.5 모델 안내에 따르면 오픈라우터 가격은 100만토큰당 입력 0.1달러, 출력 0.5달러다. 30토큰은 0.000003달러, 86토큰은 0.000043달러로 응답에 찍힌 값과 정확히 맞아떨어졌다. 오픈AI 라이브러리를 쓰는 구조는 오픈라우터의 오픈AI SDK 연동 문서에도 동일하게 안내돼 있다.
같은 모델인데 왜 값이 다를까
오픈라우터는 한 모델을 여러 백엔드 공급사가 분산 서비스한다. 기본 설정에서는 저렴한 공급사를 우선하되, 가격의 제곱에 반비례하는 확률로 분산 호출한다고 공급사 선택 라우팅 가이드는 설명한다. 공급사에 장애가 발생하면 다른 곳으로 자동 전환된다.
본지가 10월 23일 밤 큐웬(Qwen)3.8 27B를 6회 연속 호출하자 4곳의 공급사가 응답했다. 워크로드 호출 기준 공급사별 실제 비용 및 단위 경제학 차이를 실측 비교한 결과는 아래 인포그래픽과 같다.
같은 모델인데 가장 느린 곳과 빠른 곳의 속도가 20배 넘게 벌어졌고, 값도 달랐다. 엔드포인트 실시간 가격 목록을 보면 이 모델을 서비스하는 공급사는 21곳에 달하며, 출력 가격은 100만토큰당 0.5달러(Tenstorrent)부터 3.2달러(Venice·클라우드플레어(Cloudflare))까지 6.4배 차이가 난다. 공급사마다 모델을 압축한 양자화 규격(fp4·fp8·bf16 등)도 제각각이다.
마지막 호출은 Logs에서 줄을 눌러 Generation details를 열어 봤다. Provider Responses 칸에 첫 공급사 AkashML이 429(혼잡)를 반환한 기록이 남아 있었다. 1.1초 뒤 Venice로 넘어가 답을 받았고, Fallbacks 칸에는 1이 찍혔다. 더 저렴한 엔드포인트가 막히자 차선책인 고단가 공급사로 자동 전환됐다.
비용을 우선하려면 요청 본문에 "provider": {"sort": "price"}를 넣거나 모델 이름 뒤에 :floor를 붙인다. 가격 우선 정렬 옵션은 두 방식 모두 공식 문서에 안내돼 있다. 본지가 이 정렬 옵션을 적용해 추가 벤치마크를 진행하지는 않았다.
결과가 매번 같아야 하는 운영 환경이라면 무료 모델 이름을 고정해 두어야 한다.
무료 모델 자동 선택(openrouter/free)도 호출할 때마다 모델이 바뀐다. 본지 호출에는 cohere/north-mini-code:free와 dots-studio/dots-3-note-preview:free가 각각 응답했다. 한 번은 질문과 무관하게 “User Safety: safe”라는 단 한 줄만 반환되기도 했다.
막혔을 때 보는 오류
오픈라우터는 오류 원인을 HTTP 상태 코드로 반환한다고 오류 및 디버깅 가이드는 안내한다. 본지가 일부러 유효하지 않은 키를 입력하자 파란 창에는 “원격 서버에서 (401) 권한이 없음 오류를 반환했습니다.”라는 문구가 출력됐다.
| 번호 | 뜻 | 먼저 볼 곳 |
|---|---|---|
| 401 | 키가 틀렸거나 비활성화됨 | 환경변수에 키 전체가 들어갔는지 점검 |
| 402 | 크레딧 잔액 부족 | Credits 메뉴의 잔액 확인 |
| 403 | 키 또는 워크스페이스 한도 초과 | 키 설정의 Credit limit 상향 필요 |
| 429 | 요청 빈도 초과 또는 공급사 혼잡 | 잠시 대기 후 재시도 또는 대체 모델 사용 |
| 502·503 | 모델 구동 공급사 서버 장애 | 다른 백엔드 공급사나 대체 모델 선택 |
명령을 스크립트 파일로 저장해 돌릴 때도 함정이 있다. 한글이 들어간 .ps1 파일을 BOM 없는 UTF-8로 저장했더니 파란 창은 한글을 ??로 읽고 “문자열에 ” 종결자가 없습니다.”라는 오류를 냈다. 메모장에서 저장할 때 인코딩을 UTF-8(BOM)으로 고르면 된다.
비용이 새지 않게 막는 세 겹
세 겹의 안전장치를 걸어 두면 키가 유출되더라도 손해는 설정 금액 안에서 차단된다.
첫째 겹은 키 한도로, 키마다 Credit limit을 걸어 두면 그 금액에서 요청이 멈춘다. 둘째는 워크스페이스 예산이다. 왼쪽 메뉴 Settings의 Workspace budget에서 Add budget을 누르면 일·주·월·평생 단위 지출 상한을 건다. 본지 계정에는 아직 한도가 없다는 안내가 떠 있었다. 셋째는 1편에서 다룬 Auto Top-Up을 꺼 두는 일이다. 세 겹을 다 걸어 두면 키가 새도 손해는 정한 금액 안에서 멈춘다. 한도에 걸린 요청은 403 오류로 자동 차단된다고 요청 제한 규정은 설명한다.
키마다 개별 한도를 걸어 두면 유출 사고가 발생해도 손실은 그 금액에서 멈춘다.