AI Agent

Mem0 개념과 기본 사용법 완전 가이드 1편 — AI 에이전트에게 기억을 심어라

cell-devlog 2026. 5. 27. 16:10
반응형

 

"어제 채식주의자라고 했는데 오늘 스테이크 레시피를 추천한다." LLM의 고질적인 무상태성(Statelessness) 문제다. 세션이 끝나면 모든 컨텍스트가 사라진다. 사용자 입장에서는 매번 처음부터 설명해야 하는 AI는 쓸모가 없다. Mem0는 이 문제를 전용 메모리 레이어로 해결한다. 개념부터 실전 코드까지 1편에서 완전히 정리한다.


핵심 요약

→ Mem0("mem-zero")는 AI 에이전트와 LLM에 지능형 메모리 레이어를 추가하는 오픈소스 프로젝트 — 55,700+ GitHub Star, 1,400만+ 다운로드(2026년 5월 기준)
→ AI 에이전트는 3가지 메모리 레벨이 필요 — 모든 대화에 걸쳐 지속되는 사용자 레벨 선호도, 현재 인터랙션의 세션 레벨 컨텍스트, 자율 워크플로우의 에이전트 레벨 상태
→ 멀티 신호 검색 시스템 — 의미론적 검색 + BM25 키워드 매칭 + 엔티티 링킹 + 시간적 추론을 결합해 단순 벡터 유사도보다 정확한 메모리 검색
→ LOCOMO 벤치마크에서 OpenAI 내장 메모리 대비 26% 높은 성능, 2026년 4월 알고리즘 업데이트로 91.6점 달성
→ 호스팅 방식 2가지: 클라우드 관리형(app.mem0.ai) vs 자체 호스팅(Docker + Qdrant) — 동일 Python SDK로 전환 가능
→ Anthropic SDK·OpenAI Agents SDK·Google ADK 세 주요 에이전트 스택 모두 공식 통합 지원 — 에이전트 런타임 바꿔도 메모리 레이어 재작성 불필요
→ Claude Code MCP 서버 통합 지원 — mem0 init --agent로 5초 안에 API 키 발급


1. 왜 메모리 레이어가 필요한가

# 메모리 없는 에이전트의 현실

1회차 대화
User: "나 채식주의자고 견과류 알레르기 있어"
AI:   "알겠어요! 기억해 둘게요."

2회차 대화 (새 세션)
User: "오늘 저녁 뭐 먹을까?"
AI:   "스테이크 어떠세요? 아니면 땅콩 소스 파스타도 좋아요!"
                                  ↑ 완전히 잊어버림

# 프로덕션에서 이게 문제가 되는 이유
- 사용자가 매번 같은 컨텍스트 반복 설명 → UX 최악
- 대화 히스토리 전체를 컨텍스트에 주입 → 토큰 비용 폭증
- 에이전트가 이전 작업 결과를 모름 → 중복 작업 반복
# 기존 해결책과 한계

1. 대화 히스토리 전체 주입
   → 토큰 비용 선형 증가, 컨텍스트 한계 도달
   → 중요한 정보가 노이즈에 묻힘

2. 수동 요약
   → 개발자가 직접 요약 로직 구현 필요
   → 무엇을 기억할지 규칙 기반 → 유연성 없음

3. 단순 벡터 DB 저장
   → 시간적 맥락 없음 ("전 직장"이 "현 직장"으로 검색됨)
   → 충돌하는 정보 처리 불가

# Mem0의 접근
→ 대화에서 중요한 사실을 자동 추출 → 구조화 저장
→ 쿼리 시 관련 메모리만 선택적 검색 → 컨텍스트에 주입
→ 시간·엔티티·관련성 다중 신호 조합

2. Mem0 핵심 개념 — 4가지 메모리 레벨

# Mem0 메모리 레벨 체계

User Memory (사용자 레벨)
├── 범위: 해당 사용자의 모든 세션에 걸쳐 지속
├── 저장 내용: 선호도, 취향, 개인 정보, 반복 패턴
├── 식별자: user_id
└── 예시: "채식주의자, 견과류 알레르기, 다크 모드 선호"

Session Memory (세션 레벨)
├── 범위: 현재 대화 세션 내
├── 저장 내용: 현재 대화의 컨텍스트, 임시 상태
├── 식별자: user_id + session_id
└── 예시: "오늘 파스타 레시피 요청함, 이미 3가지 제안함"

Agent Memory (에이전트 레벨)
├── 범위: 특정 에이전트 인스턴스의 작업 상태
├── 저장 내용: 에이전트가 실행한 태스크, 결과, 계획
├── 식별자: agent_id
└── 예시: "파일 분석 완료, 다음 단계: 보고서 작성"

System Memory (시스템 레벨)
├── 범위: 전체 시스템에 공유되는 지식
├── 저장 내용: 공통 규칙, 도메인 지식
└── 예시: "회사 정책: 외부 API 사용 금지"

3. 설치 및 빠른 시작

클라우드 관리형 (권장 시작점)

# 설치
pip install mem0ai

# API 키 발급
# → https://app.mem0.ai 가입 후 API 키 발급
# 또는 CLI로 5초 완성:
pip install mem0-cli
mem0 init --agent --agent-caller my-agent
# → 이메일·대시보드·OTP 없이 즉시 발급
# 기본 3단계: add → search → 활용
import os
from mem0 import MemoryClient

client = MemoryClient(api_key=os.getenv("MEM0_API_KEY"))

# 1단계: 대화 내용 메모리에 추가
messages = [
    {"role": "user", "content": "나 채식주의자고 견과류 알레르기 있어."},
    {"role": "assistant", "content": "알겠어요! 식단 정보 기억해 둘게요."},
]
result = client.add(messages, user_id="user_001")
print(result)
# → {'results': [{'memory': '채식주의자이고 견과류 알레르기 있음', 'event': 'ADD'}]}

# 2단계: 관련 메모리 검색
memories = client.search(
    query="오늘 저녁 메뉴 추천해줘",
    user_id="user_001"
)
for m in memories:
    print(m['memory'])
# → '채식주의자이고 견과류 알레르기 있음'

# 3단계: 검색된 메모리를 에이전트 프롬프트에 주입
context = "\n".join([m['memory'] for m in memories])
prompt = f"""
사용자 정보:
{context}

질문: 오늘 저녁 뭐 먹을까?
"""
# → LLM에 전달 시 채식 메뉴만 추천

4. 핵심 CRUD API

from mem0 import MemoryClient

client = MemoryClient(api_key="your-api-key")
USER_ID = "user_001"
SESSION_ID = "session_20260527"

# ── ADD ── 메모리 추가
# 방법 1: 대화 메시지 배열로 추가 (자동 추출)
client.add(
    messages=[
        {"role": "user", "content": "Python보다 TypeScript 더 좋아해."},
        {"role": "assistant", "content": "기억할게요!"},
    ],
    user_id=USER_ID,
    # session_id=SESSION_ID,  # 세션 메모리로 저장 시
    # agent_id="my-agent",    # 에이전트 메모리로 저장 시
)

# 방법 2: 직접 텍스트로 추가
client.add(
    messages="사용자는 새벽 2시에 주로 작업함",
    user_id=USER_ID,
)

# ── SEARCH ── 관련 메모리 검색
results = client.search(
    query="어떤 언어 선호해?",
    user_id=USER_ID,
    limit=5,          # 최대 반환 개수
    # threshold=0.7,  # 유사도 임계값
)
# → [{'id': '...', 'memory': 'TypeScript 선호', 'score': 0.92}]

# ── GET ALL ── 사용자의 모든 메모리 조회
all_memories = client.get_all(user_id=USER_ID)
for m in all_memories:
    print(f"[{m['id']}] {m['memory']}")

# ── UPDATE ── 특정 메모리 수정
memory_id = results[0]['id']
client.update(
    memory_id=memory_id,
    data="TypeScript와 Rust 모두 선호"
)

# ── DELETE ── 특정 메모리 삭제
client.delete(memory_id=memory_id)

# ── DELETE ALL ── 사용자 메모리 전체 삭제
client.delete_all(user_id=USER_ID)

5. Claude + Mem0 실전 에이전트

import os
from anthropic import Anthropic
from mem0 import MemoryClient

anthropic_client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
mem0_client = MemoryClient(api_key=os.getenv("MEM0_API_KEY"))

def chat_with_memory(user_message: str, user_id: str, session_id: str) -> str:
    """메모리 기반 Claude 챗 함수"""

    # 1. 현재 질문과 관련된 메모리 검색
    relevant_memories = mem0_client.search(
        query=user_message,
        user_id=user_id,
        limit=5
    )

    # 2. 메모리를 시스템 프롬프트에 주입
    memory_context = ""
    if relevant_memories:
        facts = [m['memory'] for m in relevant_memories]
        memory_context = f"""
사용자에 대해 알고 있는 정보:
{chr(10).join(f'- {fact}' for fact in facts)}

위 정보를 참고해서 개인화된 응답을 제공해줘.
"""

    # 3. Claude API 호출
    response = anthropic_client.messages.create(
        model="claude-sonnet-4-6-20261022",
        max_tokens=1024,
        system=f"당신은 친절한 AI 어시스턴트입니다.{memory_context}",
        messages=[{"role": "user", "content": user_message}]
    )
    assistant_message = response.content[0].text

    # 4. 이번 대화를 메모리에 저장 (다음 세션에서 활용)
    mem0_client.add(
        messages=[
            {"role": "user", "content": user_message},
            {"role": "assistant", "content": assistant_message},
        ],
        user_id=user_id,
        session_id=session_id,
    )

    return assistant_message

# 사용 예시
if __name__ == "__main__":
    user_id = "user_001"
    session_id = "session_001"

    # 1회차
    print(chat_with_memory("나 채식주의자야", user_id, session_id))
    print(chat_with_memory("파이썬 개발자야", user_id, session_id))

    # 2회차 (새 세션)
    session_id = "session_002"
    response = chat_with_memory(
        "오늘 저녁 메뉴랑 토이 프로젝트 아이디어 추천해줘",
        user_id,
        session_id
    )
    print(response)
    # → 채식 메뉴 + Python 기반 프로젝트 아이디어 추천
    #   (이전 세션 정보를 기억해서 개인화된 응답)

6. 자체 호스팅 설정 (Docker)

# Docker로 로컬 Mem0 서버 실행
# Qdrant(벡터 DB) + Mem0 API 서버 포함

# 1단계: 저장소 클론
git clone https://github.com/mem0ai/mem0.git
cd mem0/server

# 2단계: 환경 변수 설정
cp .env.example .env
# .env 파일에서:
# OPENAI_API_KEY=your-key  (메모리 추출용 LLM)
# ADMIN_API_KEY=your-admin-key

# 3단계: 스택 시작 + 관리자 설정 (원커맨드)
make bootstrap
# → Qdrant + Mem0 API 서버 실행
# → http://localhost:3000 에서 UI 접근 가능

# 4단계: 코드에서 자체 호스팅 서버 사용
from mem0 import MemoryClient

# base_url만 변경 — 나머지 API 동일
client = MemoryClient(
    api_key="your-admin-key",
    base_url="http://localhost:8080"  # 로컬 서버
)
# 클라우드 vs 자체 호스팅 비교

                클라우드 (app.mem0.ai)    자체 호스팅 (Docker)
설정 시간       5분                       20분
데이터 위치     Mem0 서버                 내 인프라
비용            API 과금                  인프라 비용만
HIPAA 준수      Enterprise 플랜만         자체 설정 가능
스케일링        자동                      직접 관리
추천            프로토타입·중소 규모       데이터 민감·엔터프라이즈

7. 2026년 4월 업데이트 — 새 기능

# 시간적 추론 (Temporal Reasoning) — 2026년 4월 추가
# 같은 사람의 시간에 따른 변화를 추적

# 시나리오: 직장 변경
client.add("나 구글 다니고 있어", user_id="alice", metadata={"date": "2025-01"})
client.add("나 Anthropic으로 이직했어", user_id="alice", metadata={"date": "2026-03"})

# 최신 정보 검색
results = client.search("Alice 현재 직장?", user_id="alice")
# → 'Anthropic에서 근무 중' (최신 정보 우선)

# 과거 정보 검색
results = client.search(
    "Alice 2025년 초 직장?",
    user_id="alice",
    temporal_context="2025-01"
)
# → '구글 근무'

# 엔티티 링킹 — 관련 메모리 자동 연결
client.add("Claude Code 쓸 때 Opus 4.7 선호해", user_id="alice")
client.add("에이전트 프레임워크는 LangGraph 씀", user_id="alice")

results = client.search("Alice AI 개발 환경?", user_id="alice")
# → Claude Code + Opus 4.7 + LangGraph 관련 메모리 모두 반환
#   (엔티티 링킹으로 직접 언급 없이도 연결)

✅ 결론

✅ Mem0는 add/search/get_all/delete 4개 핵심 메서드만으로 세션 간 메모리 구현
✅ 사용자·세션·에이전트·시스템 4레벨로 메모리 범위 세밀하게 제어
✅ 클라우드 관리형으로 5분 만에 시작, 자체 호스팅으로 데이터 주권 확보 가능
✅ Anthropic SDK·OpenAI·Google ADK 모두 공식 통합 — 에이전트 스택 교체 시 재작성 불필요

❌ 메모리 추출에 LLM 호출 사용 → 쓰기 레이턴시 추가 (50~200ms)
❌ 고빈도 업데이트 시나리오 → 쓰기당 비용 고려 필요
❌ 메모리 staleness(오래된 정보) 문제 — 시간적 추론으로 완화되지만 완전 해결 아님


 

반응형