API Key 유출은 생각보다 흔합니다. 깃허브에 실수로 올라간 코드 한 줄이나 로그 파일에 남은 인증 헤더 하나만으로도 키가 외부로 유출될 수 있습니다. 문제는 열쇠가 복사됐다는 사실 자체를 알려 주는 알림이 따로 오지 않는다는 점입니다. 누군가 내 키로 조용히 요청을 보내기 시작해도, 서비스는 그저 정상적인 인증으로 처리할 뿐입니다.
그렇다면 유출에 어떻게 대비할 수 있을까요. 예방과 탐지, 두 가지로 나눠 봅니다. 먼저 키를 관리해 유출됐을 때의 피해 범위를 좁혀 두고, 그래도 유출되는 순간은 평소 쌓아 두던 옵저버빌리티(observability, 시스템이 남기는 로그·메트릭·트레이스를 근거로 내부에서 무슨 일이 일어나는지 파악하는 것) 데이터로 빨리 알아챕니다. 유출과 오남용은 특별한 보안 이벤트가 아니라 요청량·비용·접속 위치 같은 평소 지표의 변화로 먼저 드러나기 때문입니다.
API Key(서비스를 호출할 때 내 신원을 증명하는 문자열 형태의 열쇠)는 사실상 비밀번호와 같습니다. 열쇠 하나만 있으면 그 키에 묶인 권한 안에서 누구든 요청을 보낼 수 있습니다. 데이터를 읽어 가거나, 리소스를 만들거나, 요금이 발생하는 작업을 대신 실행할 수 있다는 뜻입니다.
AI 서비스의 키는 그 위험이 조금 더 직접적입니다. OpenAI API Key처럼 사용량만큼 과금되는 키는 호출 한 번이 곧 비용이기 때문입니다. 유출된 키로 대량의 요청을 보내면 토큰(모델이 처리하는 텍스트 단위) 소비가 순식간에 불어나고, 그 금액이 그대로 다음 청구서에 찍힙니다. 공개 저장소에 노출된 AI 키로 짧은 시간 안에 예상치 못한 비용이 발생한 사례가 반복해서 공유되는 이유입니다. 여기에 프롬프트나 응답에 민감한 데이터가 오갔다면 정보 유출까지 겹칩니다.
검색으로 이 글에 닿은 분이라면 세 용어를 함께 보셨을 수 있습니다. 셋은 모두 "요청을 보낼 자격이 있는가"를 확인하는 수단이지만 성격이 다릅니다. 깊이 알 필요는 없고, 구분만 해 두면 충분합니다.
쉽게 말하면 API Key는 오래 유지되는 고정 열쇠에 가깝고, JWT와 OAuth Access Token은 대체로 유효 기간이 정해진 임시 출입증에 가깝습니다. 특히 장기간 유지되는 API Key는 한번 유출되면 폐기하거나 만료될 때까지 악용될 수 있습니다.
유출을 탐지하기 전에, 키 자체를 덜 위험하게 관리해 두면 유출되더라도 피해 범위와 시간이 좁아집니다. 서비스 규모와 상관없이 기본이 되는 몇 가지입니다.
식별자가 있고 없고의 차이는 로그 한 줄에서 바로 드러납니다.
# 키 식별자 없음. 어느 키가 보낸 요청인지 모름
14:02 POST /v1/chat 200 ip=203.0.113.9
# 마스킹한 키 식별자를 붙임. 키 단위로 묶어 볼 수 있음
14:02 POST /v1/chat 200 ip=203.0.113.9 key_alias=llm-prod-primary메트릭도 마찬가지입니다.
llm_tokens_total{credential_id="openai-prod-02", model="gpt-4o"}처럼 키를 가리키는 내부 식별자를 태그로 달아 두면, 어느 키가 토큰을 많이 썼는지 바로 나눠 볼 수 있습니다.
이렇게 범위를 좁혀 두어도 유출을 완벽히 막지는 못합니다. 그래서 유출을 빨리 알아채는 장치를 함께 두어야 합니다. 그 장치가 바로 옵저버빌리티입니다.
여기서 먼저 구분할 점이 있습니다. 우리 서비스가 사용자나 다른 애플리케이션에 발급한 API Key가 유출됐다면, 출발지 IP·User-Agent·호출 엔드포인트 같은 흔적을 우리 서버의 접근 로그에서 확인할 수 있습니다.
반면 OpenAI API Key처럼 우리가 외부 서비스를 호출하기 위해 발급받은 키가 유출돼 공격자가 공급자 API를 직접 호출했다면, 그 요청은 우리 애플리케이션을 거치지 않을 수 있습니다. 이때는 자체 서버 로그가 아니라 해당 공급자가 제공하는 사용량·비용·프로젝트별 활동 기록과 알림을 중심으로 탐지해야 합니다. 따라서 수집할 신호는 키의 사용 방향에 따라 달라집니다.
유출된 키가 악용되면 대부분 요청량이나 비용, 접속 패턴에 평소와 다른 흔적이 나타납니다. 적절한 로그와 메트릭을 수집하고 있다면 그 변화를 읽어낼 수 있습니다. 각 데이터가 어떤 신호를 보여 주는지 순서대로 보겠습니다.
메트릭(일정 시간 간격으로 수를 세어 둔 값)은 "평소 대비 지금이 얼마나 이상한가"를 가장 빠르게 보여 줍니다. 유출 상황에서 흔히 튀는 값은 다음과 같습니다.
이 값들은 개별 사건이 아니라 추세라서, 임계값 알림을 걸어 두면 사람이 들여다보기 전에 먼저 울립니다. 이때 "요청 수 10,000 초과" 같은 절대 수치 하나로 걸면 트래픽이 늘 때마다 헛울리기 쉽습니다. "전주 같은 시간대 대비 요청 수 300% 이상 급증"이나 "최근 5분간 429 응답 비율 5% 초과"처럼 평소 대비 편차나 상태 코드를 기준으로 잡으면 오탐이 줄어듭니다.
메트릭이 "이상하다"를 알려 준다면, 로그는 "왜, 누가 그랬나"를 확인하는 근거입니다. 유출과 관련해 주로 살펴보는 항목은 인증과 접근의 흔적입니다.
로그를 볼 때 헷갈릴 수 있는 부분은 "실패한 요청만 위험하다"고 생각하기 쉽다는 점입니다. 유출된 키는 이미 유효하기 때문에, 인증에 성공한 정상 요청 속에 오남용이 숨어 있는 경우가 오히려 많습니다. 그래서 키 식별자(어떤 키가 요청했는지 구분하는 값)별로 로그를 묶어 어느 키가 튀는지 함께 봐야 합니다.
트레이스(요청 하나가 거쳐 간 경로를 이어 붙인 기록)는 이상 요청이 시스템 안에서 실제로 어디를 지나갔는지 보여 줍니다. 요청을 키·사용자·API 경로 단위로 이어 보면, 폭증한 호출이 어느 지점에서 시작해 어떤 자원을 건드렸는지 따라갈 수 있습니다.
예를 들어 특정 키의 토큰 소비량이 급증했다면, 트레이스에서 그 요청이 어떤 애플리케이션 기능과 모델 호출을 거쳤는지 확인할 수 있습니다. "어느 키가 많이 썼는가"를 넘어 "어떤 기능이 어떤 모델을 호출해 비용이 났는가"까지 좁히는 단계입니다.
특히 AI 서비스라면 표준을 활용할 수 있습니다. OpenTelemetry(관측 데이터를 수집하는 오픈소스 표준)의 생성형 AI 시맨틱 컨벤션에는 gen_ai.* 속성으로 모델 이름과 토큰 사용량을 트레이스에 실을 수 있도록 정의돼 있습니다. OpenTelemetry는 트레이스·메트릭·로그를 서로 다른 관점의 신호로 정의하는데, 이 셋을 묶어 보면 시스템 내부를 여러 각도에서 관측할 수 있습니다. 토큰 소비가 어느 호출 경로에서 튀었는지 추적하려면 이 세 가지를 나란히 놓고 보는 편이 유리합니다.
실무에서 자주 나오는 질문입니다. 결론부터 말하면 대체로 메트릭이 가장 먼저 반응합니다. 요청량이나 비용이 평소 대비 몇 배로 뛰는 변화는 집계 값인 메트릭에서 가장 빠르게 잡히기 때문입니다. 로그만으로도 유출을 찾을 수는 있지만, 로그는 개별 사건의 기록이라 "평소보다 얼마나 벗어났나"를 사람이 일일이 세어야 해서 발견이 늦어집니다.
그래서 순서를 이렇게 두면 자연스럽습니다. 메트릭 알림으로 이상을 먼저 감지하고, 로그에서 누가 어디서 그랬는지 확인한 뒤, 트레이스로 그 요청이 지나간 경로를 되짚는 흐름입니다. 어느 하나가 정답이라기보다, 세 데이터가 서로 다른 질문에 답한다고 보는 편이 맞습니다.
이상을 확인했다면 남은 건 대응입니다. 앞서 관리 단계에서 권한과 사용량 상한을 좁혀 두었다면 유출돼도 공격자가 할 수 있는 일이 제한되고, 탐지가 빠르면 그만큼 폐기와 교체도 빨라져 피해를 줄일 수 있습니다.
노출 지점은 대부분 소스 코드 쪽입니다. 깃허브 같은 공개 저장소에 키를 그대로 커밋하거나, 프런트엔드 번들이나 로그 파일에 인증 정보가 실수로 남는 경우가 많습니다. OWASP와 CWE는 자격 증명을 코드에 직접 적어 두는 하드코딩(hard-coded credentials)을 대표적인 취약점으로 분류합니다. 커밋 전 검사 도구로 키 패턴을 걸러 내고, 이미 노출된 키는 되돌리기보다 폐기하는 편이 안전합니다.
유출이 의심되면 해당 키를 즉시 폐기하거나 비활성화한 뒤 새 키를 발급합니다. 그다음 최근 사용량과 비용, 호출 시간대, 출발지 IP, 호출한 모델과 엔드포인트를 확인해 피해 범위를 파악합니다. 키가 코드나 저장소에 들어갔다면, 커밋 기록에 남은 키는 문자열을 지운 뒤에도 이력에서 복구될 수 있어 폐기하는 편이 안전합니다.
고정된 임계값 하나만으로는 부족할 때가 많습니다. 트래픽에는 요일과 시간대에 따른 자연스러운 변동이 있어서, 평소 패턴을 학습한 뒤 그 기준선에서 얼마나 벗어났는지를 함께 보는 방식이 더 정확합니다. 예를 들어 새벽 시간대의 소량 호출은 정상이지만, 같은 시간대에 평소의 수십 배가 들어오면 편차로 잡아낼 수 있습니다.
교체는 유출을 막는다기보다 노출 시간을 줄이는 장치입니다. 유출되더라도 그 키가 쓸 수 있는 범위와 시간을 좁혀 두는 접근입니다. 교체 주기는 키 민감도에 따라 다르게 두는 편이 현실적입니다. 결제나 관리자 권한처럼 위험이 큰 키는 짧게, 위험이 낮은 키는 길게 잡습니다.
API Key 보안은 예방과 탐지, 두 가지를 함께 봐야 합니다. 먼저 코드 밖 보관·최소 권한·사용량 상한·정기 교체로 유출됐을 때의 피해 범위를 좁혀 둡니다. 그래도 키는 언젠가 유출될 수 있으니, 요청량과 비용, 접속 위치 같은 평소 지표의 조용한 변화를 옵저버빌리티로 지켜보며 그 순간을 조기에 포착합니다. 이미 쌓고 있는 로그와 메트릭을 이 관점으로 다시 들여다보는 것이 첫걸음입니다.
와탭은 서버·애플리케이션·AI 서비스의 요청량과 응답, 토큰 사용량을 하나의 플랫폼에서 함께 보고, 앞서 본 편차 기반 알림을 이상 징후에 걸 수 있도록 지원합니다. 15일 무료 체험으로 내 서비스의 지표부터 확인해 보세요.