읽기 전
읽고 나면
이런 화면, 보신 적 있으시죠
설명은 잠깐 미룰게요. 이 화면에서 딱 하나만 보고 가시면 됩니다.
열쇠가 두 개인데, 위는 글자가 다 보이고 아래는 점으로 가려져 있어요.
같은 API Keys 메뉴 안입니다. 그런데 한쪽만 가렸어요.
이 절, 어떠셨어요?
최근 의견
집계 전
여기서도, 여기서도, 여기서도 만납니다
한 서비스만의 사정이 아니에요. 앞으로 붙이실 것들을 미리 보여드릴게요.
결제를 붙일 때 (Stripe)
결제를 붙일 때 (토스페이먼츠)
토스페이먼츠는 개발자센터 API 키 메뉴에서 받습니다. 이름은 클라이언트 키와 시크릿 키 둘이에요.
"시크릿 키는 외부에 노출되면 안 돼요. GitHub, 클라이언트 코드 등 외부에 보이는 곳에 추가하지 마세요."
로그인을 붙일 때 (카카오)
카카오는 [앱] > [플랫폼 키] 에서 셋, [앱] > [어드민 키] 에서 하나를 더 줍니다.
| 키 이름 | 어디서 쓰나 |
|---|---|
| JavaScript 키 | 웹 화면에서 부를 때. 웹에 나갑니다 |
| 네이티브 앱 키 | 앱 안에서 부를 때. 앱에 들어갑니다 |
| REST API 키 | 서버에서 부를 때 |
| 어드민 키 | 관리자 권한. 절대 밖으로 못 나갑니다 |
"어드민 키를 사용하는 API는 서버에서만 호출해야 합니다. 소스 코드 내에는 저장하지 않도록 주의합니다."
네 서비스가 이름을 다 다르게 붙였는데, 나누는 자리는 똑같아요. 한쪽은 나가도 되고, 한쪽은 나가면 안 됩니다.
이런 생각, 들지 않으세요
"영어로 뭐라고 써있긴 한데 무슨 뜻이지. 그냥 화면 통째로 복사해서 에이전트한테 주면 알아서 해주는 거 아닌가?"
맞아요. 그렇게 해도 오늘은 잘 돌아갑니다.
그게 문제예요.
에이전트는 시키는 대로 합니다. 어느 쪽을 어디에 둘지는 안 물어봐요.
이 절, 어떠셨어요?
최근 의견
집계 전
모르고 넘어가면 이런 일이 납니다

첫째. 내 컴퓨터에선 되는데, 배포하면 죽습니다.
몇 시간을 붙들다가 결국 검색창에 그대로 붙여넣게 되는 그 한 줄이에요.
Error: Missing required environment variable: SUPABASE_SECRET_KEY
멀쩡히 돌던 화면이 인터넷에 올리는 순간 이 글자만 남깁니다. 버그가 아니에요. 열쇠를 올바르게 감춘 결과입니다.
둘째. 청구서가 옵니다.
공개 저장소를 훑으면서 열쇠처럼 생긴 문자열만 골라내는 프로그램이 24시간 돌아요.
2025년 한 해에만, 공개 저장소에 새로 올라간 열쇠가 2,865만 건입니다. 한 조사팀은 일부러 열쇠를 올려놓고 시계를 재봤어요. 첫 악용까지 1분이 걸렸습니다. 그리고 2022년에 새어 나간 열쇠 중 64%가 지금도 살아서 쓸 수 있는 상태입니다.
숫자 출처: GitGuardian State of Secrets Sprawl 2026, Comparitech 허니팟 실험. 주소는 맨 아래 공부자료에 있어요.
내 카드로 남의 서버가 돈다는 뜻이에요. 보통은 청구서에서 압니다.
무섭게 들리시죠. 한 번만 배워두면 다음부터는 매번 똑같아요. 오늘 그 한 번을 끝냅시다.
이 화면, 실제로 보신 적 있으세요?
이 절, 어떠셨어요?
최근 의견
집계 전
먼저 이름부터 정리할게요
여기가 제일 많이 헷갈리는 자리이고, 대부분의 설명글이 여기서 낱말을 섞어 씁니다.
API 키 는 하나짜리 이름이 아니라 상위 이름입니다. 그 아래에 성격이 다른 것들이 살아요.
Stripe 공식 문서가 이 셋을 한 표로 정리해 뒀어요. "밖에 내놔도 되나" 칸이 딱 붙어 있습니다.
| Stripe 키 이름 | 접두사 | Safe to expose |
|---|---|---|
| Publishable API key | pk_ | Yes |
| Restricted API key | rk_ | No |
| Secret API key | sk_ | No |
어렵게 느껴지시죠. 어려운 게 아니라 생소한 거예요. 처음 보는 단어가 세 개 붙어 있으면 누구나 그렇습니다.
이제 집 하나로 바꿔서 볼게요. 이 글이 끝날 때까지 이 집에서 안 나갑니다.
| 집에서 | 코딩에서 | 밖에 보여도 되나 |
|---|---|---|
| 집 주소와 문패 | 퍼블리셔블 키(publishable key) | 네. 알려주라고 만든 겁니다 |
| 현관 열쇠 | 시크릿 키(secret key) | 아니요. 이걸 가지면 그냥 들어옵니다 |
| 집 설계도 | 에이전트가 짠 코드(소스 코드) | 네. 보라고 만들어서 깃허브에 올립니다 |
| 설계도를 올려둔 창고 | 코드 저장소(깃허브) | 네. 남이 복사해 갑니다 |
주소를 안다고 남이 우리 집에 들어오지는 못해요. 사고는 설계도를 창고에 올릴 때 납니다. 그 여백에 현관 열쇠를 테이프로 붙여 놓은 채로요.
이 열쇠는 좀 이상하게 생겼어요
보통 열쇠는 문에 꽂았다 뽑습니다. 열쇠 자체가 상대에게 건너가지는 않아요.
그런데 시크릿 키는 요청할 때마다 문자열 자체를 통째로 실어 보냅니다. 그래서 그 문자열을 본 사람은 그 순간부터 여러분입니다. 서비스 입장에서 진짜 여러분이에요.
비밀번호와도 다릅니다. 비밀번호는 여러 번 틀리면 잠겨요. 시크릿 키는 안 잠깁니다. 맞으면 그냥 통과입니다.
그래서 되돌릴 방법이 하나뿐이에요. 폐기하고 새로 받는 것.
이 절, 어떠셨어요?
최근 의견
집계 전
그럼 공개 키·개인 키랑은 무슨 사이인가요

검색하다 공개 키(public key) 와 개인 키(private key) 를 보셨을 거예요. 이름이 닮아서 같은 이야기 같죠.
먼저 답부터 드릴게요.
두 낱말은 사는 층이 다릅니다.
층이 둘입니다.
| 층 | 사는 곳 | 낱말 | 정체 |
|---|---|---|---|
| 컴퓨터 과학 층 | 교과서, 암호학 | 공개 키 / 개인 키 | 수학으로 짝지어진 쌍. 한쪽으로 잠그면 다른 쪽으로만 열립니다 |
| 제품 층 | 발급 화면, 설정 메뉴 | API 키 / 퍼블리셔블 키 / 시크릿 키 | 서비스가 주는 문자열. 그냥 아주 긴 비밀번호예요 |
여러분이 오늘 만난 것은 아래 칸입니다. 발급 화면에서 복사한 그 글자요.
왜 이렇게까지 헷갈릴까요. 번역 탓이 큽니다.
영어는 private key(쌍의 한쪽)와 secret key(문자열)로 낱말이 갈려 있어요. 그런데 한국어에서는 둘 다 "비밀키" 로 번역돼 왔습니다. 같은 말로 불리니 같은 물건처럼 보이는 거예요.
그래서 이 글은 개인 키(쌍의 한쪽)와 시크릿 키(문자열)로 낱말을 갈라 씁니다.
예외가 하나 있어요. 그런데 이것도 같은 틀로 풀립니다
애플의 App Store Connect API 는 문자열이 아니라 파일을 하나 내려줍니다. 애플 공식 문서의 표현이 이거예요.
"An API key has two parts: a public portion that Apple keeps, and a private key that you download." "Apple doesn't keep a copy of the private key."
🔑 보물 상자 하나. 컴퓨터 과학 층은 어디서 왔나요 (안 열어도 됩니다)
옛날에는 열쇠가 하나였어요.
잠그는 열쇠와 여는 열쇠가 같았습니다. 현관 열쇠처럼요. 이걸 대칭 키라고 부릅니다. 빠르고 단순해서 지금도 큰 파일을 나를 때는 이 방식을 씁니다.
그런데 딱 하나가 안 풀렸어요. 그 열쇠를 상대에게 어떻게 전달하죠? 보내는 길에서 뺏기면 끝입니다.
1976년에 나온 답이 열쇠를 둘로 쪼개는 것이었어요.
잠그는 열쇠와 여는 열쇠를 수학적으로 짝지어서 아예 다르게 만듭니다. 이게 비대칭 키이고, 그 한 쌍이 공개 키와 개인 키예요.
핵심은 이겁니다. 한쪽으로 잠그면 오직 다른 쪽으로만 열립니다. 그래서 잠그는 쪽을 만천하에 뿌려도 안전해요. 전달 문제가 통째로 사라집니다.
"잠그는 키를 뿌린다고요? 그럼 개인 키도 위험한 거 아닌가요."
좋은 되물음이에요. 이 질문이 나온다는 건 제대로 읽고 계시다는 뜻입니다.
개인 키는 뿌리는 게 아니에요. 뿌리는 것은 공개 키 한쪽뿐이고, 개인 키는 여러분 컴퓨터 밖으로 한 번도 안 나갑니다.
그래서 시크릿 키와 정반대입니다. 시크릿 키는 요청할 때마다 값이 나가고, 개인 키는 평생 안 나가요. 나가는 건 그것으로 찍은 도장 자국뿐입니다. 그 도장을 서명이라고 부릅니다.
애플이 쓰는 방식이 이거예요.
애플이 파일로 주는 것이 바로 이 개인 키입니다. 여러분은 그 키로 요청에 도장을 찍어 보내고, 애플은 자기가 갖고 있는 공개 쪽으로 그 도장을 확인해요. 키 값 자체는 한 번도 인터넷을 건너가지 않습니다.
그래서 애플 문서가 "Apple doesn't keep a copy of the private key" 라고 적어둔 거예요. 애플조차 사본이 없어야 이 구조가 성립하니까요.
로그인이나 결제를 깊게 파고들면 다시 만납니다. 그때 서명만 따로 판 글로 이어드릴게요.
여기까지 한 장으로 묶고 갈게요
이 절, 어떠셨어요?
최근 의견
집계 전
에이전트한테 무엇을 시키면 되나요
여기서부터가 오늘의 본론입니다. 여러분은 편집기를 열지 않아요. 시킬 겁니다.
딱 한 가지만 알면 돼요. 설계도(코드)는 창고에 올리고 열쇠는 따로 둡니다. 그 따로 두는 자리를 부르는 표준 용어가 환경변수(environment variable) 예요. 자리는 셋입니다.
| 자리 | 언제 필요한가 | 어디에 있나 |
|---|---|---|
| 내 노트북 | 지금 만들면서 돌릴 때 | 프로젝트 폴더의 .env 파일 |
| 배포 서비스 | 인터넷에 올릴 때 | Settings > Environment Variables |
| 자동 배포 | 올릴 때마다 알아서 나가게 할 때 | Settings > Secrets and variables > Actions |
1단계. 키를 방금 받았다면, 이렇게 시키세요
아래 글을 그대로 복사해서 에이전트한테 붙여넣으시면 됩니다. 읽고 이해하실 필요 없어요. 넘기는 것이 목적입니다.
방금 [서비스 이름]에서 시크릿 키를 발급받았어. 이 키를 코드에 직접 쓰지 말고 환경변수로 빼줘. .env 를 만들고, .gitignore 에 .env 가 있는지 확인해서 없으면 추가하고, .env.example 은 값을 비운 채 이름만 남겨줘. 키 값 자체는 네가 만들지 말고, 내가 붙여넣을 자리만 만들어줘.
마지막 줄이 핵심이에요. 에이전트한테 키 값을 대화창에 부르게 하면 그 대화가 곧 유출 경로가 됩니다.
2단계. 배포했는데 죽었다면, 이렇게 시키세요
아까 그 에러의 답이 여기 있어요. .env 를 창고에 안 올렸으니, 창고에서 코드를 받아가는 배포 서비스에도 안 갔습니다. 없는 걸 찾으니까 죽는 거예요. 버그가 아니라 순서 문제입니다.
로컬에서는 되는데 배포하면 environment variable 관련 에러가 나. 이 프로젝트가 필요로 하는 환경변수 이름을 전부 찾아서 목록으로 뽑아줘. 각각이 서버 전용인지 브라우저에 나가도 되는지도 표시해줘. 값은 알려주지 말고 이름만.
목록을 받으면 그 이름들을 배포 서비스의 Environment Variables 화면에 직접 넣으시면 됩니다. 이 한 번은 사람이 합니다. 값을 아는 사람이 여러분뿐이니까요.
3단계. 지금 안전한지 점검하려면, 이렇게 시키세요
이 저장소 전체에서 하드코딩된 비밀값이 있는지 훑어줘. sk-, sb_secret_, test_sk_, live_sk_ 로 시작하는 문자열, password 나 token 이나 secret 이 들어간 변수에 값이 직접 박힌 곳. 찾으면 파일과 줄 번호만 알려줘. 값 자체는 출력하지 마.
"값 자체는 출력하지 마" 를 꼭 붙이세요. 안 붙이면 점검 결과에 열쇠가 그대로 찍힙니다.
맨 위의 그 빨간 줄, 이제 읽히시죠
Never put one in a browser, a shipped application, or source control.
| 원문 | 무슨 뜻이었나 |
|---|---|
| in a browser | 화면 쪽 코드에 넣지 마라. 누구나 열어볼 수 있다 |
| a shipped application | 내보낸 앱 안에 넣지 마라. 뜯어보면 나온다 |
| source control | 코드 저장소에 올리지 마라. 여기가 사고의 90%다 |
셋 다 "남이 볼 수 있는 곳" 이에요. 그래서 답이 하나로 모입니다. 시크릿 키는 코드 밖에 둔다.
여러분 프로젝트의 시크릿 키는 지금 어디 있나요?
이 절, 어떠셨어요?
최근 의견
집계 전
이미 올려버렸다면

여기가 이 글에서 제일 중요합니다. 대부분 여기서 순서를 틀려요.
키를 올린 걸 뒤늦게 알면 보통 이렇게 시킵니다. ".env 지우고 커밋해줘."
새로고침하면 파일이 없어요. 해결된 것처럼 보입니다. "이제 된 거 아니에요?"
정말 지워졌을까요.
안 지워집니다.
깃은 파일의 지금 모습을 저장하지 않아요. 변경 하나하나를 순서대로 쌓아 둡니다.
오늘 지운 것은 "지웠다" 는 기록이 한 줄 더 붙은 거예요. 어제 "추가했다" 는 기록은 그대로 있습니다. 옛날 판본을 열면 열쇠가 그 자리에 그대로 있어요.
파일을 지우는 건 열쇠를 회수하는 게 아닙니다. 열쇠가 있던 자리를 치우는 거예요.
그래서 순서가 이렇게 됩니다. 1번은 에이전트가 못 해요. 여러분이 발급 화면을 열어야 합니다.
- 발급처에서 그 키를 폐기하고 새로 받으세요. 자물쇠 자체를 바꾸는 일이에요. 이걸 안 하면 나머지는 전부 의미가 없습니다
- 새 키를
.env에 넣고,.gitignore에.env가 있는지 확인하게 시키세요 - 배포 서비스 설정과 자동 배포 보관함의 값도 갈아 끼우세요
- 옛날 기록 정리는 그다음이고, 급하지 않아요
4번은 지금 몰라도 됩니다. 명령이 위험해서 반쯤 아는 상태로 시키면 다른 게 깨져요. 자물쇠를 바꿨으면 옛 열쇠는 이미 쇳조각입니다.
예상 밖의 사실 하나. 깃허브에 Claude 키를 흘리면 Anthropic 이 그걸 알아채고 알아서 꺼버립니다. 공식 문서에 이렇게 적혀 있어요.
"Anthropic automatically deactivates the exposed API key."
고마운 일이지만 이걸 믿고 있으면 안 됩니다. 모든 서비스가 해주는 게 아니고, 알아채기 전 1분이 이미 지나가니까요.
꿀팁
꿀팁 #1
이 절, 어떠셨어요?
최근 의견
집계 전
미리 답하고 갈게요
여기까지 읽으면서 속으로 반박하신 게 있을 거예요. 먼저 꺼내서 답할게요.
Q. 그래서 "API 키" 랑 "시크릿 키" 는 다른 건가요?
API 키 가 상위 이름이고 시크릿 키 가 그 아래 하나예요. 그러니 "API 키를 노출하지 마세요" 라는 문장은 정확히는 시크릿 키 이야기입니다. 같은 묶음의 퍼블리셔블 키는 노출해도 되니까요.
Q. 아직 깃허브에 안 올렸는데요. 내 컴퓨터에서만 돌리는데도 필요한가요? 지금은 사고가 안 납니다. 문제는 습관이 그때 붙는다는 거예요. 키를 박아두고 잘 돌아가는 걸 한 달 보고 나면 그 상태가 정상으로 느껴집니다. 처음 올리는 날은 예고 없이 옵니다.
Q. 에이전트한테 코드 봐달라고 붙여넣을 때 키도 같이 들어가는데요?
그것도 유출입니다. 붙여넣기 전에 그 줄만 sk-... 처럼 지우고 넣으세요. 대화창도 파일이나 로그와 똑같은 자리예요.
Q. 퍼블리셔블 키는 진짜 아무한테나 보여도 되나요? 네. 다만 "보여도 된다" 는 것이지 "아무거나 할 수 있다" 는 뜻은 아니에요. 그 키로 무엇까지 되는지는 서비스 쪽 설정으로 따로 잠급니다. 그 이야기는 데이터베이스 글에서 만나요.
그런데
ZERO ONE IT 만드는 사람도 이걸 다 알고 나서 한 번 더 틀렸습니다.
키를 코드에 안 넣는 것까지는 지켰어요. 대신 에러가 나면 접속 정보를 통째로 화면에 찍게 시켜 뒀습니다.
열쇠는 파일에 숨겨 뒀는데 화면에는 나오고 있었어요. 캡처 한 장이면 끝나는 상태였습니다.
열쇠 관리는 파일 하나의 문제가 아니에요. 이 값이 어디까지 흘러가는지를 보는 감각입니다.
파일, 로그, 캡처, 에이전트 대화창이 전부 그 자리예요.
오늘 이런 걸 배우셨어요
- 손에 쥔 것. 한 화면에 뜬 두 키 중 어느 쪽이 나가도 되는지 여러분이 직접 구분합니다
- 이름이 정리된 것.
API 키는 상위 이름이고, 그 아래 퍼블리셔블 키·제한 키·시크릿 키가 삽니다. 가려야 하는 건 시크릿 키예요 - 안 헷갈리게 된 것. API 키는 공개 키가 아닙니다. 제품 층과 컴퓨터 과학 층은 다른 층이고, 애플은 이름표가 겹치는 예외입니다
- 오늘부터 달라지는 행동. 새 프로젝트는
.gitignore부터 시킵니다. 키가 나갔다 싶으면 파일이 아니라 발급처부터 엽니다
이 정도면 "API 키를 다룰 줄 안다" 고 말하셔도 됩니다. 위 표를 읽을 수 있는 사람은 생각보다 적어요.
지금 바로 해보세요
- 지금 프로젝트의
.gitignore에.env한 줄이 있는지 확인한다 - 위 3단계 점검 지시문을 에이전트한테 실제로 던져본다
- 열쇠를 두는 자리 셋(내 노트북, 배포 서비스, 자동 배포)의 이름을 말해본다
더 볼 것과, 오늘의 화두
이 단어를 아는 사람들은 지금 이걸로 갈립니다.
"열쇠 관리는 처음부터 배워야 하나, 일단 만들고 나서 배워도 되나."
가르치는 사람들끼리도 갈리는 질문이에요. 아래 짝 화두에서 양쪽 근거를 다 펼쳐 뒀습니다.
더 파보고 싶으시면.
- 열쇠 관리는 처음부터 배워야 하나, 일단 만들고 나서 배워도 되나 (짝 화두): 같은 섬의 열린 토론이에요
- Stripe API keys 문서:
API 키아래 셋이 어떻게 갈리는지 "Safe to expose" 칸으로 한눈에 - Supabase API Keys 문서: 맨 위 그 붉은 경고 문구의 원문
- 토스페이먼츠 API 키 문서: 결제에서 클라이언트 키와 시크릿 키가 갈리는 자리
- 카카오 앱 키 문서: 키가 넷으로 갈리는 실제 사례
- 애플 App Store Connect API 키 문서: 이름표가 겹치는 예외가 실제로 어떻게 생겼는지
- GitGuardian State of Secrets Sprawl 2026: 2,865만 건과 64% 의 출처
- Comparitech 허니팟 실험: 올린 뒤 1분에 무슨 일이 벌어지는지
오늘 배운 걸 진짜 내 것으로 만드는 법
읽었으니까 안다고 느끼시죠. 그런데 내일 다시 물으면 절반이 날아가 있어요. 이게 정상입니다.
| 번째 | 무엇을 | 어디서 |
|---|---|---|
| 한 번째 | 읽으면서 배웁니다 | 지금 이 글 |
| 두 번째 | 직접 시켜보면서 배웁니다 | 위 지시문 세 개 |
| 세 번째 | 남한테 설명하면서 배웁니다 | 공부방 댓글 |
세 번째가 제일 세요. 설명하려고 하면 어디를 모르는지 그 자리에서 들통나거든요. 문장이 안 나오는 그 지점이 정확히 구멍입니다.
그러니 오늘은 이 한 줄만 남겨보세요.
"오늘 나는 API 키가 ___라는 걸 알았다."
막혔으면 화면에 뜬 빨간 글씨를 찍어서 그대로 올려도 됩니다. 혼자 붙들면 하루가 가는데, 스크린샷 한 장이면 5분에 끝나는 게 IT섬에는 정말 많아요.
같은 데서 막힌 사람이 보이면 공부방을 하나 만들어 보세요. 이미 있으면 골라서 들어가시면 됩니다.
다음 글에서는
에이전트가 "터미널에서 이걸 실행해 주세요" 라고 할 때, 그 검은 창이 아직 낯설 거예요. IT섬에서 막히는 사람 대부분이 실은 이 창 앞에서 멈춥니다.
다음 글은 터미널 입니다. 같은 IT섬에서 기다릴게요.
이 절, 어떠셨어요?
최근 의견
집계 전