[NHN] SKM(Secure Key Manager) 발표 준비 학습 노트 3

정세현·2026년 7월 23일

NHN AX Internship Notes

목록 보기
14/16

05. NHN Cloud SKM은 어떻게 구현했나

이 섹션의 사실들은 NHN Cloud 공식 문서(Secure Key Manager 개요/콘솔/API 가이드) 기준입니다.
발표 전 최신 문서로 한 번 더 대조하면 안전합니다. (제품 스펙은 갱신될 수 있음)

앞의 이론(3·4번)이 "실제 제품에서 어떻게 구현됐나"로 착지하는 섹션. 청중이 제일 궁금해하는 부분이니 시간 배분 넉넉히.


1) 3단 키 계층 (Root Key → System Key → User Data)

SKM은 키를 3단으로 겹쳐 보호합니다. 위 키가 아래 것을 감싸는 구조.

동작 방식:

  • 루트 키시스템 키를 보호(암호화)하는 데 쓰임.
  • 시스템 키사용자 데이터를 보호(암호화)하는 데 쓰임.
  • 시스템 키는 루트 키로 암호화된 상태로 별도의 "시스템 키 관리 서버" 에 저장됨.
  • SKM 서버는 서비스 시작 시 인증 과정을 거쳐 시스템 키 관리 서버로부터 암호화된 시스템 키를 받아오고, 루트 키로 복호화해야 비로소 시스템 키를 쓸 수 있는 상태가 됨.
  • SKM에서 생성된 모든 사용자 데이터는 시스템 키로 암호화되어 사용자 데이터 저장소에 저장됨.

이게 바로 4번의 봉투 암호화 개념을 제품 전체 구조로 확장한 것 (KEK 위에 또 KEK를 얹은 다층 구조).


2) 물리적 분리 — "세 개를 다 뚫어야 데이터를 얻는다"

핵심 방어 논리이자 발표에서 가장 임팩트 있는 포인트:

SKM에 저장한 사용자 데이터를 비정상적인 방법으로 얻으려면,
물리적으로 분리된 세 개의 시스템에서
루트 키 · 시스템 키 · 사용자 데이터모두 획득해야 한다.

flowchart LR
    subgraph S1["시스템 A (물리적 분리)"]
      RK["루트 키"]
    end
    subgraph S2["시스템 B (물리적 분리)"]
      SK["암호화된 시스템 키"]
    end
    subgraph S3["시스템 C (물리적 분리)"]
      UD["암호화된 사용자 데이터"]
    end
    RK -. "셋 다 있어야<br/>복원 가능" .- SK
    SK -. .- UD

왜 강력한가:

  • 하나만 뚫려서는 아무것도 못 얻음. (예: 사용자 데이터 저장소만 유출돼도 암호화돼 있고, 풀 시스템 키도 없음)
  • 공격자가 세 시스템을 동시에 뚫어야 하므로 난이도가 곱셈으로 증가.
  • 4번에서 말한 "노출 범위 최소화(blast radius)"를 인프라 레벨로 구현한 셈.

발표 멘트: "자물쇠 하나가 아니라, 물리적으로 떨어진 방 세 개에 열쇠를 나눠 둔 겁니다. 방 하나 털어봐야 소용없어요."


3) 클라이언트 인증 — 누가 꺼내 쓰는지 통제

2번에서 강조한 "저장 안전성 ≠ 접근 통제"의 실제 구현. SKM은 세 가지 인증 방법을 제공합니다:

인증 방법무엇을 확인하나
IPv4 주소 인증요청 클라이언트의 IPv4 주소
MAC 주소 인증요청 클라이언트의 MAC 주소 (HTTP 헤더 X-TOAST-CLIENT-MAC-ADDR로 전달)
클라이언트 인증서 인증통신에 사용하는 클라이언트 인증서

규칙 (발표에서 꼭 짚기):

  • 최소 한 개 이상의 인증 방법을 반드시 선택해야 함.
  • 두 개 이상 선택하면 → 전부 통과해야 데이터 접근 가능 (AND 조건).
  • 즉 "IP도 맞고 + 인증서도 맞아야" 처럼 겹겹이 조합 가능 → 자격증명 하나 탈취로는 부족하게 만듦.

이게 왜 중요? DB 접속정보 같은 걸 SKM에 넣어두면, 정해진 우리 서버(특정 IP/MAC/인증서)에서만 꺼낼 수 있음. 공격자가 다른 데서 API를 때려도 인증에서 걸림.


4) 키 3종류와 각각의 API

3번에서 본 데이터 3종에 대응하는 API 목록입니다. "키 값을 직접 주지 않고, SKM에게 작업을 시킨다" 는 원칙이 핵심.

(A) 기밀 데이터 (Confidential Data)

  • 32KB 이하 텍스트를 안전 보관. 대표 용도: DB 접속정보, 앱키 등.
  • API: 기밀 데이터 조회 (인증 통과한 클라이언트만 조회 가능)

(B) 대칭 키 (Symmetric Key) — 암/복호화

  • 저장한 대칭키(AES-256, 공공기관용은 ARIA-256)로 데이터를 암·복호화.
  • 대칭키 값 자체는 클라이언트에 직접 노출되지 않고 API로만 사용.
  • 주요 API:
    • 암호화: 32KB 이하 텍스트를 보내면 암호문(+keyVersion) 반환
    • 복호화: 암호문을 보내면 평문 반환
    • 로컬 키 생성 (create-local-key): 4번 봉투 암호화용! 아래 참고
    • 대칭키 조회: 저장한 대칭키 조회

create-local-key = SKM식 봉투 암호화 (중요)

create-local-key 응답에는 두 개가 옵니다:

  • localKeyPlaintext: 생성된 로컬 대칭키를 Base64 인코딩한 값. 디코딩 후 바로 데이터 암호화에 사용 → 이게 DEK(평문).
  • localKeyCiphertext: 그 로컬키를 SKM에 저장된 대칭키(=KEK 역할)로 암호화한 값. 스토리지에 저장 → 이게 암호화된 DEK.

나중에 복호화가 필요하면 저장해둔 localKeyCiphertext복호화 API로 풀어서 다시 로컬키를 얻어 사용.
→ 정확히 4번의 DEK/KEK 봉투 패턴. (이름만 "로컬 키")

봉투 암호화 일반 용어SKM 대응
DEK (평문)localKeyPlaintext
암호화된 DEK (저장용)localKeyCiphertext
KEKSKM에 저장된 사용자 대칭 키

(C) 비대칭 키 (Asymmetric Key) — 서명/검증

  • 저장한 비대칭키로 데이터 서명·검증 (위·변조 확인).
  • 서명 대상 데이터는 245 Byte 이하 텍스트.
  • 주요 API: 서명, 검증

(공통) 클라이언트 정보 조회 API

  • API를 호출한 클라이언트가 SKM에 어떻게 인식되는지(IP, MAC 헤더, 인증서 사용 여부 등) 확인용. 인증 디버깅에 유용.

5) 알아두면 발표가 단단해지는 추가 사실

  • 엔드포인트: 일반 상용은 api-keymanager.cloud.toast.com, 공공기관용은 api-keymanager.gov-nhncloudservice.com. 접근은 앱키(appkey) 기반 경로.
  • 공공기관용은 국정원 검증 알고리즘(ARIA, SEED, RSA-PSS) 모듈 탑재 → 공공 프로젝트 대응.
  • 키 순환(회전) 기능 제공. 단, "키 가져오기(import)"로 넣은 키는 회전 불가 — SKM에서 생성한 키만 회전됨. (실무 주의점, 6번에서 이어짐)
  • 승인 기능(approval): ISMS-P, ISO 등 인증 심사의 키 관리 요구사항 충족용. 승인자/요청자 역할을 나눠 키 저장소 변경에 승인 절차를 강제 → 직무 분리(separation of duties).

요약 체크

  • 루트키→시스템키→사용자데이터 3단 계층을 그릴 수 있다.
  • "물리적 분리 세 시스템" 방어 논리를 한 문장으로 말할 수 있다.
  • IPv4/MAC/인증서 인증과 "복수 선택 시 AND" 규칙을 안다.
  • create-local-key가 봉투 암호화의 DEK/KEK와 어떻게 대응하는지 매핑할 수 있다.
  • 기밀데이터=조회 / 대칭키=암복호화 / 비대칭키=서명검증 을 즉답할 수 있다.

06. 실무 적용 관점

이론과 제품 구조를 "실제로 어떻게 쓰나"로 연결하는 섹션. 인턴 발표에서 본인 경험담을 얹을 수 있는 파트라 가장 설득력이 큽니다.


1) 키 순환 시나리오 — KEK 유출 의심 시 대응 흐름

발표에서 "그래서 진짜 문제가 터지면 어떻게 하나?"에 답하는 부분. 2번(왜 어려운가)과 4번(봉투 암호화 이점)을 실제 상황에 적용해봅니다.

상황: 시스템 키/상위 키(KEK 역할)가 유출된 것으로 의심됨

봉투 암호화 + 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번 딜레마의 실전 해법)

발표 멘트: "봉투 암호화가 없다면 키 유출 = 전체 데이터 재암호화라는 지옥입니다. 있으면 '작은 열쇠들만 다시 잠그면' 되죠. 그래서 이 구조가 사고 대응 속도를 결정합니다."


2) 실제 Spring 연동 모습 — 인턴 초기 프로젝트 관점

발표자 상황: "초기 온보딩 프로젝트에 SKM이 붙어 있던 걸로 기억" → 그 경험을 이 구조에 얹으면 됨.
아래는 개념 흐름을 보여주는 예시입니다. 실제 연동 방식(SDK/직접 REST/DBCP 연동)은 프로젝트마다 다르니, 발표 전 본인 프로젝트 코드에서 확인해 정확히 맞추세요.

대표 활용 패턴 A: DB 접속정보를 "기밀 데이터"로 관리

가장 흔하고, 인트로("키를 어디 두지?")와 완벽히 연결되는 패턴입니다.

Before (2번에서 깐 나쁜 방법):

# application.yml — DB 비밀번호가 평문으로 노출 😱
spring:
  datasource:
    username: appuser
    password: P@ssw0rd!   # Git에 올라가고, 서버 침투 시 그대로 읽힘

After (SKM 기밀 데이터로 분리):

앱 부팅 → (인증 통과한 서버가) SKM 기밀 데이터 조회 API 호출
        → DB 접속정보(비번 등)를 런타임에 받아옴
        → DataSource 구성에 주입

효과:

  • 설정 파일/Git에 비밀번호가 존재하지 않음.
  • 정해진 IP/MAC/인증서를 가진 우리 서버에서만 꺼낼 수 있음 (5번 인증).
  • 비번을 바꿔도 SKM 콘솔에서 값만 바꾸면 됨 → 재배포 최소화.

개념 코드 (직접 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;
    }
}

대표 활용 패턴 B: 민감 컬럼을 봉투 암호화로 저장

주민번호·전화번호 같은 컬럼을 암호화 저장할 때 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번의 해답). 두 개가 각각 앞 이론을 회수합니다.

연동 시 실무 체크리스트

  • 이 서버의 IP/MAC/인증서가 SKM 인증 정책에 등록돼 있나? (안 되면 401/403)
  • appkey / keyid를 코드에 하드코딩하지 않았나? (이것도 설정 분리 대상)
  • SKM 호출 실패 시 fallback/재시도/캐싱 전략이 있나? (부팅 시 SKM 죽어 있으면 앱도 못 뜸 → 가용성 고려)
  • 평문 DEK를 로그·예외 메시지에 찍고 있지 않나? (제일 흔한 실수)
  • 키 회전 시 구 버전 유예 기간을 지켰나? (1번 경고)

요약 체크

  • KEK 유출 의심 시 대응 4단계를 순서대로 말할 수 있다.
  • "구 키를 성급히 지우면 안 되는" 이유를 예시로 설명할 수 있다.
  • Spring에서 DB 접속정보를 SKM 기밀데이터로 빼는 흐름을 그릴 수 있다.
  • 본인 초기 프로젝트에서 SKM이 A/B 중 어떤 패턴으로 쓰였는지 확인했다.

07. 정리 & Q&A

발표를 닫는 섹션. 핵심을 압축하고, 예상 질문을 미리 방어하고, "우리 팀엔 어떻게 적용?"으로 마무리.


1) 핵심 3줄 요약

  1. 데이터는 언젠가 유출된다. 그래서 암호화로 "유출돼도 무의미하게" 만든다 — 대신 "키를 어디 두나" 라는 새 문제가 생긴다.
  2. 이 문제는 봉투 암호화(DEK로 데이터, KEK로 DEK)전용 키 관리 시스템으로 푼다 — 성능·키순환·노출최소화를 동시에 잡는 업계 표준.
  3. NHN Cloud SKM은 이를 3단 키 계층 + 물리적 분리 + 클라이언트 인증(IP/MAC/인증서) 로 구현했고, 실무에선 키를 코드에서 분리하고 재배포 없이 순환하는 게 핵심 가치다.

한 문장으로 더 줄이면:

"키를 코드에서 떼어내고, 접근을 통제하고, 언제든 갈아끼울 수 있게 만드는 것."


2) AX 팀 관점에서 적용해본다면?

(발표 마지막을 "그래서 우리에게 의미"로 닫으면 인상이 좋습니다. 아래는 논의 씨앗 — 팀 상황에 맞게 취사선택)

  • AI/데이터 파이프라인의 비밀 관리: 모델 API 키, 외부 LLM/벤더 토큰, 데이터소스 접속정보 등이 코드·노트북·환경변수에 흩어져 있진 않은지 → 기밀 데이터로 통합 관리.
  • 학습/추론 데이터의 민감 필드: 개인정보가 포함된 데이터셋 컬럼을 봉투 암호화로 저장하면, 유출 시에도 원본 노출을 막음.
  • 직무 분리(승인 기능): 데이터·모델을 만지는 사람과 키를 관리·승인하는 사람을 분리 → 컴플라이언스(ISMS-P 등) 대응.
  • 재현성 vs 보안 균형: 실험 재현을 위해 비밀을 평문으로 공유하려는 유혹이 큰데, SKM 조회로 대체하면 재현성과 보안을 둘 다 챙김.
  • 가용성 고려: AI 서비스가 부팅 때 SKM에 의존하면, SKM 장애가 서비스 장애로 전이될 수 있음 → 캐싱/재시도 전략을 팀 표준으로.

닫는 멘트 예시: "결국 SKM은 특정 제품이라기보다 '비밀을 다루는 규율' 입니다. AX 팀도 늘어나는 API 키와 민감 데이터를 이 규율로 관리하면, 사고가 나도 피해를 최소화할 수 있습니다."


3) 예상 Q&A (질문 방어)

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) 대응, 감사 로그, 키 순환·승인 워크플로를 직접 안정적으로 구현·운영하는 비용이 큽니다. 관리형은 이 "규율과 인프라"를 검증된 형태로 제공합니다.


4) 발표 직전 최종 점검

  • 봉투 암호화 다이어그램을 말 없이 화이트보드에 그릴 수 있다.
  • SKM 3단 계층 + 3종 데이터/API를 30초 안에 요약할 수 있다.
  • 내 프로젝트에서 SKM이 실제로 어떻게 쓰였는지 한 사례를 말할 수 있다.
  • 위 Q&A 중 최소 4개는 안 보고 답할 수 있다.
  • 제품 스펙(엔드포인트/알고리즘/API명)을 최신 공식 문서로 한 번 대조했다.
profile
I'm the best

0개의 댓글