← back

AI Chatbot / Tutor

LMS에 연동되는 AI 챗봇과 과목별 AI 튜터 서비스. 범용 GPT 챗봇과, 강의자료를 RAG로 활용하는 맞춤형 AI 튜터를 제공한다.

2025.03 ~ 2025.08 · 기술 검토 / 기획 / 풀스택 개발
NestJSReactTypeScriptMongoDBOpenAI

background

대학 LMS에서 학생들의 수업 관련 질문에 교수/조교가 즉시 응답하기 어렵다. AI Chat은 범용 챗봇(GPT 기반)을, AI Tutor는 과목별 강의자료를 RAG로 활용하는 맞춤형 AI 튜터를 제공한다.


architecture

graph TD
    LMS["LMS (Canvas)"] -->|"LTI · Global / Course"| CHAT_UI
    subgraph "Client · React"
        CHAT_UI["AI Chat · AI Tutor · 통계 · 운영자"]
        STREAM["REST API + SSE 스트리밍"]
    end
    CHAT_UI -->|REST| API
    subgraph "Server · NestJS"
        API[REST API]
        SSO["Auth · JWT SSO · LMS→임시토큰→세션"]
        MODULES["Modules · chat/bot/course-bot/quiz/statistics"]
        INTEG["Integration · OpenAI GPT/Vector Store/DALL-E · Gemini"]
        WORKER["Worker + Cron"]
    end
    API --> SSO --> MODULES
    MODULES --> INTEG
    MODULES --> WORKER
    subgraph "Storage"
        MONGO[(MongoDB · 대화/설정)]
        NAS[NAS · 파일]
        VS[OpenAI Vector Store]
    end
    MODULES --> MONGO
    MODULES --> NAS
    INTEG --> VS
        

MSA 기반 독립 서비스

기존 LMS와 별도 포트, 별도 DB로 운영되는 독립 서비스. LTI 표준으로 LMS에 삽입되며, JWT SSO로 추가 로그인 없이 사용자 인증을 연결.

과목별 맞춤 RAG

AI Tutor는 과목 컨텍스트(과목ID, 역할)를 LTI로 전달받아 해당 과목의 강의자료만 OpenAI Vector Store에서 검색하여 답변. 과목마다 독립된 지식 베이스를 갖는 구조.

운영자 권한 분리

학교 운영자와 시스템 운영자의 권한을 분리. AI 모델 선택, 도구 제한, 사용자 접근 권한을 사이트별로 설정할 수 있는 관리 인터페이스 제공.


what i built

기술 검토 및 선정

LLM 모델 비교(GPT-4o, GPT-4.1 mini, Claude) → 비용 대비 품질 최적인 GPT-4.1 mini 선정
벡터DB 비교(Pinecone, Qdrant, OpenAI Vector Store) → 별도 인프라 불필요한 OpenAI Vector Store 선정
문서 파서 비교(Unstructured, Docling) → OpenAI File Search가 파싱까지 처리하므로 별도 파서 불필요로 결론
검토 결과를 Confluence에 비교 테이블로 문서화하여 팀 의사결정 지원

프로토타입 설계 및 개발

MongoDB 스키마 설계 — Bot, Thread, Message, CourseBot 등 핵심 컬렉션 정의
RESTful API 명세 — 챗봇 CRUD, 대화 관리, 메시지 스트리밍, 파일 업로드
JWT 기반 SSO 인증 흐름 설계 — LMS → 임시 토큰 → AI Chat 세션의 3단계 인증
NestJS + React로 핵심 기능 프로토타입 구현

상용화 개발

OpenAI의 Tool 개념을 기반으로 서비스 전체를 설계. 웹 검색(web_search), 파일 검색(file_search), 이미지 생성(image_generation), 코드 인터프리터(code_interpreter) 등 각 Tool별로 SSE 스트리밍 이벤트, 서버 처리 로직, 클라이언트 UI를 일관된 구조로 정의
ChatGPT의 UX를 참고하여, 도구 호출 시 진행 상태(added → processing → done)를 실시간으로 표시하고, 각 도구의 결과를 인라인으로 렌더링하는 채팅 UI 구현
Canvas LTI로 각 과목에 AI 튜터를 삽입하여 과목별 맞춤 답변 제공
운영자 관리 인터페이스 — 학교/시스템 운영자 권한 분리, AI 모델 및 도구별 활성화/비활성화 설정
모바일 반응형 대응, 설치/운영 가이드 문서화

challenges

MSA 환경에서의 SSO 인증 설계

상황 AI Chat은 기존 LMS(Canvas + LearningX)와 별도의 서비스(별도 포트, 별도 DB인 MongoDB)로 운영된다. 사용자가 LMS에 이미 로그인한 상태에서 AI Chat에 접근할 때, 추가 로그인 없이 인증이 연결되어야 했다. 또한 과목 튜터는 Canvas LTI 표준으로 진입하므로, URL 리다이렉트 방식과 LTI 방식 두 가지 인증 경로를 모두 지원해야 했다.

사고 3단계 JWT SSO 흐름을 설계했다. LMS가 사용자 정보를 담은 임시 토큰(TTL 60초)을 발급하고, AI Chat 서버가 이를 검증한 뒤 자체 JWT 세션 토큰을 발급하는 방식이다. LTI 경로에서는 Canvas가 전달하는 LTI 파라미터(user id, course role 등)에서 사용자 정보를 추출하여 동일한 세션 흐름에 합류시켰다. 비로그인 사용자는 LMS 로그인 페이지로 자동 리다이렉트.

결과 URL 리다이렉트와 LTI 두 경로 모두에서 사용자 경험 저하 없이 독립 서비스 간 인증을 연동. 이 인증 구조는 이후 AI Commons에서도 동일한 패턴으로 재활용되었다.

기술 스택 비교 평가 및 의사결정

상황 AI 챗봇이라는 제품 카테고리 자체가 팀에게 처음이었다. LLM 모델, 벡터DB, 임베딩 모델, 문서 파서 등 선택해야 할 기술이 많았고, 각각의 품질, 비용, 운영 복잡도가 달랐다.

사고 각 기술 카테고리별로 후보 3~5개를 선정하고, 평가 기준(응답 품질, 지연시간, 비용, 운영 복잡도)을 정의한 뒤, 프로토타입 수준의 PoC로 실제 성능을 측정했다. LLM은 GPT-4o, GPT-4.1 mini, Claude를 비교하여 비용 대비 품질 최적인 GPT-4.1 mini를 선정. 벡터DB는 Pinecone, Qdrant, OpenAI Vector Store를 비교하여 별도 인프라 없이 운영 가능한 OpenAI Vector Store를 선정. 검토 결과를 Confluence에 비교 테이블로 문서화하여 팀 의사결정을 지원했다.

결과 "OpenAI 생태계 올인" 전략을 도출. Vector Store, File Search, GPT를 모두 OpenAI로 통일하여 별도 벡터DB 서버 없이 운영 복잡도를 최소화했고, 이것이 4개월 만에 상용화를 완료할 수 있었던 핵심 요인이었다.

웹 검색 품질 개선 — 멀티 모델 Tool 설계

상황 GPT-4.1 mini 모델의 내장 웹 검색 도구를 사용했지만 검색 품질이 낮게 느껴지는 경우가 자주 있었다. 사고 모델(o4-mini)을 사용하면 품질은 좋지만 비용이 높고, 기본 모델은 비용은 낮지만 품질이 부족한 상황.

사고 내장 웹 검색 도구 대신, 별도 모델이 웹 검색을 전담하는 커스텀 Tool을 설계했다. 기본 대화는 GPT-4.1 mini로 처리하되, 웹 검색이 필요하면 o4-mini 기반 웹 검색 Tool을 호출하여 검색 품질을 높이는 방식이다. 추가로 Gemini Flash Lite 모델의 Search Grounding을 활용한 웹 검색 Tool도 프로토타입하여, 비용과 품질의 다양한 조합을 운영자가 선택할 수 있도록 했다.

결과 기본 모델의 비용을 유지하면서 웹 검색 품질을 개선. OpenAI의 Tool 구조를 활용하여 검색 엔진을 교체 가능한 모듈로 설계한 경험.


retrospective

처음으로 밑바닥부터. DB 스키마 설계부터 API 명세, 인증 흐름까지 서비스의 기반을 직접 설계한 첫 경험이었다. 마이페이지에서는 기존 시스템 위에서 개발했지만, 이 프로젝트에서는 빈 캔버스에서 시작해야 했고 그만큼 설계 단계의 무게를 실감했다.

먼저 조사하고, 먼저 검증하기. 처음 해보는 분야였기에 "일단 만들자"의 유혹이 컸지만, LLM/벡터DB/문서파서를 체계적으로 비교하고 PoC로 검증한 뒤 결정한 덕분에 상용화 과정에서 스택을 뒤엎는 일이 없었다. 시간을 아끼려면 오히려 조사에 시간을 쓰는 게 맞다는 걸 체감했다.

프로토타입은 버려지는 코드가 아니다. DB 스키마, API 명세, SSO 인증 흐름을 프로토타입 단계에서 충분히 설계했더니, 상용화 코드가 프로토타입의 자연스러운 확장이 됐다. "나중에 다시 짜면 되지"가 아니라 처음부터 구조를 잡는 습관이 생겼다.

내가 쓴 문서가 남을 살린다. 설치 가이드를 꼼꼼히 작성해둔 덕에 이후 여러 대학 배포를 다른 팀원이 병목 없이 진행할 수 있었다. 그때 "문서는 미래의 동료를 위한 코드"라는 말을 실감했다.