SSD Nodes Learn 8GB RAM — 연 $66
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-01

Memmy VPS 로컬 AI 에이전트 메모리 허브 구축

Memmy로 여러 AI 에이전트가 공유하는 SQLite 메모리 저장소를 Ubuntu VPS에 구축합니다. 소스 빌드부터 포트 18960 서비스 실행, 모든 데이터를 로컬에 보관하는 방법을 설명합니다.

Memmy의 기능과 저장 데이터

Memmy는 자체 VPS(virtual private server)에서 실행되는 AI 에이전트용 로컬 메모리 허브입니다. 에이전트가 학습한 내용을 하나의 SQLite 데이터베이스에 저장하며, 서버의 모든 에이전트가 동일한 저장소를 읽고 씁니다. 이 프로젝트는 MemTensor에서 memmy-agent하며 MIT 라이선스를 적용하고, 2026년 7월 기준 버전은 1.0.4입니다.

서버에서는 일부 기능만 사용합니다. Memmy는 http://127.0.0.1:18960에서 수신 대기하는 메모리 서비스, 해당 서비스와 통신하는 memmy-memory 명령줄 인터페이스(CLI), 데스크톱 워크벤치를 제공합니다. 워크벤치는 macOS와 Windows만 지원하도록 패키징되어 있습니다. 따라서 Linux VPS에서는 서비스와 CLI를 실행합니다. 이 구성만으로도 Claude Code, Codex, Cursor가 메모리를 공유할 수 있습니다.

Memmy는 저장하는 데이터를 4개 계층으로 분류합니다. L1 Trace는 요청, 응답, 도구 호출을 포함한 원시 턴입니다. L2 Policy는 추적 데이터에서 도출된 절차이며, 유용성이 입증된 경우에 해당합니다. L3 World Model은 프로젝트 또는 환경에 대한 안정적인 지식입니다. Skill은 정책에서 구체화된 호출 가능한 절차입니다. 서비스는 턴을 수집할 때 계층을 할당하므로, 사용자가 직접 계층을 만들 필요가 없습니다.

도구별 메모리와 비교했을 때 공유 메모리 허브가 달라지는 점

현재 모든 에이전트는 자체 메모리를 제공합니다. Claude Code는 저장소에 지침 파일을 보관합니다. Cursor는 작업 공간 데이터베이스에 규칙을 보관합니다. Codex는 ~/.codex 아래에 세션 로그를 보관합니다. 각 저장소는 하나의 도구에만 속하므로, 월요일에 한 도구에서 가르친 사실을 화요일에 다른 도구에서는 알 수 없습니다. 이로 인해 두 가지 비용이 발생합니다. 하나는 같은 프로젝트를 다시 설명하는 데 사용하는 토큰 비용이고, 다른 하나는 다른 곳에서 이미 수정한 가정에 따라 에이전트가 작업하여 발생하는 잘못된 작업입니다.

허브는 저장소를 도구 외부로 옮깁니다. Memmy는 기존 저장소도 읽으므로 빈 데이터베이스에서 시작하지 않습니다. 스캐너는 6개의 소스를 인식합니다. ~/.claude/projects/**/*.jsonl의 Claude Code, ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl의 Codex, ~/.local/share/opencode/opencode.db의 OpenCode, state.vscdb 파일의 Cursor, ~/.openclaw 아래의 OpenClaw SQLite 데이터베이스, ~/.hermes의 Hermes입니다. 이름과 로컬 경로를 지정하여 소스를 직접 추가할 수도 있습니다.

가져오기 카운터가 일치하지 않는 것은 정상입니다. 스캐너는 메시지를 소스와 대화별로 그룹화한 다음, 완료된 각 턴마다 L1 메모리 하나를 기록합니다. 사용자 콘텐츠가 비어 있지 않고 비어 있지 않은 assistant 메시지로 끝날 때 턴이 완료된 것으로 간주합니다. 따라서 중단된 세션은 아무것도 추가하지 않습니다. 메시지는 대화 체크포인트와 안정적인 턴 ID를 사용하여 중복 제거됩니다. 같은 실행에서도 스캔된 수, 가져온 메시지 수, 새 메모리 수는 서로 다릅니다.

이 부분은 Claude Code가 단일 세션에서 컨텍스트를 관리하는 방식과 함께 이해해야 합니다. 컨텍스트 관리는 단일 창에 무엇을 담을 수 있는지 결정합니다. 메모리 허브는 해당 창이 닫힌 후에도 무엇이 유지되는지 결정합니다.

VPS에 필요한 항목

  • Node.js 22 이상. Memmy 문서에서 이를 요구하며, Ubuntu 24.04에는 Node 18이 포함되어 있습니다.
  • git 및 빌드 도구 모음. better-sqlite3은 설치 중에 컴파일될 수 있는 네이티브 모듈이기 때문입니다.
  • 약 2 GB의 RAM. root 설치 과정에서 대규모 workspace와 프런트엔드 빌드 도구 모음을 가져옵니다.
  • node_modules 및 데이터베이스에 사용할 수 있는 여유 디스크 공간 수 GB.
sudo apt update
sudo apt install -y git build-essential python3 curl ca-certificates sqlite3
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --version

node --version의 출력은 v22 이상이어야 합니다. 여기에 v18이 표시되면 NodeSource 단계가 적용되지 않은 것입니다. 그러면 이후 프로젝트의 엔진 검사에서 설치가 실패합니다.

Ubuntu 24.04에서 소스 코드로 Memmy 설치

git clone https://github.com/MemTensor/memmy-agent.git
cd memmy-agent
cp .env.example .env
npm install
npm run memory:build

npm run memory:build@memmy/memory workspace를 Memory/dist로 컴파일합니다. 헤드리스 서버에서는 트리의 다른 항목을 빌드할 필요가 없습니다. 네이티브 모듈이 로드되는지 확인합니다.

node -e "require('better-sqlite3'); console.log('better-sqlite3 loads')"

출력하지 않고 해당 줄에서 오류가 발생하면 네이티브 모듈이 Node 버전과 일치하지 않는 것입니다. npm rebuild better-sqlite3를 실행합니다. 이 명령은 프로젝트의 자체 start script가 어떤 작업을 시작하기 전에 실행하는 명령과 정확히 같습니다.

README에서는 bash scripts/dev-start.sh를 한 번의 명령으로 실행하는 방법으로 설명합니다. 헤드리스 VPS에서는 실행하지 마십시오. 이 명령은 memory service와 함께 Electron desktop shell 및 port 19000의 Vite dev server를 시작합니다. Electron에는 display가 필요하므로 graphical session이 없는 서버에서는 script가 멈추거나 종료됩니다.

메모리 서비스를 시작하고 응답을 확인합니다

npm run memory:serve:dev

소스에서 메모리 서비스를 실행하는 문서화된 방법입니다. 127.0.0.1:18960에 바인딩하고, 데이터베이스를 ~/.memmy/memory-service/memory.sqlite에 유지하며, ~/.memmy/config.yaml에서 설정을 읽습니다. 값을 명시하려는 경우 README에도 동일한 값이 나와 있습니다.

npm run memory:serve:dev -- \
  --host 127.0.0.1 --port 18960 \
  --db ~/.memmy/memory-service/memory.sqlite \
  --config ~/.memmy/config.yaml

두 번째 셸에서 서비스가 실행 중인지 확인합니다.

curl -sS http://127.0.0.1:18960/api/v1/health

Health는 토큰을 요청하지 않는 유일한 엔드포인트이므로 적절한 프로브입니다. curl이 종료 코드 7과 Failed to connect to 127.0.0.1 port 18960 메시지를 출력하면 수신 대기 중인 서비스가 없는 것입니다. 서비스를 실행 중인 터미널을 확인해야 합니다. 시작 중 충돌이 발생하면 해당 터미널에 오류가 출력되며, 일반적인 원인은 네이티브 SQLite 모듈을 로드하지 못하는 것입니다. 서비스가 시작되면 ss -lntp | grep 18960으로 소켓을 확인할 수 있습니다.

나머지 HTTP API(application programming interface)는 /api/v1 아래에 있습니다.

  • POST /api/v1/memory/add은 메모리를 기록하고 POST /api/v1/memory/search은 쿼리를 실행합니다.
  • GET /api/v1/memory/:idDELETE /api/v1/memory/:id은 항목 하나를 조회하고 삭제합니다.
  • POST /api/v1/sessions/openPOST /api/v1/sessions/:sessionId/close은 에이전트 세션의 시작과 종료를 처리합니다.
  • POST /api/v1/turns/startPOST /api/v1/turns/:turnId/complete은 한 번의 대화를 기록합니다.
  • GET /api/v1/panel/overview, /api/v1/panel/analysis/api/v1/panel/items은 대시보드에 데이터를 제공합니다.

Memmy는 포트 블록을 예약합니다. 헤드리스 환경에서는 첫 번째 포트만 사용합니다. 18960은 메모리용, 18970은 게이트웨이 상태 확인용, 18980은 웹 UI와 관리자 HTTP용, 18990은 memmy serve이 시작하는 OpenAI 호환 API용이며, 19000과 19010은 데스크톱 프런트엔드의 개발 서버용입니다. 시스템에서 이미 이러한 포트 중 하나를 사용하고 있다면 이 목록부터 확인합니다.

memmy-memory 명령이 실제로 시작되는 위치

처음 설치할 때 대부분 여기서 문제가 발생하므로 추측하지 말고 패키지에서 확인해야 합니다. 명령 이름은 repository 이름과 관련이 없습니다. 명령은 다음 workspace의 bin 필드에서 가져옵니다.

node -p "JSON.stringify(require('./Memory/package.json').bin)"

이 명령은 {"memmy-memory":"./dist/src/cli/index.js"}을 출력합니다. 따라서 빌드된 진입점은 Memory/dist/src/cli/index.js입니다. 이 파일은 npm run memory:build 이후에만 존재합니다. 빌드 과정에서 dist가 생성되고 파일에 실행 권한이 부여되기 때문입니다. 다음과 같이 직접 실행합니다.

node Memory/dist/src/cli/index.js health

PATH에서 짧은 이름을 사용하려면 같은 파일에 link를 생성합니다.

sudo ln -s "$PWD/Memory/dist/src/cli/index.js" /usr/local/bin/memmy-memory
memmy-memory health

CLI의 기본값은 http://127.0.0.1:18960이며, --url, --token, --config, --source--user-id를 허용합니다. 하위 명령은 init, health, search, add, getdelete입니다. 또한 agent가 사용하고 사람이 사용하지 않는 session 및 turn 호출도 있습니다. memmy-memory search "deploy steps"memmy-memory add "staging migrates on deploy"는 agent가 가장 자주 실행하는 두 명령입니다.

Claude Code를 Memmy에 연결하려면 어떻게 해야 합니까?

Claude Code에는 메모리 플러그인 인터페이스가 없으므로 Memmy가 Claude Code에 직접 연결되지는 않습니다. 통합 방식은 더 단순합니다. Claude Code는 memmy-memory를 일반적인 shell 명령으로 실행하고, 지침 파일이 실행 시점을 지정합니다. Memmy의 공식 설치 프로그램은 이 파일을 대신 작성합니다. memmy-memory init --agent는 대상 agent의 rules 디렉터리에 메모리 지침 파일을 저장합니다.

지침은 한 번 직접 작성하는 것이 좋습니다. 그러면 agent에 전달된 내용을 정확히 확인할 수 있습니다. Claude Code는 모든 세션을 시작할 때 project root에서 CLAUDE.md을 읽습니다. 따라서 다음과 같은 section 하나로 통합을 구성할 수 있습니다.

## Memory

Before starting a task, run `memmy-memory search "<topic>"` and read what comes back.
When a task is done, run `memmy-memory add "<what you learned>"` for anything that will matter next session.

이 방식으로 얻는 효과를 정확히 이해해야 합니다. 이는 instruction level 통합이므로 model이 명령 실행을 결정할 때만 동작합니다. 그 외에는 동작하지 않습니다. 호출을 강제하는 요소는 없습니다. 세션이 add 없이 종료되면 아무것도 저장되지 않습니다. 다음에 검색할 때 빈 결과가 표시되는 것이 유일한 신호입니다. 이는 Claude Code 자체 메모리 파일과 같은 절충점입니다. 다만 store를 공유하므로 같은 machine의 Codex와 Cursor에서도 해당 note를 사용할 수 있다는 차이가 있습니다.

반대 방향에는 별도의 설정이 필요하지 않습니다. Memmy의 scanner는 이미 ~/.claude/projects/**/*.jsonl을 읽습니다. 이 경로에 Claude Code가 session transcript를 기록합니다. tmux session에서 Claude Code 실행과 동일한 server에서 Memmy를 실행하면, 별도의 설정 없이 어제 작업이 메모리로 저장됩니다.

Memmy는 Claude Code용 MCP 서버로 작동합니까?

아니요. 방향을 알면 불필요한 작업을 줄일 수 있습니다. MCP(model context protocol)에는 클라이언트와 서버가 있습니다. Memmy는 클라이언트입니다. Memmy는 MCP 서버에 연결하고 해당 서버의 도구를 자체 에이전트 런타임에 제공합니다. claude mcp add가 연결할 수 있는 MCP endpoint를 Memmy가 게시하지는 않습니다. 저장소에서 유일한 MCP 브리지는 desktop local API 내부의 Composio integration에 속하며, 이 API는 자체 x-memmy-mcp-token header 뒤에서 127.0.0.1의 random port에 bind됩니다.

클라이언트 측 설정은 ~/.memmy/config.yaml에 있으며, MEMMY_CONFIG가 가리키는 파일에서 tools.mcpServers 아래에 지정합니다.

tools:
  mcpServers:
    example:
      type: stdio
      command: npx
      args:
        - "-y"
        - "your-mcp-server"
      toolTimeout: 30
      enabledTools:
        - "*"

typestdio, ssestreamableHttp을 허용합니다. stdio server는 Memmy의 child process로 실행됩니다. 따라서 해당 command는 같은 box에 존재해야 하며 같은 user로 실행되어야 합니다. 이미 VPS에서 실행 중인 MCP 서버를 관리하고 있다면, 여기에 해당 서버를 나열합니다.

메모리 저장소를 비공개로 유지하기

Memmy가 사용하는 모든 항목은 ~/.memmy 아래에 있습니다. 여기에는 config.yaml, workspace, memory-service/memory.sqlite 및 runtime 파일이 포함됩니다. 검색과 수집은 로컬에서 수행되며, 메모리는 로컬 SQLite 파일에 기록됩니다. 따라서 기본 동작은 실제로 로컬 전용입니다.

네트워크에 연결되는 경로는 2개입니다. MEMMY_CLOUD_SERVICE의 기본값은 https://memmy-api.memtensor.cn이며, trial token을 사용하는 account mode를 지원합니다. 따라서 API key mode에서는 이 경로를 호출하지 않습니다. memory improvement program은 privacy settings에서 별도로 전환하는 옵션이며, 직접 활성화하기 전에는 꺼져 있습니다.

놓치기 쉬운 세 번째 경로도 있습니다. hosted embedding provider를 구성하면 모든 메모리의 텍스트가 해당 provider로 전송되어 vector로 변환됩니다. 이 경우 로컬 저장소를 사용해도 보호되지 않습니다. 직접 호스팅하는 embedding endpoint를 사용하는 것만이 이 전송을 차단하는 방법입니다.

port 18960은 loopback 주소에서 수신 대기하도록 유지합니다. 127.0.0.1에 바인딩된 service는 다른 시스템에서 전혀 접근할 수 없으므로 firewall rule이 필요하지 않습니다. 대신 SSH를 통해 laptop에서 접근합니다.

ssh -N -L 18960:127.0.0.1:18960 you@your-vps

더 넓은 주소에 바인딩해야 한다면 먼저 token을 설정합니다. config에서 storage.token을 설정하거나 MEMMY_MEMORY_TOKEN 또는 MEMORY_SERVICE_TOKEN environment variable을 설정하면 health를 제외한 모든 endpoint에 bearer token이 필요합니다. config value는 ${ENV_NAME} reference를 지원하므로 token과 model API key가 파일 자체에 저장되지 않습니다. 이는 다른 곳에서 AI agent에서 secret을 분리하는 방법을 적용하는 것과 같은 방식입니다. 또한 default deny ufw policy는 향후 버전에서 기본 bind address가 변경될 경우를 대비한 마지막 방어선입니다.

신뢰하기 전에 ~/.memmy 백업

memory.sqlite은 전체 저장소입니다. 벡터는 sqlite-vec 확장을 통해 동일한 파일에 저장되므로, 이 파일 하나만 백업하면 됩니다. 서비스가 파일에 쓰는 동안 cp로 복사하면 데이터베이스가 일관되지 않은 상태로 복사될 수 있습니다. SQLite의 자체 백업 명령을 사용합니다.

mkdir -p ~/memmy-backup
sqlite3 ~/.memmy/memory-service/memory.sqlite ".backup '$HOME/memmy-backup/memory.sqlite'"

이 명령은 서비스가 계속 실행되는 동안 일관된 복사본을 생성합니다. 오프사이트 저장소로 전송하는 restic을 사용하여 일정에 따라 서버 외부로 복사본을 전송합니다. config.yaml을 잃으면 다시 입력할 수 있는 provider 설정만 잃습니다. memory.sqlite를 잃으면 모든 memory를 잃으며, 시스템의 다른 위치에는 두 번째 복사본이 없습니다.

systemd에서 메모리 서비스를 실행합니다

셸에서 npm run memory:serve:dev을 실행하면 셸과 함께 종료됩니다. 유닛 파일을 사용하면 재부팅 후에도 서비스가 계속 실행됩니다.

[Unit]
Description=Memmy memory service
After=network-online.target

[Service]
Type=simple
User=memmy
WorkingDirectory=/opt/memmy/memmy-agent
EnvironmentFile=/etc/memmy/memory.env
ExecStart=/usr/bin/npm run memory:serve:dev
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

토큰을 유닛 파일에 넣지 마십시오. 토큰을 /etc/memmy/memory.env에 저장하고, 소유자는 root로 설정하며, 권한은 600으로 설정합니다.

MEMMY_CONFIG=/home/memmy/.memmy/config.yaml
MEMMY_MEMORY_TOKEN=replace-this-with-a-long-random-string
sudo systemctl daemon-reload
sudo systemctl enable --now memmy-memory
systemctl status memmy-memory --no-pager
curl -sS http://127.0.0.1:18960/api/v1/health

상태 출력의 status=203/EXEC은 systemd가 ExecStart을 전혀 실행하지 못했다는 의미입니다. 따라서 which npm을 확인해야 합니다. NodeSource 설치에서는 /usr/bin/npm이고, nvm에서는 사용자의 홈 디렉터리 아래에 있는 항목입니다. systemd는 해당 경로를 찾지 못합니다. 유닛이 시작된 직후 종료되었다면 npm 내부에서 실패한 것입니다. journalctl -u memmy-memory -n 50을 실행하면 원인을 확인할 수 있습니다. 작동 방식은 VPS의 다른 systemd 서비스와 동일합니다.

Memmy가 아직 수행하지 못하는 작업

  • Linux 데스크톱 빌드가 없습니다. 패키징 스크립트는 macOS와 Windows를 지원하므로, workbench, 온보딩 마법사 및 memory dashboard를 서버 자체에서 사용할 수 없습니다.
  • memory:serve:dev는 개발용 경로인 tsx을 통해 TypeScript 진입점을 실행합니다. 저장소에는 컴파일된 출력용 memory:serve도 포함되어 있습니다. 인수를 지정하지 않고 npm run를 실행하면 현재 checkout에 실제로 있는 스크립트를 확인할 수 있습니다.
  • 검색은 최신 vector 행 2,000개로 검색 범위를 만든 다음, 해당 범위 안에서 Top-K 선택을 적용합니다. 매우 큰 저장소에서는 오래된 memory가 검색 범위 밖에 있을 수 있습니다.
  • Embedding은 capture 후에 수행되며, 실패하면 agent의 turn을 차단하지 않고 retry queue로 이동합니다. 방금 추가한 memory는 아직 vector search로 검색되지 않을 수 있습니다.
  • SQLite 파일 하나는 노드 하나를 의미합니다. clustering이 없으므로 두 번째 서버는 별도의 두 번째 memory가 됩니다.

2026년 7월 기준 Version 1.0.4와 약 329개의 stars는 이 프로젝트가 아직 초기 단계임을 보여 줍니다. 릴리스에 따라 flags, paths 및 script names가 변경됩니다. 어디에서 복사한 command든, 여기의 command를 포함해 그대로 신뢰하지 말고 직접 checkout에서 bin 필드와 npm run의 출력을 확인하십시오.

FAQ

health check가 connection refused를 반환하는 이유는 무엇입니까?

port 18960에서 listening 중인 항목이 없습니다. Failed to connect to 127.0.0.1 port 18960이 포함된 curl exit code 7은 memory service가 실행 중이 아니거나 startup 중 종료되었음을 의미합니다. 따라서 해당 service가 시작된 terminal 또는 journal을 확인합니다. 일반적인 원인은 2가지입니다. 하나는 Node version과 일치하지 않는 better-sqlite3 native module이며, npm rebuild better-sqlite3으로 해결합니다. 다른 하나는 22 미만인 Node version입니다. service가 실행된 후 ss -lntp | grep 18960로 socket을 확인합니다.

source에서 build한 후 memmy-memory command는 어디에서 제공됩니까?

repository name이 아니라 @memmy/memory workspace package의 bin field에서 제공됩니다. checkout 내부에서 node -p "JSON.stringify(require('./Memory/package.json').bin)"를 실행하면 {"memmy-memory":"./dist/src/cli/index.js"}이 출력됩니다. 이 file은 npm run memory:build 이후에만 존재합니다. build 과정에서 dist을 생성하고 해당 file을 executable로 표시하기 때문입니다. node Memory/dist/src/cli/index.js health로 실행하거나, 짧은 이름으로 사용하려면 /usr/local/bin에 symlink를 생성합니다.

claude mcp add로 Memmy를 Claude Code에 추가할 수 있습니까?

아니요. Memmy는 MCP client이며 MCP server가 아닙니다. Memmy는 ~/.memmy/config.yamltools.mcpServers 아래에 나열된 server에 연결하고 해당 server의 tool을 자체 runtime에 제공합니다. Claude Code는 반대 방향으로 Memmy에 접근합니다. memmy-memory CLI를 shell command로 실행하며, memmy-memory init --agent가 agent의 rules directory에 작성하는 instruction file의 안내를 따릅니다.

Memmy를 실행하면 memory가 cloud service로 전송됩니까?

scanning과 ingestion은 local에서 실행되며, memory는 사용자의 disk에 있는 ~/.memmy/memory-service/memory.sqlite에 기록됩니다. MEMMY_CLOUD_SERVICE는 account mode와 trial token을 위해 https://memmy-api.memtensor.cn을 참조하며, memory improvement program은 사용자가 활성화할 때까지 비활성화되어 있습니다. 확인해야 할 대상은 embedding provider입니다. hosted embedding model은 memory를 vector로 변환하는 과정에서 모든 memory의 text를 수신합니다. 이 점이 중요하다면 직접 운영하는 endpoint를 사용합니다.