서비스 간 인증 키 관리: 공유 토큰부터 mTLS까지 규모별 4단계
예를 들어 직원 열 명 남짓한 쇼핑몰 운영사를 생각해 봅시다. 주문 관리 화면이 재고 서버에서 수량을 읽고, 고객센터 도구가 주문 서버에서 문의 내역을 가져오고, 사내 챗봇이 외부 AI API를 부릅니다. 연결은 세 가닥이고 키도 세 개입니다. 그런데 이 키들을 비밀 관리 도구에 옮겨 적으려고 표를 그려 보면 칸이 다섯 개 나옵니다.
값은 셋인데 칸이 다섯인 이유를 따라가 보면, 서비스끼리 서로를 어떻게 믿게 만드는지에 대한 질문 전체가 딸려 나옵니다.
키가 길면 안전하다는 오해
흔히 서비스 간 키의 안전을 길이와 무작위성으로 판단합니다. openssl rand -hex 32로 만든 64자 토큰이면 256비트이고, 영문 대소문자와 숫자 32자짜리 키도 약 190비트입니다. 어느 쪽이든 추측해서 맞히는 길은 없습니다. 여기까지는 맞는 이야기입니다.
어긋나는 곳은 그다음입니다. 위 쇼핑몰의 재고 토큰은 재고 서버와 주문 관리 화면이 같은 값을 하나씩 들고 서로 맞춰 보는 공유 비밀입니다. 그래서 비밀 관리 도구에도 서비스마다 한 칸씩, 같은 값이 두 번 들어갑니다. 문의 토큰도 마찬가지입니다. 세 개가 다섯 칸이 되는 이유입니다.
칸만 늘어나는 것도 아닙니다. 한 값의 사본을 세어 보면 비밀 관리 도구, CI의 시크릿, 호스팅 업체의 환경 변수, 배포 때 서버에 써지는 env 파일, 실행 중인 컨테이너의 환경까지 다섯 곳이 됩니다. 키는 길이로 깨지지 않습니다. 이 다섯 곳 가운데 하나에서 샙니다.
공유 비밀의 이름을 양쪽에 똑같이 두는 이유
공유 비밀에서 가장 흔하게 생기는 실수는 이름입니다. 재고 서버에서는 INVENTORY_SYNC_TOKEN이라 부르고, 주문 관리 화면에서는 어디로 가는 열쇠인지 드러내려고 STOCK_API_TOKEN이라 붙이는 식입니다. 각자의 자리에서 보면 둘 다 읽기 좋은 이름입니다.
문제는 비밀 관리 도구에서 두 칸을 나란히 볼 때 생깁니다. 같은 값이라는 단서가 어디에도 없습니다. 키를 갈 때 한쪽만 바꾸면 연결이 끊기고, 왜 끊겼는지는 이름만으로 찾을 수 없습니다. 저는 공유 비밀이라면 양쪽 이름을 똑같이 두는 쪽이 맞다고 봅니다. 출처를 이름에 담고 싶은 마음은 주석으로 채우면 됩니다.
이름을 맞추는 순서에도 함정이 있습니다. 옛 이름을 먼저 지우면 배포가 도는 사이에 연결이 빕니다. 새 이름으로 넣고, 배포하고, 실제 토큰으로 불러 본 다음에 옛 이름을 지우는 순서가 안전합니다.
접두사가 붙은 키와 맨 난수 토큰
같은 회사 안에서도 키의 모양은 제각각입니다. 외부 AI API의 키는 보통 sk-처럼 발급처가 붙인 접두사로 시작하고, 사내에서 직접 만든 공유 토큰은 접두사 없는 난수입니다.
차이는 누가 발급하느냐에서 옵니다. 여러 사용자에게 키를 나눠 주는 발급처는 대개 원문을 저장하지 않고, 앞 몇 자와 해시만 남겨 둡니다. 요청이 들어오면 앞자리로 행 하나를 찾고 해시를 대조하는 방식입니다. 접두사는 로그에 찍혀 나온 키가 무슨 키인지 바로 알아보게 해 주기도 합니다. GitHub가 2021년에 토큰 형식을 ghp_, gho_ 같은 접두사로 바꾼 것도 비밀 스캐너가 저장소에 섞여 들어간 토큰을 오탐 없이 찾게 하려는 이유였습니다(GitHub 블로그).
두 서비스가 같은 값을 그대로 비교하기만 하는 공유 토큰에는 접두사가 할 일이 거의 없습니다. 다만 유출을 알아보기 쉽게 하려고 붙이는 것은 충분히 의미가 있고, 새로 만드는 토큰이라면 붙여 둘 만하다고 봅니다.
서비스끼리 믿는 방식의 네 단계
"보통 이렇게 운영하나"에 대한 답을 하자면, 이 규모에서는 흔한 방식이지만 업계가 올라가는 길도 분명히 정해져 있습니다. 서비스끼리 서로를 믿는 방식은 대략 네 단계로 나뉜다고 봅니다.
| 단계 | 서비스끼리 인증 | 비밀이 사는 곳 |
|---|---|---|
| 1. 네트워크를 믿는다 | 없음. 같은 망 안에 있으면 우리 편 | 서버의 env 파일 |
| 2. 고정 키 | API 키나 공유 토큰을 헤더에 실음 | 비밀 관리 도구, CI, 호스팅 업체에서 주입 |
| 3. 짧게 사는 신원 | 몇 분에서 몇 시간짜리 토큰을 자동 발급(OIDC, 클라우드 IAM) | 사람이 키를 만지지 않음 |
| 4. 모든 연결을 증명 | 서비스마다 인증서를 들고 mTLS로 서로 확인 | 인증서가 자동으로 교체됨 |
예로 든 쇼핑몰은 2단계에 있습니다. 실로 이어 놓은 느낌이 드는 것은 2단계의 본질입니다. 고정 키는 양쪽이 같은 비밀을 나눠 든 것이고, 그 비밀은 누군가 바꾸기 전까지 계속 유효합니다.
3단계는 그 실을 저절로 끊어졌다 다시 이어지는 실로 바꿉니다. GitHub Actions가 클라우드에 배포할 때 저장된 키 대신 OIDC 토큰을 쓰게 하는 것이 대표적입니다(GitHub 문서). 작업이 도는 동안만 유효한 토큰이라 훔쳐 가도 곧 쓸모가 없어집니다.
4단계는 네트워크 위치를 아예 믿지 않는 쪽입니다. 구글이 사내망 경계를 걷어 내고 모든 접근을 기기와 사용자 신원으로 판단하게 바꾼 BeyondCorp가 이 흐름을 연 사례로 자주 꼽힙니다. NIST는 이를 SP 800-207 제로 트러스트 아키텍처로 정리했습니다. 서비스끼리의 신원을 표준으로 다루는 SPIFFE 같은 프로젝트도 이 단계에 속합니다.
1단계에서 2단계로는 반드시 올라가야 한다고 봅니다. "같은 망 안이니 안전하다"는 가정은 망 안의 무엇 하나가 뚫리는 순간 무너지고, 침입이 옆으로 번지는 길도 대개 그쪽입니다. 반대로 3단계와 4단계는 열 명 규모 회사의 서비스 몇 개에는 과하다고 봅니다. 서비스 메시를 들이는 순간 지키는 이득보다 관리하는 일이 커집니다.
고정 키 단계를 제대로 쓰는 조건
그래서 작은 팀의 현실적인 목표는 위 단계로 서둘러 가는 것이 아니라 2단계를 제대로 쓰는 것입니다. 제가 보는 조건은 넷입니다.
첫째는 범위입니다. 키 하나가 할 수 있는 일이 좁아야 합니다. 주문 관리 화면이 재고를 읽기만 한다면 재고 토큰도 읽기만 열어야 하고, 쓰기용 토큰을 같이 쓰면 안 됩니다. 외부 API 키라면 사용처별로 따로 발급받고 호출 상한을 걸어 둡니다.
둘째는 정본입니다. 정본은 한 곳이고 나머지는 거기서 내려받은 사본이어야 합니다. 급할 때는 배포처에 먼저 넣고 비밀 관리 도구에 나중에 옮겨 적기 쉬운데, 그러면 두 곳 중 무엇이 맞는지 판단할 근거가 사라집니다. 대조 도구가 수정 시각만 비교한다면 더 헷갈립니다. 나중에 옮겨 적은 쪽이 더 최신으로 보이기 때문입니다.
셋째는 지도입니다. 키마다 어디에 사본이 있고, 갈 때 어떤 순서로 바꾸고, 새면 무엇이 보이는지가 문서 한 장에 적혀 있어야 합니다.
넷째는 감지입니다. 틀린 토큰으로 들어온 요청을 세어 두면, 키가 샌 뒤 누군가 시험해 보는 순간이 숫자로 드러납니다.
3단계로 가는 가장 가까운 길
이미 Cloudflare Access 같은 접근 관리 도구를 쓰고 있다면 3단계에 가까운 선택지가 손에 있습니다. Access에는 사람 대신 서비스가 통과하는 서비스 토큰이 있어서, 키를 Cloudflare가 관리하고, 대시보드에서 끊고, 만료일을 걸 수 있습니다. 서비스끼리 붙는 길을 Access를 지나도록 바꿔야 하므로 작은 공사는 아니지만, 2단계의 조건을 갖춘 다음 단계로는 가장 부담이 적은 편입니다.
여기서부터는 회사마다 판단이 갈립니다. 다만 순서는 분명하다고 봅니다. 키를 몇 개 쓰는지보다, 어느 키가 어디로 이어지는지 모르는 상태가 더 위험합니다. 키 지도부터 그리는 것이 먼저입니다.
함께 읽기
- TOTP와 패스키 2단계 인증: 관리자 로그인에 직접 붙여 본 기록비밀번호 하나로 지키던 관리자 로그인에 TOTP, 신뢰 브라우저, 복구 코드, 패스키를 붙였습니다. 네 수단은 막는 공격이 다르고, 서로 어떻게 맞물리게 할지 정할 것도 생각보다 많았습니다. 이 글은 구현하면서 정한 기준과 중간에 바로잡은 설계의 기록입니다.
- 텔레그램 알림 봇 만들기: BotFather 토큰부터 chat id까지예약해 둔 작업은 사람이 없는 시각에 서버가 혼자 처리합니다. 잘 끝나면 다행이지만, 중간에 막히면 그 작업은 조용히 대기 상태로 돌아갑니다. 까닭은 기록에 남는데, 기록을 열어 보기 전에는 아무도 모릅니다. 그래서 고객사 업무 시스템의 예약 작업에 텔레그램 알림을 붙였고, 그 알림을 받을 봇을 새로 만들기로 했습니다.
- 모니터링 서비스 비교: Better Stack부터 Datadog까지 7곳Better Stack 첫 화면에는 표가 하나 있습니다. 한 달에 트레이스·로그·지표를 각각 1TB씩 보낼 때 Datadog은 약 $55,574, Better Stack은 $687이라고 적혀 있습니다. 표 아래 각주는 이 숫자가 추정치이며 연 결제, 유럽 데이터 위치, 응답자 1명, Tera 번들, 평균 이벤트 크기 1…
- 업무 시스템 보안 단계적 도입: 1단계 기준선과 나중에 붙일 것첫 고객의 업무 시스템을 만들기 시작하면 보안 항목 목록이 금세 길어집니다. MFA, 세션, 감사 로그, 백업, 접근 통제, SSO, 기기 인증, 로그 중앙화, 전용 네트워크. 목록을 다 채우고 시작하려 하면 업무 기능을 만들기 전에 인프라 설정으로 몇 주가 지나갑니다.
- DUOLABS CP 기능 탐구 3: 리드에서 수주와 계약까지 잇는 영업·매출 관리영업 정보가 명함, 메신저, 견적 파일, 담당자의 머릿속에 나뉘면 ‘누구에게 무엇을 약속했는지’부터 다시 확인해야 합니다. DUOLABS CP의 영업·매출 영역은 잠재 고객을 발견한 순간부터 견적, 수주, 계약 갱신까지 이어지는 흐름을 보여 줍니다.