

프로그래밍을 공부하기 이전에 나는 식품공학과였고 식품회사에서 품질관리로 일한적이 있다.
이 분야는 법적으로 따져야할게 많다보니 식품공전이라는 책을 끼고 궁금한게 생기면 일일이 찾아보곤 했다.
그때마다 궁금한걸 물어보면 자동으로 찾아주는 AI 챗봇 서비스에 관심이 많았다. 그렇다고 LLM을 쓰자니 내가 물어본것에 대해서 최신 자료를 가지고 있지 않았고 할루시네이션 현상이 종종 발생해서 답변의 신뢰성이 떨어졌다.
조사해보니 관련 데이터를 미리 AI에게 전달하고 이를 바탕으로 답변을 생성하는 RAG( Retrieval Augmented Generation ) 검색 생성 증강 기술이 가장 적합해보여 이를 구현하기로 생각했다.
1. RAG란 무엇인가? (What is RAG?)
RAG(Retrieval-Augmented Generation, 검색 증강 생성)는 AI 모델이 학습하지 않은 최신 데이터나 비공개 문서를 참조하여 답변하게 만드는 기술이다.
이름을 보면 알 수 있다시피 검색, 증강, 생성 3가지 기술로 구현되어 있다.
사실 검색 이전에 외부 데이터를 연관성을 기준으로 검색할 수 있도록 미리 벡터데이터로 변환하고 벡터 DB에 저장하는 임베딩 과정이 필수적이다.
- 검색 (Retrieval): 사용자의 질문이 들어오면, 질문은 벡터 표현으로 변환되고 관련된 내용을 벡터 DB에서 벡터 계산을 통해 연관성을 계산, 검색한다.
- 증강 (Augmentation): 검색된 데이터를 컨텍스트에 추가하여 사용자 프롬프트를 보강한다.
- 생성 (Generation): AI(LLM)가 제공된 정보를 읽고 사용자의 질문에 대한 정확한 답변을 생성한다.

2. 워크플로 설명 (Workflow Analysis)

① Tech Stack
- LLM AI 모델: gpt-4o-mini
- Embeddings AI 모델: text-embedding-3-small
- Vector DB: Supabase PostgreSQL, pgvector (벡터 데이터베이스 플러그인)
- DB: Google Cloud Storage Bucket
- Reranker: Cohere Rerank multilingual-v3.0


아무래도 AI 모델은 비용이 들어가는 작업이다보니 가격대비 성능을 안따질 수가 없다.
내가 알아봤을 때는 DeepSeek가 가장 저렴한 모델에 속했으나 보안 문제가 걱정되어 비교적 친숙한 OpenAI의 gpt-4o-mini를 선택했다. AI 모델 API는 사용량 기반 과금이기 때문에 결제를 미리 해두고 사용한만큼 돈이 빠져나가는 방식이다. 여러 모델에 돈을 넣어두고 사용하기보다는 한 곳에서 관리하는것이 편하다 판단해서 임베딩 모델 역시 OpenAI 모델을 사용했다.
그리고 벡터 데이터베이스는 요즘 핫하다는 Saas DB인 Supabase를 이용하여 postgres DB를 사용했다. postgres에서는 벡터 자료구조를 기본적으로 지원하지 않으나 pgvector 플러그인을 통해 사용할 수 있다.
Rerank는 RAG(검색 증강 생성) 시스템에서 검색 엔진이 찾아온 후보 문서들을 질문과의 관련성 순으로 재배치하여 더 정확한 답변을 찾는 과정이다. Rerank로 유명한 Cohere 사의 모델 중에서도 한국어 사용을 할 것이기 때문에 multilingual 모델을 사용했다.
② RAG 구성
외부 데이터를 벡터 DB에 미리 임베딩 시켜놓는 과정이다.
문서 원본을 Google Cloud Storage에 저장시켜놓고, 메타데이터와 벡터 변환된 청크들을 pgvector store 노드를 통해 저장한다.
③ 문서 처리 로직 (공정 라인)
- 파일 로더: GCS에서 가져온 파일을 PDF, 텍스트 등으로 분류한다.
- 청킹(Chunking): Recursive Character Text Splitter를 통해 1000자 단위로 텍스트를 쪼갠다.
- 벡터 저장: pgvector를 사용하여 고차원 벡터 데이터를 Postgres에 저장한다.
4. 트러블 슈팅 (Troubleshooting)
구축 과정에서 겪은 실제 에러와 해결책이다.
❌ 이슈 1: type "vector" does not exist (Postgres)
- 원인: pgvector 이미지를 사용하더라도, n8n이 접속하는 특정 데이터베이스(n8ndb) 내에서 vector 확장 기능을 활성화하지 않아 발생했다.
- 해결: 해당 DB에 직접 접속하여 명령어를 실행했다. 뜻은 postgres DB에 접속하여 vector가 활성화되어 있지 않다면 확장하는 쿼리를 실행한다는 뜻이다.
-
Bash
docker exec -it {postgresDB 컨테이너명} psql -U {사용자지정ID} -d {사용자지정DB명} -c "CREATE EXTENSION IF NOT EXISTS vector;"
❌ 이슈 2: Forbidden - storage.objects.list access denied (GCS)
- 원인: 프로젝트 소유자(Owner) 계정일지라도 Cloud Storage 버킷에 대한 명시적인 '저장소 관리자' 역할이 IAM에 등록되지 않아 발생했다.
- 해결:
- GCP 콘솔 IAM 메뉴에서 본인 계정 및 서비스 계정에 저장소 관리자(Storage Admin) 역할을 부여했다.
- 권한 설정 후 시스템 반영까지 시간차가 발생하여 잠시 대기 후 해결되었다.
❌ 이슈 3: 403 오류: access_denied (OAuth 인증)
- 원인: Google Cloud 프로젝트가 테스트 모드인 경우, 등록된 테스터 외에는 접근이 차단된다.
- 해결: OAuth 동의 화면에서 사용자의 이메일을 테스트 사용자로 등록했다.
❌ 이슈 4: 과도한 토큰 비용 발생
한번 RAG를 구성하고 검색할 시 원화 기준 500원이 사용되었다.
- 원인:
- openAI GPT 4.1 모델을 사용중이었다.
- topK 값: 25 설정으로 인해 AI가 답변할 때 너무 많은 텍스트 조각을 참조했다.
- 해결:
- 성능과 비용을 고려해서 gpt-4o-mini를 선택했다.
- Retrieve Records 노드의 topK 값을 7 정도로 하향 조정하여 비용을 절감했다.
마치며
AI는 하려면 굉장한 지식이 필요한 줄 알고 멀리했었던 기억이 있다. 하지만 이제는 개발자가 AI를 알아야만 하는 의존성이 생겼다. 그래서 프로젝트를 하게 되었는데 AI 개발이 아닌 활용을 하는 단계에서 사용해보니 생각했던 것보다는 간단하게 활용할 수 있었다.
AI는 활용도가 무궁무진하기 때문에 이번에 배운것을 토대로 여러 프로젝트에 접목시킬 수 있을 것이다.
그리고 Saas에 대한 느낀점인데 내가 미리 미니pc에 구축해놓은 n8n(이 또한 Saas가 가능하다)만 제외하고는 전부 Saas를 이용해서 간단한 RAG 시스템을 구축해봤다. Saas는 생각보다 더 간편했고 생각보다 더 유용했다. 이전에는 전부 직접 구현해봐야 개발자라는 인식이 강했지만, 딱히 그런것 같지도 않다. Saas를 이용하여 구축해서 오히려 비지니스 로직에 집중할 수 있었다는 생각도 들었다. 맨땅에 헤딩하며 구축하는 것 또한 얻는 것이 많지만 빠른 기술 속도를 따라가기 바쁜 개발자는 Saas 서비스로 만족해도 되지 않을까 생각한다. 앞으로도 개인 프로젝트 볼륨 서비스에는 Saas를 많이 사용할 것 같다.
n8n을 통해 내가 상상해오던 RAG 시스템을 간단하게 구축해봤다. 이번이 AI 공부의 첫걸음으로, 이번 경험을 자양분 삼아 지식의 뿌리를 넓게 뻗어봐야겠다.