Compartment 에이전트 메모리 암호화 및 오프라인 보안 가이드
Compartment를 사용하여 로컬 환경에서 에이전트 메모리를 암호화하는 방법을 설명합니다. XChaCha20-Poly1305 및 Argon2id 보안 모델의 실제 보호 범위와 마스터 키 분실 시 발생하는 데이터 복구 불가 문제 등 운영 시 주의사항을 상세히 다룹니다.
Compartment의 차별점
Compartment는 모든 기록을 생성된 머신에서 암호화된 상태로 유지하며 네트워크 서비스와 통신하지 않는 에이전트 메모리 저장소입니다. 이 도구는 에이전트 메모리 분야의 다른 제품들과 두 가지 측면에서 차별화됩니다. 볼트(vault)는 사용자의 암호로만 열 수 있는 단일 밀봉 파일이며, 임베딩 단계가 로컬에서 실행되므로 메모리 텍스트가 벡터로 변환되기 위해 외부로 전송되는 일이 없습니다. 2026년 8월 10일에 4.6.0 버전이 릴리스되었으며, 라이선스는 Apache-2.0이고 PyPI를 통해 설치할 수 있습니다.
이는 위협 모델에 관한 주장이므로, 본 가이드에서는 이를 하나의 주장으로 간주합니다. 저장 데이터 암호화(encryption at rest)와 오프라인 설계는 특정 항목들을 보호하지만, 다른 부분은 열려 있으며 바로 그 간극에서 운영 2일 차의 문제들이 발생합니다.
본 가이드는 2026년 8월 11일에 확인한 프로젝트 자체 문서와 릴리스 노트를 따릅니다. Compartment는 명령줄 도구 외에도 macOS의 메뉴 막대 항목, Windows의 알림 영역 아이콘을 포함한 데스크톱 애플리케이션을 제공하며, 암호 입력 프롬프트는 자동화된 컨테이너에서 제어할 수 없습니다. 아래 내용은 측정된 동작이 아닌 문서화된 동작으로 간주하십시오. 실제 데이터를 다루기 전에 여분의 머신에서 먼저 실행해 보시기 바랍니다.
저장 데이터 암호화가 실제로 보호하는 것
볼트는 AEAD(인증된 암호화 및 관련 데이터) 암호 방식인 XChaCha20-Poly1305로 봉인되며, 마스터 키를 보관하는 키슬롯은 느린 속도와 많은 메모리 사용을 위해 설계된 비밀번호 해싱 함수인 Argon2id로 래핑됩니다. 여기에는 두 가지 결과가 따릅니다. 도난당한 디스크, 오래된 백업, 또는 지원 티켓에 첨부된 파일 사본은 단순한 바이트 데이터일 뿐입니다. 또한 단일 비트만 반전되어도 파일이 열릴 때 인증에 실패하므로, 데이터 손상은 잘못된 결과가 아닌 명확한 오류로 나타납니다.
임베딩 벡터 역시 암호화되는데, 이는 생각보다 훨씬 중요합니다. 임베딩은 해시가 아닙니다. 임베딩 역전 연구에 따르면 벡터만으로도 원본 텍스트의 읽을 수 있는 파편을 복구할 수 있으므로, 암호화된 데이터베이스 옆에 평문 벡터 인덱스를 두는 것은 데이터베이스를 열어두는 것과 다름없습니다. Compartment는 평문 인덱스를 디스크에 기록하지 않습니다.
삭제는 실제 삭제를 의미합니다. 각 레코드는 고유한 키를 가지며, compartment forget --shred는 해당 키를 파기합니다. 따라서 남겨진 암호문은 본인을 포함한 누구도 복구할 수 없습니다. 데이터베이스 파일에서 행을 삭제하면 일반적으로 덮어쓰기 전까지 빈 페이지에 읽을 수 있는 상태로 남아 있는 것과 비교해 보십시오.
오프라인은 나머지 절반의 핵심입니다. 아무것도 업로드되지 않으므로 사용자의 기억을 보관하는 벤더 계정도 없으며, 기억을 유출할 수 있는 API 키도 존재하지 않습니다.
Compartment가 보호하지 않는 영역
보호 범위는 볼트(vault) 경계에서 멈추며, 그 경계는 생각보다 가깝습니다.
에이전트는 평문을 읽습니다. Recall은 메모리를 복호화하여 에이전트에게 텍스트를 전달합니다. 해당 에이전트가 호스팅된 모델인 경우, 메모리는 컨텍스트 윈도우의 다른 모든 데이터와 마찬가지로 다음 프롬프트에 포함되어 모델 제공자에게 전송됩니다. 저장 데이터 암호화(Encryption at rest)는 파일을 보호할 뿐, 검색 과정까지 보호하지는 않습니다. 따라서 저장소가 암호화되어 있다고 해서 AI 에이전트에서 비밀을 제외하는 방법의 규칙이 완화되지는 않습니다. 메모리로 저장된 비밀번호는 결국 프롬프트에 자동으로 붙여넣도록 설정한 비밀번호와 다를 바 없습니다.
실행 중인 머신에서 잠금 해제된 볼트는 열려 있는 상태입니다. 프로젝트 보안 노트에 명시된 내용입니다. 볼트가 잠금 해제되어 있는 동안 마스터 키와 작업 세트는 RAM에 상주합니다. Python은 버퍼가 완전히 삭제됨을 보장할 수 없으며, 스왑(swap)이나 최대 절전 모드 이미지(hibernation image)가 해당 메모리 내용을 디스크에 기록할 수 있습니다. 사용자의 권한으로 실행되는 악성 코드는 암호를 해독할 필요가 없습니다. 이미 잠금이 해제된 볼트에 정보를 요청하면 되기 때문입니다.
호출자 식별은 선언적입니다. 네임스페이스는 호출자별로 제한할 수 있지만, 호출자 이름은 호스트 프로세스에서 전달됩니다. 따라서 이름을 속이는 호스트는 자신이 주장하는 권한을 그대로 부여받습니다. 네임스페이스 권한은 조직적인 구분일 뿐, 적대적인 로컬 프로그램에 대한 보안 경계가 아닙니다.
파쇄(Shredding)는 복사본에 도달할 수 없습니다. forget --shred은 현재 파일 내부의 키를 파괴합니다. 파쇄 이전에 생성된 백업본에는 여전히 해당 레코드가 남아 있으며, 당시의 암호(passphrase)로 열 수 있습니다.
취약한 암호는 모든 보안을 무력화합니다. Argon2id는 추측 시도마다 많은 비용을 발생시키지만, 단어 목록(word list)에 포함된 암호까지 보호해주지는 않습니다.
고정된 릴리스에서 Compartment 설치하기
Compartment는 Python 3.11 이상이 필요합니다. 이 프로젝트는 빠르게 발전하고 있으며 2026년 8월 10일 기준으로 PyPI에 30개의 버전이 등록되어 있으므로, 설치 당일의 최신 버전을 사용하기보다 특정 버전을 고정하여 설치하십시오.
python3 --version
pip install "compartment==4.6.0"
compartment --version
compartment initcompartment --version은 고정했던 버전을 출력해야 합니다. 셸에서 compartment: command not found라고 응답한다면 설치 디렉터리가 PATH에 포함되지 않은 것이며, 대부분의 시스템에서 해당 디렉터리는 ~/.local/bin입니다. pipx install compartment==4.6.0와 uv tool install compartment==4.6.0는 자체 경로를 관리하므로 이러한 문제를 방지합니다.
compartment init은 암호를 두 번 입력하도록 요청하며 입력 내용은 화면에 표시되지 않습니다. 해당 암호가 유일한 키입니다. 이 프로젝트는 비밀번호나 복구 문구를 생성하지 않으며, 이는 의도된 설계입니다. 사용자가 보유하지 않은 자격 증명을 소프트웨어가 별도로 보관하지 않습니다.
연결을 설정하기 전에 결과를 확인하십시오.
compartment status정상적인 볼트는 잠금 해제 상태라고 보고합니다. 잠겨 있다고 표시되면 compartment unlock을 실행하고 암호를 입력하십시오. 볼트를 여는 데 필요한 자격 증명이 부팅 시마다 생성되는 비밀값에 의존하므로, 재시작하면 다시 잠깁니다. macOS에서는 compartment unlock --keychain을 사용하여 해당 자격 증명을 시스템 키체인에 저장함으로써 재부팅 후에도 잠금 상태를 유지하지 않도록 설정할 수 있습니다.
데이터가 실제로 저장되는 위치
기본 볼트는 ~/.compartment/memory.vault입니다. 모든 명령어에서 --vault PATH 플래그를 사용하거나 COMPARTMENT_VAULT 환경 변수를 설정하여 다른 위치를 지정할 수 있습니다.
이 파일 하나가 전체 저장소입니다. 파일은 형식 버전과 Argon2id 키 슬롯을 담은 헤더로 시작하며, 그 뒤에 암호화된 페이로드, 그리고 새로운 메모리가 추가될 때마다 기록되는 저널 항목들이 이어집니다. 각 저널 항목은 길이 정보와 해당 길이에 대한 CRC(순환 중복 검사)로 구성됩니다. 따라서 충돌로 인해 쓰기 작업이 중단되더라도 데이터로 읽히지 않고 잘린 항목으로 인식됩니다. 압축(Compaction) 과정에서는 볼트를 직렬화하여 임시 파일에 쓰고, fsync를 수행한 뒤 이름을 변경하여 교체합니다. 덕분에 읽기 작업 중에 절반만 기록된 볼트를 마주할 일은 없습니다.
이 구조의 유용한 결과는 백업 스크립트가 단 하나의 경로만 복사하면 된다는 점입니다. 반면 불편한 점은 grep으로 검색할 수 없으며 텍스트 편집기로 복구할 수 없다는 것입니다. cat로 읽고 git에 커밋할 수 있는 메모리를 원한다면, Memmy의 일반 로컬 메모리 파일이 정반대의 절충안입니다. 노트북 도난을 우려하는지, 도구의 고장을 우려하는지에 따라 두 방식 모두 합리적인 선택이 될 수 있습니다.
compartment uninstall은 소프트웨어를 제거하지만 볼트는 유지합니다. --purge는 의도한 경우에만 전달하십시오.
에이전트에 연결하기
단일 명령어로 지원되는 클라이언트를 연결할 수 있습니다.
compartment integrate --list
compartment integrate claudeClaude Code의 경우 MCP(model context protocol) 서버 항목을 작성하고 ~/.claude/settings.json에 PostToolUse 훅을 삽입하며, 기존 파일을 먼저 백업합니다. 또한 ~/.claude/skills/ 아래에 /compartmentalize 스킬을 설치하고, 에이전트에게 Compartment가 기존에 사용하던 파일 기반 메모리를 대체한다는 내용을 알리는 관리형 블록을 ~/.claude/CLAUDE.md에 추가합니다. 다음 두 가지를 모두 확인하십시오.
compartment hook status
compartment recent수동으로 서버를 등록하려면 다음을 사용하십시오.
claude mcp add --scope user compartment -- \
compartment --vault ~/.compartment/memory.vault --caller claude-code serveMCP를 지원하는 다른 호스트도 동일한 서버를 사용할 수 있으며, 각 호스트마다 고유한 호출자 이름을 지정해야 합니다.
{ "mcpServers": { "compartment": {
"command": "compartment",
"args": ["--vault", "/path/to/memory.vault",
"--caller", "your-agent-name", "serve"] } } }각 호스트에 서로 다른 --caller 값을 부여하십시오. 이 값은 감사 로그에 기록되는 레이블이자 네임스페이스 권한이 부여되는 기준 키이므로, 이름을 공유하면 두 용도 모두 사용할 수 없게 됩니다.
Claude Code가 이미 자체 메모리 파일에 정보를 기록하고 있었다면, compartment import-claude --dry-run을 통해 데이터가 이동하기 전에 어떤 내용이 이동할지 미리 확인할 수 있습니다. Claude Code가 메모리 파일에 보관하는 데이터를 먼저 읽어 보십시오. 1년 치의 메모를 새로운 볼트(vault)로 가져오면 의도치 않은 정보들로 메모리 저장소가 가득 찰 수 있기 때문입니다.
로컬 볼트의 속도
다음은 프로젝트에서 개인용 볼트에 대해 공식적으로 발표한 수치입니다. 이 수치는 본 환경에서 직접 측정한 결과가 아니라 프로젝트 문서에 명시된 내용입니다.
The data behind this chart
[
{
"label": "Store one memory, end to end",
"latency_ms": 40
},
{
"label": "Embed one memory, bundled model",
"latency_ms": 25
},
{
"label": "Hybrid search, median",
"latency_ms": 11.6
},
{
"label": "Vector search at 20k records, p95",
"latency_ms": 0.68
}
]메모리 하나를 저장하는 데 걸리는 시간은 40 ms이며, 2만 개의 레코드를 대상으로 하는 벡터 검색은 95번째 백분위수 기준으로 0.68 ms가 소요됩니다. 메모리를 로컬에 유지해야 한다는 프로젝트 측의 주장은 산술적 근거에 기반합니다. 호스팅된 메모리 API에 네트워크 왕복을 한 번 수행하는 비용이 이곳의 전체 하이브리드 검색 중앙값인 11.6 ms보다 큰 경우가 많기 때문입니다.
검색 수치에는 두 가지 설계적 특징이 반영되어 있습니다. 레코드가 2만 개 미만일 때는 Compartment가 모든 벡터와 쿼리를 비교하므로 근사치가 아닌 정확한 재현율(recall)을 보장합니다. 2만 개를 초과하면 속도를 위해 재현율을 일부 희생하는 근사 인덱스 방식인 HNSW(hierarchical navigable small world)로 전환됩니다. 또한 볼트는 임베딩 모델의 SHA-256 해시를 기록하며, 다른 모델을 사용할 경우 볼트를 열지 않습니다. 서로 다른 모델에서 생성된 벡터는 오류 메시지 없이 비교될 수 있으나, 그렇게 반환된 점수는 아무런 의미가 없기 때문입니다.
백업과 내년에도 열 수 있는 복사본
잠긴 볼트는 하나의 이동 가능한 파일이므로, 이를 옮기는 것은 곧 복사입니다.
compartment lock
scp ~/.compartment/memory.vault other-machine:
compartment --vault memory.vault unlock먼저 잠가야 합니다. 에이전트가 기록 중일 때 복사하면 저널 항목이 추가되는 중간에 캡처될 수 있습니다. CRC 프레이밍을 통해 리더가 마지막 조각을 건너뛸 수는 있지만, 그 안의 메모리는 사라집니다. compartment lock --sign는 Ed25519 매니페스트로 파일을 봉인하므로, 수신하는 기기는 암호를 보유하지 않고도 복사본이 온전하게 도착했는지 검증할 수 있습니다.
파일이 이미 봉인되어 있으므로 일반적인 클라우드 스토리지를 백업 장소로 사용해도 무방합니다. 이것이 바로 저장 데이터 암호화(encryption at rest)가 직접적인 이점을 제공하는 지점입니다. 백업 대상은 메모리를 전혀 볼 수 없습니다.
두 가지 주의 사항이 있습니다. 파쇄(shredding)는 백업본까지는 도달하지 못합니다. 따라서 오늘 암호화 파쇄한 기록이라도 지난주 암호를 가진 사람이라면 지난주 복사본에서 여전히 읽을 수 있습니다. 또한 compartment export --plaintext은 전체 볼트를 암호화하지 않은 상태로 기록합니다. 이는 다른 시스템으로 마이그레이션할 때는 적절한 도구이지만, ~/Downloads에 남겨두어서는 안 되는 파일입니다.
복사본은 적게 유지하고 날짜를 기록하십시오. 아무도 정리하지 않는 메모리 저장소는 부채로 변합니다. 이것이 바로 오래된 에이전트 메모리가 검색 결과를 조용히 오염시키는 이유에 대한 논거입니다.
키 관리, 교체 및 2단계 인증
compartment rekey
compartment 2fa enable
compartment 2fa statusrekey는 현재 파일의 키 슬롯에 있는 마스터 키를 다시 암호화하여 암호를 변경합니다. 이전 사본은 변경 전 바이트가 봉인되어 있고 이를 수정할 방법이 없으므로 기존 암호를 그대로 유지합니다. 사본도 함께 교체하거나, 폐기된 암호로도 여전히 데이터가 열릴 수 있음을 인지해야 합니다.
2fa enable은 키 파일을 2단계 인증 요소로 추가합니다. 키 유도 과정에서 암호와 결합되므로 볼트를 열려면 두 가지가 모두 필요합니다. 이는 분실할 수 있는 항목이 두 배로 늘어난다는 의미이기도 합니다. 키 파일은 볼트가 저장된 장비와 분리하여 보관하십시오.
스크립트 및 CI(지속적 통합) 환경에서는 COMPARTMENT_PASSPHRASE 환경 변수를 통해 암호를 전달할 수 있으며, unlock --passphrase-stdin은 파이프를 통해 암호를 읽어 들입니다. 파이프 사용을 권장합니다. 환경 변수는 동일한 사용자가 소유한 다른 프로세스에서 읽을 수 있으며, 작업 로그에 남을 가능성이 크기 때문입니다.
감사 기록은 해시 체인으로 연결되어 있으며, compartment audit verify는 이를 추적하여 첫 번째로 손상된 링크를 보고합니다. 복원 작업 후에는 반드시 이 명령을 실행하십시오. 파일이 조용히 잘려 나간 경우 이때 발견되기 때문입니다.
암호를 분실하면 어떻게 되는가
아무 일도 일어나지 않으며, 이는 의도된 설계입니다. 암호 재설정이나 복구 문구는 존재하지 않으며, 문의할 곳도 없습니다. 사용자의 기억과 선택적으로 생성한 키 파일 외에는 키의 사본이 어디에도 존재하지 않기 때문입니다. 볼트는 무작위 데이터로 보이는 파일 상태로 남게 됩니다.
따라서 복구 계획은 볼트를 위한 것이 아닙니다. 암호를 위한 계획입니다. compartment init을 실행하는 날 비밀번호 관리자에 암호를 기록하십시오. 그런 다음 테스트를 수행하십시오. 볼트를 잠그고, 기록해 둔 암호만 사용하여 잠금을 해제한 뒤, 정상적으로 작동하면 에이전트가 볼트를 채우도록 하십시오.
Compartment 또는 메모리 서버
Compartment는 설계상 단일 머신에서 사용하도록 되어 있습니다. 데이터를 공유하려면 잠긴 파일을 복사하거나 내보내기 및 가져오기를 수행해야 합니다. 동시 쓰기 기능은 없으므로, 노트북과 워크스테이션이 동일한 파일을 가리키고 있으면 서로의 작업을 덮어쓰게 됩니다.
여러 머신이 동시에 동일한 메모리를 사용해야 한다면, 이는 서버 수준의 문제입니다. VPS에서 직접 호스팅하는 Mem0 메모리 서버가 이에 대한 해결책이 됩니다. 하나의 엔드포인트에 다수의 클라이언트가 연결되며, 노트북의 수명과 관계없이 메모리가 유지됩니다. 비용에 대해서는 명확히 인지해야 합니다. 해당 서버는 저장된 데이터를 읽을 수 있는 프로세스를 실행하므로, 이제 위협 모델에는 VPS 자체와 해당 API에 접근할 수 있는 모든 주체가 포함됩니다.
실제로 우려하는 데이터 손실의 유형에 따라 선택하십시오. 노트북 도난이나 서비스 제공업체가 메모를 읽는 것이 걱정된다면, 암호화된 로컬 볼트가 더 강력한 해결책입니다. 반면 머신을 전환할 때마다 모든 내용을 잊어버리는 현상이 문제라면, 서버 방식이 적합합니다.
FAQ
Compartment의 암호화는 무엇을 보호합니까?
파일을 보호합니다. 볼트는 XChaCha20-Poly1305로 봉인되고, 키 슬롯은 Argon2id로 래핑되며, 임베딩 벡터 또한 암호화됩니다. 따라서 디스크를 도난당하거나 오래된 백업본을 확보하더라도 읽을 수 없는 바이트 데이터만 남게 됩니다. 다만, 실행 중인 머신에서 잠금이 해제된 볼트는 보호하지 못합니다. 볼트가 열려 있는 동안 마스터 키가 RAM에 상주하기 때문입니다. 또한, 리콜(recall)을 통해 평문으로 반환된 메모리를 에이전트가 어떻게 처리할지는 제어하지 않습니다.
Compartment가 오프라인 상태라면, 모델 제공자로부터 메모리를 보호할 수 있습니까?
메모리를 불러오기 전까지만 보호됩니다. 저장과 검색은 네트워크 연결 없이 이루어지며 임베딩 모델도 로컬에서 실행되므로, 기록 시점에는 머신 외부로 데이터가 유출되지 않습니다. 읽기 시점에는 에이전트가 평문을 수신하며, 해당 에이전트가 호스팅 모델인 경우 메모리는 프롬프트에 포함되어 다른 컨텍스트 윈도우와 마찬가지로 제공자에게 전송됩니다. 자격 증명(credential)은 절대 메모리로 저장하지 마십시오.
Compartment 암호를 분실하면 어떻게 됩니까?
볼트는 의도적으로 복구할 수 없게 설계되었습니다. Compartment는 시드나 복구 문구를 생성하지 않으며, 사용자가 보유하지 않은 자격 증명을 보관하지 않으므로 재설정할 방법이 없습니다. 암호는 비밀번호 관리자에 저장하고, 2FA 키 파일은 볼트가 저장된 머신과 분리하여 보관하십시오. 또한, 중요한 데이터를 저장하기 전에 복사본을 만들어 잠금 해제가 가능한지 먼저 확인하십시오.
두 대의 머신에서 하나의 Compartment 볼트를 공유할 수 있습니까?
동시에는 불가능합니다. 잠긴 볼트는 하나의 휴대 가능한 파일이며, 권장되는 방식은 볼트를 잠그고 복사한 뒤 다른 머신에서 --vault을 사용하여 잠금을 해제하는 것입니다. 동시 접근 기능은 없으므로 두 대의 머신이 하나의 파일에 동시에 쓰기를 시도하면 메모리가 손실됩니다. 동시 접근이 필요하다면 메모리 서버를 실행하십시오.