[DB Deep] 답변 생성 아키텍쳐

cup-wan·2025년 6월 1일
5

DBDeep

목록 보기
2/3

Intro


이번 프로젝트를 진행하면서 가장 많은... 고민을 한 부분입니다. 답변을 생성하는 과정을 어떻게 구상했는지 흐름과 함께 알아보겠습니다. AI에 대해 지식이 부족해서 짱 멋진 팀원들의 도움으로 아키텍쳐를 설계했습니다.

전체 아키텍쳐

저희 서비스의 답변 생성 전체 아키텍쳐입니다.

  • 사용자의 질문 의도를 파악할 것
  • 답변은 CoT 흐름 : NL2SQL -> Chart -> Insight
  • 프롬프팅 효율을 위한 RAG 기반 스키마 검색

사용자 입력 ➡️ 질문 분류

  • analysis : 분석 요청
  • follow-up : 이전 흐름에 대한 후속 질문
  • confused : 흐릿하거나 명확하지 않은 질문

일상 대화도 처리하는 Chat GPT와 다르게 저희 서비스는 기업 데이터베이스 분석에 특화되어 있는 "에이전트" 성격이 강했기 때문에 최초 질문을 분류하는 로직을 추가해야한다 생각했습니다.
LangChain으로 구현한 프록시 역할의 LLM으로 분기 처리를 한 후 어떤 답변을 생성할지 결정하는 부분입니다.
해당 로직의 판단을 돕기 위해 이전 대화 기록이 있다면 대화 기록을 프롬프트에 추가하였고 사용자의 custom_dict를 조회해 더 정확한 판단을 내릴 수 있었습니다.

CoT : NL2SQL -> Chart -> Insight

핵심 기능이었던 답변 생성입니다. 이전 프로세스에서 analysis로 분류되면 다음과 같은 연쇄 처리가 일어납니다.

  1. NL2SQL : 프롬프팅과 RAG를 통해 기업 DB 전용 쿼리 생성
  • RAG를 통한 쿼리 정확도 향상
    • Schema Description을 Pinecone에 벡터 임베딩
    • 사용자 질문과 가장 유사한 Top-K 스키마 설명 검색
    • ReRank 과정을 거쳐 최종 Top-K 선정
    • RAGAS를 이용한 정확도 (precision@K, recall@K) 측정
  • BigQuery 검증
    • 최대 5번의 재검증 (쿼리 정확도를 위함)
    • BigQuery의 고유 문법 프롬프팅에 추가
    • Pinecone에도 추가하여 최대한 비슷한 문법을 찾아가도록 유도
  1. NL2Chart, NL2Graph : SQL 결과를 바탕으로 적절한 시각화 방식 선택 및 JSON 생성
  • 초기 개발 단계에서는 이미지로 저장할 생각 (정적 리소스)
  • 구글 멘토님이 동적으로 그래프를 볼 수 있는 방법이 있는 것이 좋을 것 같다 ➡️ JSON 형식으로 제공 및 최선의 그래프 형태 제공
  • 최선의 그래프 형태를 제공하기 위한 LLM 프롬프팅 추가, 그래프가 필요없는 질문의 경우 (ex: 재직 중인 사원수 알려줘)도 판단할 수 있게 추가
  1. Insight 도출 : NL2SQL, NL2Chart를 기반으로 LLM이 핵심 인사이트 요약 및 설명 작성
  • 이전에 생성된 SQL, Chart를 CoT에 이용해 최종 인사이트 생성
  • 차트에 대한 설명, 특이점, 추가 질문이나 개선 사항 등을 제공

Follow-up 답변 & 실패 대비 로직

질문이 Follow-up으로 분류되면 직전 질문의 SQL 결과와 인사이트를 포함한 대화 히스토리 기반으로 답변이 생성됩니다.
답변 이어쓰기가 아닌 대화 맥락을 유지한 분석 + 연속적인 데이터 탐색 유도를 위한 역할입니다.

또한 실패 로직도 많이 고민한 부분입니다. 실제로 ChatGPT의 초기에 재미를 넘어 범죄에 이용될만한 질문이 많았습니다.

윈도우키를 제공하거나 기업 기밀 유출 사고 등이 빈번하게 발생했습니다.
저희도 이러한 생성형 AI의 문제점을 자각하였고 1차적으로 Gemini 2.5 pro의 향상된 보안 탐지 정책에 더해 저희들만의 보안 감지를 고려했습니다.
사내 시스템에 맞게 우선 데이터 권한에 대한 탐색을 우선했습니다.

  • 현재 로그인한 사람을 게이트웨이를 통해 Role을 파악
  • 질문 시 프롬프트에 강한 제약 제공 (Role에 따른 각 스키마 접근 권한 부여)
  • SQL 생성 단계에서 선택되는 Table의 접근 권한을 LLM 에서 제한 + 서버단에서 제한, 총 두번에 거친 검증

하지만 시간이,,, 촉박하여서 서버 검증 로직 구현을 추가하지 못햇습니다. LLM 프롬프팅을 통한 필터링은 생각보다 제어력이 약했습니다. 추가 리팩토링을 진행하여 권한 체크에 따른 보안 강화를 해야겠습니다.

WebSocket에 대해

답변 생성 파이프라인을 설계하며 동시에 채팅 로직에 대해 생각했습니다.

질문 ➡️ NL2SQL ➡️ SQL 실행 ➡️ Chart 생성 ➡️ Insight 추출

이 과정을 한번에 끝내는 동기 처리보다는 중간 단계마다 결과를 사용자에게 실시간으로 전달하는 방식이 훨씬 자연스럽다 생각했고 (ChatGPT 처럼) 통신 방식으로 SSE, WebSocket 중에 고민 했습니다.

SSE

이전 글에도 작성했듯이 SSE는 단방향 스트리밍 방식으로 서버에서 클라이언트로 실시간 데이터를 푸시할 수 있습니다.
하지만 서비스 구조와 적합하지 않다 생각했습니다. 그 이유는 다음과 같습니다.

  • 사용자의 질문을 서버로 보내야함 (API 통신으로 따로 구현해야함)
  • 중간 응답 (NL2SQL 결과, Chart, Insight)를 나눠서 보내야 하는데 SSE는 메시지 분류나 통제에 한계가 있음
  • 향후 기능 확장 (답변 중단 요청, 실시간 피드백 등)에 제한적

모든 내용을 Markdown으로 실시간 파싱하는 ChatGPT와는 다르다 생각해서 Websocket을 생각했습니다. 또한 개발자와 관리자를 위해 콘솔과 유사한 기능 또한 존재했기 때문에 WebSocket을 생각했습니다.

WebSocket

WebSocket도 완벽히 적합하다고 생각하진 않았지만 클라이언트와 서버 간 연결을 지속하며 양방향 통신이 UX 측면에서 더 유리하다 생각했습니다.

  • 실시간 질문 전달
  • 중간 응답 스트리밍
  • 사용자 상호작용
  • 상태 관리
  • 유연한 예외 핸들링

가장 중요한 건 상태 관리였습니다. WebSocket은 최초 연결 후 websocket.state를 통해 상태관리가 가능합니다.
저희 서비스는 사용자의 custom_dict, role 등이 필요했기 때문에 연결 후 해당 내용을 매번 가져오기보다 한번 저장 후 계속 사용할 수 있는 WebSocket이 더 효율적일 것이라 판단했습니다.
또한 어떤 파이프라인을 처리하다 에러가 발생했는지 파악하기 위해 예외 처리가 중요했는데 이 또한 WebSocket이 더 유연하다 생각하여 최종 통신 방식으로 WebSocket을 선택했습니다.

Outro

LLM 파이프라인을 처음 설계해보면서 정말 많이 배운 것 같습니다. 벡터 DB, LangChain, WebSocket 등 다양한 기술을 활용해보며 배울 수 있었습니다.
프로젝트 초기에 우아한 형제들의 물어보새 프로젝트를 많이 참고하였는데 많은 도움이 되었습니다. 정말 비슷한 프로젝트라 생각했는데 최신 LLM을 활용하니까 정확도가 높게 잘 나오더라구요.
나라에서 제공해주는 AI 학습용 데이터로 카드사 데이터가 약 1억개가 넘었는데 이 분량의 데이터도 빠르게 분석할 수 있는 프로젝트를 해냈다는 것이 매우 뿌듯합니다.


AI가 참 신기하고 재밌으면서도 개발자한텐 적인 것 같습니다. 직설적으로 AI의 등장으로 취업난이 가속화되고 있기 때문에 마냥 유쾌하진 않습니다. 그래도 새로운 기술의 등장에 움츠러들기보단 더욱 적극적으로 활용해보는 것이 좋은 것 같습니다.

퉁퉁퉁 사후르의 가질 수 없다면 부숴버리겠단 마인드로 AI를 활용할 수 있는 개발자가 되어야겠다는 생각을 가질 수 있는 프로젝트였습니다.

profile
아무것도 안해서 유죄 판결 받음

0개의 댓글