자바스크립트로 HTML 코드에서 순수한 텍스트만 추출하려면 어떤 방법을 써야 할까?
우리는 항상 서버단으로 데이터를 보낼 때 HTML이 포함된 본문 내용과 텍스트로만 이루어진 데이터를 함께 보내줘야 한다. 지금껏 기존의 다른 작업자분이 만들어놓은 코드를 가져와서 쓰고 있었는데 갑자기 이 코드는 어떻게 구성되어 있는건지 궁금해져서 글을 써본다.
function getPlainTextFromHTML(html = "") {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
let allText = "";
const textNodes = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
while (textNode = textNodes.nextNode()) {
allText += textNode.nodeValue.trim() + ' ';
}
return allText;
}
1. html 매개변수로 전달받은 HTML 문자열을 DOMParser를 이용해 DOM 구조로 변환
2. TreeWalker 객체를 생성해 DOM 내 텍스트 노드만 순회하며 가져온 값을 allText 변수에 저장
3. 누적된 텍스트를 호출 지점으로 반환
코드 내에 몇 가지 생소한 메소드가 있으니 알아보자.
DOMParser()와 parseFromString()
문자열로 된 HTML, XML 또는 SVG 같은 데이터를 DOM(Document Object Model) 구조로 변환할 때 사용하는 객체와 메소드다. 문자열로 된 HTML은 단순 문자열이기 때문에 자바스크립트로 조작할 수 없지만 파싱하고 난 후는 자바스크립트로도 조작이 가능하게 된다.
parseFromString()의 두 번째 매개변수는 파싱할 데이터의 MIME 유형을 지정한다.
알맞는 유형을 지정하지 않으면 파싱이 제대로 이루어지지 않을 수 있다.
createTreeWalker()
자바스크립트에서 DOM 트리를 순회하는 데 쓰이는 메소드로, 특정 기준에 맞는 노드만 선택해서 탐색하는 것도 가능하게 한다.
위의 기존 코드에서는 두 개의 매개변수를 전달하여 필터링을 시도했는데,
첫 번째 매개변수인 rootNode에는 body를, 두 번째 매개변수에는 NodeFilter.SHOW_TEXT를 전달했다. (텍스트 노드만 순회하도록 설정)
DOMParser 예외처리 추가
function getPlainTextFromHTML(html = "") {
try {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
let allText = "";
const textNodes = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT);
while (textNode = textNodes.nextNode()) {
allText += textNode.nodeValue.trim() + ' ';
}
return allText;
} catch (error) {
console.error("Error parsing HTML:", error);
return "";
}
}
DOMParser에 대해 알아보던 중 HTML 문자열이 잘못될 경우 파싱 에러가 날 수 있다는 정보를 알게 됐다.
예를 들면 클로징 태그의 누락이나 문법 오류가 있는 문자열을 파싱할 때 parsererror 라는 태그가 포함된 DOM이 반환된다고 한다.
기존의 코드는 파싱 에러에 대한 예외처리가 되어 있지 않아 try-catch 블록을 추가해줬다.
성능을 고려한 더 간단한 방법
function getPlainTextFromHTML(html = "") {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
if (!doc || doc.querySelector("parsererror"))
return "";
return doc.body.innerText.trim();
}
사실 복잡한 코드를 쓰지 않고도 innerText + trim()을 통해 빠르고 손쉽게 추출할 수 있다.
innerText 와 TreeWalker 각 방식은 장단점이 있는데, innerText를 이용하면 빠르고 직관적이게 텍스트를 추출할 수 있지만 노드 하나하나에 대해서는 제어할 수 없다. 그냥 무조건 한 번에 가져오는 게 목적일 때 사용하기 좋은 편. 그리고 화면에 표시되는 텍스트만을 반환하기에 숨겨진 요소의 텍스트는 제외된다고 한다.
TreeWalker를 사용하면 NodeFilter를 이용해 특정 유형의 노드를 필터링 할 수 있는 장점이 있지만 트리를 순차적으로 탐색하기 때문에 속도가 비교적 느린 편에 속한다. 이 속도는 당연히 HTML 문자열이 커질수록 증가한다.
내 작업의 경우 작성한 게시글의 양이 매우 클 가능성도 있기 때문에 TreeWalker의 방식은 적합하지 않다고 볼 수 있어서 innerText 방식으로 변경했다.
'Frontend > javascript' 카테고리의 다른 글
jQuery 코드 순수 자바스크립트로 마이그레이션 하기 (0) | 2024.11.12 |
---|---|
JavaScript로 파일 다운로드 하기 with 다운로드시 파일 깨짐 방지 (11) | 2024.11.10 |
JavaScript 법정동 데이터 관리와 동적 선택기 모듈 구현: 동적 셀렉트 박스 구현 (1) | 2024.11.08 |
JavaScript 법정동 데이터 관리와 동적 선택기 모듈 구현: 최신 데이터 가져오기 및 데이터 가공하기 (1) | 2024.11.07 |
자바스크립트 매개변수 기본값 처리에 대해서 (2) | 2024.10.17 |