DB를 암호화해도 안심할 수 없는 이유
"내가 볼 수 있다면, 누군가도 볼 수 있다"
들어가며
현대 클라우드 기반 데이터베이스 환경에서 암호화는 이제 선택이 아닌 필수로 여겨진다. 그러나 "DB 운영자를 신뢰하지 않는다"는 전제 하에 암호 기반 보호 모델을 진지하게 탐구해보면, 생각보다 많은 구조적 한계가 드러난다.
이 문서는 Function Encryption 같은 고급 암호 기술에서 출발하여, 현실적인 DB 설계가 어디까지 대응할 수 있는지, 그리고 어디서부터 암호의 영역을 벗어나게 되는지를 분석한다. 결론부터 말하자면, DB 보안은 단순히 "어떤 암호 알고리즘을 쓸 것인가"의 문제가 아니다. 오히려 "누가 정보를 이해할 수 있는 구조인가"라는 설계 철학의 문제에 가깝다.
1. 문제의식: 신뢰 모델이 흔들리고 있다
클라우드 DB 시대가 가져온 변화
과거 자체 서버에서 운영하던 데이터베이스는 물리적, 조직적 경계가 비교적 명확했다. 데이터는 우리 데이터센터에 있었고, 접근하는 사람은 우리 팀의 DBA였으며, 보안 통제는 내부 정책과 접근 제어로 이루어졌다.
그러나 클라우드 기반 DBaaS(Database-as-a-Service)가 확산되면서 상황이 근본적으로 바뀌었다. 이제 데이터는 클라우드 제공자의 서버에 물리적으로 존재하고, 클라우드 운영팀DBA, SRE, 백업 담당자, 기술 지원팀이 그 데이터에 접근할 수 있는 위치에 있다. 우리가 할 수 있는 것은 계약서와 SLA, 그리고 암호화 정책에 의존하는 것뿐이다.
"신뢰"는 정책일 뿐, 기술적 보장이 아니다
계약서에 "DB 운영자는 고객 데이터를 열람하지 않겠다"라는 조항이 명시되어 있다고 해서, 기술적으로 그것이 보장되는 것은 아니다.
현실을 직시해보자. 운영자는 데이터베이스 바이너리에 직접 접근할 수 있고, 운영 중인 메모리 덤프를 추출할 수 있으며, 백업 파일을 열람할 수 있고, 질의 로그를 감시할 수 있다. 이것은 기술적 통제가 아니라, 개인의 윤리와 조직의 감시 메커니즘에만 의존하는 구조다.
실제로 일부 DB 제공 업체의 운영 인력이 고객의 경영 데이터거래처 정보, 경조사 내역, 재무 지표를 수상하게 잘 알고 있었다는 과거의 이야기를 들은적이 있다. 이것은 기술적 위반이 아니었다. 만약 실제로 봤다면, 그저 접근 권한을 가진 사람이 실제로 데이터를 읽은 것이다.
신뢰하지 않는 설계가 필요하다
이런 상황에서 자연스럽게 떠오르는 질문이 있다. "기술적으로 DB 운영자가 데이터를 읽을 수 없도록 설계할 수 있지 않을까?"
이 질문이 바로 이 포스팅의 출발점이다.
2. 이상적 모델: Functional Encryption이 보여준 가능성
우리가 원했던 것
다음 속성을 모두 만족하는 DB 설계를 상상해보자.
첫째, 애플리케이션만 암호화 키를 보유하고 DB는 키를 절대 알지 못한다. 둘째, 평문 데이터는 DB에 저장되지 않고 암호문만 저장된다. 셋째, 질의 자체도 암호화되어 DB는 "무엇을 찾는지" 알 수 없다. 넷째, 키 없이는 의미 있는 검색 조건 자체를 구성할 수 없다.
이런 구조라면, DB 운영자는 설령 데이터에 물리적으로 접근하더라도 "데이터가 무엇인지" 알 수 없고, "무엇을 검색하는지" 알 수 없으며, "그 결과가 무엇인지" 해석할 수 없게 된다.
Function Encryption의 매력
Function Encryption(FE)은 바로 이 아이디어를 암호학적으로 실현하려는 시도다.
기본 개념은 공개키 암호화의 변형으로, 특정 함수 f의 결과만 복호화할 수 있고 그 외 모든 정보는 은닉된다. 암호문 상태에서 특정 조건(WHERE 절과 같은)을 평가할 수 있고, 일치 비교 연산을 키 없이도 수행할 수 있으며, 데이터 전체 형태는 결코 노출되지 않는다.
예를 들어 users 테이블의 email 필드를 FE로 보호한다면, 암호문 형태로 저장하고 FE 토큰으로 특정 이메일만 조회할 수 있다. DB는 "일치하는 행이 있다/없다"만 반환하고, 이메일 주소 자체는 절대 노출되지 않는다.
처음에는 이 가능성이 상당히 매력적으로 보였다. "FE를 DB에 적용하면, 정말로 운영자를 배제할 수 있지 않을까?" 그러나 이 기대는 DB라는 시스템의 현실과 만나면서 급속히 수그러들기 시작했다.
3. 첫 번째 좌절: DB 질의가 가진 위험성
당연한 기능들의 암호학적 비용
개발자들이 일상적으로 사용하는 DB 기능들을 다시 생각해보자.
-- 범위 쿼리 SELECT * FROM users WHERE age > 18; -- 패턴 매칭 SELECT * FROM products WHERE name LIKE '%phone%'; -- 전문 검색 SELECT * FROM articles WHERE content MATCH 'blockchain'; -- 정규식 검색 SELECT * FROM logs WHERE message REGEXP '(error|fail)';
이 모든 연산은 "간단한 비교"처럼 보이지만, 암호학적 관점에서는 데이터의 구조와 분포를 직접 드러내는 행위다.
각 연산 유형별 정보 누출
- 일치 검색(Equality)은 상대적으로 용이한 편이다.
WHERE email = '[email protected]'같은 쿼리는 결정적 암호화(Deterministic Encryption)로 처리할 수 있다. 같은 평문이 같은 암호문을 생성하므로 매칭이 가능하다. 정보 누출은 제한적이어서, 같은 값들이 그룹화되는 정도에 그친다.
- 범위 및 정렬(Order & Range)은 난이도가 높아진다.
WHERE timestamp > '2024-01-01'이나WHERE salary BETWEEN 50000 AND 100000같은 쿼리는 Order-Preserving Encryption(OPE)이 필요하다. 문제는 대소 관계가 암호문에서도 드러나기 때문에 정보 누출이 상당하다는 점이다. 누출된 정보를 활용한 통계 공격이 가능해진다.
- 패턴 매칭(Substring & Pattern)은 매우 어렵다.
WHERE name LIKE '%john%'같은 쿼리는 n-gram 기반 인덱싱으로 부분적으로 해결할 수 있지만, 부분 문자열 자체가 식별자가 되어 정보 누출이 심각하다. 빈도 분석(frequency analysis)을 통해 평문을 복원할 수 있는 경우도 있다.
- 전문 검색(Full-Text Search)은 극도로 어렵다. 토큰화된 암호문으로 가능하긴 하지만, 문서의 주제나 용어 분포가 암호문에서도 추론 가능하여 정보 누출이 극심하다.
학계가 제시한 해법들의 현실
학계에서 제시된 기술들을 살펴보면, Fully Homomorphic Encryption(FHE)은 모든 연산을 암호문 상태에서 수행할 수 있지만 1000배 이상 느려서 실무 적용이 불가능하다. Functional Encryption(FE)은 특정 함수만 복호 가능하지만 역시 매우 무거워서 적용이 어렵다. Indistinguishability Obfuscation(iO)은 알려진 구현 자체가 없다. Searchable Symmetric Encryption(SSE)은 합리적인 성능 수준을 보여주지만 조건부로만 적용 가능하다.
결론적으로, 모든 DB 기능을 강한 암호로 보호하는 것은 현재로서는 불가능하다.
4. 두 번째 좌절: DB 설계 철학과의 근본적 충돌
데이터베이스의 본질적 요구사항
데이터베이스는 다음을 전제로 설계되었다. 같은 쿼리를 여러 번 실행해도 같은 결과가 나와야 하고(반복적 질의 가능), 인덱스와 정렬, 캐싱으로 빠른 응답을 보장해야 하며(성능 최적화), 쿼리 패턴을 분석해서 접근을 최적화해야 하고(패턴 분석), 통계와 카디널리티로 실행 계획을 수립해야 한다(메타데이터 활용).
강한 암호의 요구사항
반면 강한 암호 보안은 정반대를 요구한다. 누가 언제 무엇을 접근했는지 흔적을 제거해야 하고(접근 패턴 은닉), 계산 과정의 어떤 정보도 노출하면 안 되며(중간 결과 은닉), 여러 질의 결과를 합쳐도 추론이 불가능해야 하고(누적 추론 방지), 같은 쿼리도 매번 다른 형태로 암호화되어야 한다(일회성).
이 두 철학은 양립할 수 없다
DB 철학이 "반복 가능하고, 예측 가능하고, 최적화된" 것을 추구한다면, 암호 철학은 "비결정적이고, 추적 불가능하고, 역추론 불가능한" 것을 추구한다.
구체적인 예를 들어보자. 일반적인 DB 설계에서
SELECT * FROM transactions WHERE user_id = 123이라는 쿼리는 매번 같은 결과를 반환하고, 인덱스로 빠르게 검색되며, 조회 패턴 추적이 가능하다.강한 암호를 적용하면 어떻게 될까?
SELECT * FROM transactions WHERE encrypted_user_id = f_k(123)에서 nonce 때문에 매번 다른 암호문이 생성되고, 인덱스는 무용지물이 되며, 성능은 급락하고 보안도 지속 불가능해진다.이 지점에서 중요한 인식이 생긴다. DB 전체를 "강한 암호"로 덮으려는 발상 자체가 구조적으로 무리일 수 있다는 것이다. DB는 본질적으로 정보 처리와 성능을 위해 일부 정보 누출을 필요로 하는 시스템이다. 그 일부 누출을 완전히 차단하려면, DB 자체를 포기해야 한다.
5. 현실적 설계: 우리는 어디까지 할 수 있는가
그렇다면 현실 속에서 DB 운영자를 배제하는 설계는 어디까지 가능할까?
필드 분류 기반의 차등 보호
실무에서 채택되는 방식은 필드의 특성에 따라 보호 수준을 다르게 하는 것이다.
- 계층 1: 보호 대상 제외(Protection-Exempt) 에는 ID, timestamp, category, status 같은 필드가 해당된다. 정렬이나 범위 검색, 인덱싱이 필수적인 필드들이다. 평문으로 저장하거나 OPE 같은 약한 암호를 적용한다. 패턴 분석이 가능하므로 위험도가 높지만, 의사결정은 명확하다. "이 필드는 DB가 원래 접근해야 성능이 나온다. 암호로 완전 보호는 포기한다."
- 계층 2: 암호화 + 토큰 기반 검색(Tokenized Search) 에는 이메일, 전화번호, SSN 같은 민감 정보가 해당된다. AES-GCM으로 암호화하여 저장하고, 검색용 토큰(HMAC, blind index)을 별도로 저장한다. 질의 시 애플리케이션이 토큰을 생성하여 전달한다.
# 애플리케이션 레이어 (신뢰 영역) user_email = "[email protected]" encryption_key = get_app_key() search_token = hmac.new(encryption_key, user_email).digest() # DB에 저장 db.insert({ 'encrypted_email': aes_encrypt(user_email, encryption_key), 'email_token': search_token # 토큰만 인덱싱 }) # 쿼리 실행 token = hmac.new(encryption_key, "[email protected]").digest() result = db.query("SELECT * FROM users WHERE email_token = ?", token)
이 방식에서 DB 운영자는 어떤 이메일을 검색했는지 알 수 없다. 다만 검색 빈도나 반복 패턴은 볼 수 있다.
- 계층 3: 질의 생성 권한 제어(Query Generation Control) 에서는 키 없이는 의미 있는 WHERE 절 생성 자체가 불가능하다. PRF(Pseudo-Random Function) 기반 토큰만 인정된다. 운영자는 토큰을 보지만, 그것이 무엇을 의미하는지 알지 못한다.
개념적으로 보면, 애플리케이션이 "user_id = 123을 찾아줘"라고 하면 키 기반 토큰이 생성되고, 데이터베이스는 "token_x7f2a == token_x7f2a인 행 반환"이라는 요청을 받는다. DB 운영자 관점에서는 "뭔가 같은 토큰끼리 매칭되는데, 뭘 찾는 건지는 모르겠다"가 된다.
전문 검색과 패턴 매칭의 현실적 처리
위 세 가지 계층으로는 패턴 검색을 완전히 해결할 수 없다. 현실적인 대안은 세 가지가 있다.
첫 번째 옵션은 암호화를 포기하는 것이다. 평문으로 저장하고 인덱스를 생성한다. 위험도는 매우 높지만 성능은 최고이고 기능도 완전하다. 민감도가 낮은 데이터에만 선택할 수 있다.
두 번째 옵션은 n-gram과 토큰화를 적용하는 타협안이다. 예를 들어 "blockchain"이라는 단어를 ["blo", "loc", "ock", "cka", "cha", "hai", "ain"] 같은 3-gram으로 분리하고, 각 토큰을 HMAC으로 암호화하여 저장한다. 자주 나오는 n-gram이 식별되면 단어를 추론할 수 있어서 정보 누출이 발생하지만, 전문 검색용으로는 "쓸만한 수준"이다.
세 번째 옵션은 애플리케이션 레이어에서 처리하는 것이다. DB에서 모든 암호문을 가져온 후 애플리케이션에서 복호화하고 검색한다.
# DB에서 모든 암호문 가져오기 encrypted_docs = db.query("SELECT * FROM articles") # 애플리케이션에서 복호화 + 검색 results = [] for enc_doc in encrypted_docs: doc = aes_decrypt(enc_doc) if "blockchain" in doc: results.append(doc)
DB 운영자가 검색어를 절대 알 수 없다는 장점이 있지만, 모든 행을 다운로드해야 하므로 성능은 최악이다. 데이터 크기가 작거나 실시간성이 불필요한 경우에만 선택할 수 있다.
설계 원칙: 무엇을 포기할 것인가
현실적인 DB 보안 설계의 핵심은 "우리는 운영자가 알아도 괜찮은 것과 절대 알면 안 되는 것을 구분한다"는 것이다.
데이터 평문과 검색 조건은 운영자가 접근할 수 없어야 한다. 반면 검색 빈도, 결과 행 수, 쿼리 패턴, 접근 시간 같은 메타데이터는 차단 비용이 이득보다 크기 때문에 허용할 수밖에 없는 경우가 많다.
6. 한계 인정: 암호도 완벽하지 않다
감수해야 할 위험들
위의 설계를 따르더라도 완벽한 은닉은 불가능하다.
메타데이터 기반 추론의 예를 들어보자. DB 운영자는 쿼리 빈도를 분석할 수 있다. "이 토큰은 매일 100번 조회된다", "이 토큰은 주말엔 조회가 없다" 같은 패턴을 파악하면, 토큰이 무엇인지는 몰라도 특정 사용자를 식별할 수 있게 된다.
결과 크기 분석도 가능하다. "토큰 x7f2a를 검색하면 항상 1행만 반환된다", "토큰 y3b1를 검색하면 평균 50행이 반환된다" 같은 정보로 데이터 분포를 추론할 수 있다.
시간 상관 분석이나 크로스 필드 분석도 마찬가지다. "토큰 z9c4는 매일 오전 9시에 조회된다"는 시간 패턴 기반 행동 추론으로 이어지고, 여러 필드의 토큰 조합 패턴은 레코드 연결 가능성을 높인다.
보안 모델의 단계적 이해
보안 모델을 단계별로 구분하면 이해가 쉬워진다.
신뢰 기반 모델에서는 DB를 신뢰할 수 있는 주체로 보고, 외부 침해자만 위협으로 간주한다. 보호 수준은 약하며 내부자에 대해서는 무방비다.
암호화 at-rest 모델에서는 저장 데이터를 보호하지만, 운영자는 여전히 평문에 접근할 수 있다. 보호 수준은 중간이다.
Tokenized Search 모델에서는 데이터와 일부 검색까지 보호하며, DB 운영자의 읽기 접근을 위협으로 간주한다. 의미 읽기가 불가능해지므로 보호 수준이 강하다.
완벽한 암호 모델은 모든 정보를 은닉하는 것으로, 이론적으로만 존재하며 실무 적용은 불가능하다.
선택의 여지
이 한계를 이해한 후에는 "우리는 어느 수준까지의 불편을 감수할 것인가?"라는 질문이 남는다. 약한 보호는 편하지만 위험하고, 강한 보호는 안전하지만 불편하다. 평문 저장에서 암호화, 토큰화, 애플리케이션 처리, 그리고 이론적으로만 가능한 FHE까지 스펙트럼이 존재하며, 성능은 반대 방향으로 움직인다.
7. 핵심 통찰: 구조적 설계의 재정의
정보 접근성의 구조
여기서 매우 중요한 통찰이 도출된다.
"내가 어떤 정보를 제공받고 있다는 사실은, 누군가도 그 정보를 볼 수 있는 구조 위에 서 있다는 뜻이다."
이것이 단순히 신뢰의 문제가 아니라 구조적 사실이라는 점이 핵심이다.
새로운 질문이 필요하다
기존에 우리가 던지던 질문들"암호화했는가?", "강도가 얼마나 되는가?", "해킹으로부터 안전한가?"은 이제 충분하지 않다.
새로운 질문을 던져야 한다. "누가 이 정보를 이해할 수 있는가?", "우리가 신뢰하지 않는 주체는 무엇을 볼 수 없어야 하는가?", "그 요구를 만족하려면 어느 수준의 불편을 감수해야 하는가?"
8. 암호 기술의 현재와 미래
현재 기술의 위치
현실적으로 사용 가능한 기술에는 대칭 암호화(AES-GCM), 해시 기반 인덱싱(HMAC, blind index), Order-Preserving Encryption, 조건부 Searchable Symmetric Encryption이 있다.
학계에서 진행 중이지만 아직 실무에 투입되지 않은 기술로는 Fully Homomorphic Encryption(성능 개선 중), Functional Encryption(프로토콜 단순화 진행), Trusted Execution Environments(가능성 높음), Differential Privacy(통계 쿼리 보호)가 있다.
이론적이지만 현실화가 어려운 기술로는 Indistinguishability Obfuscation(구현 미흡)가 있다.
기술 진화의 방향
암호 기술 자체의 발전 경로를 보면, 현재 FHE 연산은 1000배 느리지만 5년 후에는 100배 느린 수준이 될 가능성이 있고, 10년 후에는 특정 워크로드에서 실무 수준에 도달할 수 있다는 기대가 있다. Microsoft SEAL, IBM Encrypted Data, 양자 안전 암호(Post-Quantum Cryptography) 표준화, GPU 기반 FHE 가속 등의 진전이 있다.
신뢰 하드웨어(TEE) 활용 경로도 있다. Intel SGX, ARM TrustZone, AMD SEV 같은 신뢰 실행 환경에서 키를 관리하고 연산을 수행하는 방식이다. 암호 성능 문제를 회피하고 OS 수준 위협으로부터 격리할 수 있지만, 하드웨어 종속성과 측채널 공격 가능성, CPU 제조사 신뢰라는 다른 형태의 신뢰 모델이 필요하다.
아키텍처 재설계 경로도 고려할 수 있다. 블록체인 기반 분산 DB, Zero-Knowledge Proof 기반 검증, 다자간 계산(MPC) 기반 쿼리 같은 방식이다. 단일 신뢰 주체를 제거할 수 있지만 성능 저하와 복잡도 증가, 실무 도입 사례 부족이 문제다.
9. 결론: 결국 신뢰의 문제다
신뢰는 제거할 수 없다
이 문서를 통해 살펴본 모든 기술암호화, 토큰화, FHE, TEE에는 공통점이 하나 있다. 어딘가에 반드시 신뢰 지점(trust anchor)이 존재한다는 것이다.
암호화를 적용하면 키를 관리하는 애플리케이션을 신뢰해야 한다. TEE를 도입하면 CPU 제조사를 신뢰해야 한다. 클라우드 DB를 사용하면 제공자의 운영 정책을 신뢰해야 한다. 자체 서버를 운영해도 내부 DBA를 신뢰해야 한다.
그런데 여기서 한 걸음 더 들어가보자. 설령 완벽한 암호 기술이 등장한다 해도, 그 기술을 구현한 DB 엔진을 누가 만들었는가? 그 코드를 컴파일한 컴파일러는 신뢰할 수 있는가? 1984년 Ken Thompson은 튜링상 수상 강연에서 "컴파일러에 백도어를 심으면, 소스 코드를 아무리 검토해도 발견할 수 없다"는 것을 보여주었다. 신뢰의 체인은 우리가 생각하는 것보다 훨씬 깊은 곳까지 뻗어 있다.
완전히 신뢰를 배제한 시스템은 존재하지 않는다. 이것은 기술의 한계라기보다, 정보 시스템의 본질적 속성에 가깝다.
기술은 신뢰의 범위를 좁힐 뿐이다
그렇다면 암호 기술의 역할은 무엇인가?
"모든 신뢰를 제거하는 것"이 아니다. 오히려 "신뢰해야 하는 대상을 줄이고, 그 경계를 명확히 하는 것" 이다.
평문 DB에서는 운영자, 백업 담당자, 모니터링 시스템, 네트워크 관리자 등 수많은 주체를 암묵적으로 신뢰해야 한다. 암호화와 토큰화를 적용하면 그 범위가 "키를 보유한 애플리케이션"으로 좁혀진다. TEE를 추가하면 "CPU 제조사와 enclave 코드"로 더 좁혀진다.
기술이 발전할수록 신뢰의 원이 작아지는 것이지, 원 자체가 사라지는 것은 아니다.
설계란 신뢰 관계를 선택하는 것이다
결국 DB 보안 설계는 기술 선택의 문제가 아니라, "누구를 신뢰할 것인가"를 명시적으로 결정하는 행위다.
이 결정을 의식적으로 내리지 않으면 어떻게 될까? 암묵적으로 모든 접근 가능한 주체를 신뢰하는 셈이 된다. "우리는 클라우드 제공자를 신뢰한다"라고 명시적으로 선언한 적 없지만, 평문 DB를 그들의 서버에 올리는 순간 사실상 그렇게 결정한 것이다.
좋은 보안 설계란 이 신뢰 관계를 숨기지 않고 드러내는 것이다. "우리는 X를 신뢰하고, Y는 신뢰하지 않는다. 따라서 이런 기술을 선택했다"라고 말할 수 있어야 한다.
질문을 바꿔야 한다
"암호화했는가?"는 더 이상 충분한 질문이 아니다.
진짜 질문은 이것이다: "우리는 누구를 신뢰하기로 했고, 그 선택은 의도적인가?"
이 질문에 답할 수 있을 때, 비로소 DB 보안이 의미를 갖는다.
참고문헌
- Popa, R. A., et al. (2011). CryptDB: Protecting Confidentiality with Encrypted Query Processing. SOSP.
- Song, D. X., et al. (2000). Practical Techniques for Searches on Encrypted Data. IEEE S&P.
- Boneh, D., et al. (2015). Functional Encryption: Definitions and Challenges. Journal of Cryptology.
- Gentry, C. (2009). Fully Homomorphic Encryption Using Ideal Lattices. STOC.
- Intel SGX Explained. https://eprint.iacr.org/2016/086
- Thompson, K. (1984). Reflections on Trusting Trust. Communications of the ACM.
마치며
Function Encryption을 처음 접했을 때, "이걸로 DB 운영자를 완전히 배제할 수 있지 않을까?"라는 기대가 있었다. 하지만 깊이 파고들수록 깨닫게 된 것은, 그것이 DB를 대체하는 기술이 아니라 DB의 구조적 한계를 드러내는 기술이라는 점이었다.
그리고 그 한계의 끝에서 만난 것은 결국 신뢰라는 오래된 주제였다.
우리는 누군가를 신뢰하지 않고는 정보를 다룰 수 없다. 암호 기술이 해줄 수 있는 것은 그 "누군가"의 범위를 좁히고, 우리가 내린 신뢰의 결정을 더 명확하게 만드는 것뿐이다.
암호화는 진입점이지, 목적지가 아니다. 목적지는 다음 질문의 답을 찾는 것이다.
"우리는 누구를 신뢰하기로 했는가? 그리고 그 선택은 정말 우리가 의도한 것인가?"
이 질문을 회피하지 않을 때, DB 보안은 비로소 의미 있는 설계가 된다.
