최근 AI 기술의 발전과 더불어 LLM 및 VectorDB를 결합한 챗봇 아키텍처가 하나의 업계 표준처럼 자리 잡고 있다. 그러나 특정 기술 스택의 유행을 맹목적으로 추종하는 것은 필연적으로 시스템의 복잡도를 높이고 유지보수 비용을 증가시키는 오버엔지니어링을 초래한다.
본 글에서는 최근 챗봇 시스템을 직접 설계하고 구현하는 과정에서 경험한 기술적 의사결정의 이면과, 시스템의 본질적인 요구사항에 맞추어 아키텍처를 최적화한 과정에 대해 심도 있게 분석한다.
1. 생성형 LLM 기반 추론에서 VectorDB 기반 의미론적 검색으로의 전환
문제 인식: 초기 아키텍처는 사용자의 질의를 VectorDB에서 검색하여 문맥을 찾은 뒤, 이를 LLM에 프롬프트로 주입하여 최종 답변을 생성하는 일반적인 RAG패턴을 고려했다. 그러나, 기 정의된 (질문, 답변) 페어를 응답하는 목적이라면 매번 고비용의 LLM 추론 연산을 거치는 것이 타당한가에 대한 의문이 발생했다.
기술적 분석 및 적용: LLM을 통한 텍스트 생성은 필연적으로 토큰 당 생성 시간 지연(Time To First Token, TTFT)을 발생시키며, 환각 현상(Hallucination)에 대한 리스크 제어가 요구된다. 이를 해결하기 위해 사용자의 질의를 임베딩(Embedding) 벡터로 변환한 후, 기 구축된 VectorDB의 질의 벡터들과 비교하여 가장 유사한 데이터의 매핑된 '답변'을 직접 반환하는 의미론적 검색 방식으로 선회했다.
이 과정에서 두 고차원 벡터 간의 거리는 코사인 유사도를 통해 연산된다.
이러한 O(1)에 근접한 ANN(Approximate Nearest Neighbor) 검색 방식은 LLM의 O(N) 연산 시간(N은 생성 토큰 수)을 압도한다. 결과적으로 API 호출 비용 및 토큰 소모량을 0으로 수렴시키면서도, 시스템은 관리자가 의도한 100% 정확도와 인간적인 문맥을 유지한 응답을 획기적으로 짧은 지연 시간 내에 제공하게 되었다.
2. 프로토콜의 재평가: WebSocket에서 HTTP 통신으로의 회귀
문제 인식: 다수의 현대 챗봇 애플리케이션이 WebSocket 기반의 양방향 통신을 채택하고 있다. 그러나 본 프로젝트의 요구사항 분석 결과, 챗봇의 상호작용은 본질적으로 단편적인 요청-응답 패턴을 띄고 있었다.
기술적 분석 및 적용: WebSocket은 초기 HTTP Handshake 이후 TCP 연결을 지속적으로 유지하며 Full-duplex 통신을 지원하는 프로토콜이다. 이는 실시간 게임 통신이나 거래소 호가창 등 빈번하고 비동기적인 데이터 푸시가 필요한 환경에 적합하다.
LLM 기반 챗봇에서 WebSocket이나 SSE(Server-Sent Events)를 사용하는 기술적 이유는 단 하나, LLM이 답변을 생성하는 과정을 청크 단위로 실시간 스트리밍하기 위함이다. 그러나 앞선 1번의 최적화를 통해 시스템은 VectorDB에서 '완성된 응답 텍스트'를 단번에 꺼내오는 구조로 변경되었다.
이러한 상태에서 유휴 상태의 TCP 연결을 계속 유지하는 것은 서버의 메모리 점유율을 높이고 File Descriptor를 고갈시키는 불필요한 오버헤드다. 따라서 연결 설정과 해제가 명확한 전통적인 HTTP 프로토콜로 회귀하는 것이 서버 자원 효율성, Scale-out(서버 수평 확장), 그리고 로드 밸런싱 관점에서 시스템의 정합성에 훨씬 부합하는 아키텍처 설계다.
3. 인증 메커니즘의 최적화: JWT의 한계와 Stateful Session의 도입
문제 인식: 최근의 웹 생태계는 RESTful API 환경에서 JWT(JSON Web Token)를 무분별하게 차용하는 경향이 있다. 관리자 페이지의 인증을 구현함에 있어 초기에는 JWT를 도입하였으나, 단일 관리자 페이지(Single Admin Panel) 환경에서 JWT의 실효성에 대한 근본적인 의문이 제기되었다.
기술적 분석 및 적용: JWT의 핵심적인 아키텍처적 가치는 무상태성(Statelessness)에 있다. 마이크로서비스 아키텍처(MSA) 환경에서 인증 서버의 부하를 분산시키고, 세션 스토리지를 공유하지 않아도 Signature 검증만으로 인가(Authorization)를 처리할 수 있다는 점이 강력한 무기다.
그러나 JWT는 "토큰을 발급한 이후에는 만료 시간 전까지 서버가 이를 능동적으로 통제할 수 없다"는 치명적인 구조적 결함을 지닌다. 관리자 페이지 시스템은 보안 수준이 가장 높아야 하는 영역으로, 계정 탈취 의심이나 권한 변경 시 '즉각적인 강제 세션 만료(Revocation)' 기능이 필수적이다.
이를 JWT로 구현하기 위해서는 결국 Redis와 같은 In-memory Database에 무효화된 토큰 목록(Blacklist)을 저장하고 매 요청마다 검증해야 한다. 이는 JWT 본연의 장점인 'Stateless'를 스스로 부정하는 안티 패턴(Anti-pattern)이다.
단일 서버 환경에서 구동되는 관리자 시스템이라면, 서버의 메모리나 세션 저장소를 활용하는 전통적인 Stateful Session 방식이 세션의 라이프사이클을 완벽하게 통제할 수 있어 보안성과 관리 편의성 측면에서 압도적으로 우월하다. 향후 리팩토링 과정에서 HTTPS 기반의 보안 쿠키(HttpOnly, Secure flag 적용)를 활용한 Session 인증 방식으로 마이그레이션 할 예정이다.
결론
뛰어난 엔지니어링은 단순히 새롭고 복잡한 기술을 결합하는 데 있지 않다. 시스템의 본질적인 목적을 정확히 파악하고, 불필요한 기술적 부채를 과감히 덜어내는 과정(KISS 원칙 - Keep It Simple, Stupid)이야말로 견고하고 안정적인 소프트웨어를 구축하는 핵심임을 이번 시스템 구축을 통해 다시 한번 입증할 수 있었다.
'Tools & Setup > Study' 카테고리의 다른 글
| [PYTHON SETTING] 파이썬 저장소 devpi와 PyPI란 무엇인가? (0) | 2026.01.07 |
|---|---|
| WSL에서 파일을 삭제했는데 디스크 용량이 줄지 않는 이유와 해결 방법 (0) | 2025.12.09 |
| 리눅스에서 파일, 폴더 삭제하기: rm / rmdir 핵심 정리 (0) | 2025.11.26 |
| Python 도구: Poetry vs Conda vs Venv (2) | 2025.08.29 |
| XGBoost 이란? (2) | 2025.07.29 |