Insight
home
News
home

AI 키를 나눠주지 않기로 했습니다

날짜
2026/09/02
AI 기능을 운영하는 조직이라면 다음 질문에 답할 수 있어야 합니다.
"현재 조직에 AI 서비스 제공사 키가 몇 개 발급되어 있고, 각각의 사용 주체는 누구이며, 이번 달 사용액은 얼마인가."
즉시 답할 수 있는 조직은 많지 않습니다. 관리가 소홀해서가 아니라, 초기에 만든 구조가 이 질문에 답하도록 설계되지 않았기 때문입니다. AI 도입은 대개 서비스 한 곳의 기능 하나로 시작합니다. AI 서비스 제공사 콘솔에서 키를 발급받아 서버에서 사용해서 호출하면 곧바로 동작합니다. 이후 두 번째 서비스, 팀 단위 PoC, 개인이 만든 사내 도구, 코딩 에이전트가 차례로 추가되면서 반년이면 조직 전반에서 LLM을 호출하게 됩니다. 문제는 이러한 확산이 키를 복제하는 방식으로 일어난다는 점입니다. 새 사용처가 생길 때마다 AI 서비스 제공사의 키가 한 벌씩 더 배포되고, 일정 시점을 넘기면 발급된 키를 회수하는 것도 집계하는 것도 어려워집니다. 저희 역시 그 지점을 향해 가고 있었고, 도달하기 전에 구조를 바꾸기로 했습니다. 이 글은 문제 인식과 전환 과정, 그 결과를 정리한 것입니다.

이 구조가 오래 유지되기 어려운 이유

앞서 말한 상태를 표현하면 아래 그림과 같습니다.
서비스가 두세 개인 동안에는 문제가 드러나지 않습니다. 다만 키 관리 체계의 build-up 속도가 키 복제 속도를 따라가지 못한다는 구조적 한계가 있습니다. 이 한계는 두 가지 형태로 나타납니다. 하나는 매일 발생하는 운영 부담이고, 다른 하나는 언젠가 발생하는 리스크입니다.

매일 발생하는 운영 부담

보안 사고가 없더라도 일상 업무에서 지속적으로 비용이 발생합니다.
상황
기존 구조에서의 대응
모델 교체
앱마다 코드를 수정하고 재배포해야 합니다. 제공사가 구모델을 중단하면 전체가 동시에 대응해야 함
제공사 장애·쿼터 초과
앱별로 개별 대응합니다. 다른 모델로 전환하는 폴백은 앱마다 따로 구현해야 함
키 회전
해당 키를 사용하는 서버를 모두 찾아 갱신해야 하며, 누락 시 장애로 이어짐
신규 팀의 AI 도입
계정·결제·키 발급 협의부터 시작하고, 적용 속도가 조직 프로세스에 종속됨
제공사 추가
SDK·인증·응답 형식이 달라 앱마다 통합 코드가 중복
비용 확인
청구서 총액만 확인 가능하며, 서비스·팀·용도별로 분해할 수 없음
이 중 키 회전이 특히 문제가 됩니다. 키 회전 비용이 크면 회전 주기를 미루게 되고, 그 결과 한 번 발급된 키는 사실상 영구 키로 남습니다. 시간이 지날수록 해당 키를 보유한 지점은 계속 늘어납니다. 규칙이 없어서가 아니라 준수 비용이 높아서 지켜지지 않는 경우에 해당합니다.

언젠가 발생하는 리스크

운영 부담은 감수할 수 있습니다. 그러나 키 유출은 성격이 다릅니다. 키를 복제해 배포하면 그만큼 유출 경로도 늘어납니다. 아래는 이러한 구조에서 원리적으로 열려 있는 경로입니다.
경로
최종 도착지
소스 코드 하드코딩
깃 커밋을 거쳐 저장소 히스토리에 영구 잔존
.env 파일
실수로 커밋되거나 백업·압축 파일에 동봉
로그 · 에러 메시지
로그 수집 시스템에 그대로 적재
스크린샷 · 문서 · 티켓
캡처와 붙여넣기를 통해 확산
서드파티 도구 입력
해당 도구의 데이터베이스에 저장
프런트엔드 번들
브라우저에서 그대로 노출
게다가 최근에는 AI 코딩 에이전트라는 경로가 추가되었습니다. 에이전트에 키를 전달하면 그 키는 에이전트가 생성하는 파일·커밋·로그 어디에든 남을 수 있습니다. 개인의 주의만으로는 통제하기 어려운 영역입니다.

차단이 아니라 사후 대응 가능성이 기준

유출 확률을 제로로 만드는 방법은 없습니다. 따라서 설계 기준을 유출이 발생했을 때 무엇을 할 수 있는가로 잡았습니다.
유출된 직후
원본 키를 나눠준 구조
가상키 구조
즉시 차단
제공사 콘솔에서 폐기하면 그 키를 사용하던 모든 서비스가 함께 중단
해당 키만 삭제, 나머지는 영향 없음
피해 상한
계정 한도까지 무제한
그 키에 설정된 예산 한도까지
출처 특정
여러 지점이 공유하므로 불가능
1키 1주체이므로 즉시 특정
영향 범위 산정
호출 기록이 없어 불가능
전 호출이 기록되어 산정 가능
재발급 비용
해당 키를 사용하는 모든 서버를 찾아 재배포
저장소 값 갱신 후 자동 분배
원본 키를 나눠준 구조에서는 유출 직후 취할 수 있는 조치가 사실상 없습니다. 키를 폐기하면 그 키를 사용하던 서비스가 함께 중단되고, 피해 범위는 계정 한도까지 열려 있으며, 유출 지점과 사용량을 확인할 방법도 없습니다. 반면 가상키 구조에서는 다섯 항목 모두 대응 수단이 존재합니다.

기존 구조에 없던 세 가지

운영 부담과 리스크 모두 원인을 거슬러 올라가면 동일한 지점에 도달하게 됩니다.
기존 구조에 없던 것
그래서 생긴 문제
통제 단위
한도·만료·권한이 제공사 계정 단위뿐이어서, 서비스나 사용자 단위로 제한할 수 없음
추상화 계층
앱이 제공사를 직접 참조하므로, 모델이나 제공사가 변경되면 앱도 변경해야 함
관측
사용 주체·모델·사용량을 알 수 없어 비용도 이상 신호도 파악하지 못함
이런 세 가지 문제점들은 사고가 발생해야 알 수 있는 것들이 아니라, 구조를 보면 미리 알 수 있는 문제였습니다. 그래서 규모가 더 커지기 전에 바꾸기로 했습니다.

전환 방향: 키 배포에서 단일 통로로

각 서비스에는 원본 키 대신 가상키(Virtual Key) 를 발급합니다. 가상키는 게이트웨이가 발급하는 자체 키로 사용 가능 모델, 예산, 요청 속도, 만료일이 함께 설정됩니다. 원본 키는 게이트웨이 내부에만 보관하며 앱·서비스에는 전달하지 않습니다.

구성 요소

세 가지 오픈소스를 자체 호스팅하여 구성했습니다.
도구
역할
LiteLLM
LLM 게이트웨이. 여러 제공사를 OpenAI 호환 API로 통합하고 가상키 발급, 예산·속도 한도, 모델 라우팅을 중앙에서 관리
Langfuse
LLM 관측 플랫폼. 호출별 입출력·토큰·비용·지연·에러를 트레이스 단위로 수집·시각화
Infisical
시크릿 관리. 발급된 가상키를 앱·환경별로 저장하고 런타임에 주입

자체 호스팅을 선택한 이유

두 가지를 고려했습니다. 첫째, 데이터가 외부로 나가지 않아야 합니다. LLM 입출력에는 이용자 데이터가 포함될 수 있습니다. 관측 도구는 그 입출력을 그대로 저장하는 시스템이므로, 외부 SaaS를 사용하면 이용자 데이터가 통제 범위를 벗어납니다. SaaS 대신 자체 호스팅으로 게이트웨이와 관측 계층을 구축하면 데이터가 외부로 노출되지 않습니다. 둘째, 비용이 사용량에 비례해 증가하지 않아야 합니다. 관측 SaaS의 과금 방식은 사용량 기반이며, 대부분 호출량에 비례합니다. AI 사용량이 지속적으로 증가하는 상황에서는 관측 비용도 같은 기울기로 상승합니다. 자체 호스팅은 고정비 성격이므로 호출량이 늘어도 비용 증가가 완만합니다.

운영 원칙 네 가지

1.
단일 진입점 — 모든 LLM 호출은 게이트웨이를 경유하며, 제공사 직접 호출은 금지합니다.
2.
키 비노출 — 원본 키는 게이트웨이에만 두고, 서비스에는 가상키만 제공합니다.
3.
관리 화면 내부망 한정 — 외부에 공개하는 것은 호출 경로 하나입니다.
4.
관측 기본 적용 — 게이트웨이를 경유하면 앱 코드 수정 없이 자동 기록됩니다.

가상키 발급 정책

발급 시 아래 항목은 예외 없이 설정하며, 빈 값으로는 발급하지 않습니다.
항목
규칙
만료일
기간 선택 필수, 무기한 금지
예산 한도
키별 누적 상한, 초과 시 자동 차단
리셋 주기
예산 자동 초기화 주기
요청 속도
분당 요청 수 제한
사용 가능 모델
와일드카드 금지, 명시 목록만 허용
키는 사용 주체를 기준으로 구분합니다.
종류
대상
특징
서비스 키
운영 서비스
환경(운영/스테이징)까지 분리. 담당자가 변경되어도 서비스가 소유
개인 키
구성원 개인
1인 1키. 개인 사용량 추적, 퇴사·이동 시 회수
개인 키는 예산·속도·만료를 고정 기본값으로 발급합니다. 필요한 만큼 부여하는 방식이 아니라, 기본값을 고정하고 추가가 필요하면 실사용 근거를 받아 조정하는 방식입니다. 고정값 자체가 유출이나 오작동 시 피해를 제한하는 장치이기 때문입니다.

이름 규칙

키 값은 어디에도 평문으로 남겨서는 안 됩니다. 그러면 키를 지칭할 별도의 식별자가 필요해집니다. "지난주에 발급받은 키"라는 표현으로는 변경도 폐기도 요청할 수 없기 때문에, 모든 키에 이름을 부여하도록 했습니다.
이름 규칙을 정하면서 세 가지 효과를 얻었습니다.
키 값을 기재할 일이 없어집니다. 티켓·문서·요청은 모두 이름으로 주고받습니다
집계 기준이 확보됩니다. 별도 태깅 없이 사업별·서비스별·팀별 비용이 분해됩니다
소유 주체가 명확해집니다. 만료·회수 대상을 이름만으로 식별할 수 있습니다
모델 이름에도 같은 원칙을 적용했습니다. 동일한 모델이라도 운영용과 사내 개발용을 별도로 등록하고 서로 다른 계정 크리덴셜에 연결했습니다. 제공사 계정과 결제 수단 역시 용도별로 분리했습니다. 그 결과 AI 비용이 단일 항목이 아니라 용도별로 구분된 청구서로 산출됩니다.

발급 시 금지 사항

원칙을 서술하는 것보다 금지 목록을 명시하는 편이 실무에서 더 효과적이었습니다.
사용 가능 모델 와일드카드 지정(전체 모델 허용) 금지
무기한 만료 또는 한도 없는 키 금지
하나의 키를 여러 서비스·여러 사용자가 공유 금지
전체 권한을 가진 관리자 키의 앱 배포 금지
문서·이슈·코드에 키 값 평문 기재 금지
게이트웨이를 우회한 제공사 직접 호출 금지

코드 유입 차단

가상키 역시 과금이 발생하는 자격증명이므로, 커밋에 포함되는 것 자체를 차단해야 합니다.
단계
시점
수단
1차
커밋 전
pre-commit 훅(로컬)
2차
머지 전
PR 검사(CI)
3차
푸시 시점
플랫폼 푸시 차단
4차
사후
주기적 전체 스캔(과거 커밋 포함)
앞 단계를 통과하더라도 뒷 단계에서 검출되도록 중첩했습니다. 어느 단계에서 검출되든 대응 규정은 동일합니다. 해당 키는 노출된 것으로 간주하고 즉시 폐기·재발급합니다. 히스토리 정리는 그 다음 순서입니다.

전환 결과

항목
기존 구조
현재
앱 서버의 원본 키
서비스마다 1벌 이상
0개
키 유출 시 조치
폐기 시 관련 서비스 전체 중단
해당 키만 삭제, 나머지 영향 없음
키 회전
사용 서버를 모두 찾아 재배포
저장소 값 갱신 후 자동 분배
모델 교체
앱 코드 수정 및 재배포
게이트웨이 설정 변경만, 재배포 0회
제공사 장애 대응
앱 수정 후 긴급 배포
폴백 등록, 앱 변경 없음
사용량·비용 파악
제공사 청구서 총액
키·모델·용도별 상시 대시보드
신규 서비스 적용
제공사 계정·키 발급 협의
가상키 1개와 엔드포인트 정보

비용 가시성 확보

게이트웨이가 단일 통로이므로 제공사와 무관하게 동일 기준으로 집계됩니다. 집계 과정에서 확인한 내용은 다음과 같습니다.
사내 개발용 호출은 전체 요청의 10% 미만이면서 비용의 약 40%를 차지하고 있었습니다. 고비용 코딩 특화 모델을 사용하기 때문이며, 키와 모델을 용도별로 분리하지 않았다면 확인할 수 없었을 사실입니다. 이 수치가 확보되면서 개발용 키에 적용한 통제도 근거를 갖게 되었습니다. 개발용 키는 예산과 속도가 고정 기본값이고 사용 가능 모델은 신청 용도에 해당하는 것만 허용하는 화이트리스트 방식이며, 한도 조정이 필요하면 실사용 근거를 확인한 후 반영합니다. 용도별로 결제 수단까지 분리했기 때문에 이 비용은 사업과 활동이 구분된 상태로 청구서에 반영됩니다. "AI 비용이 증가했다" 수준이 아니라 어느 용도의 어느 모델인지까지 확인해야 조치가 가능합니다.

이상 신호 탐지

모델별 실패율을 확인하는 과정에서 특정 프리뷰 모델이 대부분의 호출에서 실패하고 있음을 발견했습니다. 기존 구조였다면 개별 앱의 간헐적 실패로 처리되었을 신호입니다. 조치 역시 게이트웨이에서 완료했습니다. 해당 모델을 사용하던 서비스에 폴백을 등록해 장애 시 다른 모델로 자동 전환되도록 구성했으며, 앱 코드는 수정하지 않았습니다. 제공사 쿼터 초과 상황도 동일한 방식으로 처리합니다.

관측 연동 불필요

관측 도구를 앱 SDK가 아니라 게이트웨이 콜백으로 연결했습니다. 따라서 신규 서비스가 추가되어도 별도의 관측 연동 작업이 없습니다. 게이트웨이를 통해 호출하면 그 시점부터 기록이 자동으로 축적됩니다.

운영하며 확인한 사항

예산 한도는 완전한 차단선이 아닙니다. 게이트웨이를 다중 인스턴스로 운영하면 카운터가 분산되어 한도를 수 % 초과한 후 차단됩니다. 정확한 상한이라기보다 피해 규모를 제한하는 장치로 이해해야 합니다.
관측은 1차 방어선이 아닙니다. 비동기 수집은 분 단위 지연이 있으므로 즉시 차단과 경보는 게이트웨이와 인프라 알람이 담당합니다. 반대로 기록이 실패해도 LLM 호출은 차단되지 않도록 구성했습니다. 관측 계층 장애가 서비스 장애로 전이되어서는 안 되기 때문입니다.
정책 문서와 실제 운영은 괴리가 발생합니다. 초안의 명명 규칙과 실제 운영이 달라져, 문서에 제안과 실제를 구분해 기재하고 실제 운영 상태를 현행 기준으로 명시했습니다. 현행과 일치하지 않는 문서는 참조되지 않습니다.
도입 난이도를 낮추는 것이 정책보다 중요합니다. 게이트웨이가 OpenAI 호환 API이므로 엔드포인트, 키, 모델명 세 항목만 변경하면 기존 SDK가 그대로 동작합니다. 사용이 번거로우면 우회 경로가 생깁니다.

정리하며

각 서비스가 원본 키를 보유하고 제공사를 직접 호출하던 구조한도·만료·추적 가능하도록 설정된 가상키로 게이트웨이를 경유하는 구조로 전환했습니다.
애플리케이션 서버의 원본 키 0개. 서버에 유출될 원본 키가 존재하지 않습니다.
키가 유출되어도 해당 키만 폐기하면 되며, 피해는 그 키의 예산 한도에 그칩니다.
모든 호출이 키 단위로 식별되고 사용 내역을 사후 확인이 가능합니다.
용도별·모델별 비용이 상시 확인되며 청구서까지 분리됩니다.
모델 교체, 장애 폴백, 키 회전이 앱 코드 변경 없이 처리됩니다.
외부 노출 표면이 호출 경로 하나로 축소되었습니다.
AI 사용량은 앞으로도 계속 증가합니다. 사용량 증가에 비례해 관리 비용과 리스크가 함께 커지지 않도록 하는 것이 이번 작업의 목적이었습니다. 현재는 신규 서비스가 LLM을 사용할 때 가상키를 발급하고 엔드포인트를 안내하는 것으로 완료되며, 해당 서비스의 호출 내역과 비용은 별도 작업 없이 대시보드에 반영됩니다.