소득세법 RAG 챗봇: 인프런 강의 따라 하기부터 나만의 개선까지 🤖
“많은 문서가 있을 때 어떻게 원하는 정보를 찾지?”
학교 관련 문서, 법 조항 등 양이 많은 문서의 경우 다시 찾는 일이 반복됐다. 검색 결과는 많지만, 정확히 필요한 조항에 바로 도달하기는 어려웠고, 용어가 조금만 달라져도 엉뚱한 문서를 보게 되는 일이 잦았다.

이때 우연히 인프런에서 세법 도메인에 LLM + RAG를 적용하고, 키워드 맵과 자동 평가까지 구현하는 강의를 보게 되었고, “이 구조를 그대로 따라 만든 뒤, 내 고민을 얹어보자”라는 생각으로 프로젝트를 시작했다.
인프런 강의 기반 설계: 세법 + RAG 구조 그대로 따라 하기 🎓
이번 챗봇의 뼈대는 인프런 강의를 기반으로 했다. 강의에서 다루는 구조는 크게 다음과 같았다.
- 세법 관련 문서를 벡터화해서 RAG 구조로 검색
- 사용자 질문과 문서 표현 사이의 간극을 줄이기 위한 키워드 맵
- LLM 답변 품질을 자동으로 평가하는 LLM 평가 파이프라인
- streamlit으로 UI를 만들고 streamlit cloud로 배포

RAG 구조와 전체 아키텍처 🛠️
강의에서는 소득세법이라는 도메인으로 확정한 후 RAG 구조를 전제로 설계했다.
- Word로 정리된 소득세법 관련 자료를 분할해 임베딩을 만들고 벡터DB에 저장한다.
- 사용자의 질문을 정규화한 뒤, 벡터 검색으로 관련 문단을 가져와 LLM의 컨텍스트로 넣는다.
- LLM은 항상 “소득세법 (XX조)에 따르면 …”처럼 조문 근거를 먼저 말하고, 2–3문장으로 요약한다.

UI는 Streamlit을 사용해 세션 기반 대화와 스트리밍 응답을 손쉽게 구현했고, 클라우드 환경에서도 별도 인프라 없이 배포할 수 있도록 했다.
핵심 기능 1: 키워드 맵 기반 질문 정규화 🧠
인프런 강의에서 특히 인상 깊었던 부분이 바로 키워드 맵이다.
사용자는 “사람”, “직장인”, “월급 받는 사람”처럼 질문하지만, 세법 문서에는 “거주자”, “근로소득자” 같은 표준 용어가 사용된다.
이 간극을 줄이기 위해, 강의에서 소개한 패턴처럼 “자연어 표현 → 세법 용어” 매핑을 만들어 검색 전에 질문을 정규화하는 구조를 그대로 적용했다.
- “사람 → 거주자” 같은 매핑을 키워드 맵에 정의했다.
- 사용자의 질문을 이 맵과 LLM 체인에 한 번 통과시켜 표준 용어로 정규화한 뒤, 그 결과를 벡터 검색에 사용했다.

이 구조를 사용한 뒤, 평가 지표에서 다음과 같은 개선이 나타났다.
- answer_helpfulness_score: 0.95 → 1.00
- answer_v_reference_score: 0.75 → 0.95
즉, 인프런 강의에서 제안된 키워드 맵 아이디어가 직접 테스트 해보니 꽤 효과적이었다.
키워드 맵 한계와 개선 방향: LLM 비중 ↓, 패턴 비중 ↑ 🤔
강의의 LLM을 많이 활용해 키워드 맵을 확장하는 방식에는 현실적인 한계도 있었다.
- 정확도: 애매한 표현에서 잘못된 매핑이 생기면, 오히려 검색 품질을 떨어뜨린다.
- 비용: 맵을 생성·보완할 때마다 LLM 호출이 늘어나 토큰 비용이 커진다.
그래서 앞으로는 다음과 같은 개선을 고민 중이다.
- 확실한 매핑(“사람 → 거주자”, “월급 → 근로소득” 등)은 정규식/룰 기반으로 고정해두고, 단순 치환으로 처리한다.
- 새로운 표현이나 애매한 케이스는 사용 로그와 도메인 문서를 직접 보면서, 사람이 사전에 추가하는 식으로 천천히 확장한다.


결국 키워드 맵 자체는 유지하되, LLM 자동 확장 비중을 줄이고, 규칙 기반 + 도메인 검수 비중을 높이는 방향으로 리팩터링할 계획이다.
핵심 기능 2: Chat History를 고려한 세법 Q&A 💬
세금 질문은 한 번에 끝나지 않는다.
- “근로소득만 있는 사람은 어떻게 돼요?”
- “그러면 퇴직금은요?”
- “그럼 이 경우에는 원천징수로 끝나는 건가요?”
이처럼 후속 질문이 앞 대화에 의존하는 경우가 많아서, 세션별 대화 히스토리를 관리하고 “이번 질문을 이전 맥락을 포함한 standalone 질문으로 재작성하는 구조”를 도입했다.
- 대화 로그를 모아 LLM으로 문맥을 포함한 질문을 다시 만들고, 이를 벡터 검색에 사용한다.
- 사용자가 “그럼 이건요?”라고만 물어도, 이전 질의를 참고해 올바른 소득세법 조항을 찾을 수 있게 했다.

이 구조 덕분에 챗봇이 단발성 Q&A를 넘어, 어느 정도 “세무 상담 같은 대화 흐름”을 가지게 되었다.
핵심 기능 3: Few-shot으로 답변 스타일 고정 ✍️
법쪽 도메인에서는 신뢰성을 위해 답변 스타일의 일관성과 출처 명시가 특히 중요하다. 그래서 config에 몇 가지 대표 Q&A를 few-shot 예시로 심어두었다.
- 소득 구분
- 과세 기간
- 원천징수 영수증 발급 시기
공통 규칙은 다음과 같다.
- 항상 “소득세법 (XX조)에 따르면 …”처럼 조문과 근거를 먼저 언급한다.
- 2–3문장 이내로 핵심만 답하고, 과도한 추론이나 가정은 줄인다.
- 문서 범위를 벗어나는 질문이면 그 사실을 명시한다.

이렇게 답변 형식을 고정해두니, 같은 질문 유형에 대해 항상 비슷한 톤과 구조로 응답해 신뢰도가 높아졌다.
LLM 평가 파이프라인: 강의의 평가 구조를 그대로 적용 🔍
인프런 강의에서 매우 좋았던 부분이 바로 LLM을 평가하는 부분 이였다. 질문과 예시 답변을 통해 LangSmith로 LLM의 답변이 올바른지 판단 후에 점수를 매기는 식이었다.
강의에 나온대로 세법 관련 질문 20개 내외를 모아, 각 질문의 “기대 답변”과 “참조해야 할 컨텍스트(조문)”를 LLM과 함께 데이터셋으로 만들었다.
- 각 실행에 대해 다음 지표를 측정했다.
- answer_evaluator: 정답과의 유사도
- answer_helpfulness_evaluator: 사용자 관점에서의 유용성
- answer_hallucination_evaluator: 근거 없는 내용 여부
이 구조 덕분에 프롬프트나 키워드 맵을 수정했을 때, 정확도·유용성·환각이 어떤 식으로 변했는지 빠르게 비교할 수 있었다.
LLM 평가 한계와 도메인 문서 검수 계획 📄
여러 번 평가를 돌려보면, 지표상으로는 괜찮은데 세법 관점에서 보면 미묘하게 아쉬운 답변들도 있었다.
- 표현은 맞지만 조문 뉘앙스를 애매하게 바꿔버리는 경우
- 중요한 예외 규정을 언급하지 않아 오해의 소지가 생기는 경우
이런 케이스는 LLM 평가도 “그럭저럭 괜찮다”고 판단하는 일이 있어서, 자동 평가만으로는 불안함이 남았다.
그래서 앞으로는 다음과 같은 방향으로 보완할 계획이다.
- 자동 평가로 지표가 낮거나 중요한 유형(과세 여부, 신고 의무, 기한 등)에 해당하는 질문을 우선 추려낸다.
- 소득세법 원문이나 신뢰할 수 있는 해설 문서를 직접 보면서, 해당 질문에 대한 챗봇 답변을 사람이 수동으로 검수·수정한다.
- 이렇게 정제된 Q&A를 다시 few-shot 예시나 평가 데이터셋에 반영해, 다음 버전 모델의 기준으로 삼는다.
즉, 인프런 강의에서 배운 자동 평가 구조는 유지하되, 세법이라는 도메인 특성상 사람이 문서를 보면서 마지막 책임을 지는 레이어를 하나 더 쌓으려는 것이다.
전체 회고: 강의를 따라 만든 프로젝트에서 고민을 통해 더 나은 챗봇으로 🎯
이번 소득세법 RAG 챗봇 프로젝트는 한 문장으로 정리하면,
“인프런 강의에서 본 구조를 세법 도메인에 그대로 적용해 보고, 실제 데이터와 비용·정확도 이슈를 겪으면서 나만의 개선 포인트를 찾는 과정”이었다.
- 강의에서 제안한 RAG 구조, 키워드 맵, LLM 평가 파이프라인을 그대로 따라 하며 전체 플로우를 빠르게 익혔다.
- 실제 소득세법 데이터에 적용해 보면서, 표현 불일치와 자동 평가가 큰 도움을 주는 동시에, 정확도·비용 측면에서는 패턴 기반 처리가 필요하며 도메인 검수는 필수적이라는 것도 경험했다.

이제 다음 단계는,
- 키워드 맵을 LLM 중심에서 패턴 중심 구조로 재구성하고,
- LLM 평가에 도메인 문서를 추가해,
“강의를 잘 따라 만든 프로젝트”에서 한 단계 더 나아가 도메인 지식을 더해 수정하고 리팩토링을 더해 더 쓸모 있는 세금 특화 챗봇으로 성장시키는 것이다.
강의 링크: https://inf.run/Ggqd2