지난 1편에서 앱을 식당에 비유했습니다. 홀(프론트엔드), 주방(백엔드), 창고(DB). 이번에는 그 구조 위에서 바이브 코딩 사고가 가장 잦은 주제를 다룹니다. API, 그리고 API 키입니다. “키를 절대 노출하지 마세요”라는 경고는 다들 한 번쯤 봤을 텐데, 정작 그 키가 뭐고 어디에 있으며 노출되면 무슨 일이 벌어지는지 짚어주는 곳은 드뭅니다. 이번 글에서 한 번에 정리합니다.
API는 주문 창구입니다
API는 Application Programming Interface의 약자인데, 약자 풀이는 잊어도 됩니다. 핵심은 이것입니다. API는 프로그램끼리 일을 시키는 주문 창구입니다.
식당 비유로 돌아가면, 손님은 주방에 들어갈 수 없습니다. 대신 주문 창구에 정해진 양식으로 주문서를 넣습니다. “김치찌개 1개, 덜 맵게.” 그러면 주방이 알아서 만들어 내보내죠. API가 정확히 이 창구입니다. 정해진 주소로 정해진 형식의 요청을 보내면 정해진 형식의 응답이 돌아옵니다.
바이브 코더의 앱에는 API가 두 방향으로 존재합니다.
- 내 앱의 API: 내 프론트엔드가 내 백엔드에 일을 시키는 창구입니다. 1편에서 본
app/api/폴더가 바로 이것입니다. - 남의 API: 내 앱이 다른 회사의 서비스에 일을 시키는 창구입니다. ChatGPT에게 글을 시키고(OpenAI API), 지도를 띄우고(지도 API), 결제를 처리하는(결제 API) 것이 전부 남의 창구에 주문서를 넣는 일입니다.
바이브 코딩으로 만드는 앱은 대부분 이 “남의 API”를 조합해서 굴러갑니다. 그리고 남의 창구에 주문을 넣으려면 반드시 필요한 것이 하나 있습니다.
API 키는 법인카드입니다
남의 API는 공짜 창구가 아닙니다. OpenAI에 요청을 한 번 보낼 때마다 비용이 발생하죠. 그래서 모든 요청에는 “이 주문의 청구서를 누구에게 보낼까”를 밝히는 신분증이 붙습니다. 그게 API 키입니다. sk-proj-...처럼 생긴 길고 무작위한 문자열이요.
API 키의 성질은 법인카드와 똑같습니다.
- 카드를 긁는 사람이 누구든, 청구서는 카드 주인에게 갑니다.
- 카드번호만 알면 쓸 수 있습니다. 얼굴 확인도, 서명 확인도 없습니다.
- 그래서 카드번호를 공개된 곳에 적어두면, 전 세계 누구나 내 돈으로 결제할 수 있게 됩니다.
“키를 숨기라”는 경고가 이렇게 무거운 이유입니다. 키 노출은 비밀번호 노출과 다릅니다. 비밀번호는 바꾸면 그만이지만, 키는 도용당한 시점부터 재발급까지 쓴 요금이 전부 내 청구서에 쌓입니다.
노출되면 실제로 벌어지는 일
“에이, 내 작은 앱의 키를 누가 찾아내겠어”라고 생각하기 쉬운데, 여기가 가장 위험한 착각입니다. 키를 찾는 것은 사람이 아니라 봇입니다.
GitHub 같은 공개 코드 저장소는 봇 수천 개가 24시간 새 코드를 훑고 있습니다. 실수로 키가 포함된 코드를 공개 저장소에 올리면, 보통 몇 분 안에 봇이 수집해갑니다. 수집된 키는 곧바로 무료 AI 호출, 암호화폐 채굴 결제, 스팸 발송 같은 데 쓰입니다. 하룻밤 사이에 수백만 원이 청구됐다는 사고 사례가 커뮤니티에 꾸준히 올라오는 이유입니다.
또 하나의 노출 경로는 1편에서 다룬 그것입니다. 프론트엔드에 키를 넣는 것. 프론트엔드 코드는 사용자 브라우저로 전송되므로, 마우스 오른쪽 버튼 “검사” 한 번이면 누구나 키를 꺼낼 수 있습니다. AI에게 “OpenAI 연동해줘”라고 시켰을 때 AI가 편의상 키를 프론트엔드에 박아버리는 경우가 실제로 있어서, 반드시 직접 확인해야 합니다.
키가 있어야 할 자리
원칙은 1편에서 이미 나왔습니다. 비밀은 백엔드에. 구체적으로는 이렇습니다.
- 키는 프로젝트의
.env파일에 적습니다. 백엔드만 읽는 비밀 값 보관함입니다. .env파일은.gitignore라는 목록에 등록해서 Git이 따라가지 않게 합니다. 그래야 GitHub에 코드를 올려도 키는 내 컴퓨터에만 남습니다. AI가 만들어준 프로젝트는 보통 등록돼 있지만, 한 번은 직접 확인할 가치가 있습니다.- 배포한 앱은 내 컴퓨터의
.env를 못 읽으므로, Vercel 같은 배포 서비스의 대시보드에 있는 “Environment Variables” 메뉴에 키를 따로 등록합니다. 이 이야기는 4편(배포)에서 다시 나옵니다.
Next.js에는 함정이 하나 더 있습니다. 환경변수 이름이 NEXT_PUBLIC_으로 시작하면, 그 값은 프론트엔드까지 전송됩니다. 이름 그대로 public, 공개된다는 뜻입니다. 지도 표시용 키처럼 공개해도 되도록 설계된 키만 여기에 두고, 요금이 나가는 키(OpenAI 등)에는 절대 NEXT_PUBLIC_을 붙이면 안 됩니다. AI가 붙여놨다면 그 자체가 위험 신호입니다.
내 앱 셀프 점검법
지금 바로 확인할 수 있는 3가지입니다.
- 브라우저 검사: 배포된 내 사이트에서 마우스 오른쪽 버튼 → 검사 → 상단 Network 또는 Sources 탭에서
sk-,key,secret같은 단어를 검색해봅니다. 내 비밀 키가 검색되면 노출된 것입니다. - GitHub 검사: 내 저장소가 공개(Public) 상태라면, 저장소 검색창에 키 앞부분을 검색해봅니다. 과거 커밋에 남아 있어도 노출입니다.
- AI에게 감사 요청: “이 프로젝트에서 API 키나 비밀 값이 프론트엔드로 전송되는 곳이 있는지 전부 찾아줘”라고 시킵니다. 만들 때 실수한 AI도 찾을 때는 잘 찾습니다.
이미 노출됐다면
노출된 키는 숨겨도 소용없습니다. 봇이 이미 복사해갔다고 가정해야 합니다. 순서는 이렇습니다.
- 해당 서비스 대시보드에서 그 키를 삭제(폐기) 합니다. 이 순간부터 도용이 멈춥니다.
- 새 키를 발급받아 이번에는
.env와 배포 대시보드에만 넣습니다. - 서비스의 사용량 한도(spending limit) 를 설정합니다. 다음 사고 때 피해 상한선이 됩니다. 이 이야기는 7편(요금 폭탄)에서 자세히 다룹니다.
정리
- API는 프로그램끼리의 주문 창구이고, 내 앱은 남의 API를 조합해 굴러갑니다.
- API 키는 법인카드입니다. 누가 쓰든 청구서는 나에게 옵니다.
- 키는 봇이 몇 분 안에 찾아냅니다. “내 앱은 작으니까”는 방어가 되지 못합니다.
- 키의 자리는
.env(로컬)와 배포 대시보드의 환경변수, 딱 두 곳입니다.NEXT_PUBLIC_이 붙은 요금 키는 위험 신호입니다. - 노출됐다면 숨기지 말고 폐기 → 재발급 → 한도 설정 순서로 대응합니다.
다음 편은 Git입니다. AI가 코드를 다 만들어주는데 왜 다들 Git을 쓰라고 하는지, 그리고 AI가 멀쩡한 앱을 망쳐놨을 때 1분 만에 되돌리는 법을 다룹니다.
