C#만으로 웹 페이지 본문 추출하기: AI 워크로드를 위한 현실적인 접근

남정현·2025년 10월 24일
0

Quick Stack

목록 보기
4/5
post-thumbnail

사진: UnsplashRicky Turner

AI 기반 시스템, 특히 RAG(Retrieval-Augmented Generation) 구조를 구현하다 보면 웹에서 수집한 문서의 품질이 모델 성능에 큰 영향을 미친다는 걸 실감하게 됩니다. 특히 뉴스나 블로그처럼 HTML로 구성된 페이지에서 본문만 정확히 추출하는 작업은 생각보다 까다롭습니다.

많은 예제나 도구들이 Python이나 Playwright 같은 브라우저 자동화 도구에 의존하지만, C# 개발자로서 저는 가능한 한 .NET 생태계 안에서 해결해보고 싶었습니다.

🧠 왜 본문 추출이 중요한가?

RAG 시스템은 검색된 외부 문서를 기반으로 답변을 생성합니다. 그런데 HTML 문서에는 광고, 메뉴, 댓글, 추천 글 등 모델에게 불필요한 정보가 너무 많습니다. 이런 노이즈를 제거하고 핵심 콘텐츠만 추출하는 전처리는 필수입니다.

🛠️ C#으로 가능한 도구들

✅ SmartReader

SmartReader는 Readability 알고리즘을 기반으로 웹 페이지에서 주요 기사나 본문을 추출해주는 라이브러리입니다. HTML을 직접 파싱하지 않고도 꽤 괜찮은 결과를 얻을 수 있습니다. 내부적으로는 AngleSharp을 사용하기 때문에, 웹 브라우저같은 무거운 외부 종속 요소 없이 빠른 처리가 가능합니다.

✅ ReverseMarkdown

본문을 추출한 뒤에는 HTML을 마크다운으로 변환해야 합니다. 이때 ReverseMarkdown을 사용하면 HTML을 깔끔하게 마크다운으로 바꿔줍니다.

💻 코드 예시

예를 들어 다음과 같이 네이버 뉴스의 본문을 추출하는 시도를 해볼 수 있겠습니다.

var url = "https://n.news.naver.com/article/001/0014522039";
var html = await new HttpClient().GetStringAsync(url);

var reader = new SmartReader.Reader(url, html);
var article = reader.GetArticle();

var converter = new ReverseMarkdown.Converter();
var markdown = converter.Convert(article.Content);

markdown.Dump(); // LINQPad에서 마크다운 확인

SmartReader는 내부적으로 PlayWright가 아닌 AngleSharp이라는, 자바스크립트 엔진은 제외한 순수 HTML 기반 라이브러리를 사용합니다.

AngleSharp은 C#에서 HTML 문서를 파싱하고 DOM 구조를 탐색할 수 있게 해주는 라이브러리로, Python의 BeautifulSoup처럼 웹 페이지의 구조를 분석하고 필요한 정보를 추출하는 데 사용됩니다. 둘 다 브라우저 없이 HTML을 다룰 수 있다는 점에서 유사하지만, AngleSharp은 CSS 선택자나 DOM 조작 기능이 더 풍부해서 웹 브라우저처럼 HTML을 다룰 수 있습니다.

⚠️ 완전한 솔루션은 아니지만…

물론 한계는 있습니다.

  • 일부 웹사이트는 JavaScript로 콘텐츠를 로딩하기 때문에 SmartReader로는 본문을 추출하지 못합니다.
  • HTML 구조가 복잡하거나 비표준인 경우, 추출 결과가 부정확할 수 있습니다.
  • Playwright처럼 렌더링된 DOM을 가져오는 방식에 비해 정밀도는 떨어질 수 있습니다.

하지만 단순한 뉴스 기사나 블로그 페이지를 대상으로 할 때는 충분히 실용적인 수준의 결과를 얻을 수 있습니다. 특히 C# 환경에서 빠르게 테스트하거나 프로토타입을 만들 때는 매우 유용합니다.

✨ 마무리하며

AI 시스템을 구축할 때 모든 걸 완벽하게 처리할 수는 없습니다. 중요한 건 현재 환경에서 최선의 방법을 찾고, 그 효용성을 검증하는 과정입니다. C#만으로도 웹 페이지 본문 추출이라는 과제를 어느 정도 해결할 수 있다는 점에서, 이 접근은 충분히 의미 있다고 생각합니다.

0개의 댓글