[Day 18] API 키 관리 best practice + .env.example의 역할

짱효·2026년 5월 6일

프론트엔드 기초 다시 쌓기 챌린지 18일차.
Part 2 "환경변수·시크릿·보안"의 세 번째 수업.

Day 16에서 NEXTPUBLIC 규칙을, Day 17에서 .env 관리법을 배웠다면,
오늘은 API 키를 체계적으로 관리하는 실전 패턴을 배웠다.


🍳 오늘의 비유: "납품업체 카드가 두 종류다"

납품업체에서 카드를 두 장 줬다.

🔓 주문 카드 (공개 키 / Publishable Key)
   - 직원 누구나 써도 됨
   - 잃어버려도 큰 문제 없음 (주문만 가능하니까)

🔒 정산 카드 (시크릿 키 / Secret Key)
   - 사장님만 갖고 있어야 함
   - 잃어버리면 누가 돈을 빼갈 수 있음!

API 키도 똑같다. 대부분의 서비스가 공개 키와 시크릿 키를 한 쌍으로 준다.


🔑 공개 키 vs 시크릿 키

실제 서비스 예시

# Stripe (결제)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123   # 🔓 공개 키
STRIPE_SECRET_KEY=sk_live_xyz789                      # 🔒 시크릿 키

# 카페24 API
NEXT_PUBLIC_CAFE24_CLIENT_ID=app_abc123    # 🔓 클라이언트 ID
CAFE24_CLIENT_SECRET=secret_xyz789          # 🔒 클라이언트 시크릿

# Google Maps
NEXT_PUBLIC_GOOGLE_MAPS_KEY=AIza_abc123    # 🔓 브라우저에서 지도 띄울 때
GOOGLE_MAPS_SERVER_KEY=AIza_xyz789          # 🔒 서버에서 좌표 변환할 때

이름으로 구분하는 법

🔓 공개 가능 (이런 이름이면 공개 OK)
   - publishable, public, client_id
   - pk_ 로 시작

🔒 비밀 (이런 이름이면 비밀!)
   - secret, private, server
   - sk_ 로 시작

판단이 안 되면 시크릿으로 취급한다. 안전한 쪽으로 가는 게 정답.


🧪 테스트 키 vs 라이브 키

거의 모든 API 서비스가 테스트 키와 라이브 키를 따로 준다:

테스트 키 (test/sandbox):
  - 실제 결제 안 됨, 개발할 때 사용
  - sk_test_..., pk_test_...

라이브 키 (live/production):
  - 실제 결제 됨, 실서비스에서 사용
  - sk_live_..., pk_live_...
# .env.development (개발용 - 테스트 키)
STRIPE_SECRET_KEY=sk_test_개발용키

# .env.production (실서비스 - 라이브 키)
STRIPE_SECRET_KEY=sk_live_실제키

⚠️ 개발할 때 라이브 키를 쓰면?

인증 에러가 나는 게 아니라 정상 작동해버리는 게 문제다!

테스트 키로 결제 → 가짜 결제 (돈 안 빠져나감) ✅
라이브 키로 결제 → 진짜 결제 (돈이 빠져나감!) 😱

개발하면서 테스트 결제를 10번 했는데 라이브 키였다면?
진짜로 10번 결제된 것이다. 고객 카드에서 실제로 돈이 빠져나간다.

레스토랑 비유: 연습 주문이라고 생각하고 10번 주문했는데,
진짜 납품처(라이브 키)로 보내서 실제 재료가 10번 배달되고 비용이 청구된 것.

그래서 .env.development에는 반드시 테스트 키를,
.env.production에만 라이브 키를 넣어야 한다.


⭐ API 키 관리 Best Practice 5가지

1. 키 이름에 용도를 명확하게

# ❌ 나쁜 예: 뭐가 뭔지 모름
KEY1=abc123
KEY2=xyz789

# ✅ 좋은 예: 이름만 봐도 알 수 있음
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_abc123
STRIPE_SECRET_KEY=sk_live_xyz789

2. 환경별로 키를 분리

# .env.development → 테스트 키
# .env.production  → 라이브 키

3. 키에 권한 제한 걸기

API 서비스 대시보드에서 키의 권한을 최소한으로 설정한다.

❌ 모든 권한이 열린 키 (읽기, 쓰기, 삭제, 관리자 전부)
✅ 필요한 권한만 열린 키 (읽기 전용 등)

레스토랑 비유: 직원 카드에 "식재료 주문만 가능, 한도 50만 원" 제한을 거는 것.

4. 키를 주기적으로 교체 (Key Rotation)

3~6개월마다:
1. 새 키 발급
2. .env, GitHub Secrets, 서버에 새 키 적용
3. 정상 작동 확인
4. 이전 키 삭제/무효화

키가 언제 유출됐는지 모를 수 있으니 주기적으로 바꾸면 피해 기간을 줄일 수 있다.

5. 키를 코드에 절대 하드코딩하지 않기

// ❌ 절대 이렇게 하면 안 됨!
const stripe = new Stripe("sk_live_xyz789_진짜키");

// ❌ 주석에도 쓰면 안 됨!
// API 키: sk_live_xyz789 ← git에 올라감!

// ✅ 항상 환경변수에서 가져오기
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

📄 .env.example 실전 가이드

좋은 .env.example 작성법

# .env.example
# 이 파일을 .env.local로 복사한 뒤 실제 값을 입력하세요.
# cp .env.example .env.local

# ============================================
# 🔓 공개 키 (NEXT_PUBLIC_)
# ============================================

# Stripe 결제 (https://dashboard.stripe.com/apikeys)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_여기에입력

# Google Maps (https://console.cloud.google.com)
NEXT_PUBLIC_GOOGLE_MAPS_KEY=여기에입력

# 사이트 기본 설정
NEXT_PUBLIC_SITE_URL=http://localhost:4040

# ============================================
# 🔒 시크릿 키 (서버 전용)
# ============================================

# Stripe 결제 시크릿
STRIPE_SECRET_KEY=sk_test_여기에입력

# 데이터베이스
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

# 카페24 API
CAFE24_CLIENT_ID=여기에입력
CAFE24_CLIENT_SECRET=여기에입력

# ============================================
# 📝 참고사항
# ============================================
# - 개발 시에는 test 키 사용 (sk_test_, pk_test_)
# - 프로덕션 키는 팀 리더에게 문의
# - 절대 이 파일에 실제 키를 입력하지 마세요!

포인트 정리

✅ 공개 키와 시크릿 키를 구분해서 정리
✅ 각 키를 어디서 발급받는지 URL 표시
✅ 설명 주석 달기
✅ 복사 명령어 안내
✅ "여기에입력" 같은 플레이스홀더 사용
❌ 실제 키 값을 절대 넣지 않기!

🔄 키 하나의 일생: 전체 흐름

[1. 키 발급]
API 서비스 대시보드에서 테스트 키 + 라이브 키 한 쌍 발급

[2. 키 저장 - 3곳에]
내 컴퓨터: .env.local에 테스트 키
서버: .env에 라이브 키
CI/CD: GitHub Secrets에 라이브 키

[3. 키 사용]
공개 키 → NEXT_PUBLIC_ 붙여서 브라우저에서 사용
시크릿 키 → 서버 사이드 코드에서만 사용

[4. 키 가이드]
.env.example에 "이런 키가 필요해요" 기록 → git에 올려서 팀 공유

[5. 키 교체 (3~6개월마다)]
새 키 발급 → 3곳 업데이트 → 이전 키 삭제

[6. 키 유출 시]
키 즉시 무효화 → 새 키 발급 → 3곳 업데이트

🔗 Day 16~18 연결: 환경변수 3일 총정리

Day 16: NEXT_PUBLIC_ 붙으면 브라우저 노출, 안 붙으면 서버 전용
        → 빌드할 때 JS 파일에 값이 직접 박히기 때문

Day 17: 환경별 .env 파일 + 유출 시 키 무효화가 1순위
        → .env.local > .env.development/.production > .env

Day 18: 공개 키 vs 시크릿 키 구분 + 키 관리 5가지 원칙
        → 테스트 키와 라이브 키 분리, 하드코딩 절대 금지

🍳 레스토랑 비유 업데이트

레스토랑서버
주문 카드 (직원 누구나 사용)공개 키 (Publishable Key)
정산 카드 (사장님만 보관)시크릿 키 (Secret Key)
연습용 납품처테스트 키 (sktest, pktest)
진짜 납품처라이브 키 (sklive, pklive)
카드에 "주문용" 라벨키 이름에 용도 명시
카드 한도 제한키 권한 최소한으로 설정
자물쇠 주기적 교체Key Rotation (3~6개월)
카드 번호를 메뉴판에 적음키를 코드에 하드코딩 = 대참사

🎯 오늘 배운 것 최종 정리

  1. 공개 키 vs 시크릿 키: publishable/pk = 공개 OK, secret/sk = 비밀!
  2. 판단이 안 되면 시크릿으로: 안전한 쪽으로 가는 게 정답
  3. 테스트 키 vs 라이브 키: 개발은 테스트 키, 실서비스는 라이브 키
  4. 라이브 키를 개발에 쓰면: 에러가 나는 게 아니라 진짜 작동해버림 (진짜 결제!)
  5. 키 관리 5가지: 이름 명확히, 환경별 분리, 권한 제한, 주기적 교체, 하드코딩 금지
  6. .env.example: 공개/시크릿 구분, 발급 URL 표시, 플레이스홀더 사용

🧪 이해도 체크

Q1. pk_live_abc123과 sk_live_xyz789 각각 어디서 사용?
→ 정답: pk(공개 키)는 NEXTPUBLIC 붙여서 브라우저에서 사용. sk(시크릿 키)는 서버 사이드 코드에서만 사용.

Q2. 개발할 때 라이브 키를 쓰면?
→ 정답: 인증 에러가 나는 게 아니라 정상 작동해버린다. 테스트 결제가 진짜 결제가 되어 실제로 돈이 빠져나감.

Q3. 새 팀원이 빠르게 프로젝트 세팅하려면?
→ 정답: .env.example이 잘 정리되어 있어야 한다. 어떤 키가 필요한지, 어디서 발급받는지, 공개/시크릿 구분까지 적혀있으면 빠르게 세팅 가능.


💭 회고

환경변수에 대해 3일 연속 배우고 있는데, 매일 "이건 몰랐다" 하는 게 나온다.

오늘 가장 충격이었던 건 라이브 키를 개발에 쓰면 에러가 나는 게 아니라 진짜 작동해버린다는 것.
"테스트 결제가 진짜 결제가 된다"는 말에 소름이 돋았다.
.env.development에 테스트 키, .env.production에 라이브 키를 분리하는 게
단순한 정리가 아니라 사고 예방이었다.

그리고 .env.example 작성법을 배우면서,
"코드만 잘 짜면 되는 게 아니라 팀이 같이 쓸 수 있게 정리하는 것도 개발"이라는 걸 느꼈다.


📚 다음 학습 예고

Day 19: 프론트엔드 보안 기본기 (XSS, CSRF 개념)
해커가 우리 사이트를 어떻게 공격하는지, 어떻게 막는지 배운다.

#프론트엔드 #API키 #환경변수 #보안 #env #2년차개발자 #기초다시쌓기

profile
✨🌏확장해 나가는 프론트엔드 개발자입니다✏️

0개의 댓글