당신의 AI 메모리는 방치되어 있다: mem0, Zep, MemOS가 하지 않은 것을 우리가 먼저 했다
요약
본 기사는 AI 에이전트 메모리 저장소의 보안 취약점을 지적하며, 기존 오픈 소스 솔루션(mem0, Zep, MemOS 등)들이 자체 호스팅 환경에서 전송 및 저장 데이터 암호화에 미흡하다고 비판합니다. 이에 필자는 TLS를 기본 탑재한 L2.5 버전을 출시하여 엔터프라이즈급 보안을 강화했습니다.
핵심 포인트
- AI 메모리 엔진은 회사의 '두 번째 뇌'로, 높은 수준의 보안이 필수적입니다.
- 기존 오픈 소스 솔루션들은 자체 호스팅 시 기본적으로 평문(plaintext)으로 운영될 위험이 높습니다.
- L2.5 버전에서는 TLS를 기본 탑재하여 gRPC와 HTTP 통신을 암호화하고 엔터프라이즈 환경에 적합하게 개선했습니다.
아무도 답하고 싶어 하지 않는 질문
먼저 불편한 질문을 던지겠습니다. 당신의 에이전트 메모리 저장소와 회사 데이터베이스 사이에는 몇 개의 암호화 계층이 존재합니까?
회사 데이터베이스는 TLS, 저장 시 암호화(at-rest encryption), 감사 추적(audit trails), 규정 준수 인증을 갖추고 있습니다. 반면, 메모리 엔진은 훨씬 더 민감한 것을 담고 있습니다. 즉, 모든 고객 대화의 원문 기록, 모든 비즈니스 결정 뒤에 숨겨진 전체 맥락, 그리고 모든 직원의 선호도와 습관입니다. 이것은 단순한 로그가 아닙니다. 이것은 회사의 두 번째 뇌(second brain)입니다.
이제 주류 오픈 소스 메모리 엔진들이 자체 호스팅을 어떻게 처리하는지 살펴보겠습니다.
- mem0 (48K 스타, 사실상의 카테고리 리더): 오픈 소스 에디션은 기본적으로 평문 HTTP를 제공하며, 저장 계층 역시 암호화되어 있지 않습니다. 암호화를 원한다면? 공식적인 조언은 "암호를 지원하는 벡터 데이터베이스(vector database)를 직접 플러그인 하라"입니다. 전송 암호화에 대한 언급은 문서에서 거의 찾아볼 수 없습니다.
- Zep: 커뮤니티 에디션은 사용 중단되었습니다. 자체 호스팅을 한다는 것은 Graphiti와 외부 그래프 데이터베이스(external graph database)를 직접 조립해야 하며, 전송 보안(transport security)은 전적으로 사용자에게 달려 있습니다.
- MemOS: 아름다운 논문을 가진 학술 프로젝트이지만, 보안 메커니즘에 대한 공개적인 설명이 거의 없습니다. 이는 비판이라기보다는 연구 프로젝트가 단순히 다른 우선순위를 갖기 때문입니다.
올해의 16차원 메모리 프레임워크 벤치마크에서 나온 한 세부 사항은 충격적입니다. 여덟 개의 프로젝트 중 단 하나만이 네이티브 저장 시 암호화(native at-rest encryption)를 제공했습니다. 전송 암호화는 더욱 심각합니다. 거의 모든 자체 호스팅 빠른 시작 가이드(quickstart)가 http://localhost:PORT로 시작하며, 이 http URL은 그대로 프로덕션 환경에 복사됩니다.
우리가 이 프로젝트들이 나쁘다고 말하는 것은 아닙니다 — 우리는 mem0의 사용 편의성에 대해 공개적으로 존중을 표했습니다. 우리가 말하고자 하는 바는 이것입니다. 메모리 엔진이 개인용 장난감에서 공유 엔터프라이즈 인프라로 이동함에 따라, "기본 평문(plaintext by default)" 설정은 언젠가 사고를 유발할 것입니다.
따라서 L2.5에서는 TLS를 탑재했습니다. 그리고 저희만의 방식으로 구현했습니다.

L2.5 TLS: 두 개의 환경 변수와 네 가지 프로토콜 스택을 함께 암호화하다
NylonME의 TLS 설계 목표는 한 문장으로 요약할 수 있습니다. 켜는 것이 수동 작업을 요구해서는 안 된다.
NYLON_TLS_CERT=server.crt
NYLON_TLS_KEY=server.key
두 변수를 설정하기만 하면 gRPC, HTTP, 웹 콘솔, 그리고 MCP — 네 가지 프로토콜 스택 모두가 TLS로 전환됩니다. 만약 이들을 설정하지 않으면 모든 것이 이전과 똑같이 평문(plaintext)으로 유지됩니다. 인증 기능 출시 때와 같은 철학입니다. 보안 기능은 준비되어 있지만, 기존 사용자에게 금요일 밤에 설정을 변경하도록 강요하지 않습니다.
진정한 기술력은 세 가지 눈에 띄지 않는 결정에 숨어 있습니다.

결정 1: 절반만 설정된 구성은 충돌해야 하며, 크게 충돌해야 한다
NYLON_TLS_CERT만 설정하고 키는 없는 경우 — 어떻게 해야 할까요?
많은 시스템들은 이렇게 답합니다.
저희 구현에서는 핸드셰이크 실패가 해당 연결 하나에만 비용을 지불하게 할 뿐이며, accept 루프는 계속 실행됩니다. 암호화 계층은 평문 계층보다 더 강력해야 합니다. 그렇지 않으면 공격자들이 DoS 트리거를 더 편리하게 만들도록 고맙게 여길 것입니다.
결정 3: 보안 기능의 최악의 적은 '켜져 있다고 생각하는 것'
이것은 L2.5에서 가장 가치 있는 버그이며, 보편적인 교훈을 주기 때문에 그 가치가 높습니다.
저희 MCP 원격 브릿지는 원격 엔진에 대한 https 연결을 지원합니다. 코드는 작성되었고, https:// 매개변수가 존재하며, 테스트도 통과했습니다. 하지만 L2.5 통합 과정에서 다음과 같은 것을 발견했습니다. 브릿지가 https 시나리오에서 조용히 평문으로 폴백(fallback)하는 것입니다. 사용자들은 성공적인 연결을 보고하고, 모든 것이 평소처럼 작동하는 것처럼 보입니다 — 단지 데이터가 네트워크상에 노출된 채로 전송되고 있으며, 아무도 모릅니다.
보안 기능이 깨지는 가장 위험한 방식은 다음과 같습니다: 오류를 내며 실패하는 것이 아니라, 완벽하게 정상적으로 보이는 상태에서 실패하는 것입니다. 이 버그는 모니터링 경고에 의해 포착된 것이 아니라, 저희의 e2e 테스트가 rcgen을 사용하여 실제 인증서를 발행하고 실제 핸드셰이크를 수행했기 때문에 발견되었습니다 — 34개의 테스트 케이스 모두 녹색이었으며, 추가로 네 라운드의 실시간 스모크 테스트도 진행했습니다. 만약 테스트들이 단순히 '설정 파싱 성공'까지만 모의(mock)했다면, 이 버그는 어떤 사용자의 보안 감사에서 발견될 때까지 존재했을 것입니다.
이 교훈은 별도의 항목을 가질 자격이 있습니다: 보안 기능 테스트는 암호화가 실제로 발생할 때까지 실행되어야 합니다. 설정 파싱 성공은 암호화가 발생했음을 의미하지 않으며, 연결 성공은 핸드셰이크가 수행되었음을 의미하지 않습니다.
클라이언트 측도 준비되었습니다: Python SDK 0.2.4는 https 및 tls_ca 매개변수를 지원하며, MCP 브릿지와 CLI가 이를 전달합니다. 클라이언트의 경우, 여전히 단 하나의 변수 변경만 필요합니다.
점수(Scores), 이왕 온 김에: 이중 벤치마크, 전체 분할, 모두 80+
이 게시물의 주인공은 보안이지만, 이참에 한 달간의 평가 진행 상황을 공유합니다. 왜냐하면 '엔터프라이즈(enterprise)'라는 단어는 '안전하다(secure)'고 말하기 전에 증거가 필요하기 때문입니다:
| 벤치마크 | 스플릿 | Evidence recall@10 | End-to-end J |
|---|---|---|---|
| LoCoMo | official full (10 세션, 1,536 질문) | 85.9% | 82.9% |
| LongMemEval-S | official full (500 질문) | 97.8% | 83.2% |
'풀(full)'이라는 단어는 세 번이나 언급되었고, 잠시 멈춰서 살펴볼 가치가 있습니다: 두 가지 벤치마크 모두 공식 풀 스플릿이며, 둘 다 80%를 초과합니다. LoCoMo의 82.9%는 동일한 비교 프로토콜 하에서 발표된 모든 시스템을 능가하며(논문에 주의사항이 완전히 공개됨); LongMemEval-S의 500개 질문 풀 스플릿은 350K 노드 그래프에서 실행되었으며, 검색 상태를 비트 단위로 작은 저장소 테스트와 비교했습니다. 20배 규모 확장에도 불구하고 정밀도 손실은 없었습니다.
우리가 조용히 자랑스러워하는 두 가지 추가적인 점이 있습니다. 이 중 어느 것도 점수와는 관련이 없습니다:
- 진행 과정에서 '잘못된 회귀(false regression)'를 포착했습니다: 한 질문 유형의 점수가 4.3점 하락했고, 우리는 엔진 회귀를 확인하기 위해 코드베이스의 절반을 거의 분할해야 했습니다. 질문별 로그 포렌식 분석 결과 답변 모델 자체가 그 아홉 일 동안 더 신중해진 것으로 나타났습니다. 같은 증거라도 9월에는 자신 있게 답변했지만 10월에는 거부했습니다. 이제 우리는 규칙을 세웠습니다: 주간 단위로 몇 개의 질문에서 발생하는 변동은 절대 신뢰하지 않으며, 모든 결론은 동일 기간의 쌍별 비교에서 나와야 합니다.
- 배치 평가 과정에서 두 번이나 인프라 오염(API 할당량 경쟁, 호스트 메모리 압력)을 겪었습니다. 매번 질문별 쌍별 진단을 통해 이를 확인하고, 해당 실행을 폐기한 후 재실행했습니다. 논문에는 이러한 오염과 제외 방법론까지 공개합니다 — 왜냐하면 우리는 깨끗한 데이터가 더러운 데이터를 어떻게 처리했는지 정확히 보여줄 때만 신뢰를 얻는다고 믿기 때문입니다.

우리가 아직 하지 않은 한 가지 — 먼저 말하다
TLS는 전송 중(in transit) 데이터를 보호합니다. 하지만 디스크에 저장되는 메모리 파일(WAL, 스냅샷, 벡터 인덱스)은 오늘날까지도 평문입니다. 저장 시 암호화(at-rest encryption)는 로드맵에 있지만 아직 구현되지 않았으며, 우리는 그렇게 가장할 생각이 없습니다.
이는 오늘의 엔터프라이즈 배포 결정에는 영향을 미치지 않습니다 (대부분의 기업은 어차피 LUKS나 BitLocker와 같은 디스크/파일시스템 계층 암호화를 데이터베이스에 사용합니다). 하지만 저희는 메모리 엔진이 네이티브 옵션을 제공해야 한다고 믿습니다. 이것이 출시되면 동일한 배포 표준을 충족할 것입니다: 기본적으로 비활성화(off by default), 동작 변화 없음, 설정 오류 시 즉시 실패(half-config fail-fast), 실제 테스트를 거친 실제 암호화 기능.
마지막 말들
저희는 오랫동안 하나의 믿음을 가지고 있었습니다: 메모리 엔진은 데이터베이스가 걸었던 길을 따를 것이라는 것입니다 — 처음에는 개인적인 장난감, 그다음 팀 도구, 그리고 마침내 엔터프라이즈 인프라스트럭처 순서로 말입니다. 데이터베이스가 이 길을 걷는 데 40년이 걸렸다면, 메모리 엔진은 단 4년만 필요할 수도 있습니다.
하지만 절대 되돌아가서는 안 되는 길이 하나 있습니다: 데이터베이스 업계는 수많은 보안 사고를 겪고 나서야 비로소 암호화를 기본값으로 만들었습니다. 메모리 엔진은 데이터베이스보다 더 민감한 것을 저장합니다 — 따라서 같은 대가를 치르면서 그 교훈을 배울 수는 없습니다.
L2.5는 저희가 만든 첫 번째 클래스일 뿐입니다. 감사(Audit), 멀티테넌시(multi-tenancy), 백업 드릴은 이전에 제출되었습니다 (Post 10 참조); 저장 시 암호화는 곧 제공될 예정입니다. 만약 여러분도 엔터프라이즈급 에이전트를 구축하고 있다면, 저희 코드를 읽어보세요 — 단지 환경 변수 두 개만 변경하면 되며, 오늘 밤부터 여러분의 메모리 스토어를 맨몸으로 운영하는 것을 멈출 수 있습니다.
NylonME: Apache-2.0 라이선스의 Rust 단일 바이너리 메모리 엔진입니다. MCP를 통해 Claude Code / Codex / VSCode / Qoder에 2분 만에 플러그인할 수 있습니다. GitHub에서 nylon-memory/NylonME를 찾거나, 저희의 Quick Start부터 시작해 보세요.
본 게시물에 있는 모든 벤치마크 숫자는 저장소의 docs/LOCOMO_BENCHMARK.md에서 재현 가능합니다. 논문(전체 제거 분석 및 여덟 가지 부정적 결과 포함)이 준비되었으며, 현재 arXiv 제출을 진행 중입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
