"키를 주기적으로 교체하라"는 말, 듣기엔 간단한데… 테라바이트짜리 데이터를 전부 다시 암호화한다는 말인가요? 😱

🎯 이 글에서 다루는 것
- 클라우드 KMS에서 "키 교체"가 실제로 의미하는 것
- 봉투 암호화(Envelope Encryption) 개념 — 이걸 모르면 키 교체를 절대 이해 못 함
- AWS KMS vs Azure Key Vault의 키 교체 동작 비교
- 직접 구현한 키(BYOK/CMK)를 교체할 때 주의할 점
- 서비스마다 동작이 다른 이유

📌 도입 / 배경
클라우드 보안 가이드를 보다 보면 꼭 나오는 문장이 있습니다.
"암호화 키는 1년마다 주기적으로 교체(Rotation)하세요."
처음 이 가이드를 보는 분들이 자연스럽게 드는 의문이 있습니다.
"그러면 기존에 암호화된 데이터를 전부 새 키로 다시 암호화해야 하나요? S3에 100TB 쌓여있는데 그걸 다 돌려야 한다는 뜻인가요?"
결론부터 말하면, 대부분의 경우 그렇지 않습니다. 이유는 클라우드 KMS가 봉투 암호화(Envelope Encryption) 라는 구조를 사용하기 때문입니다. 이 개념을 이해하면 키 교체가 왜 가볍고 빠른 작업인지 즉시 납득됩니다.
🔍 핵심 개념: 봉투 암호화(Envelope Encryption)
키가 두 계층이다.
클라우드 KMS는 키를 단 하나만 쓰는 구조가 아닙니다. 두 개의 계층으로 나뉩니다.
[ 실제 데이터 ]
↑ 암호화
[ DEK: Data Encryption Key ] ← 실제 데이터를 암호화하는 키
↑ 암호화 (wrapping)
[ KEK: Key Encryption Key ] ← DEK를 암호화하는 키 (KMS가 관리)
이를 도식으로 표현하면 이렇습니다.
- DEK (Data Encryption Key): 실제 데이터를 암호화하는 키입니다. 보통 AES-256 대칭키입니다.
- KEK (Key Encryption Key): DEK 자체를 암호화(wrap)해서 보호하는 키입니다. KMS, Key Vault 같은 서비스가 관리합니다.
스토리지에 저장되는 것은 암호화된 DEK + 암호화된 데이터입니다. KEK는 KMS 내부에만 존재하고 외부로 나오지 않습니다.
"봉투"라는 비유
편지를 쓴다고 생각해봅시다.
- 편지 내용(데이터)을 작성합니다.
- 편지를 봉투(DEK)에 넣어 밀봉합니다.
- 봉투를 또 다른 안전한 금고(KEK)에 넣어 잠급니다.
키 교체는 금고의 잠금장치(KEK)만 교체하는 것입니다. 봉투와 편지 내용은 그대로입니다.
🔍 키 교체 시 실제로 일어나는 일
AWS KMS — 자동 키 교체(Automatic Rotation)
AWS KMS에서 CMK(Customer Managed Key)의 자동 교체를 활성화하면 어떻게 될까요?
# AWS CLI로 키 자동 교체 활성화
aws kms enable-key-rotation \
--key-id arn:aws:kms:ap-northeast-2:123456789012:key/abcd-1234-...
활성화하면 AWS는 1년마다 새로운 키 재료(key material)를 생성합니다. 이때 중요한 점:
- 기존에 이 키로 암호화된 데이터는 자동으로 다시 암호화되지 않습니다.
- 기존 데이터는 과거 버전의 키 재료로 계속 복호화할 수 있습니다. AWS가 이전 버전을 내부적으로 유지합니다.
- 신규 암호화 요청부터 새 키 재료가 사용됩니다.
# boto3 예시: KMS로 데이터 암호화
import boto3
kms = boto3.client('kms', region_name='ap-northeast-2')
# 암호화: KMS가 DEK를 생성하고, KEK(CMK)로 DEK를 wrap
response = kms.generate_data_key(
KeyId='arn:aws:kms:ap-northeast-2:123456789012:key/abcd-1234-...',
KeySpec='AES_256'
)
plaintext_dek = response['Plaintext'] # 실제 암호화에 쓰는 DEK (메모리에서만 사용)
encrypted_dek = response['CiphertextBlob'] # 저장할 암호화된 DEK
# 이후 plaintext_dek로 실제 데이터를 AES 암호화
# plaintext_dek는 메모리에서 즉시 삭제
# encrypted_dek + 암호화된 데이터를 함께 저장
복호화할 때는:
# 복호화: 저장된 encrypted_dek를 KMS로 보내 plaintext_dek를 얻음
decrypt_response = kms.decrypt(
CiphertextBlob=encrypted_dek
# KeyId 명시 불필요: AWS가 어느 버전 키로 암호화됐는지 내부적으로 알고 있음
)
plaintext_dek = decrypt_response['Plaintext']
# plaintext_dek로 데이터를 복호화
AWS KMS는 CiphertextBlob 내부에 어느 키 버전으로 암호화됐는지 메타데이터가 담겨 있어서, 교체 후에도 이전 데이터를 문제없이 복호화할 수 있습니다.
Azure Key Vault — 키 버전(Key Version) 방식
Azure Key Vault는 AWS KMS와 달리 버전(Version) 으로 키를 관리합니다.
# Azure CLI로 새 버전의 키 생성 (= 키 교체)
az keyvault key create \
--vault-name myVault \
--name myEncryptionKey \
--kty RSA \
--size 2048
# 이 명령 실행 시 새 버전이 생성되고 자동으로 "current" 버전이 됨
# 현재 키의 모든 버전 확인
az keyvault key list-versions \
--vault-name myVault \
--name myEncryptionKey
버전이 교체되면:
- 이전 버전 키: disabled 처리 가능하지만, 기존 데이터 복호화를 위해 보통 enabled 유지
- 신규 암호화: 새 버전 키 사용
- 기존 데이터: 재암호화 없음 (이전 버전으로 복호화 가능)
# 특정 버전으로 암호화
az keyvault key encrypt \
--vault-name myVault \
--name myEncryptionKey \
--version <old-version-id> \ # 구버전으로도 복호화 가능
--algorithm RSA-OAEP \
--value "base64-encoded-data"
🔍 서비스마다 다른가요?
맞습니다. 키 교체 시 동작은 서비스와 구현 방식에 따라 세 가지 경우로 나뉩니다.
케이스 1: 완전 자동 — 데이터 재암호화 없음 (가장 일반적)
KMS/Key Vault에서 관리하는 봉투 암호화 기반 서비스들입니다.
| 서비스 키 | 교체 동작 |
| AWS S3 SSE-KMS | KEK만 교체, 데이터 재암호화 없음 |
| AWS EBS 볼륨 암호화 | KEK만 교체, 기존 볼륨 재암호화 없음 |
| Azure Blob Storage (CMK) | 새 키 버전 지정, 자동으로 DEK 재래핑 |
| Azure SQL Database TDE | 새 보호기 키 지정, 데이터 재암호화 없음 |
케이스 2: 자동 DEK 재래핑 — 데이터 재암호화 없음
Azure Storage, Azure Disk Encryption 등 일부 서비스는 KEK 교체 시 저장된 DEK를 새 KEK로 자동 재래핑합니다. DEK 자체는 바뀌지 않으므로 데이터 재암호화는 없습니다.
[이전] 데이터 ← DEK ← KEK(v1)
[이후] 데이터 ← DEK ← KEK(v2) ← DEK가 새 KEK로 재래핑됨
(데이터는 동일)
케이스 3: 완전 재암호화 — 드물지만 존재
직접 키를 앱에서 관리하거나, 특정 데이터베이스에서 마스터 키를 교체하는 경우입니다.
# 앱에서 직접 키 관리 시 재암호화가 필요한 패턴
def rotate_dek(data_store, old_key, new_key):
"""
앱이 직접 DEK를 관리할 경우, 기존 데이터를 모두 재암호화해야 함
→ 봉투 암호화를 쓰지 않는 경우의 안티패턴
"""
for record in data_store.all():
plaintext = aes_decrypt(record.ciphertext, old_key) # 구 키로 복호화
record.ciphertext = aes_encrypt(plaintext, new_key) # 신 키로 재암호화
data_store.save(record)
이런 경우는 봉투 암호화를 사용하지 않는 잘못된 설계이거나, 의도적으로 데이터 자체의 암호화 키를 바꿔야 하는 경우입니다. 클라우드 매니지드 서비스를 올바르게 쓰면 이 상황은 거의 발생하지 않습니다.
⚠️ 주의사항 / 흔한 실수
🚨 BYOK(Bring Your Own Key) 교체 시 이전 버전 키를 너무 빨리 삭제하면 안 됩니다.
가장 많이 발생하는 실수입니다. 새 키로 교체했다고 이전 키를 삭제하면, 이전 키로 암호화된 DEK를 복호화할 수 없어서 기존 데이터에 영구 접근 불가 상태가 됩니다.
# AWS KMS: 키 삭제는 7~30일 대기 기간 존재 (의도적 안전장치)
aws kms schedule-key-deletion \
--key-id <old-key-id> \
--pending-window-in-days 30 # 최소 7일, 최대 30일
# Azure Key Vault: soft-delete + purge protection 활성화 권장
az keyvault update \
--name myVault \
--enable-soft-delete true \
--enable-purge-protection true
🚨 키 교체 ≠ 데이터 보안 수준 즉각 향상
키 교체는 키가 유출됐을 경우의 피해 범위를 줄이는 것이지, 이미 유출된 키로 복호화된 데이터를 다시 보호하진 않습니다. 유출이 의심되면 키 교체만으로는 부족하고, 해당 키로 접근 가능했던 데이터 범위 자체를 점검해야 합니다.
🚨 앱 측에서 키 버전을 하드코딩하지 마세요.
# 나쁜 예: 특정 버전 하드코딩
KEY_ID = "arn:aws:kms:...:key/abcd-1234"
KEY_VERSION = "version-2023-01" # 교체 후 앱 코드 수정 필요 → 위험
# 좋은 예: alias 사용 (AWS), latest version 자동 참조 (Azure)
KEY_ID = "arn:aws:kms:ap-northeast-2:123456789012:alias/my-app-key"
# alias는 항상 current key를 가리킴
✅ 정리 / 마무리
| 질문 | 답 |
| 키 교체 시 기존 데이터 전부 재암호화? | ❌ 대부분 불필요 |
| 교체 후 기존 데이터 복호화 가능? | ✅ 구 키 버전이 유지되므로 가능 |
| 교체 후 신규 데이터는? | ✅ 새 KEK 사용 |
| 서비스마다 다른가? | ✅ 동작 방식 차이 있음 (재래핑 여부 등) |
| 앱이 직접 키 관리 시? | ⚠️ 재암호화 필요할 수 있음 |
핵심을 한 줄로 정리하면 이렇습니다.
봉투 암호화 구조에서 키 교체는 DEK를 감싼 KEK만 교체하는 것이며, 실제 데이터 암호화에 쓰인 DEK와 데이터 자체는 건드리지 않는다.
클라우드 관리형 서비스(S3, EBS, Azure Blob 등)를 올바르게 사용하고 있다면 키 교체는 가볍고 안전한 작업입니다. 데이터를 전부 다시 암호화해야 한다는 두려움은 봉투 암호화를 이해하면 사라집니다.
심화 학습 방향으로는 HSM(Hardware Security Module), FIPS 140-2/3 준수 키 스토어, 그리고 멀티 리전 키 복제 전략을 추천합니다.
'클라우드' 카테고리의 다른 글
| 🏗️ 개발자라면 인프라 배포를 알아야 하는 진짜 이유 — "코드만 잘 짜면 된다"는 착각 (0) | 2026.03.27 |
|---|---|
| ☁️ AWS 마이그레이션할 때 왜 AWS 콘솔 말고 테라폼을 배워야 하나? (0) | 2026.03.27 |
| Mac에서 Podman으로 멀티 아키텍처(Intel & ARM) 이미지 한 번에 빌드하기 (0) | 2026.03.18 |
| 🛡️ Docker Swarm에서 --with-registry-auth의 늪 탈출하기: 보안과 효율성 사이의 균형 (0) | 2026.01.09 |
| 🐳 도커 데몬 소켓 노출 가이드: 효율과 보안 사이의 균형 잡기 (0) | 2026.01.09 |