ZIPFIT - 공공주택 AI 에이전트

2025.11.26 ~ 2025.12.17 (3주)
ZIPFIT - 공공주택 AI 에이전트
Gallery image 1
Gallery image 2
Gallery image 3

1. 프로젝트 개요

기본 정보

  • 프로젝트 명: ZIPFIT (집핏) - 나에게 딱 맞는 공공주택 찾기 챗봇
  • 수행 역할: 시스템 설계 총괄 및 백엔드 개발
  • 핵심 기여: REST API 서버 구축, AI 대화 흐름 설계(LangGraph), 하이브리드 검색 엔진 설계(RRF), PDF 표 데이터 전처리 파이프라인 구축

2. 핵심 아키텍처 및 워크플로우

2.1. AI 대화 파이프라인 구조

RAG 시스템 아키텍처

사용자 메시지를 1회 LLM 호출로 의도를 파악하고, 5가지 처리 흐름 중 하나로 자동 분기하는 상태 그래프 기반 구조.

  • 의도 분류: GPT-4o-mini 1회 호출로 사용자 의도를 파악하고 적절한 흐름으로 분기. 상태 이상(선택 가능한 공고 없이 선택 시도 등) 시 자동 보정
  • 공고 검색: DB 조건 필터(상태·지역·유형)와 AI 벡터 검색 결합. 신규·추가·이전 검색 복원 3가지 모드 지원
  • 공고 선택: 목록 번호 또는 공고명 일부 입력으로 대상 공고 특정
  • 상세 조회: 선택된 공고 문서에서 AI 검색으로 관련 정보 추출. 면적·임대료 질문 시 표 데이터를 추가 보강하여 답변 품질 향상
  • 공고 비교: 복수 공고 각각에 대해 자격·임대료·면적·신청기간 정보를 AI 검색한 뒤 병합 응답
  • 일반 대화: 최신 정책 등 공고 외 질문 시 실시간 웹 검색 연동

2.2. 멀티턴 대화 상태 관리

대화 전체의 문맥을 서버에서 연속 유지하는 8가지 상태 항목을 설계. 이전 검색 결과나 선택 공고가 다음 대화에서도 유지되어 자연스러운 대화 흐름 구현.

상태 항목 역할
현재 의도 / 추출 데이터 사용자가 무엇을 원하는지 분류 결과
검색된 공고 목록 "1번 선택"과 같은 후속 발화의 참조 기준
현재 선택된 공고 상세조회·비교 시 AI 검색의 대상 기준
비교용 복수 공고 다중 공고 비교 처리용
검색 기록 (최대 5건) 이전 검색 결과 복원용
AI 검색 결과 단위 문서 LLM 답변 생성에 사용될 문서 조각
사용자 프로필 희망지역·연령·혼인·자녀·소득 정보
대화 이력 (최근 10턴) 맥락 연속성 유지용

2.3. 하이브리드 검색 엔진

PostgreSQL 전문 검색(Full-Text Search)과 AI 임베딩 기반 벡터 유사도 검색을 RRF(Reciprocal Rank Fusion) 알고리즘으로 결합.

  • 키워드 검색(FTS): 텍스트 일치 기반 검색. 한국어 조사(은/는/이/가/을/를 등) 전처리 후 검색
  • 의미 검색(벡터): AI 임베딩 모델로 의미적으로 유사한 문서 검색 (상위 100개 후보)
  • RRF 통합: 키워드 결과(가중치 0.4)와 의미 결과(가중치 0.6)를 순위 기반으로 통합
  • 쿼리 확장: 사용자 질문의 동의어·유의어 자동 확장 (신혼부부 → 혼인/예비신혼부부, 면적 → 전용면적/계약면적/㎡ 등)

2.4. DB 설계 (4개 테이블)

  • 공고 메타데이터: 공고명·URL·지역·상태·마감일 등 저장. 서비스 노출 여부 플래그로 공개 공고 관리
  • 공고 첨부 파일: PDF 등 원본 파일 경로 관리
  • 문서 단위 조각(청크): 공고 문서를 텍스트/표 단위로 분할 저장. 각 조각에 AI 임베딩 벡터와 키워드 검색 인덱스 동시 보유
  • 대화 세션·메시지: 세션 단위 대화 내용 저장, 메시지 순서 관리

3. 시스템 인프라 및 설계

시스템 아키텍처

3.1. 기술 스택 (Tech Stack)

Frontend: React Vite Axios Backend: Django Django REST Framework Nginx Gunicorn AI & Model: LangGraph gpt-4o-mini text-embedding-3-small Tavily (웹검색) Data: PostgreSQL pgvector tsvector (FTS) Infra: Docker Docker Compose

3.2. 데이터 수집 및 적재 파이프라인

공고 수집부터 AI 검색 DB 저장까지 4단계 자동화 파이프라인 구현.

3.2.1. 공고 목록 수집

  • LH 공식 사이트의 내부 API를 POST 방식으로 직접 호출하여 공고 데이터를 수집. 페이지를 반복 순회하며 2024년 11월 이후 게시된 공고를 모두 수집
  • 공고 유형(임대 13종 / 분양 2종 / 기타)을 자동 분류하여 메타데이터와 함께 임시 테이블에 우선 적재 후 서비스 DB에 반영

3.2.2. 공고 PDF 다운로드

  • 각 공고의 첨부 파일 목록 API를 추가 호출하여 "공고문(PDF)" 유형의 파일만 선별 다운로드

3.2.3. PDF 파싱 (하이브리드 방식)

  • AI 파서(LlamaParse): PDF 전체를 마크다운으로 변환하여 텍스트·표·제목 구조 추출
  • 표 전용 파서(Camelot): LlamaParse가 추출한 표를 Camelot 결과(정확도 70% 이상)로 교체. 복잡한 표 구조를 더 정확하게 추출하기 위한 이중 처리

3.2.4. 문서 청킹 및 AI 임베딩 저장

  • 텍스트와 표를 별도 전략으로 분할
    • 텍스트: 단락 → 문장 순서로 분할, 직전 단락을 다음 청크와 일부 중복(overlap) 포함하여 맥락 연속성 유지
    • : 헤더 행을 모든 분할 조각에 반복 보존. 표 앞 제목·단락에서 단지명·항목명을 자동 추출하여 각 조각에 맥락 헤더 부착
  • AI 임베딩 벡터 생성 후 키워드 검색 인덱스와 함께 검색 DB에 저장

3.3. PDF 표 데이터 전처리

  • 깨진 행 복원: PDF 추출 시 셀 내 줄바꿈이 행 분리로 잘못 인식되는 문제를 병합 로직으로 복원 (예: 공급\n형별공급형별)
  • 텍스트 정규화: HTML 태그 제거, 연속 공백 정리, 한글 문자 간 불필요한 줄바꿈 제거
  • 표 제목 자동 추출: 표 앞의 제목·설명에서 단지명·항목명을 자동 추출하여 각 문서 조각에 맥락 헤더로 부착

4. 개발 과정 및 문제 해결 (Development & Problem Solving)

4.1. 기술적 의사결정 (Architecture Decision)

4.1.1. 선형 파이프라인 → LangGraph 상태 그래프 전환

  • 문제: 기존 구조에서 사용자 메시지 1건 처리에 LLM을 4~5회 순차 호출하여 응답 지연 발생. 매 대화 턴마다 이전 검색 결과와 선택 공고 정보가 초기화되어 문맥 연속 대화 불가
  • 결과: 상태 그래프 도입으로 대화 문맥을 서버에서 영속 관리. 의도 분류를 1회 LLM 호출로 처리하고 해당 흐름으로 직접 분기하여 API 호출 최소화

4.1.2. 단순 벡터 검색 → RRF 하이브리드 검색 도입

  • 문제: "신혼부부", "행복주택", "접수중" 등 도메인 특화 키워드가 빈번한 공고문 특성상, 의미 기반 벡터 검색만으로는 키워드 정확 매칭 품질 부족
  • 결과: 키워드 검색(가중치 0.4)과 의미 검색(가중치 0.6)을 RRF로 통합하여 두 검색 방식의 장점을 동시에 확보

4.2. 트러블슈팅 (Troubleshooting)

4.2.1. 멀티턴 대화 시 이전 공고 맥락 유실

  • 현상: "1번 선택" 입력 시 직전 검색 공고 목록이 사라져 에이전트가 대상 공고를 특정하지 못함. "신청자격 알려줘" 입력 시 선택된 공고 정보가 없어 AI 문서 검색 불가
  • 해결: 검색 목록·선택 공고·검색 이력을 서버 상태로 명시적 관리. 의도 분류 시 상태 오류 자동 보정 — 선택 가능한 공고 없이 선택 의도 감지 시 자동으로 검색 흐름으로 전환
  • 결과: 검색 → 선택 → 상세조회 → 비교의 전체 대화 흐름이 단절 없이 연결

4.2.2. PDF 표 구조 파괴로 인한 면적·임대료 정보 누락

  • 현상: 공고문 PDF의 면적·임대료 표가 추출 과정에서 셀 내 줄바꿈이 행 분리로 잘못 인식됨. AI 검색 시 해당 정보가 조회되지 않아 "면적 정보 없음" 응답 발생
  • 해결: 깨진 행을 병합 복원하는 전처리 모듈 구현. 표 단위 문서 조각 생성 시 앞 단락 제목을 자동으로 맥락 헤더로 부착하여 검색 품질 향상. 면적·임대료 질문 시 표 데이터 조각을 키워드 조건으로 추가 보강
  • 결과: 면적·임대료 정보 검색 누락 방지, LLM의 표 데이터 해석 정확도 향상

4.2.3. 지역명 통칭 처리 (예: "전라도" → 복수 지역 매핑)

  • 현상: "전라도 공고" 입력 시 DB의 "전라남도", "전북특별자치도"와 직접 매칭되지 않아 검색 결과 누락
  • 해결: 의도 분류 단계에서 지역 통칭 처리 규칙을 AI 프롬프트에 명시. DB 지역 목록을 맥락으로 제공하여 통칭 입력 시 해당하는 모든 지역값을 자동 변환 후 OR 조건 필터 적용
  • 결과: "전라도" → [전라남도, 전북특별자치도] 자동 변환 후 OR 필터로 정확한 지역 검색 지원