[https://drive.google.com/file/d/1JW6Q\_wwvBjMz9xzOtTldFfPiF7BrdEeQ/view?usp=sharing]
1페이지
컨텍스트 엔지니어링: 세션, 메모리
저자: Kimberly Milam and Antonio Gulli
2페이지
컨텍스트 엔지니어링: 세션, 메모리
감사의 말
콘텐츠 기여자
Kaitlin Ardiff
Shangjie Chen
Yanfei Chen
Derek Egan
Hangfei Lin
Ivan Nardini
Anant Nawalgaria
Kanchana Patlolla
Huang Xia
Jun Yan
Bo Yang
Michael Zimmermann
큐레이터 및 편집자
Anant Nawalgaria
Kanchana Patlolla
디자이너
Michael Lanning
2025년 11월
3페이지
목차
소개 6
컨텍스트 엔지니어링 7
세션 12
프레임워크 및 모델 간의 차이 13
멀티 에이전트 시스템을 위한 세션 15
여러 에이전트 프레임워크 간의 상호 운용성 19
세션에 대한 프로덕션 고려 사항 20
긴 컨텍스트 대화 관리: 장단점 및 최적화 22
메모리 27
메모리 유형 34
정보 유형 35
조직 패턴 35
스토리지 아키텍처 36
생성 메커니즘 37
메모리 범위 38
4페이지
목차
멀티모달 메모리 39
메모리 생성: 추출 및 통합 41
심층 분석: 메모리 추출 44
심층 분석: 메모리 통합 47
메모리 출처 (Provenance) 49
메모리 관리 중 메모리 계보 기록 50
추론 중 메모리 계보 기록 52
메모리 생성 트리거 52
도구로서의 메모리(Memory-as-a-Tool) 53
백그라운드 작업 vs. 블로킹 작업 56
메모리 검색 56
검색 시점 58
메모리를 사용한 추론 61
시스템 명령어 내의 메모리 61
대화 기록 내의 메모리 63
절차적 메모리 64
5페이지
목차
테스트 및 평가 65
메모리에 대한 프로덕션 고려 사항 67
개인정보 보호 및 보안 위험 69
결론 70
각주 71
6페이지
컨텍스트 엔지니어링: 세션, 메모리
상태를 기억하고 개인화된 AI는 컨텍스트 엔지니어링에서 시작됩니다.
소개
이 백서에서는 상태를 기억하고(stateful), 지능적인 LLM 에이전트를 구축하는 데 있어 세션(Sessions)과 메모리(Memory)의 중요한 역할을 탐구합니다. 이를 통해 개발자는 더 강력하고 개인화되었으며 지속적인 AI 경험을 만들 수 있습니다. 대규모 언어 모델(LLM)이 상호작용을 기억하고, 학습하며, 개인화하기 위해서는 개발자가 LLM의 컨텍스트 창(context window) 내에서 정보를 동적으로 조합하고 관리해야 하는데, 이 과정을 컨텍스트 엔지니어링(Context Engineering)이라고 합니다.
이러한 핵심 개념은 아래 백서에 요약되어 있습니다.
- 컨텍스트 엔지니어링: 상태를 기억하는 지능형 에이전트를 구현하기 위해 LLM의 컨텍스트 창 내에서 정보를 동적으로 조합하고 관리하는 프로세스입니다.
- 세션: 에이전트와의 전체 대화를 담는 컨테이너로, 대화의 시간 순 기록과 에이전트의 작업 메모리를 포함합니다.
2025년 11월
7페이지
컨텍스트 엔지니어링: 세션, 메모리
- 메모리: 여러 세션에 걸쳐 핵심 정보를 포착하고 통합하여 LLM 에이전트에게 지속적이고 개인화된 경험을 제공하는 장기 지속성 메커니즘입니다.
컨텍스트 엔지니어링
LLM은 본질적으로 상태를 기억하지 못합니다(stateless). 훈련 데이터를 제외하면, LLM의 추론과 인식은 단일 API 호출의 "컨텍스트 창" 내에 제공된 정보에 국한됩니다. 이는 근본적인 문제를 야기합니다. AI 에이전트는 어떤 행동을 취할 수 있는지 식별하는 운영 지침, 추론의 근거가 되는 증거 및 사실 데이터, 현재 작업을 정의하는 즉각적인 대화 정보를 갖추어야 하기 때문입니다. 상태를 기억하고, 학습하며, 상호작용을 개인화할 수 있는 지능형 에이전트를 구축하기 위해 개발자는 대화의 매 턴마다 이러한 컨텍스트를 구성해야 합니다. 이처럼 LLM을 위해 정보를 동적으로 조합하고 관리하는 것을 컨텍스트 엔지니어링이라고 합니다.
컨텍스트 엔지니어링은 전통적인 프롬프트 엔지니어링(Prompt Engineering)에서 한 단계 발전한 개념입니다. 프롬프트 엔지니어링은 최적의, 종종 정적인 시스템 명령어를 만드는 데 중점을 둡니다. 반면, 컨텍스트 엔지니어링은 사용자, 대화 기록, 외부 데이터를 기반으로 상태를 인식하는(state-aware) 프롬프트를 동적으로 구성하여 전체 페이로드(payload)를 다룹니다. 이는 관련성을 극대화하고 노이즈를 최소화하기 위해 다양한 유형의 정보를 전략적으로 선택, 요약, 주입하는 과정을 포함합니다. RAG 데이터베이스, 세션 저장소, 메모리 관리자와 같은 외부 시스템이 이 컨텍스트의 상당 부분을 관리합니다. 에이전트 프레임워크는 이러한 시스템들을 조율하여 최종 프롬프트로 컨텍스트를 검색하고 조합해야 합니다.
컨텍스트 엔지니어링을 요리사가 요리를 시작하기 전에 모든 재료를 미리 준비하고 손질해두는 '미장플라스(mise en place)'에 비유할 수 있습니다. 요리사에게 레시피(프롬프트)만 준다면, 가지고 있는 아무 재료로나 그럭저럭 괜찮은 음식을 만들 수도 있습니다. 하지만 먼저 올바르고, 품질 좋은 재료와 특화된 도구, 그리고 표현 스타일에 대한 명확한 이해를 제공한다면, 요리사는 훌륭하고 맞춤화된 결과물을 안정적으로 만들어낼 수 있습니다. 컨텍스트 엔지니어링의 목표는 모델이 작업을 완료하는 데 필요한 가장 관련성 높은 정보를 그 이상도 그 이하도 아닌, 딱 맞게 제공하는 것입니다.
2025년 11월
8페이지
컨텍스트 엔지니어링: 세션, 메모리
컨텍스트 엔지니어링은 다양한 구성 요소를 포함할 수 있는 복잡한 페이로드의 조립을 관장합니다.
추론을 안내하는 컨텍스트는 에이전트의 기본적인 추론 패턴과 사용 가능한 행동을 정의하여 그 행동을 지시합니다.
- 시스템 명령어: 에이전트의 페르소나, 능력, 제약 조건을 정의하는 고수준 지시문입니다.
- 도구 정의: 에이전트가 외부 세계와 상호작용하기 위해 사용할 수 있는 API나 함수에 대한 스키마입니다.
- 소수샷 예시 (Few-Shot Examples): 인-컨텍스트 학습(in-context learning)을 통해 모델의 추론 과정을 안내하는 선별된 예시입니다.
증거 및 사실 데이터는 에이전트가 추론하는 실질적인 데이터로, 기존 지식과 특정 작업을 위해 동적으로 검색된 정보를 포함합니다. 이는 에이전트 응답의 '증거' 역할을 합니다.
- 장기 메모리: 여러 세션에 걸쳐 수집된 사용자나 주제에 대한 지속적인 지식입니다.
- 외부 지식: 검색 증강 생성(RAG)¹을 사용하여 데이터베이스나 문서에서 검색된 정보입니다.
- 도구 출력: 도구에 의해 반환된 데이터나 결과입니다.
- 하위 에이전트 출력: 특정 하위 작업을 위임받은 전문 에이전트가 반환한 결론이나 결과입니다.
2025년 11월
9페이지
컨텍스트 엔지니어링: 세션, 메모리
결과물(Artifacts): 사용자와 세션에 관련된 비텍스트 데이터(예: 파일, 이미지)입니다.
즉각적인 대화 정보는 에이전트가 현재 상호작용에 기반을 두도록 하여 즉각적인 작업을 정의합니다.
- 대화 기록: 현재 상호작용의 턴(turn-by-turn) 기록입니다.
- 상태 / 스크래치패드: 에이전트가 즉각적인 추론 과정에서 사용하는 임시적인 진행 중 정보 또는 계산입니다.
- 사용자 프롬프트: 처리해야 할 즉각적인 질의입니다.
컨텍스트의 동적 구성은 매우 중요합니다. 예를 들어, 메모리는 정적이지 않으며, 사용자가 에이전트와 상호작용하거나 새로운 데이터가 입력됨에 따라 선택적으로 검색되고 업데이트되어야 합니다. 또한, 효과적인 추론은 종종 인-컨텍스트 학습²(LLM이 프롬프트 내의 시연을 통해 작업을 수행하는 방법을 배우는 과정)에 의존합니다. 인-컨텍스트 학습은 에이전트가 하드코딩된 예시에 의존하기보다는 현재 작업과 관련된 소수샷 예시를 사용할 때 더 효과적일 수 있습니다. 마찬가지로, 외부 지식은 사용자의 즉각적인 질의를 기반으로 RAG 도구에 의해 검색됩니다.
컨텍스트 인식 에이전트를 구축하는 데 있어 가장 중요한 과제 중 하나는 계속해서 늘어나는 대화 기록을 관리하는 것입니다. 이론적으로는 큰 컨텍스트 창을 가진 모델이 방대한 대화 내용을 처리할 수 있지만, 실제로는 컨텍스트가 길어질수록 비용과 지연 시간이 증가합니다. 또한, 모델은 "컨텍스트 부패(context rot)" 현상을 겪을 수 있는데, 이는 컨텍스트가 길어짐에 따라 중요한 정보에 주의를 기울이는 능력이 감소하는 현상입니다. 컨텍스트 엔지니어링은 요약, 선택적 가지치기 또는 기타 압축 기술과 같이 기록을 동적으로 변경하는 전략을 사용하여 이 문제를 직접적으로 해결합니다. 이를 통해 전체 토큰 수를 관리하면서 필수 정보를 보존하고, 궁극적으로 더 강력하고 개인화된 AI 경험을 제공합니다.
2025년 11월
10페이지
컨텍스트 엔지니어링: 세션, 메모리
이러한 작업은 대화의 각 턴마다 에이전트의 운영 루프 내에서 지속적인 사이클로 나타납니다.
(이미지)
그림 1. 에이전트를 위한 컨텍스트 관리 흐름
- 사용자 질의 (User Query) -> 컨텍스트 가져오기 (Fetch Context) -> 컨텍스트 준비 (Prepare Context) -> LLM + 도구 호출 (Invoke LLMs + Tools) -> 응답 (Response)
- 컨텍스트 준비 (Prepare Context) 과정에서 컨텍스트 저장소 (Context Storage)로부터 비동기(async)로 컨텍스트를 가져올 수 있습니다.
- LLM + 도구 호출 (Invoke LLMs + Tools) 이후 컨텍스트 업로드 (Upload Context (events))가 발생하여 컨텍스트 저장소 (Context Storage)에 저장됩니다.
컨텍스트 가져오기 (Fetch Context): 에이전트는 사용자 메모리, RAG 문서, 최근 대화 이벤트와 같은 컨텍스트를 검색하는 것으로 시작합니다. 동적 컨텍스트 검색을 위해 에이전트는 사용자 질의와 기타 메타데이터를 사용하여 어떤 정보를 검색할지 결정합니다.
컨텍스트 준비 (Prepare Context): 에이전트 프레임워크는 LLM 호출을 위한 전체 프롬프트를 동적으로 구성합니다. 개별 API 호출은 비동기적일 수 있지만, 컨텍스트 준비는 블로킹(blocking) 방식의 "핫패스(hot-path)" 프로세스입니다. 컨텍스트가 준비될 때까지 에이전트는 다음 단계로 진행할 수 없습니다.
LLM 및 도구 호출 (Invoke LLM and Tools): 에이전트는 사용자를 위한 최종 응답이 생성될 때까지 LLM과 필요한 도구를 반복적으로 호출합니다. 도구 및 모델 출력은 컨텍스트에 추가됩니다.
2025년 11월
11페이지
컨텍스트 엔지니어링: 세션, 메모리
- 컨텍스트 업로드 (Upload Context): 해당 턴 동안 수집된 새로운 정보가 영구 저장소에 업로드됩니다. 이는 종종 "백그라운드" 프로세스로, 에이전트가 메모리 통합이나 다른 후처리 작업이 비동기적으로 발생하는 동안 실행을 완료할 수 있도록 합니다.
이 라이프사이클의 중심에는 세션(sessions)과 메모리(memory)라는 두 가지 기본 구성 요소가 있습니다. 세션은 단일 대화의 턴바이턴(turn-by-turn) 상태를 관리합니다. 반면, 메모리는 여러 세션에 걸쳐 핵심 정보를 포착하고 통합하여 장기적인 지속성을 위한 메커니즘을 제공합니다.
세션을 특정 프로젝트를 위해 사용하는 작업대나 책상이라고 생각할 수 있습니다. 작업하는 동안에는 필요한 모든 도구, 메모, 참고 자료로 가득 차 있습니다. 모든 것이 즉시 접근 가능하지만, 일시적이며 해당 작업에만 국한됩니다. 프로젝트가 끝나면 지저분한 책상 전체를 그냥 저장소에 밀어 넣지 않습니다. 대신, 잘 정리된 파일 캐비닛과 같은 메모리를 만드는 과정을 시작합니다. 책상 위의 자료들을 검토하고, 초안이나 중복된 메모는 버리고, 가장 중요하고 최종적인 문서만 폴더에 정리하여 보관합니다. 이렇게 하면 파일 캐비닛이 나중의 모든 프로젝트를 위한 깨끗하고 신뢰할 수 있으며 효율적인 정보의 원천으로 남게 되며, 작업대의 일시적인 혼돈으로 어수선해지지 않습니다. 이 비유는 효과적인 에이전트가 작동하는 방식을 직접적으로 보여줍니다. 세션은 단일 대화를 위한 임시 작업대 역할을 하고, 에이전트의 메모리는 꼼꼼하게 정리된 파일 캐비닛 역할을 하여 향후 상호작용에서 핵심 정보를 기억할 수 있게 합니다.
컨텍스트 엔지니어링에 대한 이러한 고수준의 개요를 바탕으로, 이제 두 가지 핵심 구성 요소인 세션과 메모리에 대해 세션부터 시작하여 더 깊이 탐구해 보겠습니다.
2025년 11월
12페이지
컨텍스트 엔지니어링: 세션, 메모리
세션
컨텍스트 엔지니어링의 기본 요소는 세션으로, 이는 단일하고 연속적인 대화의 즉각적인 대화 기록과 작업 메모리를 캡슐화합니다. 각 세션은 특정 사용자에게 연결된 독립적인 기록입니다. 세션을 통해 에이전트는 단일 대화의 범위 내에서 컨텍스트를 유지하고 일관된 응답을 제공할 수 있습니다. 사용자는 여러 세션을 가질 수 있지만, 각 세션은 특정 상호작용에 대한 별개의, 연결되지 않은 로그로 기능합니다. 모든 세션에는 두 가지 주요 구성 요소가 포함됩니다: 시간 순서에 따른 기록(이벤트)과 에이전트의 작업 메모리(상태).
이벤트는 대화의 구성 요소입니다. 일반적인 이벤트 유형에는 사용자 입력(사용자로부터의 메시지-텍스트, 오디오, 이미지 등), 에이전트 응답(사용자에 대한 에이전트의 회신), 도구 호출(에이전트가 외부 도구나 API를 사용하기로 한 결정), 또는 도구 출력(도구 호출에서 반환된 데이터로, 에이전트가 추론을 계속하는 데 사용)이 포함됩니다.
채팅 기록 외에도, 세션은 종종 상태(state)—구조화된 "작업 메모리" 또는 스크래치패드를 포함합니다. 여기에는 쇼핑 카트에 담긴 항목과 같이 현재 대화와 관련된 임시적이고 구조화된 데이터가 저장됩니다.
대화가 진행됨에 따라 에이전트는 세션에 추가 이벤트를 덧붙입니다. 또한, 에이전트 내의 로직에 따라 상태를 변경할 수 있습니다.
이벤트의 구조는 Gemini API에 전달되는 Content 객체 목록과 유사하며, 각 항목은 role과 parts를 가지고 있어 대화의 한 턴(turn)—또는 하나의 이벤트를 나타냅니다.
2025년 11월
13페이지
컨텍스트 엔지니어링: 세션, 메모리
Python
contents = [
{
"role": "user",
"parts": [ {"text": "프랑스의 수도는 어디인가요?"} ]
}, {
"role": "model",
"parts": [ {"text": "프랑스의 수도는 파리입니다."} ]
}
]
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=contents
)```
**코드 1: Gemini 멀티턴 호출 예시**
프로덕션 에이전트의 실행 환경은 일반적으로 상태를 기억하지 못하므로(stateless), 요청이 완료된 후에는 정보를 유지하지 않습니다. 따라서 지속적인 사용자 경험을 유지하려면 대화 기록을 영구 저장소에 저장해야 합니다. 인-메모리(in-memory) 스토리지는 개발에는 적합하지만, 프로덕션 애플리케이션에서는 세션을 안정적으로 저장하고 관리하기 위해 견고한 데이터베이스를 활용해야 합니다. 예를 들어, Agent Engine Sessions³와 같은 관리형 솔루션에 대화 기록을 저장할 수 있습니다.
**프레임워크 및 모델 간의 차이**
핵심 아이디어는 비슷하지만, 다른 에이전트 프레임워크는 세션, 이벤트, 상태를 각기 다른 방식으로 구현합니다. 에이전트 프레임워크는 LLM을 위한 대화 기록과 상태를 유지하고, 이 컨텍스트를 사용하여 LLM 요청을 만들며, LLM 응답을 파싱하고 저장하는 역할을 합니다.
2025년 11월
***
## **14페이지**
**컨텍스트 엔지니어링: 세션, 메모리**
에이전트 프레임워크는 당신의 코드와 LLM 사이에서 보편적인 번역기 역할을 합니다. 개발자인 당신은 각 대화 턴에 대해 프레임워크의 일관된 내부 데이터 구조로 작업하는 반면, 프레임워크는 그 구조들을 LLM이 요구하는 정확한 형식으로 변환하는 중요한 작업을 처리합니다. 이러한 추상화는 에이전트의 로직을 사용 중인 특정 LLM으로부터 분리시켜 벤더 종속성(vendor lock-in)을 방지하기 때문에 강력합니다.
**(이미지)**
**그림 2: 에이전트를 위한 컨텍스트 관리 흐름**
* **사용자 질의 (User Query)** 및 **기타 데이터 소스 (Other data sources)**가 **에이전트 프레임워크 (Agent Framework)**로 들어갑니다.
* 에이전트 프레임워크는 **세션 저장소 (Session Store)** 및 **메모리 관리자 (Memory Manager)**와 상호 작용합니다.
* 에이전트 프레임워크는 **모델 서빙 (Model Serving)**을 통해 **모델 (Model, 예: Gemini)**과 통신합니다. 이 과정은 'translate(번역)'으로 표시됩니다.
궁극적인 목표는 LLM이 이해할 수 있는 "요청"을 생성하는 것입니다. Google의 Gemini 모델의 경우, 이는 `List[Content]`입니다. 각 `Content` 객체는 두 개의 키를 포함하는 간단한 사전과 같은 구조입니다: `role`은 누가 말하고 있는지("user" 또는 "model")를 정의하고, `parts`는 메시지의 실제 내용(텍스트, 이미지, 도구 호출 등)을 정의합니다.
프레임워크는 API 호출을 하기 전에 내부 객체(예: ADK의 `Event`)의 데이터를 `Content` 객체의 해당 `role`과 `parts`에 자동으로 매핑하는 작업을 처리합니다. 본질적으로, 프레임워크는 개발자에게 안정적인 내부 API를 제공하면서, 이면에서는 다양하고 복잡한 여러 LLM의 외부 API를 관리합니다.
2025년 11월
***
## **15페이지**
**컨텍스트 엔지니어링: 세션, 메모리**
**ADK**는 `Event` 객체 목록과 별도의 상태 객체를 포함하는 명시적인 `Session` 객체를 사용합니다. `Session`은 파일 캐비닛과 같아서, 한 폴더에는 대화 기록(이벤트)을, 다른 폴더에는 작업 메모리(상태)를 보관합니다.
**LangGraph**는 공식적인 "세션" 객체가 없습니다. 대신, 상태(state)가 곧 세션입니다. 이 모든 것을 포괄하는 상태 객체는 대화 기록(`Message` 객체 목록)과 다른 모든 작업 데이터를 보유합니다. 전통적인 세션의 추가 전용(append-only) 로그와 달리, LangGraph의 상태는 변경 가능합니다. 변환될 수 있으며, 기록 압축과 같은 전략으로 기록을 변경할 수 있습니다. 이는 긴 대화와 토큰 제한을 관리하는 데 유용합니다.
**멀티 에이전트 시스템을 위한 세션**
멀티 에이전트 시스템에서는 여러 에이전트가 협력합니다. 각 에이전트는 더 작고 전문화된 작업에 집중합니다. 이 에이전트들이 효과적으로 함께 작동하려면 정보를 공유해야 합니다. 아래 다이어그램에서 볼 수 있듯이, 시스템의 아키텍처는 정보를 공유하는 데 사용하는 통신 패턴을 정의합니다. 이 아키텍처의 핵심 구성 요소는 시스템이 세션 기록—모든 상호작용의 영구적인 로그—을 처리하는 방식입니다.
2025년 11월
***
## **16페이지**
**컨텍스트 엔지니어링: 세션, 메모리**
**(이미지)**
**그림 3: 다양한 멀티 에이전트 아키텍처 패턴³⁰**
* 단일 에이전트 (Single Agent)
* 네트워크 (Network)
* 감독자 (Supervisor)
* 감독자 (도구로서) (Supervisor (as tools))
* 계층적 (Hierarchical)
* 사용자 정의 (Custom)
이 기록을 관리하기 위한 아키텍처 패턴을 살펴보기 전에, 이를 LLM에 전송되는 컨텍스트와 구별하는 것이 중요합니다. 세션 기록은 전체 대화의 영구적이고 축약되지 않은 녹취록이라고 생각하십시오. 반면에 컨텍스트는 단일 턴을 위해 LLM에 전송되는 세심하게 제작된 정보 페이로드입니다. 에이전트는 기록에서 관련 있는 발췌문만 선택하거나, 모델의 응답을 유도하기 위해 안내하는 서문과 같은 특별한 형식을 추가하여 이 컨텍스트를 구성할 수 있습니다. 이 섹션은 에이전트 간에 어떤 정보가 전달되는지에 초점을 맞추며, 반드시 LLM에 어떤 컨텍스트가 전송되는지를 다루는 것은 아닙니다.
2025년 11월
***
## **17페이지**
**컨텍스트 엔지니어링: 세션, 메모리**
에이전트 프레임워크는 멀티 에이전트 시스템의 세션 기록을 두 가지 주요 접근 방식 중 하나를 사용하여 처리합니다: 모든 에이전트가 단일 로그에 기여하는 **공유된, 통합된 기록(shared, unified history)** 또는 각 에이전트가 자신만의 관점을 유지하는 **분리된, 개별적인 기록(separate, individual histories)**⁴. 이 두 패턴 사이의 선택은 작업의 성격과 에이전트 간에 원하는 협업 스타일에 따라 달라집니다.
**공유된, 통합된 기록** 모델에서는 시스템의 모든 에이전트가 동일한 단일 대화 기록에서 읽고 씁니다. 모든 에이전트의 메시지, 도구 호출, 관찰은 시간 순서대로 하나의 중앙 로그에 추가됩니다. 이 접근 방식은 한 에이전트의 출력이 다음 에이전트의 직접적인 입력이 되는 다단계 문제 해결 과정과 같이, 단일 진실 공급원(single source of truth)을 필요로 하는 긴밀하게 연결된 협업 작업에 가장 적합합니다. 공유된 기록을 사용하더라도, 하위 에이전트는 LLM에 전달하기 전에 로그를 처리할 수 있습니다. 예를 들어, 관련 이벤트의 일부만 필터링하거나 각 이벤트를 생성한 에이전트를 식별하기 위해 레이블을 추가할 수 있습니다.
ADK의 LLM 기반 위임을 사용하여 하위 에이전트에게 작업을 전달하면, 하위 에이전트의 모든 중간 이벤트는 루트 에이전트와 동일한 세션에 기록됩니다⁵:
**Python**
```python
from google.adk.agents import LlmAgent
# 하위 에이전트는 세션에 접근하여 이벤트를 기록합니다.
sub_agent_1 = LlmAgent(...)
# 선택적으로, 하위 에이전트는 최종 응답 텍스트(또는 구조화된 출력)를
# 지정된 상태 키에 저장할 수 있습니다.
sub_agent_2 = LlmAgent(
output_key="..."
)
# 계속...
2025년 11월
18페이지
컨텍스트 엔지니어링: 세션, 메모리
# 부모 에이전트.
root_agent = LlmAgent(
...,
sub_agents=[sub_agent_1, sub_agent_2]
)
코드 2: 여러 에이전트 프레임워크 간의 A2A 통신
분리된, 개별적인 기록 모델에서는 각 에이전트가 자신만의 비공개 대화 기록을 유지하며 다른 에이전트에게는 블랙박스처럼 작동합니다. 중간 생각, 도구 사용, 추론 단계와 같은 모든 내부 프로세스는 에이전트의 비공개 로그 내에 유지되며 다른 에이전트에게는 보이지 않습니다. 통신은 명시적인 메시지를 통해서만 발생하며, 에이전트는 자신의 과정이 아닌 최종 결과물만 공유합니다.
이러한 상호작용은 일반적으로 에이전트를 도구처럼 구현하는 에이전트-애즈-어-툴(Agent-as-a-Tool) 방식을 사용하거나, 에이전트-투-에이전트(A2A) 프로토콜을 사용하여 구현됩니다. 에이전트-애즈-어-툴 방식을 사용하면, 한 에이전트가 다른 에이전트를 마치 표준 도구처럼 호출하여 입력을 전달하고 최종적이고 독립적인 출력을 받습니다⁶. 에이전트-투-에이전트(A2A) 프로토콜을 사용하면, 에이전트들은 직접적인 메시지 교환을 위해 구조화된 프로토콜을 사용합니다⁷.
다음 세션에서 A2A 프로토콜에 대해 더 자세히 살펴보겠습니다.
2025년 11월
19페이지
컨텍스트 엔지니어링: 세션, 메모리
여러 에이전트 프레임워크 간의 상호 운용성
(이미지)
그림 4: 다른 프레임워크를 사용하는 여러 에이전트 간의 A2A 통신
- 왼쪽에는 Agent Development Kit (ADK)를 사용하는 에이전트가 있고, 오른쪽에는 LangGraph를 사용하는 에이전트가 있습니다.
- 두 에이전트는 A2A 프로토콜을 통해 통신합니다.
- ADK 에이전트는 세션 저장소(Session storage)를 사용하고, LangGraph 에이전트는 체크포인트 저장소(Checkpoint storage)를 사용합니다.
- 이 둘은 조직적 또는 기술적 경계로 구분됩니다.
프레임워크가 내부 데이터 표현을 사용하는 것은 멀티 에이전트 시스템에 있어 중요한 아키텍처적 절충안을 만듭니다: 에이전트를 LLM으로부터 분리시키는 바로 그 추상화가 다른 에이전트 프레임워크를 사용하는 에이전트로부터도 격리시킨다는 점입니다. 이러한 격리는 영속성 계층(persistence layer)에서 더욱 공고해집니다. Session의 스토리지 모델은 일반적으로 데이터베이스 스키마를 프레임워크의 내부 객체에 직접 결합시켜, 상대적으로 이식성이 떨어지는 경직된 대화 기록을 만듭니다. 따라서 LangGraph로 구축된 에이전트는 ADK 기반 에이전트가 영속화한 별개의 Session 및 Event 객체를 기본적으로 해석할 수 없으므로, 원활한 작업 전달이 불가능합니다.
2025년 11월
20페이지
컨텍스트 엔지니어링: 세션, 메모리
이러한 격리된 에이전트 간의 협업을 조정하기 위해 떠오르는 아키텍처 패턴 중 하나는 에이전트-투-에이전트(A2A) 통신입니다⁸. 이 패턴은 에이전트들이 메시지를 교환할 수 있게 해주지만, 풍부하고 맥락적인 상태를 공유하는 핵심 문제를 해결하지는 못합니다. 각 에이전트의 대화 기록은 해당 프레임워크의 내부 스키마로 인코딩되어 있습니다. 결과적으로, 세션 이벤트를 포함하는 A2A 메시지는 유용하게 사용되기 위해 번역 계층이 필요합니다.
상호 운용성을 위한 더 강력한 아키텍처 패턴은 공유된 지식을 메모리(Memory)와 같이 프레임워크에 구애받지 않는(framework-agnostic) 데이터 계층으로 추상화하는 것입니다. Events나 Messages와 같은 원시적이고 프레임워크 특정적인 객체를 보존하는 Session 저장소와 달리, 메모리 계층은 처리된, 정규화된(canonical) 정보를 저장하도록 설계되었습니다. 요약, 추출된 엔티티, 사실과 같은 핵심 정보는 대화에서 추출되어 일반적으로 문자열이나 사전 형태로 저장됩니다. 메모리 계층의 데이터 구조는 특정 프레임워크의 내부 데이터 표현에 종속되지 않으므로, 보편적이고 공통적인 데이터 계층 역할을 할 수 있습니다. 이 패턴을 통해 이질적인 에이전트들이 사용자 정의 번역기 없이 공통된 인지 자원을 공유함으로써 진정한 협업 지능을 달성할 수 있습니다.
세션에 대한 프로덕션 고려 사항
에이전트를 프로덕션 환경으로 이전할 때, 세션 관리 시스템은 단순한 로그에서 견고한 엔터프라이즈급 서비스로 발전해야 합니다. 주요 고려 사항은 보안 및 개인정보 보호, 데이터 무결성, 성능의 세 가지 중요한 영역으로 나뉩니다. Agent Engine Sessions와 같은 관리형 세션 저장소는 이러한 프로덕션 요구 사항을 해결하기 위해 특별히 설계되었습니다.
2025년 11월
21페이지
컨텍스트 엔지니어링: 세션, 메모리
보안 및 개인정보 보호
세션 내에 포함된 민감한 정보를 보호하는 것은 타협할 수 없는 요구 사항입니다. 엄격한 격리(Strict Isolation)는 가장 중요한 보안 원칙입니다. 세션은 단일 사용자에 의해 소유되며, 시스템은 한 사용자가 다른 사용자의 세션 데이터에 절대 접근할 수 없도록(즉, ACL을 통해) 엄격한 격리를 강제해야 합니다. 세션 저장소에 대한 모든 요청은 세션 소유자에 대해 인증되고 권한이 부여되어야 합니다.
개인 식별 정보(PII)를 처리하는 가장 좋은 방법은 세션 데이터가 저장소에 기록되기 전에 이를 삭제(redact)하는 것입니다. 이는 잠재적인 데이터 유출의 위험과 "피해 범위(blast radius)"를 극적으로 줄이는 근본적인 보안 조치입니다. Model Armor⁹와 같은 도구를 사용하여 민감한 데이터가 절대 영속화되지 않도록 함으로써, GDPR 및 CCPA와 같은 개인정보 보호 규정 준수를 간소화하고 사용자 신뢰를 구축할 수 있습니다.
데이터 무결성 및 수명 주기 관리
프로덕션 시스템은 세션 데이터가 시간이 지남에 따라 어떻게 저장되고 유지되는지에 대한 명확한 규칙을 요구합니다. 세션은 영원히 존재해서는 안 됩니다. 비활성 세션을 자동으로 삭제하여 스토리지 비용을 관리하고 데이터 관리 부담을 줄이는 TTL(Time-to-Live) 정책을 구현할 수 있습니다. 이를 위해서는 세션을 보관하거나 영구적으로 삭제하기 전에 얼마 동안 보관해야 하는지를 정의하는 명확한 데이터 보존 정책이 필요합니다.
또한, 시스템은 세션 기록에 작업이 결정론적 순서(deterministic order)로 추가되는 것을 보장해야 합니다. 이벤트의 정확한 시간 순서를 유지하는 것은 대화 로그의 무결성에 근본적으로 중요합니다.
2025년 11월
22페이지
컨텍스트 엔지니어링: 세션, 메모리
성능 및 확장성
세션 데이터는 모든 사용자 상호작용의 "핫 패스(hot path)"에 있으므로 성능이 주요 관심사입니다. 응답성 있는 사용자 경험을 보장하기 위해 세션 기록의 읽기와 쓰기는 매우 빨라야 합니다. 에이전트 런타임은 일반적으로 상태를 기억하지 않으므로(stateless), 전체 세션 기록은 매 턴이 시작될 때마다 중앙 데이터베이스에서 검색되어 네트워크 전송 지연이 발생합니다.
지연 시간을 줄이려면 전송되는 데이터의 크기를 줄이는 것이 중요합니다. 핵심적인 최적화 방법은 세션 기록을 에이전트로 보내기 전에 필터링하거나 압축하는 것입니다. 예를 들어, 대화의 현재 상태에 더 이상 필요하지 않은 오래되고 관련 없는 함수 호출 출력을 제거할 수 있습니다. 다음 섹션에서는 긴 컨텍스트 대화를 효과적으로 관리하기 위해 기록을 압축하는 여러 전략에 대해 자세히 설명합니다.
긴 컨텍스트 대화 관리: 장단점 및 최적화
단순한 아키텍처에서 세션은 사용자와 에이전트 간의 불변의 대화 로그입니다. 그러나 대화가 길어질수록 대화의 토큰 사용량이 증가합니다. 최신 LLM은 긴 컨텍스트를 처리할 수 있지만, 특히 지연 시간에 민감한 애플리케이션에서는 한계가 존재합니다¹⁰:
컨텍스트 창 제한: 모든 LLM은 한 번에 처리할 수 있는 텍스트의 최대 양(컨텍스트 창)이 있습니다. 대화 기록이 이 한도를 초과하면 API 호출이 실패합니다.
API 비용 ($): 대부분의 LLM 제공업체는 보내고 받는 토큰 수에 따라 요금을 부과합니다. 기록이 짧을수록 토큰 수가 줄어들고 턴당 비용이 낮아집니다.
2025년 11월
23페이지
컨텍스트 엔지니어링: 세션, 메모리
지연 시간 (속도): 모델에 더 많은 텍스트를 보내면 처리하는 데 더 오래 걸리므로 사용자의 응답 시간이 느려집니다. 압축을 통해 에이전트가 빠르고 반응성 있게 느껴지도록 유지할 수 있습니다.
품질: 토큰 수가 증가함에 따라 컨텍스트에 추가적인 노이즈와 자기회귀적 오류(autoregressive errors)가 발생하여 성능이 저하될 수 있습니다.
에이전트와 긴 대화를 관리하는 것은 장거리 여행을 위해 여행 가방을 싸는 현명한 여행객에 비유할 수 있습니다. 여행 가방은 에이전트의 제한된 컨텍스트 창을 나타내고, 옷과 물품들은 대화의 정보 조각들입니다. 만약 모든 것을 그냥 쑤셔 넣으려고 하면, 가방은 너무 무겁고 어수선해져서 필요한 것을 빨리 찾기 어렵게 됩니다. 이는 과부하된 컨텍스트 창이 처리 비용을 증가시키고 응답 시간을 늦추는 것과 같습니다. 반면에, 너무 적게 챙기면 여권이나 따뜻한 외투 같은 필수품을 빠뜨려 전체 여행을 망칠 위험이 있습니다. 이는 에이전트가 중요한 컨텍스트를 잃어 관련 없거나 부정확한 답변을 내놓는 것과 같습니다. 여행객과 에이전트 모두 비슷한 제약 하에 있습니다: 성공은 얼마나 많이 가지고 가느냐가 아니라, 필요한 것만 가지고 가느냐에 달려 있습니다.
압축 전략은 긴 대화 기록을 줄여서, 대화를 모델의 컨텍스트 창에 맞추고 API 비용과 지연 시간을 줄입니다. 대화가 길어질수록 매 턴마다 모델에 보내는 기록이 너무 커질 수 있습니다. 압축 전략은 가장 중요한 컨텍스트를 보존하면서 기록을 지능적으로 잘라내어 이 문제를 해결합니다.
그렇다면, 가치 있는 정보를 잃지 않으면서 세션에서 어떤 내용을 버려야 할지 어떻게 알 수 있을까요? 전략은 단순한 잘라내기부터 정교한 압축까지 다양합니다.
- 최근 N개의 턴 유지: 이것은 가장 간단한 전략입니다. 에이전트는 대화의 가장 최근 N개의 턴("슬라이딩 윈도우")만 유지하고 그보다 오래된 모든 것을 버립니다.
2025년 11월
24페이지
컨텍스트 엔지니어링: 세션, 메모리
토큰 기반 잘라내기: 기록을 모델에 보내기 전에, 에이전트는 가장 최근 메시지부터 시작하여 거꾸로 작업하면서 메시지의 토큰을 계산합니다. 미리 정의된 토큰 한도(예: 4000 토큰)를 초과하지 않으면서 가능한 한 많은 메시지를 포함합니다. 그보다 오래된 모든 것은 단순히 잘려나갑니다.
재귀적 요약: 대화의 오래된 부분은 AI가 생성한 요약으로 대체됩니다. 대화가 길어지면, 에이전트는 주기적으로 다른 LLM 호출을 사용하여 가장 오래된 메시지들을 요약합니다. 이 요약은 그 후 기록의 압축된 형태로 사용되며, 종종 더 최근의 원문 메시지 앞에 붙여집니다.
예를 들어, ADK의 내장 플러그인을 사용하여 ADK 앱이 모델에 보내는 컨텍스트를 제한함으로써 최근 N개의 턴을 유지할 수 있습니다. 이는 세션 저장소에 저장된 과거 이벤트를 수정하지 않습니다.
Python
from google.adk.apps import App
from google.adk.plugins.context_filter_plugin import ContextFilterPlugin
app = App(
name='hello_world_app',
root_agent=agent,
plugins=[
# 최근 10개의 턴과 가장 최근의 사용자 쿼리를 유지합니다.
ContextFilterPlugin(num_invocations_to_keep=10),
],
)
코드 3: ADK를 사용하여 최근 N개의 턴만 사용하도록 세션 잘라내기
2025년 11월
25페이지
컨텍스트 엔지니어링: 세션, 메모리
정교한 압축 전략이 비용과 지연 시간을 줄이는 것을 목표로 하는 만큼, (재귀적 요약과 같은) 비용이 많이 드는 작업을 비동기적으로 백그라운드에서 수행하고 결과를 영속화하는 것이 중요합니다. "백그라운드에서"는 클라이언트가 기다리지 않도록 보장하고, "영속화"는 비용이 많이 드는 계산이 과도하게 반복되지 않도록 보장합니다. 종종 에이전트의 메모리 관리자가 이러한 재귀적 요약을 생성하고 영속화하는 책임을 모두 집니다. 에이전트는 또한 압축된 요약에 어떤 이벤트가 포함되었는지 기록을 유지해야 합니다. 이는 원래의 더 장황한 이벤트가 불필요하게 LLM에 전송되는 것을 방지합니다.
또한, 에이전트는 압축이 필요할 때를 결정해야 합니다. 트리거 메커니즘은 일반적으로 몇 가지 뚜렷한 범주로 나뉩니다.
횟수 기반 트리거 (토큰 크기 또는 턴 수 임계값): 대화가 미리 정의된 특정 임계값을 초과하면 압축됩니다. 이 접근 방식은 컨텍스트 길이를 관리하는 데 "충분히 좋은" 경우가 많습니다.
시간 기반 트리거: 대화의 크기가 아니라 활동 부족에 의해 압축이 트리거됩니다. 사용자가 일정 기간(예: 15분 또는 30분) 동안 상호작용을 멈추면, 시스템은 백그라운드에서 압축 작업을 실행할 수 있습니다.
이벤트 기반 트리거 (의미/작업 완료): 에이전트는 특정 작업, 하위 목표 또는 대화 주제가 끝났다고 감지했을 때 압축을 트리거하기로 결정합니다.
예를 들어, ADK의 EventsCompactionConfig를 사용하여 구성된 턴 수 이후에 LLM 기반 요약을 트리거할 수 있습니다.
2025년 11월
26페이지
컨텍스트 엔지니어링: 세션, 메모리
Python
from google.adk.apps import App
from google.adk.apps.app import EventsCompactionConfig
app = App(
name='hello_world_app',
root_agent=agent,
events_compaction_config=EventsCompactionConfig(
compaction_interval=5,
overlap_size=1,
),
)
코드 4: ADK를 사용하여 요약으로 세션 압축하기
메모리 생성은 장황하고 노이즈가 많은 데이터 소스에서 지속적인 지식을 추출하는 광범위한 기능입니다. 이 섹션에서는 대화 기록에서 정보를 추출하는 주요 예시인 세션 압축에 대해 다루었습니다. 압축은 전체 대화의 원문 기록을 정제하여, 대화의 군더더기를 버리면서 핵심 사실과 요약을 추출합니다.
압축을 바탕으로, 다음 섹션에서는 메모리 생성과 관리를 더 폭넓게 탐구할 것입니다. 우리는 에이전트의 장기적인 지식을 구축하기 위해 메모리가 생성되고, 저장되며, 검색될 수 있는 다양한 방법에 대해 논의할 것입니다.
2025년 11월
27페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리
메모리와 세션은 깊은 공생 관계를 공유합니다: 세션은 메모리를 생성하기 위한 주요 데이터 소스이며, 메모리는 세션의 크기를 관리하기 위한 핵심 전략입니다. 메모리는 대화나 데이터 소스에서 추출된 의미 있는 정보의 스냅샷입니다. 이는 중요한 컨텍스트를 보존하는 압축된 표현으로, 향후 상호작용에 유용하게 사용됩니다. 일반적으로 메모리는 여러 세션에 걸쳐 영속화되어 지속적이고 개인화된 경험을 제공합니다.
전문화되고 분리된 서비스로서, "메모리 관리자"는 멀티 에이전트 상호 운용성의 기반을 제공합니다. 메모리 관리자는 종종 간단한 문자열이나 사전과 같이 프레임워크에 구애받지 않는 데이터 구조를 사용합니다. 이를 통해 다른 프레임워크로 구축된 에이전트들이 단일 메모리 저장소에 연결할 수 있으며, 연결된 모든 에이전트가 활용할 수 있는 공유 지식 기반을 만들 수 있습니다.
참고: 일부 프레임워크는 세션이나 원문 대화를 "단기 메모리"라고 부르기도 합니다. 이 백서에서는 메모리를 턴바이턴 대화의 원시 기록이 아닌, 추출된 정보로 정의합니다.
메모리를 저장하고 검색하는 것은 정교하고 지능적인 에이전트를 구축하는 데 매우 중요합니다. 강력한 메모리 시스템은 기본적인 챗봇을 진정으로 지능적인 에이전트로 변모시키며, 여러 핵심 기능을 가능하게 합니다.
- 개인화: 가장 일반적인 사용 사례는 사용자 선호도, 사실, 과거 상호작용을 기억하여 향후 응답을 맞춤화하는 것입니다. 예를 들어, 사용자가 좋아하는 스포츠팀이나 선호하는 비행기 좌석을 기억하는 것은 더 유용하고 개인적인 경험을 만들어냅니다.
2025년 11월
28페이지
컨텍스트 엔지니어링: 세션, 메모리
컨텍스트 창 관리: 대화가 길어지면 전체 기록이 LLM의 컨텍스트 창을 초과할 수 있습니다. 메모리 시스템은 요약을 생성하거나 핵심 사실을 추출하여 이 기록을 압축할 수 있으며, 매 턴마다 수천 개의 토큰을 보내지 않고도 컨텍스트를 보존할 수 있습니다. 이는 비용과 지연 시간을 모두 줄입니다.
데이터 마이닝 및 인사이트: 많은 사용자에 걸쳐 저장된 메모리를 (집계되고 개인정보를 보호하는 방식으로) 분석함으로써 노이즈 속에서 인사이트를 추출할 수 있습니다. 예를 들어, 소매 챗봇은 많은 사용자가 특정 제품의 반품 정책에 대해 묻고 있음을 파악하여 잠재적인 문제를 발견할 수 있습니다.
에이전트 자가 개선 및 적응: 에이전트는 자신의 성능에 대한 절차적 메모리를 생성하여 이전 실행으로부터 학습합니다. 성공적인 결과로 이어진 전략, 도구 또는 추론 경로를 기록하는 것입니다. 이를 통해 에이전트는 효과적인 해결책의 플레이북을 구축하여 문제 해결 능력을 시간에 따라 적응하고 향상시킬 수 있습니다.
AI 시스템에서 메모리를 생성, 저장, 활용하는 것은 협업적인 과정입니다. 최종 사용자부터 개발자의 코드까지, 스택의 각 구성 요소는 뚜렷한 역할을 합니다.
사용자: 메모리를 위한 원시 소스 데이터를 제공합니다. 일부 시스템에서는 사용자가 직접 메모리를 제공할 수도 있습니다 (예: 양식을 통해).
에이전트 (개발자 로직): 무엇을 언제 기억할지 결정하는 방법을 구성하고, 메모리 관리자 호출을 조율합니다. 간단한 아키텍처에서는 개발자가 메모리가 항상 검색되고 항상 생성되도록 로직을 구현할 수 있습니다. 더 발전된 아키텍처에서는 개발자가 '도구로서의 메모리(memory-as-a-tool)'를 구현하여 에이전트(LLM을 통해)가 언제 메모리를 검색하거나 생성해야 할지를 결정하게 할 수 있습니다.
2025년 11월
29페이지
컨텍스트 엔지니어링: 세션, 메모리
에이전트 프레임워크 (예: ADK, LangGraph): 메모리 상호작용을 위한 구조와 도구를 제공합니다. 프레임워크는 배관(plumbing) 역할을 합니다. 개발자의 로직이 대화 기록에 접근하고 메모리 관리자와 상호작용하는 방법을 정의하지만, 장기적인 저장 자체를 관리하지는 않습니다. 또한 검색된 메모리를 컨텍스트 창에 어떻게 채워 넣을지도 정의합니다.
세션 저장소 (예: Agent Engine Sessions, Spanner, Redis): 세션의 턴바이턴 대화를 저장합니다. 이 원시 대화는 메모리를 생성하기 위해 메모리 관리자로 수집됩니다.
메모리 관리자 (예: Agent Engine Memory Bank, Mem0, Zep): 메모리의 저장, 검색, 압축을 처리합니다. 메모리를 저장하고 검색하는 메커니즘은 사용되는 제공자에 따라 다릅니다. 이는 에이전트에 의해 식별된 잠재적 메모리를 가져와 전체 수명 주기를 처리하는 전문화된 서비스 또는 구성 요소입니다.
- 추출은 소스 데이터에서 핵심 정보를 추출합니다.
- 통합은 중복되는 엔티티를 병합하기 위해 메모리를 큐레이션합니다.
- 저장은 메모리를 영구 데이터베이스에 영속화합니다.
- 검색은 새로운 상호작용에 컨텍스트를 제공하기 위해 관련 메모리를 가져옵니다.
2025년 11월
30페이지
컨텍스트 엔지니어링: 세션, 메모리
(이미지)
그림 5: 세션, 메모리, 외부 지식 간의 정보 흐름
- 왼쪽의 사용자는 에이전트(Agent)와 상호작용합니다.
- 에이전트는 LLM과 도구(Tools)를 사용합니다.
- 에이전트는 메모리 관리자(Memory Manager)에서 메모리를 읽고 생성합니다. 메모리 생성은 내부적으로("memory-as-a-tool") 또는 외부적으로 트리거될 수 있습니다.
- 메모리 관리자는 세션 저장소(Session Store)에서 메모리 생성을 위한 소스 데이터를 가져옵니다. 에이전트의 활동은 세션 저장소에 이벤트로 기록됩니다.
- 에이전트는 외부 지식 기반(External Knowledge Bases, 예: RAG 데이터베이스)에서도 정보를 읽습니다.
- 이 모든 정보는 에이전트 실행 전후에 읽고 쓰여지며, 에이전트에게 전달되어 오른쪽의 사용자에게 응답을 제공합니다.
책임의 분할은 개발자가 메모리 영속성 및 관리를 위한 복잡한 기본 인프라를 구축할 필요 없이 에이전트의 고유한 로직에 집중할 수 있도록 보장합니다. 메모리 관리자는 수동적인 벡터 데이터베이스가 아니라 능동적인 시스템이라는 점을 인식하는 것이 중요합니다. 검색을 위해 유사성 검색을 사용하지만, 그 핵심 가치는
2025년 11월
31페이지
컨텍스트 엔지니어링: 세션, 메모리
시간이 지남에 따라 지능적으로 메모리를 추출, 통합, 큐레이션하는 능력에 있습니다. Agent Engine Memory Bank와 같은 관리형 메모리 서비스는 메모리 생성 및 저장의 전체 라이프사이클을 처리하여, 여러분이 에이전트의 핵심 로직에 집중할 수 있도록 해줍니다.
이러한 검색 기능 때문에 메모리는 또 다른 핵심 아키텍처 패턴인 검색 증강 생성(RAG)과 자주 비교됩니다. 그러나 이 둘은 서로 다른 아키텍처 원칙에 기반을 두고 있습니다. RAG는 정적인 외부 데이터를 처리하는 반면, 메모리는 동적인 사용자별 컨텍스트를 큐레이션합니다. 이 둘은 두 가지 뚜렷하고 상호 보완적인 역할을 수행합니다: RAG는 에이전트를 사실에 대한 전문가로 만들고, 메모리는 에이전트를 사용자에 대한 전문가로 만듭니다. 다음 차트는 이들의 고수준 차이점을 분석합니다.
2025년 11월
32페이지
컨텍스트 엔지니어링: 세션, 메모리
| RAG 엔진 | 메모리 관리자 | |
|---|---|---|
| 주요 목표 | 외부의 사실적 지식을 컨텍스트에 주입하는 것. | 개인화되고 상태를 기억하는(stateful) 경험을 만드는 것. 에이전트는 사실을 기억하고, 시간에 따라 사용자에게 적응하며, 장기적인 컨텍스트를 유지합니다. |
| 데이터 소스 | 정적이고, 사전에 인덱싱된 외부 지식 베이스 (예: PDF, 위키, 문서, API). | 사용자와 에이전트 간의 대화. |
| 격리 수준 | 일반적으로 공유됨. 지식 베이스는 일반적으로 모든 사용자가 접근할 수 있는 전역적이고 읽기 전용인 리소스로, 일관된 사실적 답변을 보장합니다. | 고도로 격리됨. 메모리는 데이터 유출을 방지하기 위해 거의 항상 사용자별로 범위가 지정됩니다. |
| 정보 유형 | 정적, 사실적, 권위적. 종종 도메인 특정 데이터, 제품 세부 정보 또는 기술 문서를 포함합니다. | 동적이고 (일반적으로) 사용자 특정적. 메모리는 대화에서 파생되므로, 본질적인 불확실성이 있습니다. |
| 쓰기 패턴 | 배치 처리. 오프라인, 관리 작업으로 트리거됩니다. | 이벤트 기반 처리. 특정 주기(예: 매 턴 또는 세션 종료 시) 또는 '도구로서의 메모리'(에이전트가 메모리 생성을 결정)로 트리거됩니다. |
| 읽기 패턴 | RAG 데이터는 거의 항상 "도구로서" 검색됩니다. 에이전트가 사용자의 질의에 외부 정보가 필요하다고 판단할 때 검색됩니다. | 두 가지 일반적인 읽기 패턴이 있습니다: - 도구로서의 메모리: 사용자의 질의가 사용자에 대한 추가 정보(또는 다른 신원)를 필요로 할 때 검색됩니다. - 정적 검색: 메모리는 매 턴이 시작될 때 항상 검색됩니다. |
| 데이터 형식 | 자연어 "청크". | 자연어 스니펫 또는 구조화된 프로필. |
| 데이터 준비 | 청킹 및 인덱싱: 소스 문서를 더 작은 청크로 나누고, 이를 임베딩으로 변환하여 빠른 조회를 위해 저장합니다. | 추출 및 통합: 대화에서 핵심 세부 정보를 추출하여, 내용이 중복되거나 모순되지 않도록 합니다. |
표 1: RAG 엔진과 메모리 관리자 비교
2025년 11월
33페이지
컨텍스트 엔지니어링: 세션, 메모리
이 차이를 이해하는 데 도움이 되는 좋은 방법은 RAG를 에이전트의 연구 사서로, 메모리 관리자를 에이전트의 개인 비서로 생각하는 것입니다.
연구 사서(RAG)는 백과사전, 교과서, 공식 문서로 가득 찬 거대한 공공 도서관에서 일합니다. 에이전트가 제품의 기술 사양이나 역사적 날짜와 같은 확립된 사실을 필요로 할 때, 이 사서에게 문의합니다. 사서는 이 정적이고, 공유되며, 권위 있는 지식 베이스에서 정보를 검색하여 일관되고 사실적인 답변을 제공합니다. 사서는 세상의 사실에 대한 전문가이지만, 질문하는 사용자에 대해서는 개인적으로 아무것도 알지 못합니다.
반면, 개인 비서(메모리)는 에이전트를 따라다니며 특정 사용자와의 모든 상호작용의 세부 사항을 개인 수첩에 기록합니다. 이 수첩은 동적이고 고도로 격리되어 있으며, 개인적 선호, 과거 대화, 변화하는 목표를 포함합니다. 에이전트가 사용자의 좋아하는 스포츠팀이나 지난주 프로젝트 논의의 맥락을 떠올려야 할 때, 이 비서에게 의지합니다. 비서의 전문 분야는 전 세계적인 사실이 아니라, 바로 그 사용자 자신입니다.
궁극적으로, 진정으로 지능적인 에이전트에게는 둘 다 필요합니다. RAG는 세상에 대한 전문 지식을 제공하고, 메모리는 에이전트가 서비스하는 사용자에 대한 전문적인 이해를 제공합니다.
다음 섹션에서는 메모리의 개념을 그 핵심 구성 요소들을 통해 해부해 보겠습니다: 저장하는 정보의 유형, 조직 패턴, 저장 및 생성 메커니즘, 범위의 전략적 정의, 그리고 텍스트 데이터 대비 멀티모달 데이터의 처리 방식.
2025년 11월
34페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리 유형
에이전트의 메모리는 정보가 어떻게 저장되고 어떻게 캡처되었는지에 따라 분류될 수 있습니다. 이러한 다양한 유형의 메모리는 함께 작동하여 사용자와 그들의 요구에 대한 풍부하고 맥락적인 이해를 만들어냅니다. 모든 유형의 메모리에서, 메모리는 예측이 아닌 서술적이라는 규칙이 적용됩니다.
"메모리"는 메모리 관리자에 의해 반환되고 에이전트가 컨텍스트로 사용하는 원자적(atomic) 컨텍스트 조각입니다. 정확한 스키마는 다를 수 있지만, 단일 메모리는 일반적으로 내용(content)과 메타데이터(metadata)라는 두 가지 주요 구성 요소로 이루어집니다.
내용은 소스 데이터(즉, 세션의 원시 대화)에서 추출된 메모리의 실체입니다. 중요한 점은, 내용은 모든 에이전트가 쉽게 수용할 수 있는 간단한 데이터 구조를 사용하여 프레임워크에 구애받지 않도록(framework-agnostic) 설계된다는 것입니다. 내용은 구조화된 데이터이거나 비구조화된 데이터일 수 있습니다. 구조화된 메모리는 일반적으로 사전이나 JSON과 같은 보편적인 형식으로 저장되는 정보를 포함합니다. 그 스키마는 특정 프레임워크가 아닌 개발자에 의해 일반적으로 정의됩니다. 예를 들면, {"seat_preference": "Window"}와 같습니다. 비구조화된 메모리는 더 긴 상호작용, 이벤트 또는 주제의 본질을 포착하는 자연어 설명입니다. 예를 들면, "사용자는 창가 좌석을 선호합니다."와 같습니다.
메타데이터는 메모리에 대한 컨텍스트를 제공하며, 일반적으로 간단한 문자열로 저장됩니다. 여기에는 메모리의 고유 식별자, 메모리의 "소유자"에 대한 식별자, 그리고 메모리의 내용이나 데이터 소스를 설명하는 레이블이 포함될 수 있습니다.
2025년 11월
35페이지
컨텍스트 엔지니어링: 세션, 메모리
정보 유형
기본적인 구조 외에도, 메모리는 그들이 나타내는 지식의 근본적인 유형에 따라 분류될 수 있습니다. 에이전트가 메모리를 어떻게 사용 하는가를 이해하는 데 중요한 이 구분은, 인지 과학¹¹에서 파생된 두 가지 주요 기능적 범주로 메모리를 나눕니다: 서술 기억 ("무엇을 아는지")과 절차 기억 ("어떻게 하는지 아는지").
서술 기억은 사실, 수치, 사건에 대한 에이전트의 지식입니다. 이는 에이전트가 명시적으로 말하거나 "서술"할 수 있는 모든 정보입니다. 메모리가 "무엇"에 대한 질문의 답이라면, 그것은 서술 기억입니다. 이 범주는 일반적인 세상 지식(의미론적 기억)과 특정 사용자 사실(엔티티/일화적 기억)을 모두 포함합니다.
절차 기억은 기술과 작업 흐름에 대한 에이전트의 지식입니다. 이는 작업을 올바르게 수행하는 방법을 암묵적으로 보여줌으로써 에이전트의 행동을 안내합니다. 메모리가 "어떻게"에 대한 질문에 답하는 데 도움이 된다면—예를 들어, 여행 예약을 위한 올바른 도구 호출 순서—그것은 절차 기억입니다.
조직 패턴
메모리가 생성되면, 다음 질문은 그것을 어떻게 조직할 것인가입니다. 메모리 관리자는 일반적으로 메모리를 조직하기 위해 다음 패턴 중 하나 이상을 사용합니다: 컬렉션¹², 구조화된 사용자 프로필, 또는 "롤링 요약". 이 패턴들은 개별 메모리가 서로 그리고 사용자와 어떻게 관련되는지를 정의합니다.
2025년 11월
36페이지
컨텍스트 엔지니어링: 세션, 메모리
컬렉션¹³ 패턴은 콘텐츠를 단일 사용자를 위한 여러 개의 독립적인 자연어 메모리로 조직합니다. 각 메모리는 별개의 이벤트, 요약 또는 관찰이지만, 단일 상위 주제에 대해 컬렉션 내에 여러 메모리가 있을 수 있습니다. 컬렉션을 사용하면 특정 목표나 주제와 관련된 더 크고 덜 구조화된 정보 풀을 저장하고 검색할 수 있습니다.
구조화된 사용자 프로필 패턴은 메모리를 사용자에 대한 핵심 사실 집합으로 조직하며, 이는 새로운 안정적인 정보로 지속적으로 업데이트되는 연락처 카드와 같습니다. 이름, 선호도, 계정 세부 정보와 같은 필수적인 사실 정보를 빠르게 조회하도록 설계되었습니다.
구조화된 사용자 프로필과 달리, "롤링" 요약 패턴은 모든 정보를 전체 사용자-에이전트 관계의 자연어 요약을 나타내는 단일하고 진화하는 메모리로 통합합니다. 새로운 개별 메모리를 생성하는 대신, 관리자는 이 하나의 마스터 문서를 지속적으로 업데이트합니다. 이 패턴은 긴 세션을 압축하고, 전체 토큰 수를 관리하면서 중요한 정보를 보존하는 데 자주 사용됩니다.
스토리지 아키텍처
또한, 스토리지 아키텍처는 에이전트가 얼마나 빠르고 지능적으로 메모리를 검색할 수 있는지를 결정하는 중요한 결정입니다. 아키텍처의 선택은 에이전트가 개념적으로 유사한 아이디어를 찾는 데 뛰어난지, 구조화된 관계를 이해하는 데 뛰어난지, 아니면 둘 다에 뛰어난지를 정의합니다.
메모리는 일반적으로 벡터 데이터베이스 및/또는 지식 그래프에 저장됩니다. 벡터 데이터베이스는 쿼리와 개념적으로 유사한 메모리를 찾는 데 도움을 줍니다. 지식 그래프는 메모리를 엔티티와 그들의 관계 네트워크로 저장합니다.
2025년 11월
37페이지
컨텍스트 엔지니어링: 세션, 메모리
벡터 데이터베이스는 가장 일반적인 접근 방식으로, 정확한 키워드가 아닌 의미적 유사성에 기반한 검색을 가능하게 합니다. 메모리는 임베딩 벡터로 변환되고, 데이터베이스는 사용자의 쿼리에 가장 가까운 개념적 일치 항목을 찾습니다. 이는 컨텍스트와 의미가 핵심인 비구조화된 자연어 메모리(즉, "원자적 사실"¹⁴)를 검색하는 데 탁월합니다.
지식 그래프는 메모리를 엔티티(노드)와 그들의 관계(엣지)의 네트워크로 저장하는 데 사용됩니다. 검색은 이 그래프를 탐색하여 직접적이고 간접적인 연결을 찾는 것을 포함하며, 이를 통해 에이전트는 다른 사실들이 어떻게 연결되어 있는지 추론할 수 있습니다. 이는 구조화된 관계형 쿼리와 데이터 내의 복잡한 연결을 이해하는 데 이상적입니다(즉, "지식 삼중항"¹⁵).
지식 그래프의 구조화된 엔티티를 벡터 임베딩으로 보강하여 두 가지 방법을 하이브리드 접근 방식으로 결합할 수도 있습니다. 이를 통해 시스템은 관계형 검색과 의미론적 검색을 동시에 수행할 수 있습니다. 이는 그래프의 구조화된 추론 능력과 벡터 데이터베이스의 미묘하고 개념적인 검색 능력을 모두 제공하여, 양쪽의 장점을 최대한 활용할 수 있게 합니다.
생성 메커니즘
우리는 또한 정보가 어떻게 파생되었는지를 포함하여 메모리가 어떻게 생성되었는지에 따라 분류할 수 있습니다. 명시적 메모리는 사용자가 에이전트에게 무언가를 기억하라고 직접 명령할 때 생성됩니다(예: "내 기념일이 10월 26일이라는 것을 기억해"). 반면에, 암시적 메모리는 에이전트가 직접적인 명령 없이 대화에서 정보를 추론하고 추출할 때 생성됩니다(예: "다음 주가 기념일이야. 파트너를 위한 선물을 찾는 데 도와줄 수 있니?").
2025년 11월
38페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리는 또한 메모리 추출 로직이 에이전트 프레임워크 내부에 위치하는지 외부에 위치하는지에 따라 구별될 수 있습니다. 내부 메모리는 에이전트 프레임워크에 직접 내장된 메모리 관리를 의미합니다. 시작하기에는 편리하지만 종종 고급 기능이 부족합니다. 내부 메모리는 외부 스토리지를 사용할 수 있지만, 메모리를 생성하는 메커니즘은 에이전트 내부에 있습니다.
외부 메모리는 메모리 관리에 전념하는 별도의 전문 서비스를 사용하는 것을 포함합니다(예: Agent Engine Memory Bank, Mem0, Zep). 에이전트 프레임워크는 이 외부 서비스에 API 호출을 하여 메모리를 저장, 검색 및 처리합니다. 이 접근 방식은 의미론적 검색, 엔티티 추출, 자동 요약과 같은 더 정교한 기능을 제공하며, 메모리 관리라는 복잡한 작업을 목적에 맞게 제작된 도구에 위임합니다.
메모리 범위
메모리가 누구 또는 무엇을 설명하는지도 고려해야 합니다. 이는 메모리를 집계하고 검색하는 데 사용하는 엔티티(즉, 사용자, 세션 또는 애플리케이션)에 영향을 미칩니다.
사용자 수준 범위는 가장 일반적인 구현으로, 각 개인에게 지속적이고 개인화된 경험을 제공하도록 설계되었습니다. 예를 들어, "사용자는 가운데 좌석을 선호합니다."와 같습니다. 메모리는 특정 사용자 ID에 연결되어 모든 세션에 걸쳐 유지되므로, 에이전트는 사용자의 선호도와 기록에 대한 장기적인 이해를 구축할 수 있습니다.
세션 수준 범위는 긴 대화를 압축하기 위해 설계되었습니다. 예를 들어, "사용자는 2025년 11월 7일에서 11월 14일 사이에 뉴욕과 파리 간의 티켓을 쇼핑하고 있습니다. 그들은 직항 항공편과 가운데 좌석을 선호합니다."와 같습니다. 이는 단일 세션에서 추출된 통찰력의 영구적인 기록을 생성하여, 에이전트가 장황하고
2025년 11월
39페이지
컨텍스트 엔지니어링: 세션, 메모리
토큰이 많이 소모되는 대화 기록을 간결한 핵심 사실 집합으로 대체할 수 있게 합니다. 결정적으로, 이 메모리는 원시 세션 로그와는 구별됩니다. 이는 대화 자체가 아닌, 대화에서 처리된 통찰력만을 포함하며, 그 컨텍스트는 해당 특정 세션에만 격리됩니다.
애플리케이션 수준 범위(또는 전역 컨텍스트)는 애플리케이션의 모든 사용자가 접근할 수 있는 메모리입니다. 예를 들어, "코드명 XYZ는 해당 프로젝트를 의미합니다..."와 같습니다. 이 범위는 공유 컨텍스트를 제공하거나, 시스템 전체 정보를 방송하거나, 공통 지식의 기준선을 설정하는 데 사용됩니다. 애플리케이션 수준 메모리의 일반적인 사용 사례는 에이전트에게 "방법" 지침을 제공하는 절차적 메모리입니다. 이 메모리는 일반적으로 모든 사용자를 위한 에이전트의 추론을 돕기 위한 것입니다. 사용자 간의 데이터 유출을 방지하기 위해 이러한 메모리에서 모든 민감한 콘텐츠를 제거하는 것이 매우 중요합니다.
멀티모달 메모리
"멀티모달 메모리"는 에이전트가 이미지, 비디오, 오디오와 같은 비텍스트 정보를 어떻게 처리하는지를 설명하는 중요한 개념입니다. 핵심은 메모리가 파생된 데이터(소스)와 메모리가 저장되는 데이터(콘텐츠)를 구별하는 것입니다.
멀티모달 소스로부터의 메모리는 가장 일반적인 구현입니다. 에이전트는 텍스트, 이미지, 오디오 등 다양한 데이터 유형을 처리할 수 있지만, 생성하는 메모리는 해당 소스에서 파생된 텍스트적 통찰입니다. 예를 들어, 에이전트는 사용자의 음성 메모를 처리하여 메모리를 생성할 수 있습니다. 오디오 파일 자체를 저장하는 대신, 오디오를 텍스트로 변환하고 "사용자가 최근 배송 지연에 대해 불만을 표현했습니다."와 같은 텍스트 메모리를 생성합니다.
2025년 11월
40페이지
컨텍스트 엔지니어링: 세션, 메모리
멀티모달 콘텐츠를 포함한 메모리는 메모리 자체가 비텍스트 미디어를 포함하는 더 발전된 접근 방식입니다. 에이전트는 단순히 콘텐츠를 설명하는 것이 아니라 콘텐츠를 직접 저장합니다. 예를 들어, 사용자가 이미지를 업로드하고 "이 디자인을 우리 로고로 기억해 줘."라고 말할 수 있습니다. 에이전트는 사용자의 요청과 연결된 이미지 파일을 직접 포함하는 메모리를 생성합니다.
대부분의 현대 메모리 관리자는 텍스트 콘텐츠를 생성하면서 멀티모달 소스를 처리하는 데 중점을 둡니다. 이는 이미지나 오디오와 같은 비구조화된 이진 데이터를 특정 메모리에 대해 생성하고 검색하려면 전문화된 모델, 알고리즘, 인프라가 필요하기 때문입니다. 모든 입력을 공통적이고 검색 가능한 형식인 텍스트로 변환하는 것이 훨씬 간단합니다.
예를 들어, Agent Engine Memory Bank를 사용하여 멀티모달 입력¹⁶으로부터 메모리를 생성할 수 있습니다. 출력 메모리는 해당 콘텐츠에서 추출된 텍스트적 통찰이 될 것입니다.
Python
from google.genai import types
client = vertexai.Client(project=..., location=...)
response = client.agent_engines.memories.generate(
name=agent_engine_name,
direct_contents_source={
"events": [
{
"content": types.Content(
role="user",
parts=[
types.Part.from_text(
"이것은 멀티모달 입력에 대한 컨텍스트입니다."
),
# 계속...
2025년 11월
41페이지
컨텍스트 엔지니어링: 세션, 메모리
types.Part.from_bytes(
data=CONTENT_AS_BYTES,
mime_type=MIME_TYPE
),
types.Part.from_uri(
file_uri="file/path/to/content",
mime_type=MIME_TYPE
)
]
)
}
]
},
scope={"user_id": user_id}
)
코드 5: Agent Engine Memory Bank를 위한 예제 메모리 생성 API 호출
다음 섹션에서는 메모리 생성의 메커니즘을 살펴보고, 소스 데이터에서 새로운 정보를 추출하는 단계와 그 정보를 기존 메모리 코퍼스와 통합하는 두 가지 핵심 단계를 자세히 설명합니다.
메모리 생성: 추출 및 통합
메모리 생성은 원시 대화 데이터를 구조화되고 의미 있는 통찰로 자율적으로 변환하는 과정입니다. 이를 메모리를 추출하고 압축하도록 설계된 LLM 기반 ETL(추출, 변환, 로드) 파이프라인으로 생각할 수 있습니다. 메모리 생성의 ETL 파이프라인은 메모리 관리자를 RAG 엔진 및 전통적인 데이터베이스와 구별하는 특징입니다.
개발자가 수동으로 데이터베이스 작업을 지정하도록 요구하는 대신, 메모리 관리자는 LLM을 사용하여 언제 메모리를 추가, 업데이트 또는 병합할지 지능적으로 결정합니다. 이러한 자동화는 메모리 관리자의 핵심 강점입니다. 데이터베이스 콘텐츠 관리, LLM 호출 체이닝, 데이터 처리를 위한 백그라운드 서비스 배포의 복잡성을 추상화합니다.
2025년 11월
42페이지
컨텍스트 엔지니어링: 세션, 메모리
(이미지)
그림 6: 새로운 데이터 소스에서 메모리를 추출하고 기존 메모리와 통합하는 메모리 생성의 고수준 알고리즘
- 데이터 소스 (예: 세션 이벤트) -> 메모리 추출 (LLM) -> 원시 메모리
- 원시 메모리는 기존 유사 메모리 검색 단계로 이어지고, 검색된 유사 메모리와 함께 메모리 통합 (LLM) 단계로 들어갑니다.
- 메모리 통합 결과는 작업이 포함된 통합된 메모리 (예: 추가, 업데이트)가 되어 메모리 저장소에 저장됩니다.
특정 알고리즘은 플랫폼(예: Agent Engine Memory Bank, Mem0, Zep)에 따라 다르지만, 메모리 생성의 고수준 프로세스는 일반적으로 다음 네 단계를 따릅니다.
수집: 클라이언트가 메모리 관리자에게 원시 데이터 소스(일반적으로 대화 기록)를 제공하면서 프로세스가 시작됩니다.
추출 및 필터링: 메모리 관리자는 LLM을 사용하여 소스 데이터에서 의미 있는 콘텐츠를 추출합니다. 핵심은 이 LLM이 모든 것을 추출하는 것이 아니라, 미리 정의된 주제 정의에 맞는 정보만 캡처한다는 것입니다. 만약 수집된 데이터에 이 주제와 일치하는 정보가 없으면, 메모리는 생성되지 않습니다.
통합: 이것은 가장 정교한 단계로, 메모리 관리자가 충돌 해결과 중복 제거를 처리합니다. "자가 편집" 프로세스를 수행하며, LLM을 사용하여 새로 추출된 정보를 기존 메모리와 비교합니다. 사용자의 지식 기반이 새로운 정보를 바탕으로 시간이 지남에 따라 일관되고 정확하며 발전하도록 보장하기 위해, 관리자는 다음과 같이 결정할 수 있습니다.
- 새로운 통찰을 기존 메모리에 병합합니다.
2025년 11월
43페이지
컨텍스트 엔지니어링: 세션, 메모리
- 이제 유효하지 않게 된 기존 메모리를 삭제합니다.
- 주제가 새로운 경우 완전히 새로운 메모리를 생성합니다.
- 저장: 마지막으로, 새롭거나 업데이트된 메모리는 향후 상호작용에서 검색될 수 있도록 영구 저장 계층(예: 벡터 데이터베이스 또는 지식 그래프)에 영속화됩니다.
Agent Engine Memory Bank와 같은 관리형 메모리 관리자는 이 파이프라인을 완전히 자동화합니다. 그들은 대화의 노이즈를 구조화된 지식으로 바꾸는 단일하고 일관된 시스템을 제공하여, 개발자가 기본 데이터 인프라를 구축하고 유지하는 대신 에이전트 로직에 집중할 수 있도록 합니다. 예를 들어, Memory Bank로 메모리 생성을 트리거하는 것은 간단한 API 호출만 필요합니다¹⁷:
Python
from google.cloud import vertexai
client = vertexai.Client(project=..., location=...)
client.agent_engines.memories.generate(
name="projects/.../locations/...reasoningEngines/...",
scope={"user_id": "123"},
direct_contents_source={
"events": [...]
},
config={
# 백그라운드에서 메모리 생성을 실행합니다.
"wait_for_completion": False
}
)
코드 6: Agent Engine Memory Bank로 메모리 생성하기
2025년 11월
44페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리 생성 과정은 정원을 가꾸는 성실한 정원사의 작업에 비유할 수 있습니다. 추출은 새로운 씨앗과 묘목(대화에서 얻은 새로운 정보)을 받는 것과 같습니다. 정원사는 그것들을 무작위로 밭에 던지지 않습니다. 대신, 잡초를 뽑고(중복되거나 충돌하는 데이터 삭제), 기존 식물의 건강을 개선하기 위해 무성하게 자란 가지를 치고(기존 메모리 정제 및 요약), 그리고 나서 새로운 묘목을 최적의 위치에 신중하게 심는 통합 작업을 수행합니다. 이러한 지속적이고 사려 깊은 큐레이션은 정원이 시간이 지나도 무성하고 쓸모없는 잡동사니가 되는 대신, 건강하고 정리된 상태를 유지하며 계속 번성하도록 보장합니다. 이 비동기적인 과정은 백그라운드에서 일어나므로, 정원은 다음 방문을 위해 항상 준비되어 있습니다.
이제 메모리 생성의 두 가지 핵심 단계인 추출과 통합에 대해 깊이 파고들어 보겠습니다.
심층 분석: 메모리 추출
메모리 추출의 목표는 "이 대화에서 어떤 정보가 메모리가 될 만큼 의미 있는가?"라는 근본적인 질문에 답하는 것입니다. 이것은 단순한 요약이 아닙니다. 신호(중요한 사실, 선호도, 목표)를 노이즈(인사말, 군더더기 텍스트)로부터 분리하도록 설계된, 목표 지향적이고 지능적인 필터링 과정입니다.
"의미 있다"는 것은 보편적인 개념이 아닙니다. 그것은 전적으로 에이전트의 목적과 사용 사례에 의해 정의됩니다. 고객 지원 에이전트가 기억해야 할 것(예: 주문 번호, 기술적 문제)은 개인 웰니스 코치가 기억해야 할 것(예: 장기 목표, 감정 상태)과 근본적으로 다릅니다. 따라서 어떤 정보를 보존할지 맞춤화하는 것이 진정으로 효과적인 에이전트를 만드는 핵심입니다.
2025년 11월
45페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리 관리자의 LLM은 보통 복잡한 시스템 프롬프트에 내장된, 세심하게 구성된 프로그래밍 방식의 가드레일과 지침 세트를 따라 무엇을 추출할지 결정합니다. 이 프롬프트는 LLM에게 주제 정의 세트를 제공함으로써 "의미 있는" 것이 무엇인지를 정의합니다. 스키마 및 템플릿 기반 추출을 사용하면, LLM은 구조화된 출력¹⁸과 같은 LLM 기능을 사용하여 미리 정의된 JSON 스키마나 템플릿을 제공받습니다. LLM은 대화에서 해당 정보를 사용하여 JSON을 구성하도록 지시받습니다. 대안으로, 자연어 주제 정의를 사용하면, LLM은 주제에 대한 간단한 자연어 설명에 의해 안내됩니다.
소수샷 프롬프팅(few-shot prompting)을 사용하면, LLM에게 예시를 통해 어떤 정보를 추출해야 하는지 "보여줍니다". 프롬프트는 여러 입력 텍스트 예시와 추출되어야 할 이상적인 고품질 메모리를 포함합니다. LLM은 예시로부터 원하는 추출 패턴을 학습하여, 스키마나 간단한 정의로 설명하기 어려운 사용자 정의 또는 미묘한 주제에 대해 매우 효과적입니다.
대부분의 메모리 관리자는 사용자 선호도, 핵심 사실 또는 목표와 같은 일반적인 주제를 찾아 즉시 사용 가능하도록 작동합니다. 많은 플랫폼에서는 개발자가 자신만의 사용자 정의 주제를 정의하여 특정 도메인에 맞게 추출 프로세스를 조정할 수도 있습니다. 예를 들어, Agent Engine Memory Bank가 어떤 정보를 의미 있는 것으로 간주하여 영속화할지 자신만의 주제 정의와 소수샷 예시를 제공하여 맞춤화할 수 있습니다¹⁹:
Python```python
from google.genai.types import Content, Part
자세한 정보는 https://cloud.google.com/agent-builder/agent-engine/memory-bank/set-up 를 참조하세요.
memory_bank_config = {
"customization_configs": [{
"memory_topics": [
{ "managed_memory_topic": {"managed_topic_enum": "USER_PERSONAL_INFO" }},
계속...
2025년 11월
***
## **46페이지**
**컨텍스트 엔지니어링: 세션, 메모리**
```python
{
"custom_memory_topic": {
"label": "business_feedback",
"description": """커피숍에서의 경험에 대한 구체적인 사용자 피드백입니다.
음료, 음식, 페이스트리, 분위기, 직원 친절도, 서비스 속도,
청결도 및 개선 제안에 대한 의견을 포함합니다."""
}
}
],
"generate_memories_examples": {
"conversationSource": {
"events": [
{
"content": Content(
role="model",
parts=[Part(text="The Daily Grind에 다시 오신 것을 환영합니다! 방문에 대한 피드백을 듣고 싶습니다.")])
},{
"content": Content(
role="user",
parts=[Part(text="안녕하세요. 오늘 드립 커피가 좀 미지근해서 아쉬웠어요. 그리고 음악이 너무 커서 친구 말을 거의 들을 수가 없었어요.")])
}]
},
"generatedMemories": [
{"fact": "사용자는 드립 커피가 미지근하다고 보고했습니다."},
{"fact": "사용자는 가게의 음악이 너무 크다고 느꼈습니다."}
]
}
}]
}
agent_engine = client.agent_engines.create(
config={
"context_spec": {"memory_bank_config": memory_bank_config }
}
)코드 7: Agent Engine Memory Bank가 의미 있다고 간주하여 영속화할 정보 맞춤화하기
메모리 추출 자체가 "요약"은 아니지만, 알고리즘은 정보를 정제하기 위해 요약을 포함할 수 있습니다. 효율성을 높이기 위해, 많은 메모리 관리자는 대화의 롤링 요약을 메모리 추출에 직접 통합합니다.
2025년 11월
47페이지
컨텍스트 엔지니어링: 세션, 메모리
프롬프트²⁰. 이 압축된 기록은 가장 최근의 상호작용에서 핵심 정보를 추출하는 데 필요한 컨텍스트를 제공합니다. 이는 컨텍스트를 유지하기 위해 매 턴마다 전체의 장황한 대화를 반복적으로 처리할 필요를 없애줍니다.
정보가 데이터 소스에서 추출되면, 기존 메모리 코퍼스는 통합을 통해 새로운 정보를 반영하도록 업데이트되어야 합니다.
심층 분석: 메모리 통합
메모리가 장황한 대화에서 추출된 후, 통합은 새로운 정보를 일관되고, 정확하며, 진화하는 지식 기반으로 통합해야 합니다. 이는 메모리 수명 주기에서 가장 정교한 단계라고 할 수 있으며, 단순한 사실 모음을 사용자에 대한 큐레이션된 이해로 변환합니다. 통합이 없다면, 에이전트의 메모리는 캡처된 모든 정보 조각의 노이즈가 많고, 모순되며, 신뢰할 수 없는 로그가 될 것입니다. 이러한 "자가 큐레이션"은 일반적으로 LLM에 의해 관리되며, 메모리 관리자를 단순한 데이터베이스 이상으로 끌어올리는 요소입니다.
통합은 대화 데이터에서 발생하는 근본적인 문제들을 해결합니다.
정보 중복: 사용자는 여러 대화에 걸쳐 같은 사실을 다양한 방식으로 언급할 수 있습니다 (예: "뉴욕행 비행기가 필요해"와 나중에 "뉴욕으로 여행 갈 계획이야"). 단순한 추출 과정은 두 개의 중복된 메모리를 생성할 것입니다.
정보 충돌: 사용자의 상태는 시간이 지나면서 변합니다. 통합이 없다면, 에이전트의 메모리는 모순되는 사실을 포함하게 될 것입니다.
정보 진화: 단순한 사실이 더 미묘해질 수 있습니다. "사용자는 마케팅에 관심이 있다"는 초기 메모리는 "사용자는 4분기 고객 확보에 초점을 맞춘 마케팅 프로젝트를 이끌고 있다"로 진화할 수 있습니다.
2025년 11월
48페이지
컨텍스트 엔지니어링: 세션, 메모리
- 메모리 관련성 감쇠: 모든 메모리가 영원히 유용한 것은 아닙니다. 에이전트는 지식 기반을 관련성 있고 효율적으로 유지하기 위해 오래되고, 진부하며, 신뢰도가 낮은 메모리를 능동적으로 삭제하는 잊기(forgetting)에 참여해야 합니다. 잊기는 통합 중에 LLM에게 새로운 정보에 우선순위를 두도록 지시하거나, TTL(time-to-live)을 통한 자동 삭제를 통해 발생할 수 있습니다.
통합 과정은 새로 추출된 통찰을 사용자의 기존 메모리와 비교하는 LLM 기반 워크플로우입니다. 먼저, 워크플로우는 새로 추출된 메모리와 유사한 기존 메모리를 검색하려고 시도합니다. 이 기존 메모리들이 통합의 후보가 됩니다. 만약 기존 메모리가 새로운 정보와 모순된다면, 삭제될 수 있습니다. 만약 보강된다면, 업데이트될 수 있습니다.
두 번째로, LLM에게 기존 메모리와 새로운 정보가 모두 제공됩니다. 핵심 작업은 이들을 함께 분석하고 어떤 작업이 수행되어야 하는지 식별하는 것입니다. 주요 작업은 다음과 같습니다.
- 업데이트: 기존 메모리를 새롭거나 수정된 정보로 수정합니다.
- 생성: 새로운 통찰이 완전히 새롭고 기존 메모리와 관련이 없는 경우, 새로운 메모리를 생성합니다.
- 삭제 / 무효화: 새로운 정보가 오래된 메모리를 완전히 관련 없거나 부정확하게 만드는 경우, 해당 메모리를 삭제하거나 무효화합니다.
마지막으로, 메모리 관리자는 LLM의 결정을 메모리 저장소를 업데이트하는 트랜잭션으로 변환합니다.
2025년 11월
49페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리 출처 (Provenance)
"쓰레기가 들어가면, 쓰레기가 나온다(garbage in, garbage out)"는 고전적인 머신러닝의 격언은 LLM에서 더욱 중요합니다. LLM의 결과는 종종 "쓰레기가 들어가면, 자신감 있는 쓰레기가 나온다"이기 때문입니다. 에이전트가 신뢰할 수 있는 결정을 내리고 메모리 관리자가 효과적으로 메모리를 통합하기 위해서는, 자신의 메모리의 품질을 비판적으로 평가할 수 있어야 합니다. 이러한 신뢰성은 메모리의 출처(provenance)—그 기원과 역사에 대한 상세한 기록—에서 직접 파생됩니다.
(이미지)
그림 7: 데이터 소스와 메모리 간의 정보 흐름. 단일 메모리는 여러 데이터 소스에서 파생될 수 있으며, 단일 데이터 소스는 여러 메모리에 기여할 수 있습니다.
- 요청 1(데이터 소스 A) -> 메모리 1 -> 메모리 리비전 1
- 요청 2(데이터 소스 B) -> 메모리 1 -> 메모리 리비전 2
- 요청 3(데이터 소스 C) -> 메모리 1 -> 메모리 리비전 3
- 요청 4(데이터 소스 D) -> 메모리 2 -> 메모리 리비전 1, 메모리 리비전 2
메모리 통합—여러 소스의 정보를 단일하고 진화하는 메모리로 병합하는 과정—은 그 계보를 추적할 필요성을 만듭니다. 위 다이어그램에서 볼 수 있듯이, 단일 메모리는 여러 데이터 소스의 혼합일 수 있으며, 단일 소스는 여러 메모리로 분할될 수 있습니다.
2025년 11월
50페이지
컨텍스트 엔지니어링: 세션, 메모리
신뢰성을 평가하기 위해, 에이전트는 각 소스의 기원(소스 유형)과 생성 시점("최신성")과 같은 핵심 세부 정보를 추적해야 합니다. 이러한 세부 정보는 두 가지 이유로 중요합니다: 메모리 통합 중에 각 소스가 갖는 가중치를 결정하고, 추론 중에 에이전트가 해당 메모리에 얼마나 의존해야 하는지를 알려줍니다.
소스 유형은 신뢰를 결정하는 가장 중요한 요소 중 하나입니다. 데이터 소스는 세 가지 주요 범주로 나뉩니다.
부트스트랩 데이터: CRM과 같은 내부 시스템에서 사전 로드된 정보입니다. 이 높은 신뢰도의 데이터는 사용자의 메모리를 초기화하여, 에이전트가 한 번도 상호작용한 적 없는 사용자에게 개인화된 경험을 제공하는 과제인 콜드 스타트 문제를 해결하는 데 사용될 수 있습니다.
사용자 입력: 여기에는 명시적으로 제공된 데이터(예: 양식을 통한 높은 신뢰도의 데이터) 또는 대화에서 암시적으로 추출된 정보(일반적으로 신뢰도가 낮음)가 포함됩니다.
도구 출력: 외부 도구 호출에서 반환된 데이터입니다. 도구 출력에서 메모리를 생성하는 것은 일반적으로 권장되지 않습니다. 이러한 메모리는 불안정하고 오래되기 쉬워, 이 소스 유형은 단기 캐싱에 더 적합하기 때문입니다.
메모리 관리 중 메모리 계보 기록
이러한 동적인 다중 소스 접근 방식은 메모리를 관리할 때 충돌 해결과 파생 데이터 삭제라는 두 가지 주요 운영 과제를 만듭니다.
메모리 통합은 필연적으로 한 데이터 소스가 다른 데이터 소스와 충돌하는 상황을 야기합니다. 메모리의 출처는 메모리 관리자가 정보 소스에 대한 신뢰 계층을 설정할 수 있게 해줍니다. 다른 소스의 메모리가 서로 모순될 때,
2025년 11월
51페이지
컨텍스트 엔지니어링: 세션, 메모리
에이전트는 이 계층 구조를 충돌 해결 전략에 사용해야 합니다. 일반적인 전략에는 가장 신뢰할 수 있는 소스를 우선시하거나, 가장 최근 정보를 선호하거나, 여러 데이터 포인트에 걸친 확증을 찾는 것이 포함됩니다.
메모리를 삭제할 때 또 다른 과제가 발생합니다. 하나의 메모리는 여러 데이터 소스에서 파생될 수 있습니다. 사용자가 하나의 데이터 소스에 대한 접근을 철회하면, 해당 소스에서 파생된 데이터도 제거되어야 합니다. 해당 소스에 의해 "영향을 받은" 모든 메모리를 삭제하는 것은 지나치게 공격적일 수 있습니다. 더 정밀하지만 계산 비용이 많이 드는 접근 방식은, 영향을 받은 메모리를 남아있는 유효한 소스만을 사용하여 처음부터 다시 생성하는 것입니다.
정적인 출처 세부 정보 외에도, 메모리에 대한 신뢰도는 진화해야 합니다. 신뢰도는 여러 신뢰할 수 있는 소스가 일관된 정보를 제공하는 경우와 같은 확증을 통해 증가합니다. 그러나 효율적인 메모리 시스템은 더 이상 유용하지 않은 메모리를 식별하고 "잊는" 과정인 메모리 가지치기(pruning)를 통해 기존 지식을 적극적으로 큐레이션해야 합니다. 이 가지치기는 여러 요인에 의해 트리거될 수 있습니다.
- 시간 기반 감쇠: 메모리의 중요성은 시간이 지남에 따라 감소할 수 있습니다. 2년 전 회의에 대한 메모리는 지난주 회의에 대한 메모리보다 관련성이 낮을 가능성이 높습니다.
- 낮은 신뢰도: 약한 추론으로 생성되었고 다른 소스에 의해 확증되지 않은 메모리는 가지치기될 수 있습니다.
- 무관련성: 에이전트가 사용자에 대해 더 정교한 이해를 얻게 되면, 일부 오래되고 사소한 메모리가 사용자의 현재 목표와 더 이상 관련이 없다고 판단할 수 있습니다.
반응형 통합 파이프라인과 능동형 가지치기를 결합함으로써, 메모리 관리자는 에이전트의 지식 기반이 단순히 말한 모든 것을 기록하는 성장하는 로그가 아니라, 사용자에 대한 큐레이션되고, 정확하며, 관련성 있는 이해가 되도록 보장합니다.
2025년 11월
52페이지
컨텍스트 엔지니어링: 세션, 메모리
추론 중 메모리 계보 기록
코퍼스의 내용을 큐레이션하는 동안 메모리의 계보를 고려하는 것 외에도, 추론 시점에도 메모리의 신뢰성을 고려해야 합니다. 메모리에 대한 에이전트의 신뢰도는 정적이지 않아야 합니다. 새로운 정보와 시간의 흐름에 따라 진화해야 합니다. 신뢰도는 여러 신뢰할 수 있는 소스가 일관된 정보를 제공할 때와 같은 확증을 통해 증가합니다. 반대로, 오래된 메모리가 진부해지면 시간이 지남에 따라 신뢰도가 감소(또는 감쇠)하며, 모순된 정보가 도입될 때도 떨어집니다. 결국, 시스템은 신뢰도가 낮은 메모리를 보관하거나 삭제함으로써 "잊을" 수 있습니다. 이 동적인 신뢰도 점수는 추론 시점에 매우 중요합니다. 사용자에게 보여지는 대신, 메모리와 가능한 경우 신뢰도 점수가 프롬프트에 주입되어, LLM이 정보의 신뢰성을 평가하고 더 미묘한 결정을 내릴 수 있게 합니다.
이 전체 신뢰 프레임워크는 에이전트의 내부 추론 과정을 지원합니다. 메모리와 그 신뢰도 점수는 일반적으로 사용자에게 직접 표시되지 않습니다. 대신, 시스템 프롬프트에 주입되어 LLM이 증거를 평가하고, 정보의 신뢰성을 고려하며, 궁극적으로 더 미묘하고 신뢰할 수 있는 결정을 내릴 수 있도록 합니다.
메모리 생성 트리거
메모리 관리자가 일단 생성이 트리거되면 메모리 추출 및 통합을 자동화하더라도, 에이전트는 여전히 언제 메모리 생성을 시도할지 결정해야 합니다. 이것은 데이터 최신성과 계산 비용 및 지연 시간 사이의 균형을 맞추는 중요한 아키텍처 선택입니다. 이 결정은 일반적으로 에이전트의 로직에 의해 관리되며, 여러 트리거 전략을 사용할 수 있습니다. 메모리 생성은 다양한 이벤트에 기반하여 시작될 수 있습니다.
- 세션 완료: 멀티턴 세션이 끝날 때 생성을 트리거합니다.
2025년 11월
53페이지
컨텍스트 엔지니어링: 세션, 메모리
턴 주기: 특정 턴 수 이후에 프로세스를 실행합니다 (예: 5턴마다).
실시간: 매 단일 턴 이후에 메모리를 생성합니다.
명시적 명령: 직접적인 사용자 명령에 따라 프로세스를 활성화합니다 (예: "이것을 기억해").
트리거의 선택은 비용과 충실도(fidelity) 사이의 직접적인 절충안을 포함합니다. 빈번한 생성(예: 실시간)은 메모리가 매우 상세하고 최신 상태를 유지하며 대화의 모든 뉘앙스를 포착하도록 보장합니다. 그러나 이는 가장 높은 LLM 및 데이터베이스 비용을 발생시키며, 제대로 처리되지 않으면 지연 시간을 유발할 수 있습니다. 드문 생성(예: 세션 완료 시)은 훨씬 비용 효율적이지만, LLM이 한 번에 훨씬 더 큰 대화 블록을 요약해야 하므로 충실도가 낮은 메모리를 생성할 위험이 있습니다. 또한, 메모리 관리자가 동일한 이벤트를 여러 번 처리하지 않도록 주의해야 합니다. 이는 불필요한 비용을 발생시키기 때문입니다.
도구로서의 메모리(Memory-as-a-Tool)
더 정교한 접근 방식은 에이전트가 스스로 언제 메모리를 생성할지 결정하도록 허용하는 것입니다. 이 패턴에서, 메모리 생성은 도구(예: create_memory)로 노출됩니다. 도구 정의는 어떤 유형의 정보가 의미 있는 것으로 간주되어야 하는지를 정의해야 합니다. 그러면 에이전트는 대화를 분석하고, 지속할 가치가 있는 의미 있는 정보를 식별했을 때 이 도구를 자율적으로 호출하기로 결정할 수 있습니다. 이는 "의미 있는 정보"를 식별하는 책임을 외부 메모리 관리자에서 에이전트(그리고 개발자인 당신) 자신에게로 옮깁니다.
예를 들어, ADK를 사용하여 메모리 생성 코드를 에이전트가 대화가 지속할 가치가 있다고 판단할 때 호출하기로 결정하는 Tool²¹로 패키징할 수 있습니다. 세션을 Memory Bank에 보내면, Memory Bank가 대화 기록에서 메모리를 추출하고 통합할 것입니다.
2025년 11월
54페이지
컨텍스트 엔지니어링: 세션, 메모리
Python
from google.adk.agents import LlmAgent
from google.adk.memory import VertexAiMemoryBankService
from google.adk.runners import Runner
from google.adk.tools import ToolContext
def generate_memories(tool_context: ToolContext):
"""세션을 기억하기 위해 메모리 생성을 트리거합니다."""
# 옵션 1: ADK 메모리 서비스를 사용하여 전체 대화 기록에서 메모리를 추출합니다.
tool_context._invocation_context.memory_service.add_session_to_memory(
session)
# 옵션 2: 마지막 대화 턴에서 메모리를 추출합니다.
client.agent_engines.memories.generate(
name="projects/.../locations/...reasoningEngines/...",
direct_contents_source={
"events": [
{"content": tool_context._invocation_context.user_content}
]
},
scope={
"user_id": tool_context._invocation_context.user_id,
"app_name": tool_context._invocation_context.app_name
},
# 백그라운드에서 메모리 생성
config={"wait_for_completion": False}
)
return {"status": "success"}
agent = LlmAgent(
...
tools=[generate_memories]
)
runner = Runner(
agent=agent,
app_name=APP_NAME,
session_service=session_service,
memory_service=VertexAiMemoryBankService(
agent_engine_id=AGENT_ENGINE_ID,
project=PROJECT,
location=LOCATION
)
)
코드 8: 사용자 정의 도구를 사용하여 메모리 생성을 트리거하는 ADK 에이전트. Memory Bank가 메모리를 추출하고 통합합니다.
2025년 11월
55페이지
컨텍스트 엔지니어링: 세션, 메모리
또 다른 접근 방식은 내부 메모리를 활용하는 것인데, 이 경우 에이전트가 대화에서 무엇을 기억할지 능동적으로 결정합니다. 이 워크플로우에서, 에이전트는 핵심 정보를 추출하는 책임을 집니다. 선택적으로, 이 추출된 메모리는 사용자의 기존 메모리와 통합되기 위해 Agent Engine Memory Bank로 전송될 수 있습니다²²:
Python
def extract_memories(query: str, tool_context: ToolContext):
"""정보를 기억하기 위해 메모리 생성을 트리거합니다.
Args:
query: 사용자에 대해 영속화되어야 할 의미 있는 정보.
"""
client.agent_engines.memories.generate(
name="projects/.../locations/...reasoningEngines/...",
# 의미 있는 정보는 이미 대화에서 추출되었으므로,
# 동일한 사용자의 기존 메모리와 통합하기만 하면 됩니다.
direct_memories_source={
"direct_memories": [{"fact": query}]
},
scope={
"user_id": tool_context._invocation_context.user_id,
"app_name": tool_context._invocation_context.app_name
},
config={"wait_for_completion": False}
)
return {"status": "success"}
agent = LlmAgent(
...
tools=[extract_memories]
)
코드 9: 사용자 정의 도구를 사용하여 대화에서 메모리를 추출하고 Agent Engine Memory Bank로 통합을 트리거하는 ADK 에이전트. 코드 8과 달리, 이 에이전트는 Memory Bank가 아닌 메모리 추출을 책임집니다.
2025년 11월
56페이지
컨텍스트 엔지니어링: 세션, 메모리
백그라운드 작업 vs. 블로킹 작업
메모리 생성은 LLM 호출과 데이터베이스 쓰기를 요구하는 비용이 많이 드는 작업입니다. 프로덕션 환경의 에이전트를 위해, 메모리 생성은 거의 항상 백그라운드 프로세스로 비동기적으로 처리되어야 합니다²³.
에이전트가 사용자에게 응답을 보낸 후, 메모리 생성 파이프라인은 사용자 경험을 차단하지 않고 병렬로 실행될 수 있습니다. 이러한 분리는 에이전트를 빠르고 반응성 있게 유지하는 데 필수적입니다. 사용자가 응답을 받기 전에 메모리가 기록되기를 기다려야 하는 블로킹(또는 동기식) 접근 방식은 용납할 수 없을 정도로 느리고 답답한 사용자 경험을 만들 것입니다. 이는 메모리 생성이 에이전트의 핵심 런타임과 아키텍처적으로 분리된 서비스에서 발생해야 함을 필요로 합니다.
메모리 검색
메모리 생성 메커니즘이 준비되면, 이제 검색이라는 중요한 작업으로 초점을 옮길 수 있습니다. 지능적인 검색 전략은 에이전트의 성능에 필수적이며, 어떤 메모리를 언제 검색해야 하는지에 대한 결정을 포함합니다.
메모리 검색 전략은 메모리가 어떻게 조직되어 있는지에 크게 의존합니다. 구조화된 사용자 프로필의 경우, 검색은 일반적으로 전체 프로필이나 특정 속성에 대한 간단한 조회입니다. 그러나 메모리 컬렉션의 경우, 검색은 훨씬 더 복잡한 검색 문제입니다. 목표는 비구조화되거나 반구조화된 데이터의 큰 풀에서 가장 관련성 있고 개념적으로 연관된 정보를 발견하는 것입니다. 이 섹션에서 논의되는 전략들은 메모리 컬렉션에 대한 이 복잡한 검색 과제를 해결하기 위해 설계되었습니다.
2025년 11월
57페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리 검색은 현재 대화에 가장 적합한 메모리를 찾습니다. 효과적인 검색 전략은 매우 중요합니다. 관련 없는 메모리를 제공하면 모델을 혼란스럽게 하고 응답의 질을 떨어뜨릴 수 있는 반면, 완벽한 컨텍스트 조각을 찾으면 놀랍도록 지능적인 상호작용으로 이어질 수 있습니다. 핵심 과제는 엄격한 지연 시간 예산 내에서 메모리의 '유용성'의 균형을 맞추는 것입니다.
고급 메모리 시스템은 단순한 검색을 넘어 여러 차원에 걸쳐 잠재적인 메모리를 평가하여 최적의 적합성을 찾습니다.
- 관련성 (의미론적 유사성): 이 메모리가 현재 대화와 개념적으로 얼마나 관련이 있는가?
- 최신성 (시간 기반): 이 메모리는 얼마나 최근에 생성되었는가?
- 중요성 (의의): 이 메모리는 전반적으로 얼마나 중요한가? 관련성과 달리, 메모리의 "중요성"은 생성 시점에 정의될 수 있습니다.
벡터 기반 관련성에만 의존하는 것은 흔한 함정입니다. 유사성 점수는 개념적으로는 유사하지만 오래되거나 사소한 메모리를 표면에 드러낼 수 있습니다. 가장 효과적인 전략은 세 가지 차원의 점수를 모두 결합하는 혼합 접근 방식입니다.
정확성이 가장 중요한 애플리케이션의 경우, 쿼리 재작성, 재순위 매기기 또는 특화된 검색기와 같은 접근 방식을 사용하여 검색을 개선할 수 있습니다. 그러나 이러한 기술은 계산 비용이 많이 들고 상당한 지연 시간을 추가하므로, 대부분의 실시간 애플리케이션에는 부적합합니다. 이러한 복잡한 알고리즘이 필요하고 메모리가 빨리 진부해지지 않는 시나리오에서는 캐싱 계층이 효과적인 완화책이 될 수 있습니다. 캐싱을 통해 비용이 많이 드는 검색 쿼리의 결과를 일시적으로 저장하여, 후속 동일한 요청에 대한 높은 지연 시간 비용을 우회할 수 있습니다.
2025년 11월
58페이지
컨텍스트 엔지니어링: 세션, 메모리
쿼리 재작성을 통해 LLM을 사용하여 검색 쿼리 자체를 개선할 수 있습니다. 이는 사용자의 모호한 입력을 더 정확한 쿼리로 재작성하거나, 단일 쿼리를 여러 관련 쿼리로 확장하여 주제의 다른 측면을 포착하는 것을 포함할 수 있습니다. 이는 초기 검색 결과의 품질을 크게 향상시키지만, 프로세스 시작 시 추가 LLM 호출의 지연 시간을 추가합니다.
재순위 매기기를 통해 초기 검색은 유사성 검색을 사용하여 광범위한 후보 메모리 세트(예: 상위 50개 결과)를 가져옵니다. 그런 다음 LLM은 이 작은 세트를 재평가하고 재순위 매겨 더 정확한 최종 목록을 생성할 수 있습니다²⁴.
마지막으로, 미세 조정을 사용하여 특화된 검색기를 훈련시킬 수 있습니다. 그러나 이는 레이블이 지정된 데이터에 대한 접근이 필요하며 비용을 크게 증가시킬 수 있습니다.
궁극적으로, 검색에 대한 최상의 접근 방식은 더 나은 메모리 생성에서 시작됩니다. 메모리 코퍼스가 고품질이고 관련 없는 정보가 없도록 보장하는 것이 검색된 모든 메모리 세트가 도움이 될 것이라는 것을 보장하는 가장 효과적인 방법입니다.
검색 시점
검색에 대한 최종 아키텍처 결정은 언제 메모리를 검색할 것인가입니다. 한 가지 접근 방식은 사전 검색(proactive retrieval)으로, 매 턴이 시작될 때 메모리가 자동으로 로드됩니다. 이는 컨텍스트가 항상 사용 가능하도록 보장하지만, 메모리 접근이 필요 없는 턴에 불필요한 지연 시간을 발생시킵니다. 메모리는 단일 턴 동안 정적으로 유지되므로, 이러한 성능 비용을 완화하기 위해 효율적으로 캐시될 수 있습니다.
예를 들어, ADK에서 내장된 PreloadMemoryTool이나 사용자 정의 콜백²⁵을 사용하여 사전 검색을 구현할 수 있습니다.
2025년 11월
59페이지
컨텍스트 엔지니어링: 세션, 메모리
Python
# 옵션 1: 내장된 PreloadMemoryTool을 사용하여 매 턴마다 유사성 검색으로 메모리를 검색합니다.
agent = LlmAgent(
...
tools=[adk.tools.preload_memory_tool.PreloadMemoryTool()]
)
# 옵션 2: 사용자 정의 콜백을 사용하여 메모리 검색 방식을 더 세밀하게 제어합니다.
def retrieve_memories_callback(callback_context, llm_request):
user_id = callback_context._invocation_context.user_id
app_name = callback_context._invocation_context.app_name
response = client.agent_engines.memories.retrieve(
name="projects/.../locations/...reasoningEngines/...",
scope={
"user_id": user_id,
"app_name": app_name
}
)
memories = [f"* {memory.memory.fact}" for memory in list(response)]
if not memories:
# 시스템 명령어에 추가할 메모리가 없습니다.
return
# 서식이 지정된 메모리를 시스템 명령어에 추가합니다.
llm_request.config.system_instruction += "\n사용자에 대한 정보는 다음과 같습니다:\n"
llm_request.config.system_instruction += "\n".join(memories)
agent = LlmAgent(
...
before_model_callback=retrieve_memories_callback,
)
코드 10: ADK에서 내장 도구나 사용자 정의 콜백을 사용하여 매 턴 시작 시 메모리 검색하기
2025년 11월
60페이지
컨텍스트 엔지니어링: 세션, 메모리
대안으로, 에이전트가 자신의 메모리에 쿼리할 도구를 제공받아 스스로 언제 컨텍스트를 검색할지 결정하는 사후 검색("도구로서의 메모리")을 사용할 수 있습니다. 이는 더 효율적이고 강력하지만 추가적인 LLM 호출이 필요하여 지연 시간과 비용이 증가합니다. 그러나 메모리는 필요할 때만 검색되므로 지연 시간 비용이 덜 자주 발생합니다. 또한, 에이전트는 검색할 관련 정보가 존재하는지 알지 못할 수 있습니다. 그러나 이는 사용 가능한 메모리 유형을 에이전트에게 알림으로써(예: 사용자 정의 도구를 사용하는 경우 도구 설명에) 완화될 수 있어, 언제 쿼리할지에 대한 더 정보에 입각한 결정을 내릴 수 있게 합니다.
Python
# 옵션 1: 내장된 LoadMemory를 사용합니다.
agent = LlmAgent(
...
tools=[adk.tools.load_memory_tool.LoadMemoryTool()],
)
# 옵션 2: 어떤 유형의 정보가 사용 가능할지 설명할 수 있는 사용자 정의 도구를 사용합니다.
def load_memory(query: str, tool_context: ToolContext):
"""사용자를 위한 메모리를 검색합니다.
다음과 같은 유형의 정보가 사용자를 위해 저장될 수 있습니다:
* 사용자의 좋아하는 음식과 같은 사용자 선호도.
...
"""
# 유사성 검색을 사용하여 메모리 검색.
response = tool_context.search_memory(query)
return response.memories
agent = LlmAgent(
...
tools=[load_memory],
)
코드 11: 내장 도구나 사용자 정의 도구를 사용하여 ADK 에이전트가 언제 메모리를 검색해야 할지 결정하도록 구성하기
2025년 11월
61페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리를 사용한 추론
관련 메모리가 검색되면, 마지막 단계는 이를 모델의 컨텍스트 창에 전략적으로 배치하는 것입니다. 이는 중요한 과정입니다. 메모리의 배치는 LLM의 추론에 큰 영향을 미치고, 운영 비용에 영향을 주며, 궁극적으로 최종 답변의 품질을 결정할 수 있습니다.
메모리는 주로 시스템 명령어에 추가하거나 대화 기록에 주입하는 방식으로 제공됩니다. 실제로는 하이브리드 전략이 가장 효과적인 경우가 많습니다. 항상 존재해야 하는 안정적이고 전역적인 메모리(사용자 프로필과 같은)에는 시스템 프롬프트를 사용하십시오. 그 외, 대화의 즉각적인 컨텍스트에만 관련된 일시적이고 일화적인 메모리에는 대화 주입이나 도구로서의 메모리를 사용하십시오. 이는 지속적인 컨텍스트의 필요성과 실시간 정보 검색의 유연성 사이의 균형을 맞춥니다.
시스템 명령어 내의 메모리
추론에 메모리를 사용하는 간단한 옵션은 메모리를 시스템 명령어에 추가하는 것입니다. 이 방법은 검색된 메모리를 서문과 함께 시스템 프롬프트에 직접 추가하여, 전체 상호작용의 기본 컨텍스트로 구성함으로써 대화 기록을 깨끗하게 유지합니다. 예를 들어, Jinja를 사용하여 시스템 명령어에 동적으로 메모리를 추가할 수 있습니다.
2025년 11월
62페이지
컨텍스트 엔지니어링: 세션, 메모리
Python
from jinja2 import Template
template = Template("""
{{ system_instructions }}
<MEMORIES>
사용자에 대한 정보는 다음과 같습니다:
{% for retrieved_memory in data %}* {{ retrieved_memory.memory.fact }}
{% endfor %}</MEMORIES>
""")
prompt = template.render(
system_instructions=system_instructions,
data=retrieved_memories
)
코드 12: 검색된 메모리를 사용하여 시스템 명령어 구축하기
시스템 명령어에 메모리를 포함하는 것은 메모리에 높은 권한을 부여하고, 컨텍스트를 대화와 명확하게 분리하며, 사용자 프로필과 같은 안정적인 "전역" 정보에 이상적입니다. 그러나 에이전트가 모든 주제를 부적절한 경우에도 핵심 명령어의 메모리와 연관시키려 할 수 있는 과도한 영향의 위험이 있습니다.
이 아키텍처 패턴은 몇 가지 제약을 도입합니다. 첫째, 매 LLM 호출 전에 시스템 프롬프트의 동적 구성을 지원하는 에이전트 프레임워크가 필요합니다. 이 기능이 항상 쉽게 지원되는 것은 아닙니다. 또한, 이 패턴은 시스템 프롬프트가 LLM이 메모리 검색 도구를 호출하기로 결정하기 전에 최종적으로 확정되어야 하므로 "도구로서의 메모리"와 호환되지 않습니다. 마지막으로, 비텍스트 메모리를 잘 처리하지 못합니다. 대부분의 LLM은 시스템 명령어에 텍스트만 허용하므로, 이미지나 오디오와 같은 멀티모달 콘텐츠를 프롬프트에 직접 포함하기 어렵습니다.
2025년 11월
63페이지
컨텍스트 엔지니어링: 세션, 메모리
대화 기록 내의 메모리
이 접근 방식에서는 검색된 메모리가 턴바이턴 대화에 직접 주입됩니다. 메모리는 전체 대화 기록 이전이나 최신 사용자 질의 바로 앞에 배치될 수 있습니다.
그러나 이 방법은 검색된 메모리가 관련이 없는 경우 토큰 비용을 증가시키고 모델을 혼란스럽게 할 수 있어 노이즈가 많을 수 있습니다. 주요 위험은 대화 주입으로, 모델이 메모리를 대화에서 실제로 말한 내용으로 잘못 취급할 수 있는 것입니다. 또한, 대화에 주입하는 메모리의 관점에 대해 더 신중해야 합니다. 예를 들어, "user" 역할을 사용하고 사용자 수준 메모리를 주입하는 경우, 메모리는 1인칭 시점으로 작성되어야 합니다.
대화 기록에 메모리를 주입하는 특별한 경우는 도구 호출을 통해 메모리를 검색하는 것입니다. 메모리는 도구 출력의 일부로 대화에 직접 포함될 것입니다.
Python
def load_memory(query: str, tool_context: ToolContext):
"""대화 기록으로 메모리를 로드합니다..."""
response = tool_context.search_memory(query)
return response.memories
agent = LlmAgent(
...
tools=[load_memory],
)
코드 13: 도구로서 메모리를 검색하여 대화에 직접 삽입하기
2025년 11월
64페이지
컨텍스트 엔지니어링: 세션, 메모리
절차적 메모리
이 백서는 주로 서술 기억에 초점을 맞추어 왔으며, 이는 현재 상업용 메모리 환경을 반영하는 집중입니다. 대부분의 메모리 관리 플랫폼 역시 "무엇"—사실, 역사, 사용자 데이터—을 추출, 저장, 검색하는 데 탁월한 이 서술적 접근 방식을 위해 설계되었습니다.
그러나 이러한 시스템들은 에이전트의 작업 흐름과 추론을 개선하는 메커니즘인 절차적 메모리를 관리하도록 설계되지 않았습니다. "어떻게"를 저장하는 것은 정보 검색 문제가 아니라, 추론 증강 문제입니다. 이 "어떻게 아는지"를 관리하는 것은 유사한 고수준 구조를 가졌지만, 완전히 분리되고 전문화된 알고리즘적 수명 주기를 요구합니다²⁶:
추출: 절차적 추출은 단순히 사실이나 의미 있는 정보를 포착하는 것이 아니라, 성공적인 상호작용에서 재사용 가능한 전략이나 "플레이북"을 추출하도록 설계된 전문화된 프롬프트를 요구합니다.
통합: 서술적 통합이 관련된 사실("무엇")을 병합하는 반면, 절차적 통합은 작업 흐름 자체("어떻게")를 큐레이션합니다. 이는 기존의 "모범 사례"에 새로운 성공적인 방법을 통합하고, 알려진 계획의 결함 있는 단계를 수정하며, 구식이거나 비효율적인 절차를 가지치기하는 데 중점을 둔 능동적인 로직 관리 과정입니다.
검색: 목표는 질문에 답하기 위해 데이터를 검색하는 것이 아니라, 복잡한 작업을 어떻게 실행할지에 대해 에이전트를 안내하는 계획을 검색하는 것입니다. 따라서 절차적 메모리는 서술적 메모리와 다른 데이터 스키마를 가질 수 있습니다.
에이전트가 자신의 로직을 '자가 진화'시키는 이러한 능력은 자연스럽게 일반적인 적응 방법인 미세 조정—종종 인간 피드백 기반 강화 학습(RLHF)²⁷을 통해—과 비교하게 됩니다. 두 과정 모두 에이전트 행동 개선을 목표로 하지만, 그 메커니즘은
2025년 11월
65페이지
컨텍스트 엔지니어링: 세션, 메모리
과 애플리케이션은 근본적으로 다릅니다. 미세 조정은 모델 가중치를 변경하는 비교적 느린 오프라인 훈련 과정입니다. 절차적 메모리는 올바른 "플레이북"을 프롬프트에 동적으로 주입하여, 어떠한 미세 조정 없이도 인-컨텍스트 학습을 통해 에이전트를 안내함으로써 빠르고 온라인적인 적응을 제공합니다.
테스트 및 평가
이제 메모리 지원 에이전트가 준비되었으니, 포괄적인 품질 및 평가 테스트를 통해 그 행동을 검증해야 합니다. 에이전트의 메모리를 평가하는 것은 다층적인 과정입니다. 평가는 에이전트가 올바른 것을 기억하고 있는지(품질), 필요할 때 그 메모리를 찾을 수 있는지(검색), 그리고 그 메모리를 사용하는 것이 실제로 목표 달성에 도움이 되는지(작업 성공)를 검증하는 것을 요구합니다. 학계는 재현 가능한 벤치마크에 초점을 맞추는 반면, 산업계의 평가는 메모리가 프로덕션 에이전트의 성능과 사용성에 어떻게 직접적인 영향을 미치는지에 중점을 둡니다.
메모리 생성 품질 메트릭은 메모리 자체의 내용을 평가하며, "에이전트가 올바른 것을 기억하고 있는가?"라는 질문에 답합니다. 이는 일반적으로 에이전트가 생성한 메모리를 수동으로 만든 이상적인 메모리의 "골든 셋"과 비교하여 측정됩니다.
정밀도: 에이전트가 생성한 모든 메모리 중 정확하고 관련 있는 비율은 얼마인가? 높은 정밀도는 지식 기반을 관련 없는 노이즈로 오염시키는 "과도하게 열성적인" 메모리 시스템을 방지합니다.
재현율: 소스에서 기억했어야 할 모든 관련 사실 중 얼마나 많은 비율을 포착했는가? 높은 재현율은 에이전트가 중요한 정보를 놓치지 않도록 보장합니다.
F1-점수: 정밀도와 재현율의 조화 평균으로, 단일하고 균형 잡힌 품질 척도를 제공합니다.
2025년 11월
66페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리 검색 성능 메트릭은 에이전트가 적시에 올바른 메모리를 찾는 능력을 평가합니다.
Recall@K: 메모리가 필요할 때, 상위 'K'개의 검색 결과 내에서 올바른 것이 발견되는가? 이는 검색 시스템의 정확도를 측정하는 주요 척도입니다.
지연 시간: 검색은 에이전트 응답의 "핫 패스"에 있습니다. 전체 검색 과정은 사용자 경험을 저하시키지 않도록 엄격한 지연 시간 예산(예: 200ms 미만) 내에서 실행되어야 합니다.
엔드-투-엔드 작업 성공 메트릭은 "메모리가 실제로 에이전트가 자신의 일을 더 잘 수행하는 데 도움이 되는가?"라는 질문에 답하는 궁극적인 테스트입니다. 이는 에이전트의 메모리를 사용하여 다운스트림 작업에서의 성능을 평가함으로써 측정되며, 종종 LLM "판정관"이 에이전트의 최종 출력을 정답과 비교합니다. 판정관은 에이전트의 답변이 정확했는지 판단하여, 메모리 시스템이 최종 결과에 얼마나 잘 기여했는지를 효과적으로 측정합니다.
평가는 일회성 이벤트가 아니라 지속적인 개선을 위한 엔진입니다. 위 메트릭은 약점을 식별하고 시간이 지남에 따라 메모리 시스템을 체계적으로 향상시키는 데 필요한 데이터를 제공합니다. 이 반복적인 과정은 기준선을 설정하고, 실패를 분석하며, 시스템을 튜닝하고(예: 프롬프트 개선, 검색 알고리즘 조정), 변경의 영향을 측정하기 위해 재평가하는 것을 포함합니다.
위 메트릭은 품질에 초점을 맞추지만, 프로덕션 준비 상태는 성능에도 달려 있습니다. 각 평가 영역에 대해 기본 알고리즘의 지연 시간과 부하 상태에서의 확장 능력을 측정하는 것이 중요합니다. "핫 패스에서" 메모리를 검색하는 것은 엄격한, 수백 밀리초 단위의 지연 시간 예산을 가질 수 있습니다. 생성과 통합은 종종 비동기적이지만, 사용자 수요를 따라잡을 수 있는 충분한 처리량을 가져야 합니다. 궁극적으로, 성공적인 메모리 시스템은 실제 세계 사용을 위해 지능적이고, 효율적이며, 강력해야 합니다.
2025년 11월
67페이지
컨텍스트 엔지니어링: 세션, 메모리
메모리에 대한 프로덕션 고려 사항
성능 외에도, 메모리 지원 에이전트를 프로토타입에서 프로덕션으로 전환하려면 엔터프라이즈급 아키텍처 문제에 대한 집중이 필요합니다. 이러한 전환은 확장성, 복원력, 보안에 대한 중요한 요구 사항을 도입합니다. 프로덕션급 시스템은 지능뿐만 아니라 엔터프라이즈 수준의 견고함을 위해 설계되어야 합니다.
계산 비용이 많이 드는 메모리 생성 과정으로 인해 사용자 경험이 결코 차단되지 않도록 보장하기 위해, 강력한 아키텍처는 메모리 처리를 주 애플리케이션 로직과 분리해야 합니다. 이는 이벤트 기반 패턴이지만, 일반적으로 자체 관리형 메시지 큐보다는 전용 메모리 서비스에 대한 직접적이고 논블로킹 API 호출을 통해 구현됩니다. 흐름은 다음과 같습니다.
에이전트가 데이터를 푸시: 관련 이벤트(예: 세션 종료) 후, 에이전트 애플리케이션은 메모리 관리자에게 논블로킹 API 호출을 하여 원시 소스 데이터(대화 기록 등)를 처리하도록 "푸시"합니다.
메모리 관리자가 백그라운드에서 처리: 메모리 관리자 서비스는 즉시 요청을 확인하고 생성 작업을 자체 내부 관리 큐에 넣습니다. 그런 다음 비동기적인 무거운 작업, 즉 메모리를 추출, 통합 및 형식화하기 위해 필요한 LLM 호출을 하는 전적인 책임을 집니다. 관리자는 특정 비활성 기간이 경과할 때까지 이벤트 처리를 지연시킬 수 있습니다.
메모리가 영속화됨: 서비스는 최종 메모리—새로운 항목이거나 기존 항목의 업데이트일 수 있음—를 전용의 내구성 있는 데이터베이스에 기록합니다. 관리형 메모리 관리자의 경우, 스토리지는 내장되어 있습니다.
에이전트가 메모리 검색: 주 에이전트 애플리케이션은 새로운 사용자 상호작용을 위한 컨텍스트를 검색해야 할 때 이 메모리 저장소를 직접 쿼리할 수 있습니다.
2025년 11월
68페이지
컨텍스트 엔지니어링: 세션, 메모리
이러한 서비스 기반의 논블로킹 접근 방식은 메모리 파이프라인의 실패나 지연 시간이 사용자 대면 애플리케이션에 직접적인 영향을 미치지 않도록 보장하여 시스템을 훨씬 더 복원력 있게 만듭니다. 이는 또한 대화의 최신성에 이상적인 온라인(실시간) 생성과 과거 데이터로 시스템을 채우는 데 유용한 오프라인(배치) 처리 사이의 선택을 알려줍니다.
애플리케이션이 성장함에 따라, 메모리 시스템은 실패 없이 고빈도 이벤트를 처리해야 합니다. 동시 요청이 주어졌을 때, 시스템은 여러 이벤트가 동일한 메모리를 수정하려고 할 때 교착 상태나 경쟁 조건을 방지해야 합니다. 트랜잭션 데이터베이스 작업이나 낙관적 잠금을 사용하여 경쟁 조건을 완화할 수 있지만, 여러 요청이 동일한 메모리를 수정하려고 할 때 큐잉이나 스로틀링을 유발할 수 있습니다. 강력한 메시지 큐는 대량의 이벤트를 버퍼링하고 메모리 생성 서비스가 압도되는 것을 방지하는 데 필수적입니다.
메모리 서비스는 또한 일시적인 오류에 대해 복원력이 있어야 합니다(오류 처리). LLM 호출이 실패하면, 시스템은 지수 백오프를 사용한 재시도 메커니즘을 사용하고 영구적인 실패는 분석을 위해 데드-레터 큐로 라우팅해야 합니다.
전 세계적인 애플리케이션의 경우, 메모리 관리자는 낮은 지연 시간과 높은 가용성을 보장하기 위해 내장된 다중 지역 복제 기능이 있는 데이터베이스를 사용해야 합니다. 클라이언트 측 복제는 통합이 충돌을 방지하기 위해 단일하고 트랜잭션적으로 일관된 데이터 뷰를 요구하기 때문에 실현 가능하지 않습니다. 따라서 메모리 시스템은 복제를 내부적으로 처리하여, 기본 지식 기반이 전 세계적으로 일관되도록 보장하면서 개발자에게 단일의 논리적 데이터 저장소를 제공해야 합니다.
Agent Engine Memory Bank와 같은 관리형 메모리 시스템은 이러한 프로덕션 고려 사항을 해결하는 데 도움을 주므로, 여러분은 핵심 에이전트 로직에 집중할 수 있습니다.
2025년 11월
69페이지
컨텍스트 엔지니어링: 세션, 메모리
개인정보 보호 및 보안 위험
메모리는 사용자 데이터에서 파생되고 이를 포함하므로, 엄격한 개인정보 보호 및 보안 통제가 필요합니다. 유용한 비유는 시스템의 메모리를 전문 아키비스트가 관리하는 안전한 기업 아카이브로 생각하는 것입니다. 그의 임무는 회사를 보호하면서 귀중한 지식을 보존하는 것입니다.
이 아카이브의 기본 규칙은 데이터 격리입니다. 아키비스트가 다른 부서의 기밀 파일을 절대 섞지 않는 것처럼, 메모리는 사용자 또는 테넌트 수준에서 엄격하게 격리되어야 합니다. 한 사용자를 서비스하는 에이전트는 제한적인 접근 제어 목록(ACL)으로 강제된 다른 사용자의 메모리에 절대 접근해서는 안 됩니다. 또한, 사용자는 자신의 데이터에 대한 프로그래밍 방식의 제어권을 가져야 하며, 메모리 생성을 거부하거나 아카이브에서 자신의 모든 파일 삭제를 요청할 수 있는 명확한 옵션이 있어야 합니다.
문서를 보관하기 전에, 아키비스트는 중요한 보안 단계를 수행합니다. 첫째, 각 페이지를 꼼꼼히 검토하여 민감한 개인 정보(PII)를 삭제하고, 법적 책임을 만들지 않고 지식을 저장하도록 보장합니다. 둘째, 아키비스트는 위조되거나 의도적으로 오해를 유발하는 문서를 발견하고 폐기하도록 훈련받습니다. 이는 메모리 포이즈닝²⁸에 대한 안전장치입니다. 같은 방식으로, 시스템은 악의적인 사용자가 프롬프트 주입을 통해 에이전트의 영구적인 지식을 손상시키는 것을 방지하기 위해 정보를 장기 메모리에 커밋하기 전에 검증하고 삭제해야 합니다. 시스템은 정보를 장기 메모리에 커밋하기 전에 검증하고 삭제하기 위해 Model Armor와 같은 안전장치를 포함해야 합니다²⁹.
또한, 절차적 메모리(에이전트에게 무언가를 하는 방법을 가르치는)와 같이 여러 사용자가 동일한 메모리 세트를 공유하는 경우 유출 위험이 있습니다. 예를 들어, 한 사용자의 절차적 메모리가 다른 사용자에게 예시로 사용되는 경우—마치 회사 전체에 메모를 공유하는 것처럼—아키비스트는 먼저 사용자 경계를 넘어 민감한 정보가 유출되는 것을 방지하기 위해 엄격한 익명화를 수행해야 합니다.
2025년 11월
70페이지
컨텍스트 엔지니어링: 세션, 메모리
결론
이 백서는 컨텍스트 엔지니어링이라는 분야를 탐구하며, 그 두 가지 핵심 구성 요소인 세션과 메모리에 초점을 맞추었습니다. 단순한 대화의 한 턴에서 지속적이고 실행 가능한 정보 조각으로의 여정은 이 관행에 의해 지배됩니다. 여기에는 대화 기록, 메모리, 외부 지식을 포함한 모든 필요한 정보를 LLM의 컨텍스트 창으로 동적으로 조합하는 과정이 포함됩니다. 이 전체 과정은 즉각적인 세션과 장기적인 메모리라는 두 개의 뚜렷하지만 상호 연결된 시스템 간의 상호 작용에 의존합니다.
세션은 "현재"를 관장하며, 단일 대화를 위한 저지연의 시간순 컨테이너 역할을 합니다. 주요 과제는 성능과 보안으로, 저지연 접근과 엄격한 격리를 요구합니다. 컨텍스트 창 오버플로우와 지연 시간을 방지하기 위해, 토큰 기반 잘라내기나 재귀적 요약과 같은 추출 기술을 사용하여 세션 기록이나 단일 요청 페이로드 내의 콘텐츠를 압축해야 합니다. 또한, 보안이 가장 중요하므로, 세션 데이터가 영속화되기 전에 PII 삭제를 의무화해야 합니다.
메모리는 장기 개인화의 엔진이자 여러 세션에 걸친 영속성을 위한 핵심 메커니즘입니다. 이는 에이전트를 사실에 대한 전문가로 만드는 RAG를 넘어, 에이전트를 사용자에 대한 전문가로 만듭니다. 메모리는 대화 기록에서 가장 중요한 정보를 추출하는 능동적인 LLM 기반 ETL 파이프라인으로, 추출, 통합, 검색을 책임집니다. 추출을 통해 시스템은 가장 중요한 정보를 핵심 메모리 포인트로 정제합니다. 이어서, 통합은 이 새로운 정보를 기존 코퍼스와 큐레이션하고 통합하며, 충돌을 해결하고 중복 데이터를 삭제하여 일관된 지식 기반을 보장합니다. 빠른 사용자 경험을 유지하기 위해, 메모리 생성은 에이전트가 응답한 후 비동기적인 백그라운드 프로세스로 실행되어야 합니다. 출처를 추적하고 메모리 포이즈닝과 같은 위험에 대한 안전장치를 사용함으로써, 개발자는 사용자와 함께 진정으로 배우고 성장하는 신뢰할 수 있고 적응력 있는 비서를 구축할 수 있습니다.
2025년 11월
71~72페이지
각주 (Endnotes)
- https://cloud.google.com/use-cases/retrieval-augmented-generation?hl=en
- https://arxiv.org/abs/2301.00234
- https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/sessions/overview
- https://langchain-ai.github.io/langgraph/concepts/multi_agent/#message-passing-between-agents
- https://google.github.io/adk-docs/agents/multi-agents/
- https://google.github.io/adk-docs/agents/multi-agents/#c-explicit-invocation-agenttool
- https://agent2agent.info/docs/concepts/message/
- https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
- https://cloud.google.com/security-command-center/docs/model-armor-overview
- https://ai.google.dev/gemini-api/docs/long-context#long-context-limitations
- https://huggingface.co/blog/Kseniase/memory
- https://langchain-ai.github.io/langgraph/concepts/memory/#semantic-memory
- https://langchain-ai.github.io/langgraph/concepts/memory/#semantic-memory
- https://arxiv.org/pdf/2412.15266
- https://arxiv.org/pdf/2412.15266
- https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference#sample-requests-text-gen-multimodal-prompt
- https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/generate-memories
- https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/control-generated-output
- https://cloud.google.com/agent-builder/agent-engine/memory-bank/set-up#memory-bank-config
- https://arxiv.org/html/2504.19413v1
- https://google.github.io/adk-docs/tools/#how-agents-use-tools
- https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/generate-memories#consolidate-pre-extracted-memories
- https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/memory-bank/generate-memories#background-memory-generation
- https://arxiv.org/pdf/2503.08026
- https://google.github.io/adk-docs/callbacks/
- https://arxiv.org/html/2508.06433v2
- https://cloud.google.com/blog/products/ai-machine-learning/rlhf-on-google-cloud
- https://arxiv.org/pdf/2503.03704
- https://cloud.google.com/security-command-center/docs/model-armor-overview
- https://cloud.google.com/architecture/choose-design-pattern-agentic-ai-system
'LLM으로 뽑은 잡지식' 카테고리의 다른 글
| 프롬프트 엔지니어링: 개요 및 가이드 (Prompt Engineering: Overview and Guide) (0) | 2025.11.17 |
|---|---|
| Google - ContextEngineering:Sessions, Memory (쉬운 설명) (0) | 2025.11.17 |
| 양자 역학이란 무엇인가? (0) | 2025.11.16 |
| HCLS AI 전환 전략 심층 분석: Anthropic의 3단계 프레임워크 해부 및 실행 로드맵 (0) | 2025.11.16 |
| 앤트로픽의 프롬프트 엔지니어링에 대한 모범 사례 (현대어 번역) (0) | 2025.11.16 |