Projects
CARO AI 서버 개발 회고
FastAPI, Redis Streams, vLLM을 기반으로 개발자 역량 분석, 자기소개 생성, 명함 OCR 기능을 구현한 AI 서버 프로젝트입니다.
프로젝트 개요
이 프로젝트는 팀 서비스에서 AI 기능을 담당하는 서버입니다. 사용자의 GitHub 활동과 이력 데이터를 분석해 협업 성향을 점수화하고, 회사와 직무 정보를 바탕으로 자기소개 문장을 생성하며, 명함 이미지를 분석해 연락처 정보를 구조화하는 기능을 제공합니다.
- 구분: 카카오테크 부트캠프 팀 프로젝트
- 역할: AI 서버 설계 및 구현
- 주요 기술: FastAPI, Python, Redis Streams, vLLM, GitHub API, Tavily Search API, 임베딩 서비스, OCR
- 링크: GitHub
배포 자동화와 CI/CD 구성은 이 글의 범위에서 제외하고, 서비스 기능과 AI 서버 구현 관점에서 정리했습니다.
문제
AI 기능은 일반적인 CRUD API보다 응답 시간이 길고 실패 가능성이 높습니다. GitHub API, 검색 API, LLM, OCR 모델처럼 외부 의존성이 많은 기능을 동기 요청 하나로 처리하면 사용자는 긴 시간 동안 응답을 기다려야 하고, 서버도 처리 상태를 추적하기 어렵습니다.
또한 LLM은 항상 원하는 형식으로 답하지 않을 수 있습니다. 서비스에서는 자연어 문장이 아니라 프론트엔드가 바로 사용할 수 있는 JSON 구조가 필요했기 때문에, 모델 호출 전후의 검증과 후처리가 중요했습니다.
구현
FastAPI 서버는 요청을 받으면 Redis Streams에 작업을 등록하고, 별도의 Worker가 작업을 소비해 처리하는 구조로 구성했습니다. 사용자는 작업 제출 후 task_id를 받고, /ai/tasks/{task_id}와 /ai/tasks/{task_id}/result로 진행 상태와 결과를 조회할 수 있습니다.
FastAPI API Server
-> Redis Streams
-> AI Worker
-> Task Result Store
-> Client Polling
HEX 분석
HEX 분석 기능은 GitHub 활동 데이터를 수집한 뒤 협업, 소통, 기술, 문서화, 신뢰성, 선호도 6개 축으로 점수를 계산합니다. PR 생성 수, PR 리뷰 수, 이슈 코멘트, 언어 다양성, README 작성 비율, 머지율 같은 지표를 기반으로 1차 점수를 만들고, 필요하면 vLLM을 호출해 분석 요약을 생성하도록 구성했습니다.
LLM이 임의의 형식으로 응답하지 않도록 시스템 프롬프트에 JSON 스키마와 점수 보정 범위를 명시했습니다. 점수 보정은 입력 데이터에서 관측 가능한 근거가 있을 때만 허용되도록 제한해, 분석 결과가 과하게 생성되는 문제를 줄였습니다.
자기소개 생성
직무 기반 자기소개 생성 기능은 회사, 부서, 직무, 프로젝트 정보를 입력받아 3문장 자기소개를 생성합니다. 먼저 임베딩 기반 직무 필터를 거쳐 개발과 무관한 직무를 사전에 차단하고, 부트캠프 수강생이나 강사처럼 일반 회사원과 다른 역할은 별도 유형으로 분기했습니다.
검색 컨텍스트는 Tavily Search API로 보강했습니다. 회사와 부서, 프로젝트명을 바탕으로 검색 쿼리를 만들고, 검색 결과의 개수와 관련도를 이용해 search_confidence를 계산했습니다. 유사한 요청은 시맨틱 캐시에 저장해 반복적인 LLM 호출을 줄이도록 했습니다.
고민한 점
가장 크게 신경 쓴 부분은 "AI 응답을 서비스 데이터로 다루는 방식"이었습니다. 모델은 자연어 생성에 강하지만 서비스는 예측 가능한 스키마가 필요합니다. 그래서 프롬프트에 출력 형식을 강하게 제한하고, 응답 파싱에 실패했을 때 재시도하거나 기본값으로 처리하는 흐름을 넣었습니다.
또 하나는 긴 작업을 어떻게 사용자 경험으로 연결할지였습니다. LLM과 OCR 호출은 지연 시간이 길 수 있으므로, 요청을 바로 처리하지 않고 Redis Streams 기반 비동기 작업으로 분리했습니다. 이 구조 덕분에 API 서버는 작업 접수에 집중하고, Worker는 작업 유형별로 확장할 수 있게 되었습니다.
배운 점
이 프로젝트를 통해 AI 서버는 모델 호출 코드만으로 완성되지 않는다는 점을 배웠습니다. 입력 검증, 외부 API 장애 대응, JSON 스키마 강제, 캐싱, 작업 상태 관리, 후처리까지 포함해야 실제 서비스에서 사용할 수 있는 기능이 됩니다.
또한 LLM을 사용할 때는 "좋은 답변을 생성하는 것"보다 "서비스가 신뢰할 수 있는 형태로 제한하는 것"이 더 중요했습니다. 특히 점수 분석과 OCR처럼 결과가 화면과 로직에 직접 연결되는 기능에서는 모델 응답을 그대로 믿기보다, 규칙 기반 계산과 후처리를 함께 두는 방식이 더 안정적이었습니다.
