Vault를 도입할 때 가장 먼저 부딪히는 선택지는 “시크릿을 Vault에 저장할 것인가, 아니면 Vault를 암호화 서비스로만 사용할 것인가”입니다. 둘 다 Vault의 Secret Engine이지만, 데이터의 위치와 책임 경계가 완전히 다릅니다. 이 글은 KV 기반 저장 방식과 Transit 기반 암호화 서비스를 비교하고, 오픈소스 선택지를 분류해 정리합니다.
KV: 시크릿 저장·조회
Transit: 암호화 서비스, 데이터는 외부
그림 관계를 글로 읽기
- KV: 애플리케이션이 kv put으로 시크릿 값을 Vault KV에 쓴다.
- KV는 시크릿 값을 Vault 스토리지 백엔드에 보관한다.
- kv get으로 읽으면 Vault가 시크릿 값을 반환한다.
- Transit: 애플리케이션이 평문을 base64로 인코딩해 encrypt 요청을 보낸다.
- Vault Transit이 보관한 키로 연산해 ciphertext를 반환한다. 평문은 저장하지 않는다.
- 애플리케이션이 ciphertext를 외부 DB/앱 저장소에 보관한다.
- 복호화: ciphertext로 decrypt를 요청하면 plaintext(base64)를 돌려받는다.
KV Secret Engine: 시크릿을 Vault 내부에 저장
KV는 말 그대로 Key-Value 저장소입니다. 애플리케이션이 필요한 시크릿(예: DB 비밀번호, API 토큰)을 Vault 내부에 저장하고 필요할 때 읽어옵니다. Vault의 접근 제어와 감사 로그를 그대로 받으며, Vault가 단일 진실 원천이 됩니다.
핵심 특징
- 데이터 저장 위치: Vault 스토리지 백엔드
- 접근 패턴: 읽기/쓰기 중심
- KV v2 지원 시 버전 관리와 메타데이터 제공
- Vault가 장애 나면 시크릿 조회도 불가능하므로 가용성 설계가 중요
예시: KV v2 기본 동작
# 환경 변수
export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="s.xxxxx"
# 시크릿 저장
vault kv put secret/app db_password="p@ssw0rd" api_key="abcd1234"
# 시크릿 조회
vault kv get secret/app
예상 출력 형태는 다음과 같습니다.
===== Data =====
Key Value
--- -----
api_key abcd1234
db_password p@ssw0rd
KV v2를 쓰면 버전 관리가 가능하고, 삭제/복구/영구 삭제를 구분할 수 있습니다. 운영 중 오탈자나 잘못된 업데이트가 잦다면 v2가 훨씬 안전합니다.
Transit Secret Engine: 키는 Vault, 데이터는 외부
Transit은 “암호화 서비스”입니다. 데이터는 애플리케이션이나 DB에 남아 있고, Vault는 키 보관과 암호화/복호화 연산만 담당합니다. Vault가 평문을 저장하지 않는다는 점이 가장 큰 차이입니다.
핵심 특징
- 데이터 저장 위치: 애플리케이션/DB 등 외부 시스템
- 접근 패턴: 암호화/복호화/서명/검증 API 호출
- 키는 Vault 내부에 보관, 키 회전과 재암호화(rewrap) 가능
- 서비스 가용성과 지연 시간이 곧 애플리케이션 성능에 영향을 줌
예시: Transit 기본 동작
# 키 생성
vault write -f transit/keys/payments
# 평문을 base64로 인코딩해서 암호화 요청
PLAINTEXT=$(printf 'card-1234' | base64)
vault write transit/encrypt/payments plaintext="$PLAINTEXT"
예상 출력 형태는 다음과 같습니다.
Key Value
--- -----
ciphertext vault:v1:AbCdEf...==
복호화는 ciphertext를 전달해 plaintext(base64)를 돌려받는 형태입니다.
vault write transit/decrypt/payments ciphertext="vault:v1:AbCdEf...=="
Key Value
--- -----
plaintext Y2FyZC0xMjM0
KV vs Transit 비교표
| 항목 | KV Secret Engine | Transit Secret Engine |
|---|---|---|
| 목적 | 시크릿 저장소 | 암호화/복호화 서비스 |
| 데이터 위치 | Vault 내부 | 외부 시스템 |
| 책임 경계 | Vault가 데이터까지 보관 | Vault는 키와 연산만 담당 |
| 접근 패턴 | read/write | encrypt/decrypt/sign/verify |
| 가용성 영향 | 시크릿 조회 시점에 영향 | 모든 암호화 요청에 영향 |
| 회전 전략 | 값 자체 갱신, 버전 관리 | 키 버전 회전, rewrap |
| 백업/복구 | Vault 백업이 곧 시크릿 백업 | Vault 백업은 키 보존에 중요 |
선택 기준: 언제 KV, 언제 Transit인가
-
KV가 맞는 경우
- 애플리케이션 설정이나 토큰처럼 “값 자체”가 필요하다.
- 중앙 저장소에서 접근 제어와 감사 로그를 일원화하고 싶다.
- 데이터 암호화보다 시크릿 관리 일관성이 우선이다.
-
Transit이 맞는 경우
- 데이터는 외부에 두고, 키만 중앙에서 통제하고 싶다.
- DB 필드 단위 암호화처럼 데이터가 많은 환경이다.
- 키 회전과 재암호화 자동화가 중요하다.
-
같이 쓰는 경우
- KV로 앱 설정과 자격 증명을 관리하고
- Transit으로 민감 데이터(예: PII) 암호화를 처리한다.
운영 관점 체크리스트 (Delegate → Review → Own)
실무에서는 “누가 무엇을 자동화하고, 누가 최종 책임을 지는가”가 보안 안정성을 좌우합니다.
- Delegate: 정책 템플릿과 마운트 구조, 표준 경로 규칙을 자동화한다.
- Review: 보안 담당자가 정책 범위와 최소 권한 원칙을 검토한다.
- Own: 키 회전 정책과 장애 시 대응 방식은 서비스 오너가 최종 결정한다.
오픈소스 옵션 맵
Vault의 KV/Transit 개념은 널리 알려졌지만, 오픈소스 생태계의 접근 방식은 다양합니다. 아래는 “KV 저장”과 “Transit형 암호화 서비스” 기준으로 분류한 목록입니다.
KV 기반 시크릿 저장소
| 프로젝트 | 유형 | 비고 |
|---|---|---|
| HashiCorp Vault (OSS) | 중앙 KV + 다양한 Secret Engine | KV v1/v2, Transit 포함 |
| OpenBao | Vault 호환 포크 | KV, Transit 포함 |
| CyberArk Conjur OSS | 중앙 시크릿 관리 | 정책 기반 접근 제어 |
| Keywhiz | 시크릿 배포 서버 | 대규모 배포 사례 있음 |
| Confidant | 시크릿 배포 서버 | 유지관리 상태 확인 필요 |
| Kubernetes Secrets | 클러스터 내 KV | etcd 암호화 설정 필수 |
Transit형 암호화 서비스
| 프로젝트 | 유형 | 비고 |
|---|---|---|
| HashiCorp Vault Transit | 암호화/복호화 API | 키 회전, rewrap 지원 |
| OpenBao Transit | Vault 호환 암호화 API | Vault와 유사한 모델 |
| OpenStack Barbican | KMS 형태 | 키/시크릿 관리 API 제공 |
GitOps/파일 기반 암호화(보조 수단)
| 프로젝트 | 유형 | 비고 |
|---|---|---|
| Mozilla SOPS | 파일 암호화 도구 | KMS 연동 기반 |
| Bitnami Sealed Secrets | Kubernetes CRD | GitOps 시크릿 암호화 |
오픈소스는 기능 못지않게 유지보수 상태가 중요합니다. 실제 도입 전에는 릴리스 주기와 커뮤니티 활동성을 확인하는 것이 안전합니다.