오늘은 지금까지 사용했던 Supabase, Upstash 같은 외부 서비스를 넘어 Docker를 이용해 PostgreSQL과 Redis를 직접 실행하고 관리하는 방법을 본격적으로 공부했다.
오전에는 OpenAI API, Ollama, PostgreSQL, pgvector, Redis 등 앞으로 AI Agent 개발에 필요한 전체 환경을 구성했고, 이후에는 Supabase Auth와 RLS를 이용해 일반 사용자와 관리자의 권한을 구분하는 방법을 실습했다.
후반부에는 기존
Frontend → FastAPI → Supabase PostgreSQL
프로젝트를
Frontend → FastAPI → Docker PostgreSQL
구조로 변경하는 리팩토링까지 진행했다.
특히 오늘은 AI에게 무작정 코드를 만들어달라고 하기보다 계획서를 먼저 만들고 검토한 다음 구현시키는 방법을 많이 강조하셨다.
1교시 | 지금까지 배운 내용 복습과 Chapter 5 준비
첫 시간에는 Python 기초부터 FastAPI, PostgreSQL, Redis, JWT까지 지금까지 배운 내용을 다시 정리했다.
Python 문법을 프로젝트에서 항상 직접 사용하지는 않더라도, AI에게 코드를 요청하려면 최소한 어떤 기능과 문법이 존재하는지는 알고 있어야 한다는 이야기가 기억에 남았다.
백엔드에서는 지금까지 다음과 같은 기술을 사용했다.
FastAPI → Backend API
PostgreSQL → 데이터 저장
Redis → 빠른 임시 데이터 처리
JWT → 사용자 인증
여기서 다시 정리한 부분이 하나 있었다.
Supabase라는 데이터베이스를 사용한 것이 아니라
Supabase에서 제공하는 PostgreSQL을 사용한 것이다.
또 단순 CRUD보다 실제 서비스에서는 Authentication과 Authorization, 즉 인증과 권한 관리가 훨씬 중요할 수 있다는 이야기도 들었다.
앞으로 AI 코딩 도구를 사용할 때도
기능 설계 → 필요한 구조 결정 → AI에게 구현 요청
순서로 진행하는 것이 중요하다.
아무 계획 없이 Codex에게 계속 수정 요청을 하면 토큰과 비용도 빠르게 늘어날 수 있기 때문이다.
2교시 | OpenAI API Key와 Ollama, AI Agent 환경 구성
OpenAI Platform과 Google AI Studio에서 API Key를 확인하고 프로젝트 환경변수에 넣는 방법을 살펴봤다.
API Key는 코드에 직접 작성하지 않고 .env에서 관리한다.
예를 들면 다음과 같다.
OPENAI_API_KEY=...
OPENAI_MODEL=...
M_MODE=REAL
개발 과정에서는 실제 API를 계속 호출하면 비용이 발생하기 때문에 REAL과 MOCK을 나누는 방식도 사용할 수 있다.
REAL → 실제 AI 호출
MOCK → 테스트용 가짜 응답
처럼 환경설정만 변경하면 프로그램 코드를 수정하지 않고 실행 방식을 바꿀 수 있다.
Ollama와 LLM 구분하기
오늘 다시 확실히 정리한 부분이다.
Ollama = LLM을 실행하는 엔진
Llama / Gemma = 실제 LLM
따라서
Ollama를 LLM으로 사용했다.
보다는
Ollama 환경에서 Llama 모델을 실행했다.
라고 표현하는 것이 더 정확하다.
앞으로 시스템 구조도 하나의 Backend에 모든 기능을 넣는 것이 아니라 다음처럼 분리할 수 있다.
Frontend
↓
Backend API
↓
AI Agent Server
↓
LLM
AI 처리는 시간이 오래 걸릴 수 있기 때문에 일반 API 서버와 Agent 서버를 나누고, 서버 간 요청에는 Timeout과 Retry 같은 설정도 필요하다.
3교시 | Docker PostgreSQL·pgvector·Redis 직접 사용하기
이제 Supabase나 Upstash에서 제공하는 화면을 사용하는 대신 Docker에서 직접 PostgreSQL과 Redis를 실행했다.
PostgreSQL 컨테이너 안으로 들어가 SQL을 직접 실행하면서 테이블도 생성했다.
SELECT * FROM user_memories;
SQL 마지막에는 ;을 붙여야 한다는 기본도 다시 확인했다.
schema.sql과 apply_schema.py
프로젝트에는 DB 구조를 정의한 schema.sql이 준비되어 있었다.
테이블을 하나씩 직접 입력하는 대신 Python의 apply_schema.py를 실행해서
schema.sql 읽기
→ PostgreSQL 접속
→ SQL 실행
→ 테이블 생성
과정을 자동화할 수 있었다.
프로젝트 규모가 커지면 테이블이 수십 개가 될 수도 있기 때문에 이런 방식이 훨씬 편리하다.
pgvector
이번 Chapter에서는 일반 PostgreSQL뿐 아니라 pgvector도 사용한다.
Vector 검색에서는 텍스트를 숫자로 변환해서 저장하고, 검색할 때도 질문을 숫자로 변환해 가장 가까운 값을 찾는다.
텍스트
→ Vector
→ DB 저장
→ 유사도 검색
앞으로 RAG를 공부할 때 중요하게 사용하게 될 부분이다.
Redis의 세 가지 특징
Redis도 Docker로 직접 실행했다.
먼저
PING
을 입력하고
PONG
이 돌아오는지 확인했다.
Redis에서 기억할 특징은 크게 세 가지였다.
- 빠른 데이터 저장과 조회
- TTL을 이용한 자동 삭제
- Pub/Sub을 이용한 실시간 데이터 전달
특히 TTL(Time To Live)은 데이터를 저장한 뒤 일정 시간이 지나면 자동으로 삭제해준다.
인증번호나 세션, AI 챗봇의 임시 대화 기록처럼 영구 저장할 필요가 없는 데이터에 유용하다.
4교시 | Supabase Auth와 RLS로 권한 관리하기
이번에는 Supabase의 인증 기능을 본격적으로 사용했다.
먼저 두 개념을 구분했다.
Authentication
→ 이 사람이 누구인가?
Authorization
→ 이 사람이 무엇을 할 수 있는가?
기존에는 우리 사용자 테이블에 아이디와 비밀번호까지 직접 저장했지만, 이번에는 구조가 달라졌다.
이메일 + 비밀번호
→ Supabase Auth
이름 + Role + 서비스 정보
→ 우리 사용자 테이블
즉 중요한 로그인 정보는 Supabase Auth가 관리한다.
로그인에 성공하면 Supabase가 JWT Access Token도 발급해준다.
로그인
→ Supabase 인증
→ Access Token 발급
→ Frontend 저장
→ API 요청마다 Token 전송
화면에서 버튼을 숨기는 것은 보안이 아니다
일반 사용자에게 등록 버튼을 안 보이게 만드는 것은 어렵지 않다.
하지만 사용자가 API 주소를 알고 직접 요청을 보내면 문제가 생길 수 있다.
그래서 실제 제한은 DB에서도 이루어져야 한다.
이번 RLS 정책은 대략 다음과 같이 만들었다.
일반 사용자
→ 상품 조회 가능
관리자
→ 조회
→ 등록
→ 수정
→ 삭제 가능
즉 프론트엔드는 화면을 구분하고, 실제 데이터 접근 제한은 RLS가 담당한다.
이 차이를 확실하게 기억해야겠다.
5교시 | RLS 코드 분석과 PostgreSQL 리팩토링 계획
앞에서 만든 기능이 실제 코드에서는 어떻게 동작하는지 하나씩 따라가 봤다.
로그인 성공 후 프론트엔드에서는 Access Token과 사용자 정보를 session_state 등에 보관한다.
그리고 role == "admin"이면 관리자 메뉴를 보여주는 방식이다.
백엔드에서는 Supabase Auth로 로그인 요청을 보내고 정상이라면 다음과 같은 값을 받아 사용한다.
Access Token
User ID
Name
Email
Role
FastAPI에서 Pydantic 객체를 Dictionary로 바꿀 때 사용하는 model_dump()도 다시 확인했다.
data = product.model_dump()
오늘의 핵심 리팩토링 목표
기존 프로젝트는
Frontend
→ FastAPI
→ Supabase PostgreSQL
구조였다.
이것을
Frontend
→ FastAPI
→ Docker PostgreSQL
구조로 변경하기로 했다.
중요한 조건은 기존 frontend와 backend를 바로 수정하지 않는 것이다.
원본은 그대로 보존하고 새로운 PostgreSQL 버전용 폴더를 만들어 별도로 작업한다.
그리고 AI에게도 바로
PostgreSQL 버전 만들어줘.
라고 하지 않는다.
먼저
프로젝트 분석
→ 단계별 계획 작성
→ PLAN.md 작성
→ 사람이 검토
→ 계획 수정
→ 구현
순서로 진행한다.
6교시 | Codex 사용량 부족과 다른 AI 코딩 도구 찾아보기
오늘 직접 작업하면서 Codex나 Claude Code의 사용량이 부족해지는 문제도 생겼다.
그래서 대체할 수 있는 도구도 찾아봤다.
Gemini CLI
Codex나 Claude Code처럼 프로젝트 폴더를 기준으로 파일을 읽고 수정할 수 있는 CLI 도구로 Gemini CLI를 사용해보려고 했다.
그런데 설치 과정에서
npm : 명령을 찾을 수 없습니다.
npx : 명령을 찾을 수 없습니다.
오류가 발생했다.
원인은 Gemini CLI가 아니라 Windows에 Node.js가 설치되어 있지 않아 npm과 npx 자체를 사용할 수 없었던 것이었다.
Docker의 node:24-alpine 이미지를 받는 것은 Docker 컨테이너 안에서 Node.js를 사용하는 것이기 때문에 Windows PowerShell의 npm과는 별개라는 점도 알게 됐다.
GitHub Copilot Plan 활용
VS Code에서는 Copilot의 Plan 기능도 사용할 수 있었다.
이번처럼 큰 리팩토링을 할 때는 바로 Agent에게 코드를 수정하게 하는 것이 아니라 먼저 Plan을 이용해서
현재 코드 분석
→ Supabase 의존성 찾기
→ 새로운 폴더 구조 결정
→ 작업 계획 작성
까지 진행한 뒤 구현시키는 방법이 안전하다.
결국 어떤 AI 도구를 쓰더라도 계획부터 세우는 것이 핵심이었다.
7교시 | AI와 함께 Supabase → PostgreSQL 마이그레이션
7교시에는 실제로 AI 코딩 도구에게 PostgreSQL 전환 작업을 시켜봤다.
먼저 Docker PostgreSQL 정보를 알려주고 마이그레이션 계획서를 만들게 했다.
예를 들면 다음 정보다.
PostgreSQL 버전
Container 이름
Port
Database 이름
User
Password
AI는 기존 Supabase 프로젝트 구조를 분석하고 필요한 DB Schema와 새로운 Backend 구조까지 계획했다.
여기서 중요한 것은 계획서의 설정값도 반드시 사람이 확인해야 한다는 점이다.
실제로 비밀번호가 우리가 Docker에 설정했던 값과 다르게 작성된 부분도 발견했다.
계획이 확정된 뒤에는 AI가 기존 Supabase 코드를 참고해 PostgreSQL 버전을 만들었다.
기존에는
FastAPI
→ Supabase Client
→ PostgreSQL
이었다면 새로운 코드는
FastAPI
→ PostgreSQL Session
→ SQL 실행
→ 데이터 반환
형태로 바뀌었다.
AI가 몇 분 만에 코드를 만들어주더라도 끝이 아니다.
기존 Supabase 코드와 PostgreSQL 코드가 어떻게 달라졌는지 비교하면서 공부하는 과정이 꼭 필요하다.
8교시 | AI 없이 PostgreSQL 백엔드 기능 직접 추가하기
마지막 시간에는 Codex가 없다고 가정하고 직접 기능을 추가하는 연습을 시작했다.
완전히 처음부터 만드는 것은 아니다.
기존에 배운 코드와 AI가 만들어준 PostgreSQL 코드를 참고해서 새로운 테이블 하나를 연결한다.
작업 순서는 다음과 같다.
PostgreSQL 테이블 생성
→ Schema 작성
→ Service 작성
→ Router 작성
→ API 테스트
FastAPI에서 계속 사용했던
Router
→ Service
→ Database
구조를 다시 직접 적용하는 연습이다.
Copilot 같은 자동완성 도구는 사용할 수 있지만, 프로젝트 전체를 AI에게 통째로 맡기기보다 기존 코드에서 어떤 부분을 참고해야 하는지 판단하고 직접 연결하는 연습이 중요하다.
이 과정은 앞으로 AWS에 배포할 때도 이어진다고 한다.
향후에는 PostgreSQL과 Redis 등을 Docker 기반으로 구성해 AWS에서 실행하게 될 예정이기 때문에 이번 로컬 실습이 그 준비 단계인 셈이다.
오늘 직접 겪은 오류와 해결 과정
오늘은 환경을 직접 구성하면서 오류도 꽤 많이 만났다.
1. Redis 이미지가 삭제되지 않음
Docker에서 redis:7 이미지를 지우려고 했는데 다음 메시지가 나왔다.
Image redis:7 is in use.
Image를 사용하는 Container가 남아 있어서 발생한 문제였다.
Container 삭제
→ Image 삭제
순서로 해결했다.
Docker에서 Image와 Container는 서로 다른 것이라는 개념을 다시 복습할 수 있었다.
2. npm, npx 명령어를 찾지 못함
Gemini CLI를 설치하려고 했는데 PowerShell에서 npm과 npx를 인식하지 못했다.
처음에는 Docker의 Node.js 이미지를 받아야 하나 생각했지만, Gemini CLI를 Windows에서 실행하려면 Windows 자체에 Node.js가 설치되어 있어야 했다.
Windows Node.js 설치
→ node -v
→ npm -v
→ npx -v
순서로 확인하면 된다.
3. Docker Compose의 version is obsolete
the attribute `version` is obsolete
메시지도 봤다.
처음에는 PostgreSQL 이미지 문제인가 생각했지만 실제 에러가 아니라 현재 Docker Compose에서는 예전 version: 설정을 더 이상 필요로 하지 않는다는 Warning이었다.
docker-compose.yml의 오래된 version: 부분을 제거하면 된다.
4. PostgreSQL 컨테이너 접속 실패
PostgreSQL에 들어가려고 처음에는 다음처럼 실행했다.
docker exec -it mini_postgres ...
하지만 실제 Container 이름이 달라서
No such container
오류가 발생했다.
컨테이너 이름을 맞춘 뒤에는 다시
role "postgres" does not exist
오류가 나왔다.
실제 환경변수를 확인해보니 설정은 다음과 같았다.
POSTGRES_USER=agent_user
POSTGRES_PASSWORD=agent_pwd
POSTGRES_DB=agent_db
따라서 실제 접속 명령도 해당 값을 사용해야 했다.
docker compose exec postgres psql -U agent_user -d agent_db
오늘 오류들을 겪으면서 단순히 명령어를 복사하기보다 현재 Container 이름과 .env, docker-compose의 설정값을 먼저 확인하는 습관이 중요하다는 것을 느꼈다.
오늘의 회고
오늘은 단순히 FastAPI 코드를 만드는 수업보다 서비스를 실제로 어떤 환경에서 운영할 것인지에 더 가까운 내용을 많이 배웠다.
예전에는
DB → Supabase
Redis → Upstash
LLM → 외부 API
처럼 외부에서 준비된 서비스를 사용하는 경우가 많았다.
이제는 Docker를 이용해
PostgreSQL
pgvector
Redis
Ollama
같은 환경을 직접 실행하면서 조금씩 실제 서버 구성에 가까워지고 있다.
특히 Supabase Auth와 RLS를 배우면서 단순히 “로그인이 된다”에서 끝나는 것이 아니라
누구인지 확인
→ Authentication
무엇을 할 수 있는지 확인
→ Authorization
DB 데이터까지 접근 가능한지 확인
→ RLS
처럼 보안이 여러 단계로 나뉜다는 것도 이해할 수 있었다.
또 오늘 가장 기억에 남는 것은 AI 코딩 도구를 사용하는 방법이었다.
예전에는 막히면 바로
이거 만들어줘.
라고 요청하는 경우가 많았는데, 프로젝트가 커질수록 그렇게 하면 AI도 기존 코드를 예상하지 못한 방향으로 수정할 수 있다.
앞으로는
분석
→ 계획
→ PLAN.md
→ 검토
→ 구현
→ 변경된 코드 공부
순서로 사용하는 습관을 들여야겠다.
AI가 코드를 빠르게 만들어주는 것은 분명 편하지만, 결국 내가 어떤 구조로 만들어야 하는지 판단하고 AI가 만든 결과를 검토할 수 있어야 한다.
다음부터는 본격적으로 LLM, Agent, LangGraph 같은 Chapter 5 내용을 배우게 될 것 같다. 오늘 구축한 Docker PostgreSQL, Redis, Ollama 환경부터 다시 한번 정리해두고 넘어가야겠다.
'AI 오케스트레이션 캠프 > 일차별 회고' 카테고리의 다른 글
| 28일차 회고|프롬프트·Structured Output·Kakao Map|AI 오케스트레이션 개발자 국비지원 (0) | 2026.08.19 |
|---|---|
| 27일차 회고 | LLM 라우팅·멀티 에이전트·이미지 분석·TTS 실습 | AI 오케스트레이션 개발자 국비지원 (0) | 2026.08.18 |
| 25일차 회고 | JWT 인증·RLS·Docker·로컬 LLM | AI 오케스트레이션 개발자 국비지원 (0) | 2026.08.13 |
| 24일차 회고 | 공공임대 청약 통합 안내 서비스 최종 발표와 미니프로젝트 마무리 | AI 오케스트레이션 개발자 국비지원 (0) | 2026.08.12 |
| 23일차 회고|안전한 일괄 삭제·Gemini 문서 분석|AI 오케스트레이션 개발자 국비지원 (0) | 2026.08.11 |
댓글