Windows에서 API 키 안전하게 관리하기
Windows에서 API 키
안전하게 관리하기
환경변수, Windows 자격증명 관리자, .env 파일까지 — 개발자라면 매일 쓰는 API 키, 한 번 유출되면 과금 폭탄이나 데이터 침해로 이어집니다. 코드에 키를 절대 하드코딩하지 않는 실전 방법을 정리합니다.
API 키 유출이 왜 위험한가
API 키는 비밀번호와 같습니다. 한 번 유출되면 공격자는 여러분 명의로 API를 마음껏 사용하거나, 민감한 데이터에 접근할 수 있습니다. 특히 GitHub에 실수로 올린 키는 자동화된 봇이 수 초 안에 탐지합니다.
| 유출 경로 | 발생 빈도 | 위험도 |
|---|---|---|
| GitHub 공개 저장소 커밋 | 매우 높음 | 🔴 치명적 |
| 코드 내 하드코딩 | 높음 | 🔴 심각 |
| 로그 파일에 키 출력 | 중간 | 🟡 주의 |
| Slack / 이메일에 공유 | 중간 | 🟡 주의 |
| 환경변수 미설정 → 빈값 처리 실수 | 낮음 | 🟡 주의 |
절대 하면 안 되는 것들
먼저 잘못된 패턴을 명확히 알아야 실수를 피할 수 있습니다.
# ❌ 절대 하면 안 됨 — 코드에 직접 하드코딩
import openai
openai.api_key = "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # 위험!
# ❌ 절대 하면 안 됨 — 설정 파일에 평문 저장 후 Git 커밋
# config.py (Git에 올라가는 파일)
STRIPE_SECRET = "sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" # 위험!
AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE" # 위험!
# ❌ 절대 하면 안 됨 — 로그에 키 출력
print(f"Using API key: {api_key}") # 로그 파일에 노출!
git log나 git diff에서도 보이므로
반드시 키를 즉시 폐기하고 새로 발급받아야 합니다.
방법 1: 환경변수(Environment Variable) 사용
가장 기본적이고 범용적인 방법입니다. 코드에는 키 이름만, 실제 값은 운영체제가 관리합니다. Windows에서는 시스템 환경변수와 사용자 환경변수 두 가지로 나뉩니다.
GUI로 설정하기
OPENAI_API_KEY / 변수 값: 실제 키 입력 후 확인.os.environ.get() 또는 process.env로 가져옵니다. 키 값은 코드 어디에도 없습니다.PowerShell로 설정하기
# 사용자 환경변수로 영구 저장 (재부팅 후에도 유지)
[Environment]::SetEnvironmentVariable(
"OPENAI_API_KEY",
"sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"User"
)
[Environment]::SetEnvironmentVariable(
"STRIPE_SECRET_KEY",
"sk_live_xxxxxxxxxxxxxxxxxxxxxxxx",
"User"
)
# 설정 확인
[Environment]::GetEnvironmentVariable("OPENAI_API_KEY", "User")
# 삭제할 때
[Environment]::SetEnvironmentVariable("OPENAI_API_KEY", $null, "User")
코드에서 사용하기
import os
import openai
# ✅ 환경변수에서 가져오기 — 코드에 키 없음
api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
raise ValueError("OPENAI_API_KEY 환경변수가 설정되지 않았습니다.")
openai.api_key = api_key
// ✅ process.env로 가져오기
const apiKey = process.env.OPENAI_API_KEY;
if (!apiKey) {
throw new Error('OPENAI_API_KEY 환경변수가 설정되지 않았습니다.');
}
const openai = new OpenAI({ apiKey });
방법 2: Windows 자격증명 관리자 활용
Windows 자격증명 관리자(Credential Manager)는 운영체제 수준에서 암호화하여 저장하는 보안 저장소입니다. 환경변수보다 한 단계 더 안전하며, 사용자 계정과 연동되어 다른 계정에서는 접근할 수 없습니다.
PowerShell로 자격증명 저장 / 조회
# API 키를 자격증명 관리자에 저장
$credential = Get-Credential -Message "API 키를 입력하세요" -UserName "OPENAI_API_KEY"
New-StoredCredential -Target "OPENAI_API_KEY" -Credentials $credential
# 저장된 키 조회 (복호화하여 가져오기)
$cred = Get-StoredCredential -Target "OPENAI_API_KEY"
$apiKey = $cred.GetNetworkCredential().Password
# cmdkey 명령어로도 저장 가능 (CredentialManager 모듈 없이)
cmdkey /add:"OPENAI_API_KEY" /user:"api" /pass:"sk-xxxxxxxx"
Python에서 자격증명 관리자 사용
# 설치: pip install keyring
import keyring
# 키 저장 (최초 1회)
keyring.set_password("myapp", "OPENAI_API_KEY", "sk-xxxxxxxxxxxxxxxx")
# 키 불러오기 (코드에서 매번)
api_key = keyring.get_password("myapp", "OPENAI_API_KEY")
if not api_key:
raise ValueError("키가 저장되어 있지 않습니다.")
# Windows에서는 자동으로 자격증명 관리자를 백엔드로 사용
.env 파일 + .gitignore 패턴
로컬 개발 환경에서 가장 많이 쓰이는 패턴입니다. .env 파일에 키를 저장하고,
.gitignore로 Git에 절대 올라가지 않도록 막습니다.
팀 전체가 이 패턴을 사용하면 "키를 어디서 관리하냐"는 혼란을 줄일 수 있습니다.
# .env (절대 Git에 올리지 마세요)
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
DATABASE_URL=postgresql://user:password@localhost:5432/mydb
# .gitignore에 반드시 추가
.env
.env.local
.env.production
.env.*.local
*.key
secrets/
# .env.example (Git에 올려도 되는 파일 — 키 값 없이 형식만)
OPENAI_API_KEY=your_openai_api_key_here
STRIPE_SECRET_KEY=your_stripe_secret_key_here
AWS_ACCESS_KEY_ID=your_aws_access_key_here
AWS_SECRET_ACCESS_KEY=your_aws_secret_here
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
.env.example은 Git에 커밋해도 됩니다. 새 팀원이 합류하면
.env.example을 복사해 .env로 만들고, 실제 키는 별도 채널(1Password, 사내 비밀 관리 도구)로 전달하는 것이 안전한 팀 운영 방식입니다.
Python / Node.js에서 .env 불러오기
# pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # .env 파일 자동 로드
api_key = os.environ.get("OPENAI_API_KEY")
stripe_key = os.environ.get("STRIPE_SECRET_KEY")
// npm install dotenv
require('dotenv').config(); // 파일 최상단에 추가
const apiKey = process.env.OPENAI_API_KEY;
const stripeKey = process.env.STRIPE_SECRET_KEY;
Git에 실수로 올렸을 때 대처법
누구나 실수할 수 있습니다. 만약 키가 이미 커밋되었다면 히스토리에서 지우는 것보다 즉시 키를 폐기하는 게 먼저입니다. 봇은 push 후 수 초 안에 탐지하기 때문에 히스토리 정리로는 이미 늦을 수 있습니다.
2. 새 키를 발급받아 환경변수에 설정
3. Git 히스토리 정리 (BFG Repo Cleaner 또는 git filter-branch)
4. 강제 푸시(force push) 및 팀원들에게 재클론 요청
# 방법 1: git filter-branch (Git 내장)
git filter-branch --force --index-filter `
"git rm --cached --ignore-unmatch config.py" `
--prune-empty --tag-name-filter cat -- --all
# 강제 푸시 (원격 히스토리 덮어쓰기)
git push origin --force --all
git push origin --force --tags
# 방법 2: BFG Repo Cleaner (더 빠르고 안전)
# https://rtyley.github.io/bfg-repo-cleaner/ 에서 다운로드 후
java -jar bfg.jar --replace-text secrets.txt
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --force
API 키 보안 체크리스트
| 항목 | 확인 방법 | 중요도 |
|---|---|---|
| 코드에 키 하드코딩 없음 | 코드 검색: grep -r "sk-" . | 필수 |
| .env가 .gitignore에 포함됨 | git check-ignore .env | 필수 |
| .env.example만 Git에 커밋됨 | git ls-files | grep env | 필수 |
| 환경변수 또는 자격증명 관리자 사용 | 코드에서 os.environ / keyring 확인 | 필수 |
| 키에 최소 권한만 부여 | 각 서비스 대시보드에서 권한 확인 | 권장 |
| 키 사용량 모니터링 설정 | OpenAI/AWS 사용량 알림 설정 | 권장 |
| 로그에 키 출력 없음 | 로그 파일 검색: grep -i "key\|token\|secret" | 필수 |
| 키 주기적 교체(Rotation) | 3~6개월마다 새 키 발급 후 교체 | 권장 |
댓글
댓글 쓰기