보안 가이드

보안 기본: .env와 API 키의 진짜 위험은 무엇인가

API 키가 유출되면 누군가 내 이름으로 서비스를 쓰고 요금은 내게 청구됩니다. .env와 API 키의 위험을 쉽게 설명하고, 오늘 들일 수 있는 네 가지 습관을 정리했습니다.

게시 2026-06-07 업데이트 2026-10-06 6분 읽기
이 페이지에서

"보안이 중요하다는 말은 계속 듣는데, 대체 어디서 시작하지?" 이것이 인디 개발자를 위한 가장 첫걸음이다. 겁주려는 게 아니라 — 오늘 실천할 수 있는 것만, 순서대로.

왜 시크릿(.env와 API 키)부터인가

실제 사고 대부분은 정교한 공격이 아니라 유출된 시크릿에서 시작된다. 본 사이트가 토대로 삼는 두 사례는 모두 시크릿 유출이었다:

시크릿을 지키면 흔한 사고 대부분을 막는다. 그래서 여기서 시작한다.

.env란 무엇인가 (30초)

.env는 앱의 시크릿 값을 모아둔 파일이다: 데이터베이스 비밀번호, 외부 API 키, 세션을 암호화하는 키. 시크릿들이 한 파일에 함께 있으니, 한 번 유출되면 전부 한꺼번에 노출된다 — 그래서 가장 먼저 지켜야 할 파일이다(→ 용어집: .env란 무엇인가).

시크릿을 두는 곳(.env, 환경 변수, 시크릿 관리 서비스)

시크릿을 두는 곳은 .env만이 아니다. 규모와 용도에 맞춰 고른다.

두는 곳알맞은 경우주의할 점
.env 파일로컬 개발, 작은 서버 한 대Git과 공개 디렉터리 바깥에 둔다
호스팅의 환경 변수 설정(관리 화면에서 입력)운영 환경관리 화면에 접근할 수 있는 사람을 제한하고, 빌드 로그에 값이 남지 않게 한다
CI(자동 테스트·배포)의 시크릿GitHub Actions 같은 자동화CI에서 실행되는 외부 도구도 값을 볼 수 있다. 필요한 권한만 가진 키를 넘긴다
시크릿 관리 서비스여러 사람, 여러 서버읽기 권한을 최소로 두고 정기적으로 교체한다

CI 시크릿에 대해서는 2021년 Codecov 사고가 참고가 된다. CI에서 실행되던 외부 도구가 변조되어, CI 환경 변수에 담긴 시크릿이 빼돌려졌다(→ Codecov 사고).

공개해도 되는 키와 안 되는 키

API 키 중에는 브라우저나 모바일 앱 안에 넣어 배포하도록 만든 것도 있고, 서버 전용인 것도 있다. 브라우저로 보내는 것은 누구나 읽을 수 있다고 생각한다.

예공개해도 되나이유
Stripe 공개 가능 키(pk_로 시작)된다문서에 프런트엔드 코드에 넣어도 된다고 나와 있고, 결제 생성 같은 민감한 작업은 할 수 없다
Stripe 비밀 키(sk_)나 제한 키(rk_)안 된다서버 측 작업을 할 수 있다. 문서는 권한을 좁힌 제한 키를 권한다
NEXT_PUBLIC_이 붙은 Next.js 환경 변수공개된다빌드할 때 값이 브라우저용 JavaScript에 그대로 들어간다
NEXT_PUBLIC_이 없는 Next.js 환경 변수공개되지 않는다(서버 전용)비밀 값은 여기에 둔다

망설여지면 그 서비스의 공식 문서에서 클라이언트 측에서 써도 되는 키인지 확인한다. 나와 있지 않다면 공개해서는 안 되는 키로 다룬다.

API 키 유출이 뜻하는 것

API 키는 "서비스가 호출한 사람을 당신으로 취급하게 하는 문자열" 이다. 잘못된 손에 들어가면 피해가 이렇게 퍼진다.

① API 키가 유출(공개 디렉터리, git 커밋, 또는 취약점 경유)
↓ 시간차를 두고(며칠+)
② 제3자가 외부 서비스를 "당신으로서" 사용
↓
③ 부정 과금 / 데이터 읽기·쓰기 / 사칭
처음엔 조용하다. 시간차를 두고 악용되다 — 어느 날 청구서나 침해로 드러난다.

탈취된 키는 흔히 재판매되어 시간차를 두고 악용된다 — "처음엔 아무 일 없다가, 어느 날 갑작스러운 청구서"가 전형적 패턴이다. 그러니 "알아챈 뒤"는 너무 늦다. 핵심은 애초에 유출하지 않는 것이다.

키가 유출됐을 수 있을 때 할 일

코드에서 키를 지워도 키는 멈추지 않는다. GitGuardian의 2025년 보고서에 따르면, 2022년에 공개 리포지토리에서 유출된 시크릿의 70%가 보고서 시점에도 여전히 유효했다. 다음 순서로 대응한다.

  1. 발급처의 관리 화면에서 키를 폐기하거나 교체한다. 서비스에 유예 기간이 있다면 유출된 키는 "지금 바로" 끝낸다
  2. 운영 환경에 새 키를 설정하고 앱이 동작하는지 확인한다
  3. 발급처의 사용 이력과 청구 내역에서 내가 하지 않은 활동이 없는지 확인한다
  4. 파일과 Git 이력에서 지우는 일은 폐기한 뒤에 해도 된다(지우기만 해서는 이미 사본을 가진 사람을 막지 못한다)

자세한 내용은 GitHub에 공개된 자격 증명 54만 건이 여전히 유효하다에 있다. GitHub는 개인 계정이 공개 리포지토리에 시크릿을 푸시하는 것을 막는 "푸시 보호"를 기본으로 켜 두지만, 모든 종류의 시크릿을 잡아내지는 못한다.

오늘 시작할 네 가지 습관

어려운 것 없다. 이 넷뿐이다.

1

노출하지 마라

.env나 앱 본체를 웹에서 보이는 디렉터리(웹 루트)에 두지 마라. public/ 만 노출하라. 공유 호스팅용 구체적 절차: 이 가이드.

2

커밋하지 마라

.env* 를 .gitignore에 추가하고(!.env.example은 허용); 값이 없는 예시만 공유하라. 한 번 커밋되면 히스토리에서 복원되니, 처음부터 빼두라.

3

유출되면 전부 교체하라

키 하나만이 아니라 — 유출됐을 수 있는 모든 시크릿을 교체하라. 순서: 외부 API / OAuth → 암호화 키 → 메일 → DB. 본 것처럼 행동하라.

4

스스로 점검하라

가끔 /.env가 외부에서 열리지 않는지 확인하라(아래).

자가 점검(자신이 소유한 도메인에 대해서만)

# 본문이 있는 200이면 노출된 것. 403/404면 일단 괜찮음.
curl -sI https://your-domain/.env | head -1
curl -sI https://your-domain/.git/config | head -1

배포할 때마다 이걸 확인하면 배치 실수를 일찍 잡는다.

외부에서 보이는 것 말고도 Git과 빌드 결과물도 확인한다(자기 리포지토리에서 실행).

# .env가 커밋된 적이 있는가? (출력이 있으면 어느 시점에 커밋된 것)
git log --all --oneline -- .env
# 지금 Git이 추적하는 env 계열 파일(.env.example 말고 다른 것이 있으면 확인)
git ls-files | grep -i "env"

브라우저로 키가 나가지 않는지 확인하려면, 빌드 결과물 폴더(Next.js라면 .next/static)에서 키의 앞 몇 글자를 검색한다. 공개 전에 코드를 시크릿 유출 스캐너에 붙여 넣어 확인할 수도 있다(어디에도 전송되지 않는다).

흔한 실수 vs 올바른 첫걸음

흔함

  • "되니까", .env를 public 바로 아래 둠
  • "나중에 지우지", .env를 한 번 커밋함
  • 악용을 본 키 하나만 교체

올바른 첫걸음

  • 앱 본체를 웹 루트 바깥에, public/만 노출
  • 처음부터 .gitignore로 .env 제외
  • 유출되면 환경의 모든 시크릿 교체

다음 단계

여기서부터 다음 주제는 "내 스택의 위험한 기본값"과 "공개된 CVE에 뒤처지지 않는 시스템"이다. 서두르지 말고, 하나씩.

출처

다음으로 읽기

FAQ

Q보안은 어디서부터 시작해야 하나요?
A

시크릿(.env와 API 키)을 유출하지 않는 것부터입니다. 실제 사고 대부분이 거기서 시작됩니다. 노출하지 말고, git에 커밋하지 말고, 유출되면 전부 교체하고, 가끔 스스로 점검하세요 — 그러면 대부분을 막습니다.

QAPI 키가 유출되면 구체적으로 무슨 일이 일어나나요?
A

누군가 외부 서비스에 대해 당신처럼 행동할 수 있습니다. 흔한 결과는 부정 과금(과도한 사용량이 당신에게 청구됨)과 데이터 읽기/쓰기입니다. 탈취된 키는 흔히 재판매되어 시간차를 두고 악용됩니다.

Q.env를 git에 넣어도 되나요?
A

안 됩니다. .env* 를 .gitignore에 추가하고 값이 없는 .env.example만 공유하세요. 한 번 커밋되면, 나중에 지워도 git 히스토리에서 복원될 수 있습니다.

Q.env 파일이란 무엇인가요?
A

앱의 설정, 특히 비밀번호나 API 키 같은 비밀 값을 코드와 분리해 두는 텍스트 파일입니다. 한 줄에 하나씩 이름=값 형식으로 씁니다. Laravel, Next.js, Django를 비롯한 많은 프레임워크가 시작할 때 이 파일을 읽습니다. 시크릿이 한곳에 모여 있으므로 Git과 공개 디렉터리 바깥에 두어야 합니다.

Q.env와 환경 변수는 무엇이 다른가요?
A

환경 변수는 OS나 런타임이 프로그램에 값을 넘기는 구조 자체입니다. .env 파일은 그 값을 파일에 담아 두는 그릇이며, 앱이나 라이브러리가 시작할 때 이를 환경 변수로 읽어 들입니다. 운영 환경에서는 .env 파일을 쓰지 않고, 호스팅 관리 화면이나 시크릿 관리 서비스에서 환경 변수를 넘기는 구성도 많습니다.

Q프런트엔드(브라우저) 코드에 API 키를 넣어도 되나요?
A

공개해도 된다고 명시된 키만 됩니다. 브라우저로 보내는 JavaScript는 누구나 읽을 수 있습니다. 예를 들어 Stripe 문서는 공개 가능 키(pk_로 시작)는 프런트엔드 코드에 넣어도 되지만, 비밀 키(sk_)와 제한 키(rk_)는 노출해서는 안 된다고 설명합니다. Next.js에서는 NEXT_PUBLIC_으로 시작하는 환경 변수가 브라우저 코드에 그대로 들어가므로, 시크릿에는 절대 이 접두사를 붙이지 마세요.