왜 하나의 RAG만으로는 부족했을까: Jira 백로그 분석을 위한 멀티 RAG 파이프라인 구축
요약
Jira 백로그 분석기를 구축하며 단일 RAG 시스템의 한계를 극복하기 위해 멀티 RAG 파이프라인을 도입한 사례를 다룹니다. 프로젝트 지식을 인도된 사항, 시스템 작동 방식, 프로젝트 방향성이라는 세 가지 범주로 분리하여 검색 품질을 높였습니다.
핵심 포인트
- 단일 RAG는 일반적이고 최신 정보가 반영되지 않은 답변을 생성할 위험이 있음
- 소프트웨어 프로젝트 지식은 성격에 따라 서로 다른 조직적 기억으로 취급해야 함
- 지식 베이스를 세 가지 역할(인도 사항, 시스템 작동, 프로젝트 방향)로 분리하여 구축
- 멀티 RAG 구조를 통해 컨텍스트 제공량보다 검색 품질 향상에 집중
대규모 언어 모델 (Large language models)은 당신이 제공하는 컨텍스트만큼만 성능을 발휘합니다. LLM 기반의 Jira 백로그 분석기 (Jira Backlog Analyzer)를 구축하면서, 저는 단순히 검색 증강 생성 (Retrieval-Augmented Generation, RAG)을 추가하는 것만으로는 충분하지 않다는 것을 배웠습니다. 진정한 돌파구는 서로 다른 유형의 프로젝트 지식을 서로 다른 종류의 조직적 기억 (organizational memory)으로 취급하는 데서 왔습니다.
유용한 정보가 아닌 좋은 추천이 문제일 때
저의 Jira 백로그 분석기 (Jira Backlog Analyzer)의 목표 중 하나는 꽤 간단했습니다. 프로젝트 매니저들이 수백 개의 백로그 항목을 이해할 수 있도록 돕는 것이었습니다. 이 분석기는 관련된 Jira 티켓들을 그룹화하고, 잠재적인 중복 항목을 표시하며, 기술적 트렌드와 우선순위를 다루는 경영진 요약본 (executive summaries)을 생성합니다.
첫 번째 프로토타입은 기대했던 것보다 더 잘 작동했습니다. 가공되지 않은 Jira 티켓 데이터만 주어져도, LLM은 클러스터 (clusters)를 요약하고, 중복된 이슈를 찾아내며, 심지어 다음에 무엇을 해야 할지 제안할 수도 있었습니다.
하지만 그 제안들 중 상당수는 쓸모가 없을 정도로 일반적이었습니다.
느린 API 응답 시간에 관한 티켓 클러스터를 예로 들어보겠습니다. 모델은 다음과 같이 권장했습니다: "응답 시간을 개선하기 위해 쿼리 성능 최적화를 고려하십시오.". 합리적으로 들립니다. 하지만 이미 두 번의 릴리스 전에 응답 시간을 절반으로 줄여준 캐싱 레이어 (caching layer)가 배포된 상태였습니다. 그 권장 사항이 정확히 틀린 것은 아니었지만, 단지 최신 정보가 아니었을 뿐입니다.
그런 일이 계속 발생했습니다. 모델은 현재의 프로그램 인크리먼트 (program increment)가 이미 신뢰성 (reliability)에 집중하고 있다는 사실을 모른 채 보안 작업을 우선시하라고 제안하곤 했습니다. 말투는 항상 자신감 있게 들렸습니다. 하지만 실질적인 내용은 없는 경우가 많았습니다. 읽기에는 좋았지만, 실제로는 거의 아무런 도움이 되지 않았습니다.
그래서 저는 대부분의 사람들이 이 시점에서 하는 일을 했습니다. 바로 RAG를 추가하는 것이었습니다. 도움이 되긴 했지만, 절반의 성공에 그쳤습니다.
단일 지식 베이스의 한계
대부분의 RAG 튜토리얼은 당신에게 하나의 문서 더미가 있다고 가정합니다. 가장 관련성 높은 청크 (chunks)를 검색하여 프롬프트 (prompt)에 집어넣고, 모델이 나머지를 처리하도록 맡깁니다. 이는 많은 질의응답 (question-answering) 유스케이스 (use cases)에서 잘 작동합니다. 하지만 소프트웨어 프로젝트는 그보다 훨씬 더 복잡합니다. 모든 프로젝트 지식이 동일한 질문에 답하기 위해 존재하는 것은 아니기 때문입니다.
제가 실제로 프로젝트 매니저가 알아야 할 것이 무엇인지 앉아서 고민해 보았을 때, 그것은 세 가지 범주로 나뉘었습니다:
- 무엇이 이미 인도(delivered)되었는가?
- 시스템이 실제로 어떻게 작동하는가?
- 프로젝트가 어디로 향하고 있는가?
이것들은 매우 다른 세 가지 질문이며, 단일 문서 컬렉션 (document collection)으로는 이 모든 질문에 제대로 답할 수 없습니다. 그래서 저는 하나의 거대한 지식 베이스 (knowledge base) 대신, 프로젝트 지식을 세 개의 별도 RAG 소스 (sources)로 분리했습니다. 그 결정 하나가 그 어떤 양의 추가 컨텍스트 (context)를 제공하는 것보다 출력 품질 향상에 더 큰 도움이 되었습니다.
세 개의 RAG, 세 가지의 서로 다른 역할
어느 시점부터 저는 RAG를 단순히 "추가 문서"로 생각하는 것을 멈추고, 각 소스를 서로 다른 종류의 조직적 기억 (organizational memory)으로 생각하기 시작했습니다.
역사적 기억 (Historical Memory): 릴리스 노트 (Release Notes)
릴리스 노트는 이미 출시된 것들, 즉 완료된 기능, 종료된 버그, 인도된 역량에 대한 기록입니다. 이를 분석기 (analyzer)에 입력하면, 모델은 이미 완료된 작업을 추천하는 일을 멈춥니다. 또한 모델은 모든 티켓 (ticket)을 개별적으로 판단하는 대신, 프로젝트가 릴리스마다 어떻게 진화해 왔는지에 대해 추론할 수 있습니다.
운영적 기억 (Operational Memory): 프로그램 컨텍스트 (Program Context)
이 부분은 정의하기가 더 까다로운데, 왜냐하면 숙련된 팀원들이 머릿속에 담고 다니면서 티켓에 거의 작성하지 않는 내용들이기 때문입니다. 프로그램 목표, 시스템 아키텍처 (architecture), 엔지니어링 제약 사항 (constraints), 이해관계자 (stakeholder)의 우선순위, 아무도 정의하려 들지 않는 도메인 전문 용어 (domain jargon) 등이 여기에 해당합니다. 이것이 없다면, 모델은 티켓에 무엇이 적혀 있는지는 말해줄 수 있어도 왜 그것이 중요한지는 말해주지 못합니다. 프로그램 컨텍스트를 추가하자 클러스터 설명 (cluster descriptions)이 눈에 띄게 날카로워졌는데, 모델이 마침내 티켓을 그것이 속한 더 큰 시스템과 연결할 수 있게 되었기 때문입니다.
전략적 기억 (Strategic Memory): FY26 테마 (FY26 Themes)
마지막 RAG는 로드맵 정보와 현재 계획 주기(planning cycle)를 위한 전략적 테마(strategic themes)입니다. 릴리스 노트(Release notes)가 과거를 돌아본다면, 이 RAG는 미래를 바라봅니다. 결과적으로 이 데이터는 경영진 요약(executive summaries)에서 가장 중요한 역할을 하게 되었습니다. 분석기가 단순히 백로그(backlog)에 무엇이 있는지를 설명하는 대신, 티켓(ticket) 클러스터가 프로그램이 나아가고자 하는 방향과 실제로 일치하는지 그 비중을 따져볼 수 있게 된 것입니다. 권장 사항(Recommendations)은 단순히 이력을 반영하는 것을 넘어 목적지를 반영하기 시작했습니다.
내부 구조: 하나의 인덱스가 아닌 세 개의 인덱스
각 소스는 자신만의 벡터 인덱스(vector index)에 존재합니다. 릴리스 노트, 프로그램 문서, 로드맵 문서는 각각 청킹(chunking) 및 임베딩(embedding)되어, 현재 실행 중인 작업의 범위(scope)에 맞춰진 LangChain 검색 체인(retrieval chain)을 통해 호출됩니다. 이들을 하나의 인덱스로 병합하는 대신 분리하여 유지하는 것이 매우 중요하다는 사실이 밝혀졌습니다. 결합된 인덱스에서 유사도 검색(Similarity search)을 수행하면, 우연히 청크(chunk)가 가장 많은 소스가 표면으로 드러나는 경향이 있으며, 이는 대개 로드맵 테마를 산더미 같은 릴리스 노트 텍스트 아래에 파묻어 버립니다. 작업별로 범위가 지정된 세 개의 작은 인덱스는 하나의 커다란 인덱스가 결코 따라올 수 없는 정밀한 검색을 수행합니다.
모든 프롬프트에 모든 RAG가 필요한 것은 아니다
여기 제가 깨닫는 데 다소 시간이 걸렸던 교훈이 있습니다. 컨텍스트(context)가 많다고 해서 반드시 더 좋은 컨텍스트인 것은 아니라는 점입니다.
처음에는 모든 프롬프트에 세 가지 RAG 소스를 전부 집어넣었습니다. 철저해 보였습니다. 하지만 실제로는 유용한 컨텍스트가 노이즈(noise)와 섞여 희석될 뿐이었습니다.
그래서 저는 소스를 작업에 맞춰 매칭했습니다:
- 중복 분석(Duplicate analysis)은 릴리스 이력에 의존합니다. 이미 수행된 작업이 무엇인지 아는 것이 두 티켓이 동일한 작업을 설명하는지 판단하는 기준이 되기 때문입니다.
- 클러스터 분석(Cluster analysis)은 프로그램 컨텍스트와 FY26 테마에 의존합니다. 이를 통해 모델이 왜 특정 티켓 그룹이 함께 묶이는지 실제로 설명할 수 있습니다.
- 경영진 요약(Executive summaries)은 기술적 발견 사항을 프로그램의 방향성과 연결하기 위해, 로드맵 테마에 가중치를 두어 세 가지 소스 모두를 활용합니다.
이런 방식으로 프롬프트 (prompts)를 줄이는 것은 출력 품질을 향상시키는 동시에 크기를 더 작게 만들었습니다. 때로는 더 나은 엔지니어링 방법이 정보를 더 많이 추가하는 것이 아닐 수도 있습니다. 그것은 올바른 정보를 추가하고 나머지는 제외하는 것입니다.
| 작업 (Task) | 기본 RAG (Primary RAG) | 배경 (Background) |
|---|---|---|
| 클러스터 명명 및 PM 권장 사항 | 2026_theme.md | project_context.md |
| ... |
예상치 못한 이점
평가 과정에서 한 가지 놀라운 점이 있었습니다. 저는 자동화된 LLM 심사위원 (LLM judges)과 인간 검토자 (human reviewers) 모두를 통해 여러 LLM의 출력을 비교하고 점수를 매겼습니다.
심사위원들이 품질에 대해 항상 서로 일치하는 의견을 가진 것은 아니었지만, 한 가지에는 모두 동의했습니다. 실제 프로젝트 지식에 근거한 (grounded in) 출력이 일반적인 소프트웨어 조언보다 매번 더 뛰어났다는 점입니다.
그리고 개선 사항은 요약이 더 길어지거나 상세해진 것이 아니었습니다. 요약이 더 구체적으로 변한 것이었습니다.
분석기가 단순히 "시스템 성능을 개선하십시오"라고 권장하는 대신, 실제 로드맵 우선순위, 이미 출시된 릴리스(release), 또는 이미 진행 중인 엔지니어링 이니셔티브 (engineering initiative)와 권장 사항을 연결할 수 있었습니다. 프로젝트 매니저들이 실제로 원하는 것은 더 많은 단어가 아니라 바로 이러한 구체성입니다.
실용적인 디자인 패턴
저는 제가 구축한 것을 더 이상 "RAG를 추가하는 것"이라고 생각하지 않습니다. 저는 이것을 조직의 지식 (institutional knowledge)을 정리하는 것이라고 생각합니다.
- 역사적 지식 (Historical knowledge)은 우리가 어디에 있었는지를 답합니다.
- 운영 지식 (Operational knowledge)은 시스템이 어떻게 작동하는지를 설명합니다.
- 전략적 지식 (Strategic knowledge)은 우리가 어디로 가고 있는지를 기술합니다.
이러한 책임들을 분리함으로써 프롬프트 설계 (prompt design)가 더 단순해졌고, 불필요한 컨텍스트 (context)를 많이 제거할 수 있었으며, 프로젝트에 실제로 필요한 것과 일치하는 권장 사항을 도출할 수 있었습니다.
이는 Jira 백로그에만 국한된 이야기가 아닙니다. 모든 엔터프라이즈 LLM 애플리케이션에는 아마도 정책, 운영 절차, 역사적 기록, 미래 계획 등 여러 범주의 조직 지식이 떠다니고 있을 것이며, 각 범주는 하나의 공유된 인덱스 (shared index)에 한꺼번에 쏟아붓기보다는 각자의 고유한 검색 전략 (retrieval strategy)을 가질 가치가 있을 것입니다.
이러한 시스템이 성숙해짐에 따라, 저는 진정한 이득이 더 많은 문서를 검색하는 것에서 오는 것이 아니라, 검색된 내용을 더 사려 깊게 조직화하는 것에서 올 것이라고 생각합니다. 하나의 RAG는 시작하기에 좋은 지점입니다. 하지만 그것이 항상 여러분이 도달해야 하는 최종 목적지는 아닙니다.
RAG 파일은 GitHub에서 확인할 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기