오늘은 FastAPI로 만든 백엔드 API를 Supabase 데이터베이스와 연결하고, Render에 배포하는 과정을 실습했다. 여기에 Upstash Redis를 이용한 캐시 기능까지 추가하면서 실제 AI 서비스가 어떻게 구성되는지 배웠다.
FastAPI와 Supabase 연결
FastAPI는 사용자의 요청을 받아 처리하는 백엔드 서버이고, Supabase는 회원이나 게시글 등의 데이터를 보관하는 데이터베이스다.
오늘은 팀원들이 각자 만든 CRUD 기능을 Supabase와 연결하고 다음 기능이 제대로 작동하는지 확인했다.
- 데이터 전체 조회
- 특정 데이터 조회
- 새로운 데이터 생성
- 기존 데이터 수정
- 데이터 삭제
Swagger 문서에서 API를 직접 실행해 보고, 입력한 데이터가 Supabase 테이블에 실제로 저장되는지도 확인했다.
코드에서 오류가 발생하지 않았더라도 데이터가 엉뚱한 Supabase 프로젝트에 들어갈 수 있기 때문에, API 실행 후 데이터베이스까지 직접 확인하는 습관이 중요했다.
Render를 이용한 백엔드 배포
로컬 컴퓨터에서만 실행되던 FastAPI 서버를 다른 사람도 사용할 수 있도록 Render에 배포했다.
배포 과정에서는 코드뿐만 아니라 환경변수 설정도 매우 중요했다. 특히 로컬의 .env 파일과 Render에 등록한 환경변수가 다르면 배포된 서버가 정상적으로 작동하지 않을 수 있다.
확인해야 할 주요 환경변수는 다음과 같았다.
- Supabase 프로젝트 URL
- Supabase API 키
- 데이터베이스 연결 정보
- LLM API 키
- Redis 연결 정보
실습 중 Supabase 프로젝트 URL이 잘못 입력되어 500 오류가 발생했지만, 올바른 URL로 수정한 뒤 데이터 생성이 정상적으로 처리되는 것을 확인했다.
또한 Supabase의 anon key는 일반 사용자용이고, service role key는 서버 관리자 권한을 가진 키라는 차이도 배웠다. service role key는 권한이 강하기 때문에 외부에 공개하지 않고 서버의 환경변수로만 관리해야 한다.
404 오류와 500 오류 구분하기
오늘 여러 API를 테스트하면서 404 오류와 500 오류의 차이도 다시 확인했다.
- 404 Not Found: 요청한 주소나 API 경로를 찾을 수 없는 경우
- 500 Internal Server Error: 서버 코드, 환경변수 또는 데이터베이스 연결 등에 문제가 생긴 경우
404 오류가 발생하면 라우터와 URL 경로를 먼저 살펴보고, 500 오류가 발생하면 서버 로그와 환경변수, Supabase 연결 상태를 확인해야 한다.
단순히 “API가 안 된다”라고 생각하기보다 오류 코드와 로그를 통해 문제 범위를 좁혀 가는 것이 중요했다.
Redis란?
Redis는 데이터를 빠르게 읽고 쓸 수 있는 임시 저장소다.
Supabase가 데이터를 오랫동안 안전하게 보관하는 창고라면, Redis는 자주 사용하는 데이터를 가까운 곳에 잠시 꺼내 두는 공간이라고 이해할 수 있다.
오늘은 클라우드에서 Redis를 사용할 수 있는 Upstash를 FastAPI와 연결했다.
Redis는 다음과 같은 기능에 활용할 수 있다.
- 자주 조회하는 데이터 임시 저장
- LLM 질문과 답변 캐시
- 로그인 및 인증 정보 저장
- 사용자의 대화 기록 저장
- 일정 시간이 지나면 자동으로 삭제되는 데이터 관리
LLM 답변을 Redis에 캐시하기
사용자가 질문할 때마다 LLM API를 호출하면 응답 시간이 길어지고 API 비용도 계속 발생한다. 이를 줄이기 위해 한 번 생성한 답변을 Redis에 저장하는 캐시 방식을 실습했다.
전체 흐름은 다음과 같다.
사용자 질문
→ Redis에 같은 질문이 있는지 확인
→ 저장된 답변이 있으면 바로 반환
→ 저장된 답변이 없으면 LLM 호출
→ LLM의 답변을 Redis에 저장
→ 사용자에게 답변 반환
실습에서는 답변의 저장 시간을 600초로 설정했다. 따라서 한 번 질문한 내용은 10분 동안 Redis에 보관된다.
10분 안에 같은 질문이 들어오면 LLM을 다시 호출하지 않고 Redis에 저장된 답변을 바로 보여준다. 이렇게 하면 응답 속도가 빨라지고 불필요한 LLM API 호출도 줄일 수 있다.
캐시에 저장된 데이터는 설정한 시간이 지나면 자동으로 삭제된다. 이처럼 데이터의 유효 시간을 설정하는 기능을 TTL이라고 한다.
대화 기록과 컨텍스트
Redis에는 단순한 질문과 답변뿐 아니라 사용자의 이전 대화 기록도 저장할 수 있다.
AI 시스템에서는 현재 질문을 이해하는 데 필요한 이전 대화나 추가 정보를 ‘컨텍스트(Context)’라고 한다.
예를 들어 사용자가 먼저 다음과 같이 질문했다고 가정할 수 있다.
다음 주에 가족 6명과 강아지를 데리고 제주도로 2박 3일 여행을 갈 거야.
이후 사용자가 “숙소도 알아봐 줘”라고만 말해도 AI가 이전 대화를 기억한다면 제주도, 가족 6명, 강아지 동반이라는 조건을 함께 사용할 수 있다.
이처럼 이전 질문과 답변을 이어서 대화하는 방식을 멀티턴 대화라고 한다. Redis에 대화 기록을 일정 시간 저장하면 이러한 멀티턴 대화를 구현할 수 있다.
MCP에서 말하는 컨텍스트
MCP는 Model Context Protocol의 약자다.
여기에서 컨텍스트는 AI가 답변을 만들 때 참고하는 여러 정보를 의미한다.
- 이전 대화 내용
- 데이터베이스에 저장된 정보
- 검색을 통해 찾은 최신 정보
- 사용자가 업로드한 문서
- 외부 서비스에서 가져온 데이터
LLM이 모든 정보를 처음부터 알고 있는 것은 아니다. 따라서 필요한 정보를 검색하거나 데이터베이스에서 가져온 뒤 질문과 함께 전달해야 더욱 정확하고 구체적인 답변을 만들 수 있다.
앞으로의 AI 서비스는 단순히 정보를 알려주는 데서 끝나지 않고, 검색과 비교를 거쳐 예약이나 결제 같은 실제 작업까지 수행하는 방향으로 발전할 수 있다는 내용도 들었다.
팀 프로젝트 통합과 오류 해결
수업 후에는 팀원들이 각자 만든 CRUD 기능을 하나의 프로젝트에 합치고, Supabase와 Render에서 정상적으로 작동하는지 테스트했다.
이 과정에서 다음과 같은 점을 확인했다.
- 팀원마다 연결된 Supabase 프로젝트가 다를 수 있다.
- 로컬 환경변수와 Render 환경변수가 같아야 한다.
- 잘못된 Supabase URL은 500 오류의 원인이 될 수 있다.
- API 실행 후 데이터가 어느 데이터베이스에 저장됐는지 확인해야 한다.
- 더미 데이터의 ID와 테이블 구조를 통합 전에 맞춰야 한다.
- 각 브랜치의 코드를 합친 후 모든 API를 다시 테스트해야 한다.
같은 코드라도 환경변수와 배포 환경이 달라지면 전혀 다른 결과가 나올 수 있다는 것을 직접 경험했다.
오늘의 회고
오늘은 FastAPI, Supabase, Render, Redis가 서로 어떻게 연결되는지 전체적인 흐름을 이해할 수 있었다.
특히 Redis 캐시를 사용하면 AI 서비스의 응답 속도를 높이고 LLM API 호출 비용까지 줄일 수 있다는 점이 인상적이었다. 대화 기록을 Redis에 저장하면 이전 대화를 기억하는 멀티턴 AI 서비스도 구현할 수 있다는 것을 알게 됐다.
팀 프로젝트에서는 코드를 작성하는 것만큼 환경변수와 배포 설정을 정확히 관리하는 일이 중요했다. 500 오류의 원인을 찾는 과정이 쉽지는 않았지만, 서버 로그와 Supabase URL을 하나씩 확인하면서 문제를 해결할 수 있었다.
오늘 실습을 통해 백엔드 개발은 단순히 기능을 만드는 작업이 아니라 서버, 데이터베이스, 배포 환경, 캐시가 모두 제대로 연결됐는지 확인하는 과정이라는 것을 배웠다.
댓글