본문 바로가기
Agentic AI/Memory

4. [Docker & PostgreSQL] 장기 메모리(Long-term Memory)(1)

by 아톨 2026. 9. 1.
반응형

지금 하려는 것은 우리가 지금까지 만든 짧은 대화 기억(History + Summary)에서 한 단계 발전해서,

Agent가 대화가 끝나도 중요한 정보를 PostgreSQL DB에 저장하고, 나중에 다시 꺼내 사용하는 장기 메모리(Long-term Memory)

를 만드는 것입니다.

그리고 지금까지 해오신 Python → OpenAI API → Agent → History → Summary 학습 흐름에서 아주 자연스러운 다음 단계입니다.

 

[전체 요약]

# 1. Docker Desktop 설치

 

# 2. PowerShell 또는 CMD:  
     docker --version   
     ===> Docker version 29.7.2, build a7dcaa6
    docker ps            
     ===> (아직 실행 중인 컨테이너가 없다면)

     CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

 

# 3. PostgreSQL Docker 실행 명령어
     docker run --name agent-postgres -e POSTGRES_USER=agent_user -e POSTGRES_PASSWORD=agent_password -e POSTGRES_DB=agent_db -p 5432:5432 -d postgres:15
     (처음부터 Volume을 사용하는 것을 권장. 아래.)
     docker stop agent-postgres
     docker rm agent-postgres
     docker run --name agent-postgres -e POSTGRES_USER=agent_user -e POSTGRES_PASSWORD=agent_password -e POSTGRES_DB=agent_db -p 5432:5432 -v agent_postgres_data:/var/lib/postgresql/data -d postgres:15
     ===> (정상이라면 긴 문자열) b01fdca870cde5c..............

 

# 4. PostgreSQL이 실행 중인지 확인
     docker ps
     ===>

     CONTAINER ID   IMAGE         COMMAND                   CREATED          STATUS          PORTS                                         NAMES
b01fdca870cd   postgres:15   "docker-entrypoint.s…"   21 seconds ago   Up 21 seconds   0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp   agent-postgres

 

# 5. Docker 내부의 PostgreSQL에 직접 접속
     docker exec -it agent-postgres psql -U agent_user -d agent_db
     ===> agent_db=#

 

# 6. SQL을 직접 실행
     \dt 
     ===> 아직 아무 테이블도 없으므로 비어 있을 것

 

# 7. user_profiles 테이블 만들기
    CREATE TABLE user_profiles (
         user_id SERIAL PRIMARY KEY,
         user_name VARCHAR(50),
         location VARCHAR(100),
         preferences VARCHAR(200)
     );
     ===> (성공하면)CREATE TABLE

 

# 8. 테이블 구조 확인
     \d user_profiles
     ===>  Table "public.user_profiles"
         Column      |          Type               | Collation | Nullable  |                    Default
     -------------+------------------------+-----------+----------+------------------------------------------------
       user_id      | integer                     |              | not null  | nextval('user_profiles_user_id_seq'::regclass)
       user_name  | character varying(50)   |              |             |
       location      | character varying(100) |              |             |
       preferences | character varying(200) |              |             |
     Indexes:  "user_profiles_pkey" PRIMARY KEY, btree (user_id)

 

# 9. 테스트 데이터 넣기
     INSERT INTO user_profiles (
          user_name,
          location,
         preferences
     )
     VALUES (
         'Kim',
         'Seoul',
         'AI Agent 코드를 자세하게 설명받는 것을 선호'
     );
     ===> 확인: SELECT * FROM user_profiles;
     ===> 결과:
       user_id  | user_name | location |                 preferences
     ---------+-----------+----------+---------------------------------------------
           1     | Kim     | Seoul  | AI Agent 코드를 자세하게 설명받는 것을 선호

# 10. Python에서 PostgreSQL 접속 & Python DB연결 테스트
     우선 설치: pip install "psycopg[binary]"
     Python DB 연결 테스트: (새 파일 만들고, 코드 입력) test_postgres.py
     실행: python test_postgres.py
     ===> PostgreSQL 연결 성공! (1, 'Kim', 'Seoul', 'AI Agent 코드를 자세하게 설명받는 것을 선호') 연결 종료


0. 전체 그림부터 이해하기

지금까지 만든 Chat Agent는 대략 이렇습니다.

사용자
   │
   ▼
┌──────────────┐
│   Chat Loop  │
└──────────────┘
   │
   ▼
┌──────────────┐
│   messages   │
│ 단기 대화기억 │
└──────────────┘
   │
   ▼
┌──────────────┐
│ OpenAI Model │
└──────────────┘
   │
   ▼
 사용자에게 답변
 

문제는 프로그램을 종료하면:

messages = []
 

가 되어버린다는 것입니다.

즉,

어제:
사용자 → 나는 AI Agent를 공부하고 있어.

오늘:
프로그램 다시 실행

Agent → 처음 만난 사람처럼 행동
 

할 수 있습니다.

그래서 DB가 등장합니다.


1. PostgreSQL을 넣으면 무엇이 달라질까?

구조가 이렇게 바뀝니다.

                    ┌──────────────────┐
                    │    PostgreSQL    │
                    │                  │
                    │ 사용자 프로필     │
                    │ 사용자 선호       │
                    │ 중요한 정보       │
                    │ 장기 기억         │
                    └────────▲─────────┘
                             │
                       저장 / 조회
                             │
                             ▼
┌──────────┐         ┌──────────────────┐
│  사용자   │ ──────► │      Agent       │
└──────────┘         │                  │
                     │ Short-term Memory│
                     │ Summary Memory   │
                     │ Long-term Memory │
                     └────────┬─────────┘
                              │
                              ▼
                       ┌──────────────┐
                       │ OpenAI Model │
                       └──────────────┘
                              │
                              ▼
                           답변
 

여기서 기억을 3단계로 나누면 이해가 쉽습니다.

기억저장 장소역할
Short-term Memory Python messages 최근 대화
Summary Memory Python 메시지 오래된 대화 압축
Long-term Memory PostgreSQL 프로그램 종료 후에도 유지

이제 우리가 PostgreSQL로 만들려는 것은 바로 세 번째입니다.


2. Docker가 왜 필요한가?

원래 PostgreSQL을 설치하려면:

PostgreSQL 다운로드
       ↓
Windows 설치
       ↓
환경설정
       ↓
서비스 설정
       ↓
포트 설정
       ↓
계정 설정
 

등을 해야 합니다.

Docker를 사용하면:

Docker
   │
   ▼
PostgreSQL이라는 완성된 상자(Container)
   │
   ▼
바로 실행
 

이라고 생각하면 됩니다.

조금 더 정확히 표현하면:

Docker Image
    ↓
postgres:15
    ↓
Docker Container 생성
    ↓
agent-postgres
    ↓
실행
 

입니다.


3. 지금 가지고 있는 Docker Desktop의 역할

이미 Docker Desktop을 설치하셨다면 기본 준비는 상당 부분 되어 있습니다.

우선 PowerShell 또는 CMD를 열고 아래를 입력하세요.

 
docker --version
 

정상이라면 대략:

Docker version 28.x.x
 

처럼 나옵니다.

그리고:

 
docker ps
 

를 입력해 보세요.

아직 실행 중인 컨테이너가 없다면:

CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS
 

처럼 비어 있어도 정상입니다.


4. PostgreSQL 실행 명령어의 중요한 오류

사용하신 명령어:

 
docker run --name agent-postgres \
    -e POSTGRES_USER=agent_user \
    -e POSTGRES_PASSWORD=agent_password \
    -e POSTGRES_DB=agent_db \
    -e 5432:5432 \
    -d postgres:15
 

여기에는 작은 오류가 있습니다.

이 부분:

-e 5432:5432
 

는 잘못되었습니다.

-e는 환경변수(Environment Variable)를 의미합니다.

포트 연결은:

-p
 

를 사용해야 합니다.

즉:

 
-p 5432:5432
 

이어야 합니다.


5. 추천하는 PostgreSQL Docker 실행 명령어

Windows PowerShell에서 한 줄로 실행하면 가장 쉽습니다.

 
docker run --name agent-postgres -e POSTGRES_USER=agent_user -e POSTGRES_PASSWORD=agent_password -e POSTGRES_DB=agent_db -p 5432:5432 -d postgres:15
 

각 부분을 하나씩 보겠습니다.


docker run

 
docker run
 

의미:

Docker Image를 이용해서 새로운 Container를 만들고 실행해라.


--name agent-postgres

 
--name agent-postgres
 

Container의 이름입니다.

agent-postgres
 

라는 이름의 PostgreSQL 서버가 만들어집니다.

나중에:

 
docker stop agent-postgres
 

처럼 사용할 수 있습니다.


-e POSTGRES_USER=agent_user

 
-e POSTGRES_USER=agent_user
 

PostgreSQL 사용자 계정을 만듭니다.

사용자 ID

agent_user
 

-e POSTGRES_PASSWORD=agent_password

 
-e POSTGRES_PASSWORD=agent_password
 

비밀번호입니다.

학습용으로는 괜찮지만 실제 서비스에서는 절대 이렇게 단순하게 사용하면 안 됩니다.

예를 들어:

agent_user
agent_password
 

가 데이터베이스 접속 계정이 됩니다.


-e POSTGRES_DB=agent_db

 
-e POSTGRES_DB=agent_db
 

처음 생성할 데이터베이스 이름입니다.

agent_db
 

-p 5432:5432

이 부분이 매우 중요합니다.

-p 5432:5432
 

의미는:

내 Windows PC
localhost:5432

        │

        │ Docker 연결

        ▼

Docker Container
PostgreSQL:5432
 

입니다.

PostgreSQL의 기본 포트는:

5432
 

입니다.

그래서 Python에서는 나중에:

 
host="localhost"
port=5432
 

로 접속할 수 있습니다.


-d

 
-d
 

백그라운드 실행입니다.

즉:

터미널은 계속 사용할 수 있고

PostgreSQL은 뒤에서 계속 실행
 

합니다.


postgres:15

 
postgres:15
 

PostgreSQL 15 버전 Image를 사용한다는 뜻입니다.

Docker에 해당 이미지가 없으면:

Docker Hub
      ↓
postgres:15 다운로드
      ↓
Container 생성
      ↓
PostgreSQL 실행
 

을 자동으로 합니다.


6. 먼저 실행해보세요

PowerShell에서:

 
docker run --name agent-postgres -e POSTGRES_USER=agent_user -e POSTGRES_PASSWORD=agent_password -e POSTGRES_DB=agent_db -p 5432:5432 -d postgres:15
 

실행합니다.

정상이라면 긴 문자열이 나옵니다.

예:

7f8d9e....
 

이것은 Container ID입니다.


7. PostgreSQL이 실행 중인지 확인

 
docker ps
 

입력합니다.

정상이라면:

CONTAINER ID   IMAGE         STATUS
xxxxxxxxxxxx   postgres:15   Up 2 minutes
 

그리고 이름은:

agent-postgres
 

일 것입니다.


8. 가장 중요한 문제: 데이터가 사라질 수 있다

처음 명령어에는 Volume 설정이 없습니다.

이 상태에서는 Container를 삭제할 경우 데이터가 같이 사라질 가능성이 있습니다.

그래서 저는 처음부터 Volume을 사용하는 것을 권장합니다.

기존 Container를 만들었다면:

 
docker stop agent-postgres
 

그리고:

 
docker rm agent-postgres
 

한 뒤 다시 만듭니다.

추천 명령어:

 
docker run --name agent-postgres -e POSTGRES_USER=agent_user -e POSTGRES_PASSWORD=agent_password -e POSTGRES_DB=agent_db -p 5432:5432 -v agent_postgres_data:/var/lib/postgresql/data -d postgres:15
 

추가된 부분은:

-v agent_postgres_data:/var/lib/postgresql/data
 

입니다.

구조는:

Docker Container
┌────────────────────────────┐
│                            │
│       PostgreSQL           │
│                            │
└─────────────┬──────────────┘
              │
              ▼
      Docker Volume
      agent_postgres_data
              │
              ▼
       실제 DB 데이터
 

이렇게 하면 Container를 삭제하더라도 Volume을 유지하면 데이터를 계속 사용할 수 있습니다.


9. Docker 안의 PostgreSQL에 직접 접속하기

이제 Docker Container 내부의 PostgreSQL에 들어갈 수 있습니다.

 
docker exec -it agent-postgres psql -U agent_user -d agent_db
 

이 명령어는:

docker exec
    ↓
실행 중인 Container 안에서 명령 실행

agent-postgres
    ↓
Container 이름

psql
    ↓
PostgreSQL 명령어 프로그램

-U agent_user
    ↓
사용자

-d agent_db
    ↓
데이터베이스
 

정상이라면:

agent_db=#
 

처럼 나옵니다.

이 상태는:

PostgreSQL 안에 직접 들어온 상태

입니다.


10. 지금부터 SQL을 직접 실행할 수 있습니다

예를 들어 현재 테이블 확인:

 
\dt
 

아직 아무 테이블도 없으므로 비어 있을 것입니다.


11. user_profiles 테이블 만들기

정상 코드는:

CREATE TABLE user_profiles (
    user_id SERIAL PRIMARY KEY,
    user_name VARCHAR(50),
    location VARCHAR(100),
    preferences VARCHAR(200)
);
 

입니다.

PostgreSQL에서 실행해보세요.

CREATE TABLE user_profiles (
    user_id SERIAL PRIMARY KEY,
    user_name VARCHAR(50),
    location VARCHAR(100),
    preferences VARCHAR(200)
);
 

성공하면:

CREATE TABLE
 

이 나옵니다.


12. 테이블 구조 확인

 
\d user_profiles
 

그러면 대략:

Column       Type
--------------------------------
user_id      integer
user_name    character varying(50)
location     character varying(100)
preferences  character varying(200)
 

처럼 나옵니다.


13. 테스트 데이터를 넣어봅시다

 
INSERT INTO user_profiles (
    user_name,
    location,
    preferences
)
VALUES (
    'Kim',
    'Seoul',
    'AI Agent 코드를 자세하게 설명받는 것을 선호'
);
 

확인:

 
SELECT * FROM user_profiles;
 

결과:

user_id | user_name | location | preferences
--------------------------------------------------
1       | Kim       | Seoul    | AI Agent 코드를...
 

이제 중요한 것을 한 것입니다.

Python 프로그램 메모리
       ❌ 프로그램 종료하면 사라짐

PostgreSQL
       ✅ 프로그램 종료해도 유지
 

14. Python에서 PostgreSQL 접속하기

이제 Python으로 넘어갑니다.

우선 설치:

 
pip install psycopg
 

그런데 Windows에서는 저는 조금 더 명확하게 이것을 추천합니다.

 
pip install "psycopg[binary]"
 

그러면 Python에서 PostgreSQL 드라이버를 쉽게 사용할 수 있습니다.


15. Python DB 연결 테스트

새 파일을 만드세요.

test_postgres.py
 

그리고:

 
import psycopg


# ============================================================
# PostgreSQL 연결
# ============================================================

conn = psycopg.connect(
    host="localhost",
    port=5432,
    dbname="agent_db",
    user="agent_user",
    password="agent_password"
)


print("PostgreSQL 연결 성공!")


# ============================================================
# Cursor 생성
# ============================================================

cursor = conn.cursor()


# ============================================================
# 데이터 조회
# ============================================================

cursor.execute(
    """
    SELECT *
    FROM user_profiles
    """
)


rows = cursor.fetchall()


# ============================================================
# 출력
# ============================================================

for row in rows:

    print(row)


# ============================================================
# 종료
# ============================================================

cursor.close()

conn.close()


print("연결 종료")
 

실행:

 
python test_postgres.py
 

예상 결과:

PostgreSQL 연결 성공!

(1, 'Kim', 'Seoul', 'AI Agent 코드를 자세하게 설명받는 것을 선호')

연결 종료
 

여기까지 성공하면:

Python ↔ PostgreSQL ↔ Docker

연결이 성공한 것입니다.


16. 지금 만든 구조를 그림으로 보면

┌──────────────────────────────────────┐
│             Windows PC               │
│                                      │
│   ┌──────────────┐                   │
│   │ Python Agent │                   │
│   └──────┬───────┘                   │
│          │                           │
│          │ psycopg                   │
│          │                           │
│          ▼                           │
│      localhost:5432                  │
│          │                           │
│          ▼                           │
│   ┌───────────────────────┐          │
│   │   Docker Desktop      │          │
│   │                       │          │
│   │ ┌───────────────────┐ │          │
│   │ │ agent-postgres    │ │          │
│   │ │                   │ │          │
│   │ │ PostgreSQL 15     │ │          │
│   │ │ Port 5432         │ │          │
│   │ └───────────────────┘ │          │
│   └───────────────────────┘          │
│                                      │
└──────────────────────────────────────┘
 

17. 그런데 이것만으로는 아직 "Agent 장기 메모리"는 아닙니다

현재 구조는 단순히:

Python
   ↓
SQL
   ↓
DB 저장
 

입니다.

진짜 Agent Long-term Memory는 다음 단계가 필요합니다.

사용자:
"나는 AI Agent를 공부하고 있어"

          ↓

Agent
          ↓

이 정보가 중요한가?

          ↓ YES

PostgreSQL 저장

user_id = 1
memory_type = preference
content = AI Agent를 공부하고 있음
 

그리고 나중에:

사용자:
"내가 요즘 뭘 공부하고 있지?"

        ↓

Agent

        ↓

PostgreSQL 검색

        ↓

AI Agent 학습

        ↓

답변:
"AI Agent를 공부하고 계십니다."
 

입니다.


18. 추천하는 DB 구조

처음부터 너무 복잡하게 만들지 않는 것이 좋습니다.

우선은 2개의 테이블이면 충분합니다.

사용자 기본정보

 
CREATE TABLE user_profiles (

    user_id SERIAL PRIMARY KEY,

    user_name VARCHAR(50),

    location VARCHAR(100),

    preferences TEXT

);
 

그리고 두 번째:

장기 기억

 
CREATE TABLE memories (

    memory_id SERIAL PRIMARY KEY,

    user_id INTEGER REFERENCES user_profiles(user_id),

    memory_type VARCHAR(50),

    content TEXT,

    importance INTEGER DEFAULT 5,

    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

);
 

이 구조가 중요한 이유는:

user_profiles

Kim
│
├── 이름
├── 위치
└── 기본 선호


memories

Kim
│
├── AI Agent 공부 중
├── Python 학습 중
├── 코드 설명은 자세한 것을 선호
└── 실제 업무용 Agent 개발 목표
 

처럼 구성할 수 있기 때문입니다.


19. 앞으로 우리가 만들 Agent의 모습

제가 추천하는 학습 순서는 다음과 같습니다.

1단계
Docker PostgreSQL 설치
        ↓
2단계
Python에서 DB 연결
        ↓
3단계
SQL로 데이터 저장 / 조회
        ↓
4단계
Memory 저장 함수 만들기
        ↓
save_memory()
        ↓
5단계
Memory 검색 함수 만들기
        ↓
get_memories()
        ↓
6단계
Agent에 연결
        ↓
사용자 질문
        ↓
DB에서 관련 기억 검색
        ↓
OpenAI에게 전달
        ↓
답변
        ↓
중요한 새 정보 발견
        ↓
DB 저장
 

최종적으로:

                   사용자
                     │
                     ▼
              ┌──────────────┐
              │    Agent     │
              └──────┬───────┘
                     │
          ┌──────────┼──────────┐
          │          │          │
          ▼          ▼          ▼
      최근대화     Summary    PostgreSQL
      Memory      Memory     Long Memory
          │          │          │
          └──────────┼──────────┘
                     │
                     ▼
               OpenAI Model
                     │
                     ▼
                    답변
 

추천하는 다음 실습

지금은 바로 Agent 전체를 만들기보다 두 번째 단계로 가는 것이 좋습니다.

즉, 다음 코드를 직접 만들어보는 것입니다.

database.py

├── connect_db()
├── create_user()
├── get_user()
├── save_memory()
├── get_memories()
└── close_connection()
 

그리고 별도의:

test_memory_db.py
 

에서:

1. 사용자 생성
2. 사용자 조회
3. 기억 저장
4. 기억 여러 개 저장
5. 기억 조회
6. 결과 출력
 

을 테스트하는 것입니다.

이 단계를 확실히 해두면 그 다음에 "OpenAI가 사용자의 말에서 중요한 정보를 판단 → PostgreSQL 저장 → 다음 대화에서 검색해서 기억하는 진짜 Long-term Memory Agent"로 매우 자연스럽게 연결할 수 있습니다.

반응형