lifecarelog
백엔드

감정 데이터 필드 암호화, pgsodium 대신 앱 레이어 AES-GCM을 택한 이유

감정·건강 데이터 필드레벨 암호화를 DB 확장 대신 앱 레이어 AES-GCM으로 구현한 이유와 IV·키 관리 규칙, 트레이드오프를 정리했어요.

5분 읽기

감정 기록처럼 민감한 데이터를 DB에 평문으로 넣어도 괜찮을까요? 개발 중인 AI 정신건강 앱 플랜티(plan-t)의 저장 구조를 설계하면서 이 고민을 오래 했어요. 결론은 DB 확장이 아니라 앱 레이어에서 AES-GCM으로 필드 단위 암호화하는 쪽이었어요.

pgsodium을 먼저 검토했지만

Postgres에는 libsodium 기반 암호화 확장인 pgsodium이 있어요. DB 안에서 암호화가 끝나니 편해 보였는데, 지금은 Supabase 문서에서 deprecated로 표시돼 있어요. 새 프로젝트가 기대기엔 부담스러운 상태예요.

더 근본적인 이유도 있었어요. 키 관리가 DB와 가까울수록, DB가 뚫렸을 때 암호문과 키가 같이 노출될 위험이 커져요. 앱 레이어에서 암호화하면 DB에는 처음부터 암호문만 도착하고, 키는 서버 환경변수나 시크릿 저장소에만 있어요. SQL 함수 호출로 암호화하는 방식은 쿼리 로그에 평문이 스칠 가능성까지 신경 써야 하는데, 그 경로 자체가 사라지는 것도 마음에 들었어요.

감정 기록 평문API 서버에서 AES-GCM 암호화DB에는 암호문만 저장

구현은 생각보다 단순해요

직접 만들어 보니 핵심 코드는 20줄이 안 됐어요. Python은 cryptography의 AESGCM, Node는 node:crypto의 aes-256-gcm처럼 검증된 표준 구현만 쓰고, 암호화 로직을 자체 제작하지 않는 게 출발점이에요.

지키는 규칙은 세 가지예요.

  • IV는 매번 12바이트 랜덤으로 새로 만들어요. 같은 키에 IV를 재사용하면 GCM에서는 치명적이거든요.
  • 32바이트 키는 코드와 DB 밖, 시크릿 저장소에만 둬요.
  • 레코드마다 키 버전 필드를 붙여서 나중에 키 순환에 대비해요.

적용해 봤더니 암호문 뒤에 인증 태그 16바이트가 붙어서, 저장된 값이 위변조되면 복호화 단계에서 바로 실패해요. 이 무결성 검증이 따라오는 게 GCM을 고른 이유예요.

감수한 트레이드오프

암호화한 필드는 LIKE 검색이나 인덱스를 못 써요. 그래서 검색이 필요한 필드와 통째로 잠글 필드를 스키마 설계 단계에서 먼저 나눴어요. 테스트해 보면 base64로 저장할 때 용량이 약 33% 늘어나는데, 짧은 텍스트 필드라 체감되진 않았어요. 암복호화 지연도 실제로 돌려 보니 밀리초 단위라 병목이 아니었어요.

민감 데이터 암호화는 나중에 붙이는 기능이 아니라, 스키마를 그릴 때 같이 정하는 기본값에 가까워요. 지금 만드는 서비스에 감정이나 건강 관련 필드가 있다면, 어떤 컬럼을 잠글지부터 한 줄 적어 보세요.

#AES-GCM#필드레벨암호화#pgsodium

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글

댓글

아직 댓글이 없어요. 첫 댓글을 남겨주세요.