My AI Smarteasy 사용자 정의 AI 에이전트 – 일타 강사 저스틴 – 이번 생 마지막 양자역학 강의

안녕하세요, 일타 강사 저스틴입니다! 🎓 오늘은 판다스 스튜디오님의 유튜브 영상 ‘아래아 한글(HWP) 문서 RAG/ 문서에서 Table(표) 인식 (Markdown 변환) – 랭체인(LangChain), 올라마(Ollama), 허깅페이스(Huggingface)‘을 분석해봅니다. 이 강의를 통해 여러분은 아래아 한글 문서의 숨겨진 보물, 특히 ‘표’ 데이터를 RAG 모델이 똑똑하게 이해하도록 만드는 비법을 터득하게 될 겁니다! 여러분의 RAG 프로젝트 성공률을 확 높여줄 비장의 무기, 지금부터 함께 파헤쳐 보시죠!

아래아 한글(HWP) 문서, RAG의 첫 관문! 🚪

자, 여기 별표 세 개 치세요! 🌟🌟🌟 대한민국에서 정부나 공공기관 문서는 거의 대부분 ‘아래아 한글’, 즉 HWP 파일로 만들어진다는 사실, 다들 아시죠? 그런데 이 중요한 HWP 문서를 RAG(검색 증강 생성) 모델에 잘 먹이는 게 생각보다 쉽지 않습니다.

원본 영상에서는 ragchain이라는 아주 유용한 프로젝트를 활용합니다. 특히 윈도우 환경에서는 win32_hwp_loader를, 리눅스나 맥에서는 hwp_loader를 써야 한다는 점, 이거 중요해요! 마치 각자 맞는 옷이 있듯이, OS별로 적절한 로더를 써야 문서가 우리 RAG 모델에게 잘 전달됩니다. 그리고 ragchain을 쓰려면 .env 파일에 LINKER_TYPE과 JSON_LINKER_PATH를 설정하는 환경 변수 작업이 필요하다는 점도 꼭 기억하세요.

이렇게 로더를 활용하면 HWP 문서가 랭체인(LangChain)의 Document 객체로 변환됩니다. 여기서 잠깐! 원본 영상에서는 5페이지짜리 외교부 공고문이 10개의 문서 객체로 분할되는 것을 보여줬는데요. 왜 그럴까요? 바로 문서 안에 있는 표 같은 구조화된 데이터들이 별도의 객체로 쪼개질 수 있기 때문입니다. 마치 큰 덩어리 음식을 잘게 썰어서 먹기 좋게 만드는 것과 같아요. 이해되시죠?

골칫덩이 ‘표(Table)’ 데이터, 어떻게 먹일까? 🍽️

많은 분들이 여기서 헷갈리시는데요… 아래아 한글 문서의 ‘표’ 데이터, 이게 RAG 모델에겐 양날의 검입니다. 표 안에는 핵심 정보가 가득하지만, 일반적인 문서 로더로 읽어 들이면 HTML 태그 덩어리로 들어와 버려요.

생각해 보세요. 중요한 정보는 딱 ‘한 줄’인데, 그걸 감싸는 HTML 태그가 수십 줄이라면? 우리 모델은 뭐가 중요한지 헷갈리고, 쓸데없는 태그들 때문에 ‘토큰’만 낭비하게 됩니다. 마치 맛있는 알맹이는 작은데 껍데기가 너무 많은 과일 같은 거죠! 불필요한 토큰은 RAG 모델의 성능을 떨어뜨리고, 심하면 엉뚱한 답변, 즉 ‘환각(Hallucination)’을 유발하는 주범이 되기도 합니다. 이거 시험에 나와요!

원본 영상에서는 이 문제를 해결하기 위한 두 가지 핵심 전략을 제시합니다.

  1. HTML 태그 제거: 순수한 텍스트만 추출하는 방법. (장점: 토큰 감소 / 단점: 표 구조 손실)
  2. HTML 태그 유지: 구조를 살리지만, 불필요한 토큰이 많아져 검색 정확도가 떨어질 수 있음.

하지만 여기서 저스틴의 비장의 무기가 등장합니다! 바로 ‘마크다운(Markdown) 변환’ 입니다! HTML 태그의 복잡한 껍데기는 벗겨내고, 표의 핵심 구조는 깔끔하게 살리는 스마트한 방법이죠. 마치 복잡한 설명서 대신 핵심만 요약한 안내서 같달까요? 마크다운으로 변환하면 불필요한 태그는 줄고, 표의 구조는 명확해져서 우리 RAG 모델이 정보를 훨씬 더 잘 이해하게 됩니다.

RAG 체인 구축의 핵심 요소들! 🏗️

이제 HWP 문서와 표 데이터를 어떻게 처리할지 알았으니, 실제 RAG 체인을 구축해봐야겠죠? 원본 영상에서는 다음과 같은 구성 요소들을 활용했습니다.

  • 벡터 스토어: Chroma DB (정보를 저장하는 똑똑한 도서관)
  • LLM 모델: Ollama를 통해 실행되는 구글의 Gemma 2 (우리 질문에 답변해 줄 똑똑한 비서)
  • 임베딩 모델: Hugging Face의 한국어 sbert 임베딩 모델 (문서와 질문을 이해하기 쉬운 언어로 번역해 줄 통역사)
    • 이 모델을 선택한 이유는 긴 시퀀스 길이를 허용하기 때문입니다. 긴 글도 척척 이해한다는 뜻이죠!
  • 토크나이저: 임베딩 모델 학습에 사용된 토크나이저를 그대로 사용 (번역 기준을 통일하는 것과 같죠!)
  • 텍스트 스플리터: RecursiveCharacterTextSplitter
    • chunk_size=500chunk_overlap=50으로 설정하여 문서를 토큰 개수 기준으로 쪼개고 겹치게 만듭니다. 마치 긴 소설을 요약본으로 만들 때, 앞뒤 내용이 끊기지 않도록 살짝 겹쳐주는 것과 같습니다.
  • 리트리버: 유사도 높은 상위 2개의 문서를 검색 (저스틴의 족집게 강의처럼 가장 중요한 것만 쏙쏙 뽑아오는 거죠!)
    • 여기서 중요한 점은, 너무 많은 문서를 가져오면 불필요한 정보가 섞여 오히려 환각을 유발할 수 있기 때문에, 정확하고 구체적인 질문에는 적은 수의 문서가 더 효과적일 수 있다는 겁니다.
  • 프롬프트 템플릿: 기본적인 RAG 템플릿을 적용합니다.
  • 후처리: 검색된 문서 중 중복되는 내용을 제거하여 모델에 전달되는 컨텍스트의 효율성을 높입니다.

표 데이터를 위한 RAG, 성공과 실패의 갈림길 🎯

처음에는 마크다운 변환 없이 일반적인 방식으로 RAG 체인을 구성해서 몇 가지 질문을 던져봤습니다.

  • 성공 사례: “파견 기간은 얼마인가요?” 모델은 “원칙적으로 4에서 6개월이나, 기구 사정에 따라 변동 가능하다”고 정확히 답변했습니다.
  • 성공 사례: “필기 시험이 있는 날짜는 언제인가요?” 모델은 “2024년 6월 4일 화요일”이라고 정확하게 답변했습니다.

여기까지는 문제가 없었습니다. 그런데 문제가 터진 건 바로 ‘표’ 데이터가 포함된 질문에서였죠. “국제이주기구 파견에 대한 정보를 알려주세요”라고 질문하니, 모델은 “해당 기구에 대한 정보를 포함하고 있지 않다”고 답변했습니다. 😱

자, 여기 별표 세 개! 🌟🌟🌟 왜 이런 일이 발생했을까요? 바로 ‘표’ 데이터가 HTML 태그 덩어리로 들어가 있었기 때문입니다. “국제 이주 기구”라는 핵심 키워드가 수많은 HTML 태그와 공백 속에 묻혀버려, 임베딩 모델이 유사도를 제대로 계산하지 못하고 검색에서 누락된 것이죠. 마치 보물찾기 게임에서 보물이 쓰레기 더미 속에 파묻혀버린 것과 같습니다. 감 오시나요?

마크다운 변환, RAG의 신의 한 수! ✨

이 문제를 해결하기 위해 원본 영상에서는 ‘HTML 표를 마크다운으로 변환’하는 비법을 적용합니다.

적용 과정:

  1. BeautifulSoup을 이용해 HTML 문자열을 파싱해서 HTML 객체로 만듭니다.
  2. pandas.read_html 함수로 HTML 테이블을 DataFrame으로 변환합니다.
  3. DataFrame의 to_markdown() 함수를 사용해 깔끔한 마크다운 형식으로 바꿔줍니다.

그 결과는 놀라웠습니다! 복잡한 HTML 형식일 때는 토큰 수가 351개였던 표 데이터가, 마크다운으로 변환하니 203개로 거의 절반 가까이 줄어들었습니다. 토큰 수가 줄어든다는 건, LLM이 더 효율적으로 정보를 처리할 수 있고, 비용도 절감된다는 뜻이죠!

이렇게 마크다운으로 변환된 표 데이터를 다시 RAG 체인에 넣어 질문을 던졌습니다. “국제이주기구 파견은 언제 하는지”라고 물으니, “국제 이주 기구 파견은 6개월 동안 페루에서 이루어집니다”라고 정확하게 답변하는 것을 확인할 수 있었습니다. 아하! 드디어 표 데이터 속 핵심 정보를 모델이 제대로 찾아낸 거죠!

텍스트와 표를 구분하는 스마트한 청킹 전략 🧠

마지막으로 원본 영상에서는 더욱 똑똑한 청킹(Chunking) 전략을 제시합니다. 단순히 문서 전체를 토큰 기준으로 쪼개는 것이 아니라, 문서 객체의 메타데이터에 있는 page_type 정보를 활용하는 겁니다.

  • page_type이 ‘테이블(table)’인 경우: 앞서 배운 HTML->마크다운 변환 함수를 적용해서 page_content를 업데이트합니다.
  • page_type이 ‘텍스트(text)’인 경우: 그대로 유지합니다.

이렇게 문서의 각 부분을 성격에 맞게 전처리한 후, RecursiveCharacterTextSplitter를 적용하여 청크를 나눕니다. 마치 텍스트는 텍스트대로, 표는 표대로 가장 효율적인 형태로 가공한 후에 우리 모델에게 전달하는 것과 같습니다. 이 과정을 거치면 총 26개의 문서 청크가 생성되며, 이는 RAG 모델이 표 관련 질문에도 더욱 정확하게 답변할 수 있는 기반이 됩니다.

잠깐, 여기서 퀴즈! 💡 만약 여러분이 윈도우 노트북에서 이 실습을 한다면 속도가 왜 느릴까요? (정답: LLM 모델을 로컬에서 구동하면 자원 소모가 크기 때문입니다!) 그래서 오픈AI API나 Groq 같은 서비스를 활용하거나, 애플 실리콘(M1/M2) 칩이 탑재된 장비를 사용하면 훨씬 쾌적한 환경에서 실습할 수 있다는 꿀팁도 영상에서 알려주고 있습니다.

오늘의 정리

오늘 판다스 스튜디오님의 글을 함께 분석해봤는데요, 핵심은 다음과 같습니다.

  1. HWP 문서 처리: ragchain 프로젝트를 활용하여 아래아 한글 문서를 RAG 모델에 효과적으로 로드할 수 있습니다.
  2. 표 데이터의 함정: 문서 내 표 데이터를 HTML 태그 그대로 사용하면 토큰 낭비와 검색 정확도 저하로 RAG 성능이 떨어집니다.
  3. 마크다운의 힘: HTML 표를 마크다운으로 변환하면 표 구조는 유지하면서 토큰 수를 줄여 RAG 검색 정확도와 모델 답변 품질을 크게 향상시킬 수 있습니다.

특히 판다스 스튜디오님이 강조하신 “텍스트와 표의 특성을 이해하고 각 데이터 타입에 맞는 전처리 전략을 적용하는 것” 은 정말 중요합니다. 이것이야말로 RAG 모델의 성능을 한 단계 끌어올리는 핵심 비법입니다!

여러분도 HWP 문서를 다루는 RAG 프로젝트가 있다면, 오늘 배운 마크다운 변환 전략을 꼭 한번 적용해 보시길 추천드립니다! 분명 “아하!” 하는 순간을 경험하실 겁니다.

About the Author
(주)뉴테크프라임 대표 김현남입니다. 저에 대해 좀 더 알기를 원하시는 분은 아래 링크를 참조하세요. http://www.umlcert.com/kimhn/

Leave a Reply

*