
이 섹션의 사실들은 NHN Cloud 공식 문서(Secure Key Manager 개요/콘솔/API 가이드) 기준입니다.
발표 전 최신 문서로 한 번 더 대조하면 안전합니다. (제품 스펙은 갱신될 수 있음)
앞의 이론(3·4번)이 "실제 제품에서 어떻게 구현됐나"로 착지하는 섹션. 청중이 제일 궁금해하는 부분이니 시간 배분 넉넉히.
SKM은 키를 3단으로 겹쳐 보호합니다. 위 키가 아래 것을 감싸는 구조.

동작 방식:
이게 바로 4번의 봉투 암호화 개념을 제품 전체 구조로 확장한 것 (KEK 위에 또 KEK를 얹은 다층 구조).
핵심 방어 논리이자 발표에서 가장 임팩트 있는 포인트:
SKM에 저장한 사용자 데이터를 비정상적인 방법으로 얻으려면,
물리적으로 분리된 세 개의 시스템에서
루트 키 · 시스템 키 · 사용자 데이터를 모두 획득해야 한다.
flowchart LR
subgraph S1["시스템 A (물리적 분리)"]
RK["루트 키"]
end
subgraph S2["시스템 B (물리적 분리)"]
SK["암호화된 시스템 키"]
end
subgraph S3["시스템 C (물리적 분리)"]
UD["암호화된 사용자 데이터"]
end
RK -. "셋 다 있어야<br/>복원 가능" .- SK
SK -. .- UD
왜 강력한가:
발표 멘트: "자물쇠 하나가 아니라, 물리적으로 떨어진 방 세 개에 열쇠를 나눠 둔 겁니다. 방 하나 털어봐야 소용없어요."
2번에서 강조한 "저장 안전성 ≠ 접근 통제"의 실제 구현. SKM은 세 가지 인증 방법을 제공합니다:
| 인증 방법 | 무엇을 확인하나 |
|---|---|
| IPv4 주소 인증 | 요청 클라이언트의 IPv4 주소 |
| MAC 주소 인증 | 요청 클라이언트의 MAC 주소 (HTTP 헤더 X-TOAST-CLIENT-MAC-ADDR로 전달) |
| 클라이언트 인증서 인증 | 통신에 사용하는 클라이언트 인증서 |
규칙 (발표에서 꼭 짚기):
이게 왜 중요? DB 접속정보 같은 걸 SKM에 넣어두면, 정해진 우리 서버(특정 IP/MAC/인증서)에서만 꺼낼 수 있음. 공격자가 다른 데서 API를 때려도 인증에서 걸림.
3번에서 본 데이터 3종에 대응하는 API 목록입니다. "키 값을 직접 주지 않고, SKM에게 작업을 시킨다" 는 원칙이 핵심.
create-local-key 응답에는 두 개가 옵니다:
localKeyPlaintext: 생성된 로컬 대칭키를 Base64 인코딩한 값. 디코딩 후 바로 데이터 암호화에 사용 → 이게 DEK(평문).localKeyCiphertext: 그 로컬키를 SKM에 저장된 대칭키(=KEK 역할)로 암호화한 값. 스토리지에 저장 → 이게 암호화된 DEK.나중에 복호화가 필요하면 저장해둔 localKeyCiphertext를 복호화 API로 풀어서 다시 로컬키를 얻어 사용.
→ 정확히 4번의 DEK/KEK 봉투 패턴. (이름만 "로컬 키")
| 봉투 암호화 일반 용어 | SKM 대응 |
|---|---|
| DEK (평문) | localKeyPlaintext |
| 암호화된 DEK (저장용) | localKeyCiphertext |
| KEK | SKM에 저장된 사용자 대칭 키 |
api-keymanager.cloud.toast.com, 공공기관용은 api-keymanager.gov-nhncloudservice.com. 접근은 앱키(appkey) 기반 경로.이론과 제품 구조를 "실제로 어떻게 쓰나"로 연결하는 섹션. 인턴 발표에서 본인 경험담을 얹을 수 있는 파트라 가장 설득력이 큽니다.
발표에서 "그래서 진짜 문제가 터지면 어떻게 하나?"에 답하는 부분. 2번(왜 어려운가)과 4번(봉투 암호화 이점)을 실제 상황에 적용해봅니다.
봉투 암호화 + SKM 구조 덕분에 대응이 "전체 데이터 재암호화"가 아니라 "키 계층만 손보기" 로 축소됩니다.
flowchart TD
A["🚨 KEK 유출 의심 탐지"] --> B["새 키 버전 생성 (키 회전)<br/>기존 v1 → 신규 v2"]
B --> C["신규 데이터는 v2로 암호화 시작"]
C --> D["저장된 '암호화된 DEK'들을<br/>v2로 재암호화 (데이터 본문은 그대로!)"]
D --> E["v1 키는 즉시 삭제하지 않고<br/>유예 기간 유지 (구 데이터 복호화용)"]
E --> F["모든 데이터가 v2 기준으로 정리되면<br/>v1 폐기"]
핵심 원칙:
1. 버전을 올린다 (rotate). SKM은 키에 버전(v1, v2…)을 매기므로 새 버전을 만들면 됨.
2. 실제 데이터 본문은 안 건드린다. 봉투 구조라 재암호화 대상은 "암호화된 DEK(작은 것)"뿐. → 2번에서 말한 "수억 건 재암호화" 악몽을 피함.
3. 구 버전 키를 성급히 지우지 않는다. ⚠️ 공식 문서도 경고: 예를 들어 로그 암호화에 쓰던 대칭키를 회전한 뒤 이전 버전을 바로 삭제하면, 그 키로 암호화된 로그를 영영 복호화할 수 없다. 반드시 "구 데이터가 모두 새 키로 이전됐는지" 확인 후 폐기.
4. 클라이언트 코드는 그대로. SKM이 키 값을 감추고 API로만 다루므로, 애플리케이션은 배포 없이 키 교체가 됨. (2번 딜레마의 실전 해법)
발표 멘트: "봉투 암호화가 없다면 키 유출 = 전체 데이터 재암호화라는 지옥입니다. 있으면 '작은 열쇠들만 다시 잠그면' 되죠. 그래서 이 구조가 사고 대응 속도를 결정합니다."
발표자 상황: "초기 온보딩 프로젝트에 SKM이 붙어 있던 걸로 기억" → 그 경험을 이 구조에 얹으면 됨.
아래는 개념 흐름을 보여주는 예시입니다. 실제 연동 방식(SDK/직접 REST/DBCP 연동)은 프로젝트마다 다르니, 발표 전 본인 프로젝트 코드에서 확인해 정확히 맞추세요.
가장 흔하고, 인트로("키를 어디 두지?")와 완벽히 연결되는 패턴입니다.
Before (2번에서 깐 나쁜 방법):
# application.yml — DB 비밀번호가 평문으로 노출 😱
spring:
datasource:
username: appuser
password: P@ssw0rd! # Git에 올라가고, 서버 침투 시 그대로 읽힘
After (SKM 기밀 데이터로 분리):
앱 부팅 → (인증 통과한 서버가) SKM 기밀 데이터 조회 API 호출
→ DB 접속정보(비번 등)를 런타임에 받아옴
→ DataSource 구성에 주입
효과:
개념 코드 (직접 REST 호출 예시, 실제 인증 헤더/경로는 프로젝트 설정에 맞춰야 함):
// ⚠️ 개념 예시일 뿐 — 실제 appkey/keyid/인증 방식은 본인 프로젝트 값으로
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource(SkmClient skm) {
// SKM에서 DB 접속정보(기밀 데이터)를 런타임에 조회
String dbPassword = skm.getConfidential("db-password-keyid");
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://.../mydb");
ds.setUsername("appuser");
ds.setPassword(dbPassword); // 파일이 아니라 SKM에서 온 값
return ds;
}
}
주민번호·전화번호 같은 컬럼을 암호화 저장할 때 5번의 create-local-key(=DEK) 활용:
// 개념 흐름
// 1) 저장 시
LocalKey dek = skm.createLocalKey("sym-keyid"); // 평문DEK + 암호화된DEK
byte[] cipher = AES.encrypt(dek.plaintext(), rawSsn); // 로컬에서 빠르게 암호화
repo.save(cipher, dek.ciphertext()); // 암호문 + 암호화된DEK 저장
// dek.plaintext() 는 사용 직후 메모리에서 폐기
// 2) 조회 시
byte[] plainDek = skm.decrypt("sym-keyid", row.dekCiphertext()); // 암호화된DEK 복호화
String ssn = AES.decrypt(plainDek, row.cipher()); // 로컬에서 복호화
발표에서: 패턴 A는 "키/비밀을 코드에서 분리"(2번의 해답), 패턴 B는 "봉투 암호화 실전"(4번의 해답). 두 개가 각각 앞 이론을 회수합니다.
발표를 닫는 섹션. 핵심을 압축하고, 예상 질문을 미리 방어하고, "우리 팀엔 어떻게 적용?"으로 마무리.
- 데이터는 언젠가 유출된다. 그래서 암호화로 "유출돼도 무의미하게" 만든다 — 대신 "키를 어디 두나" 라는 새 문제가 생긴다.
- 이 문제는 봉투 암호화(DEK로 데이터, KEK로 DEK) 와 전용 키 관리 시스템으로 푼다 — 성능·키순환·노출최소화를 동시에 잡는 업계 표준.
- NHN Cloud SKM은 이를 3단 키 계층 + 물리적 분리 + 클라이언트 인증(IP/MAC/인증서) 로 구현했고, 실무에선 키를 코드에서 분리하고 재배포 없이 순환하는 게 핵심 가치다.
한 문장으로 더 줄이면:
"키를 코드에서 떼어내고, 접근을 통제하고, 언제든 갈아끼울 수 있게 만드는 것."
(발표 마지막을 "그래서 우리에게 의미"로 닫으면 인상이 좋습니다. 아래는 논의 씨앗 — 팀 상황에 맞게 취사선택)
닫는 멘트 예시: "결국 SKM은 특정 제품이라기보다 '비밀을 다루는 규율' 입니다. AX 팀도 늘어나는 API 키와 민감 데이터를 이 규율로 관리하면, 사고가 나도 피해를 최소화할 수 있습니다."
Q. SKM(KMS) 자체가 뚫리면 다 끝 아닌가요?
A. 그래서 SKM은 단일 지점이 아니라 물리적으로 분리된 3개 시스템(루트키/시스템키/사용자데이터) 으로 나눠 하나만 뚫려선 복원이 안 되게 설계돼 있습니다. 또 KEK는 시스템 밖으로 나오지 않고, 접근은 IP/MAC/인증서 인증으로 통제됩니다. "완전 무적"은 아니지만 공격 난이도를 곱셈으로 올리는 구조입니다.
Q. 봉투 암호화 안 쓰고 그냥 KMS로 직접 암호화하면 안 되나요?
A. 가능하지만 대용량에서 무너집니다. KMS 직접 암호화는 보통 작은 크기 제한(예: AWS는 4KB)이 있고, 매번 데이터를 네트워크로 왕복시키면 느리고 KMS가 병목이 됩니다. 봉투 방식은 무거운 암호화를 로컬에서(빠른 대칭키) 하고, 작은 DEK만 KMS로 보냅니다.
Q. 키를 바꾸면 기존 데이터는 다 복호화 못 하나요?
A. 아닙니다. SKM은 키에 버전을 매기고, 봉투 구조라 재암호화 대상은 실제 데이터가 아니라 작은 "암호화된 DEK" 뿐입니다. 구 버전 키는 유예 기간 동안 남겨 구 데이터를 복호화하다가, 이전이 끝나면 폐기합니다. (성급히 지우면 구 데이터 복호화 불가라 주의)
Q. 대칭키가 더 빠르면 비대칭키는 왜 필요하죠?
A. 용도가 다릅니다. 대칭키는 데이터 암·복호화(속도), 비대칭키는 서명·검증(위·변조 확인, 부인 방지) 에 씁니다. SKM도 이 둘을 데이터 타입으로 분리해 둡니다.
Q. IP 인증이면 IP 스푸핑으로 우회되지 않나요?
A. 그래서 SKM은 인증 방법을 조합(AND) 할 수 있습니다. IP + MAC + 클라이언트 인증서를 함께 걸면 하나만 위조해선 통과 못 합니다. 특히 인증서 기반은 스푸핑이 훨씬 어렵습니다.
Q. 애플리케이션이 부팅 때 SKM에 의존하면 SKM 장애 = 서비스 장애 아닌가요?
A. 맞는 리스크입니다. 그래서 실무에선 조회 결과 캐싱, 재시도/타임아웃, 부분 축약 기동 같은 가용성 전략을 함께 설계합니다. 보안과 가용성의 트레이드오프를 팀 정책으로 정해두는 게 좋습니다.
Q. 왜 굳이 유료 관리형 SKM을 쓰나요? 직접 만들면?
A. 물리적 분리, 인증 심사(ISMS-P/ISO) 대응, 감사 로그, 키 순환·승인 워크플로를 직접 안정적으로 구현·운영하는 비용이 큽니다. 관리형은 이 "규율과 인프라"를 검증된 형태로 제공합니다.