Case study 02 · Memory isolation

개인 업무기록은 가리고
팀 지식은 쌓이게 만들기

회사에서 팀 메모리를 세우며 개인정보 격리와 누락 없는 축적을 동시에 요구받았고, 채택 이유를 일주일 만에 실측으로 기각했습니다. 계약이 끝난 뒤 같은 문제를 개인 스택 Hindsight-Crew(비공개 리포)로 다시 풀었습니다. 이 문서는 그 둘을 나눠 적습니다.

제조업 기반 중견기업 · 팀 메모리 · 2026.05 - 06 (6주) 이후 개인 스택 · Hindsight-Crew (비공개 리포) Hindsight · Access control · MCP gateway

01문제

에이전트를 업무에 붙이면 사람이 쓴 것보다 훨씬 촘촘한 기록이 남습니다. 무엇을 물었고 무엇을 고쳤고 어떤 파일을 봤는지가 자동으로 쌓입니다. 조직은 이것을 지식 자산으로 모으고 싶고, 개인은 자기 작업 로그가 통째로 열람되는 상태를 받아들일 수 없습니다. 두 요구는 정면으로 충돌합니다.

흔한 타협은 둘 중 하나를 포기하는 것입니다. 전사 공유를 포기하면 지식관리가 안 되고, 개인 격리를 포기하면 도입 자체가 거부됩니다. 이 과제에서는 둘 다 포기하지 않는 대신 격리가 실제로 강제되는지를 증명하는 방식을 요구 사항으로 올렸습니다.

기술적으로 걸린 지점은 명확했습니다. 도입 후보였던 오픈소스 에이전트 메모리 Hindsight는 기본 인증이 단일 공유 키 하나뿐이었습니다. 키를 가진 클라이언트는 누구의 저장소든 조회할 수 있고, 누가 어느 저장소를 볼 수 있는지를 강제하는 계층이 없었습니다. 이 상태로 팀 전체를 붙이면 테넌트 간 열람이 기본 동작이 됩니다.

02제약

03회사에서 한 것 - 팀 메모리 (6주)

1) 자작하지 않고 골랐습니다

직전 넉 달 동안 에이전트 메모리를 직접 만들고 부순 경험이 있었습니다. 바퀴를 다시 만들 시간이 없어 오픈소스 Hindsight를 채택했고, 그 경험은 여기서 고르는 눈으로 쓰였습니다.

2) 개인·팀 bank로 나누고 권한을 등급으로 묶었습니다

직원별 personal bank와 team bank를 구성하고 Recall·Reflect 권한을 보안 등급으로 제어했습니다. 개인 bank는 본인만 엽니다. 팀 bank는 귀속이 기록되고, 개인 → 팀 → 전사 3단계 승격 구조를 뼈대로 잡았습니다.

3) 채택 이유를 실측했습니다

1주 트라이얼에서 운영 기록 211건을 쌓고 채택 근거였던 의미 기반 검색을 쟀습니다. 카테고리 질의 재현율은 15.6%였고 뱅크가 커질수록 나빠졌습니다. 실제로 일하고 있던 것은 단순 적재, 목록 조회, 태그였습니다.

4) 보고 파이프라인의 0.45를 열어봤습니다

임원 일일보고 자동 합성 파이프라인을 사람이 채점했더니 활동 재현율 0.45(환각률 0, 구조 적합도 1.0)가 나왔습니다. 빠진 22건을 한 건씩 열었습니다. 대부분은 제가 임원 보고에서 일부러 뺀 항목이었고 진짜 손실은 1건이었습니다. 고칠 대상은 검색기가 아니라 임원에게 갈 항목을 가르는 분류기였습니다.

5) 운용 원칙으로 대체했습니다

원본을 덮어쓰는 자동 요약 레이어는 껐습니다. 누락이 치명적인 보고 작업은 검색 대신 시간 범위 직조회를 원칙으로 확정했습니다. 채택 근거를 한 주 만에 스스로 반증하고 운용 원칙으로 바꾼 것이 이 6주의 결과입니다.

04그 뒤 개인 스택으로 - Hindsight-Crew

회사 스택은 계약과 함께 끝났습니다. 남은 문제는 업스트림의 단일 공유 키였고, 계약 종료 뒤 Hindsight 위에 격리를 증명하는 스택을 얹었습니다. 비공개 개인 리포이며, 아래는 회사 데이터와 무관한 개인 작업입니다.

1) 강제 지점을 하나로 만들었습니다

메모리 서버 앞에 정책 게이트웨이를 두고 모든 요청이 그 한 곳을 지나게 했습니다. 기본값은 거부입니다. 토큰이 자기 저장소에 대한 권한을 증명하지 못하면 통과하지 못합니다. 업스트림 본체는 수정하지 않았으므로 업그레이드 경로가 살아 있습니다.

2) 헤더만 보지 않고 본문까지 봤습니다

저장소 지정은 헤더에만 있지 않고 호출 본문의 인자에도 들어옵니다. 헤더만 검사하는 구현은 본문에 다른 저장소를 실어 보내는 요청을 그대로 통과시킵니다. 이 우회는 실제로 재현해 본 뒤 막았습니다.

3) 성공 기준을 문장에서 종료코드로 옮겼습니다

검증 스크립트가 9개 게이트를 모두 통과할 때만 통과로 정의했습니다. 상태 확인, 저장소 프로비저닝, 적재-조회 왕복, 격리와 귀속, 적대적 우회 거부, 계약 드리프트, 강제 규칙 동작, 리랭커 구성 일치, 백업 복원. 한 개라도 0이 아니면 배포로 치지 않습니다.

4) 적대적 시나리오를 상시 검사에 넣었습니다

권한 없는 토큰, 경로 우회, 헤더와 본문을 동시에 쓰는 저장소 스머글링, 귀속 위조 4종을 매 실행에서 거부하는지 확인합니다. 회귀 검사로 상주시켜 나중에 생긴 구멍도 잡히게 했습니다.

5) 리랭킹 55.8초를 2초 아래로 내렸습니다

가상머신 CPU에서 35~55초 걸리던 bge-reranker-v2-m3를 표준 해법 TEI(Text Embeddings Inference)로 붙여 실측했더니 Mac GPU 직접 경로보다 10배 느렸습니다. 기각하고 PyTorch MPS 사이드카(FastAPI + sentence-transformers, fp16)를 자작해 같은 호출 형식으로 교체했습니다. 검색 왕복 55.8초 → 1.8~2.6초.

6) 성공 보고를 믿지 않게 됐습니다

저장 호출 18건이 0초 abort로 전부 실패했는데 반환값은 성공이었습니다. 이미 취소된 AbortSignal이 브리지를 건너온 것이 원인이었습니다. 가드와 예외로 바꾸고, 쓰기 성공은 게이트웨이 접근 로그와 받은 쪽 역방향 조회로만 판정하는 절차를 넣었습니다.

7) 같은 조건에서 비교했습니다 - memory-bench

mem0와 Hindsight를 recall 정확도, p50/p95 지연, 오프라인 가능성, 격리 강제, 풋프린트로 같은 조건에서 비교하는 하네스를 열었습니다. mem0 recall 0.0의 원인은 어댑터의 API 오용(지연 0ms + 저장 100%의 지문)이었고, 패자 쪽 오류 필드를 먼저 여는 규칙이 됐습니다.

05결과

회사 팀 메모리 (2026.05 - 06)

항목실측
트라이얼 운영 기록211건 / 1주
의미 검색 카테고리 질의 재현율15.6% (뱅크가 커질수록 악화)
일일보고 활동 재현율 (사람 채점)0.45 · 환각률 0 · 구조 적합도 1.0
누락 22건 전수 개봉 후 진짜 손실1건
승격 구조개인 → 팀 → 전사 3단계

Hindsight-Crew (계약 종료 뒤, 비공개 개인 리포)

항목실측
통과 기준 실행 게이트9개 전부 GREEN
매 실행 거부를 확인하는 적대적 우회4종
리랭킹 검색 왕복55.8초 → 1.8~2.6초
완전 오프라인 구성 런타임 메모리1.5-2.1GB
상시 운용개인 런타임 4개의 메모리
재현율 15.6%가 설계 근거가 됐습니다. 이 값을 모르고 검색에 보고를 맡기면 빠진 기록을 아무도 눈치채지 못합니다. 측정하지 않은 것을 측정했다고 말하지 않는 것이 이 시스템의 유일한 안전장치입니다.

근거 · 재현율 0.45의 분모 ↗ · CLAUDE.md 243줄 → 77줄 ↗ · TEI가 내 맥에서 10배 느렸다 ↗ · 저장 18건 보고, 실제 0건 ↗

06재현 가능한 부분

다음은 Hindsight-Crew(비공개 개인 리포)에 구현돼 있습니다. 공개된 벤치 하니스는 memory-bench(MIT)입니다.

회사 쪽에서 이식 가능한 것은 개인 → 팀 → 전사 승격 구조 설계, 시간 범위 직조회 원칙, 보고 합성 파이프라인의 사람 채점 방식입니다. 이식되지 않는 것은 고객사의 조직 구조와 권한 등급 매핑, 그리고 실제 업무 데이터입니다.

격리 요건이 있는 지식관리 도입을 검토 중이라면

bk@bkan.dev 문의 폼은 두지 않습니다. 메일 한 통이면 됩니다.