DOMParser와 Serverless를 활용한 탄력적인 메타 태그 분석기 구축
Source: Dev.to
SEO 도구를 만드는 일은 겉보기엔 간단해 보이지만, 현대 웹 스크래핑의 두 가지 장벽—**교차 출처 리소스 공유 (CORS)**와 임의의 HTML을 파싱하는 복잡함—에 부딪히면 금세 어려워집니다.
저는 최근에 Meta Tag Analyzer 를 제작했습니다. 이 도구는 개발자들이 Open Graph와 Twitter Card 태그를 디버깅할 수 있도록 도와줍니다. 목표는 간단했습니다: URL을 입력받아 해당 페이지의 소스 코드를 가져오고, 소셜 플랫폼이 페이지를 어떻게 보는지 시각화하는 것이었습니다.
아래에서는 데이터 가져오기 아키텍처에 대한 기술적인 분석과, Cheerio나 JSDOM 같은 무거운 라이브러리를 사용하지 않고 브라우저에서 HTML을 안전하게 파싱하는 방법을 자세히 설명합니다.
문제: CORS와 “HTML용 정규식” 함정
1. CORS 차단
브라우저에서 다음과 같이 단순히 실행할 수 없습니다:
fetch('https://example.com')
브라우저 보안 정책이 요청을 차단합니다. 대상 도메인이 귀하의 사이트에 대해 Access-Control-Allow-Origin 헤더를 보내지 않기 때문입니다.
2. 파싱 전략
HTML을 (보통 프록시를 통해) 얻은 뒤에는 방대한 문자열 텍스트가 됩니다. 초보자들은 종종 정규식을 사용해 “ 태그를 추출하려고 시도합니다. 유명한 StackOverflow 게시물이 경고하듯, 정규식으로 HTML을 파싱하는 것은 나쁜 아이디어이며, 닫히지 않은 태그, 주석, 혹은 예상치 못한 줄 바꿈에서 깨집니다.
솔루션: 프록시 + DOMParser 아키텍처
1. 서버리스 프록시
가벼운 서버리스 함수가 터널 역할을 합니다:
- 대상 URL을 받습니다.
- 서버 측에서 콘텐츠를 가져옵니다 (CORS가 적용되지 않는 곳).
- 프론트엔드에 원시 HTML 문자열을 반환합니다.
2. 네이티브 DOMParser
클라이언트 측에서는 무거운 파싱 라이브러리를 가져오는 대신, 브라우저에 내장된 DOMParser API를 사용합니다. 이 API는 스크립트를 실행하거나 외부 리소스(이미지, CSS 등)를 로드하지 않고 HTML 문자열을 조작 가능한 DOM 문서로 변환합니다.
코드: HTML 문자열을 안전하게 파싱하기
/**
* Extracts meta tags from a raw HTML string using the DOMParser API.
*
* @param {string} rawHtml - The HTML string fetched from the proxy.
* @returns {object} - An object containing standard, OG, and Twitter metadata.
*/
const extractMetaData = (rawHtml) => {
// 1. Initialise the DOMParser
const parser = new DOMParser();
// 2. Parse the string into a Document.
// 'text/html' ensures it parses as HTML, forgiving syntax errors.
const doc = parser.parseFromString(rawHtml, "text/html");
// Helper to safely get content from a selector
const getMeta = (selector, attribute = "content") => {
const element = doc.querySelector(selector);
return element ? element.getAttribute(attribute) : null;
};
// 3. Extract Data
// querySelector handles fallback logic efficiently
const data = {
title: doc.title || getMeta('meta[property="og:title"]'),
description:
getMeta('meta[name="description"]') ||
getMeta('meta[property="og:description"]'),
// Open Graph specifics
og: {
image: getMeta('meta[property="og:image"]'),
url: getMeta('meta[property="og:url"]'),
type: getMeta('meta[property="og:type"]'),
},
// Twitter Card specifics
twitter: {
card: getMeta('meta[name="twitter:card"]'),
creator: getMeta('meta[name="twitter:creator"]'),
},
// Technical SEO
robots: getMeta('meta[name="robots"]'),
viewport: getMeta('meta[name="viewport"]'),
canonical: getMeta('link[rel="canonical"]', "href"),
};
return data;
};
이 접근 방식이 잘 작동하는 이유
| 측면 | 이점 |
|---|---|
| 보안 | DOMParser는 비활성 문서를 생성합니다. rawHtml 내부의 스크립트는 실행되지 않도록 표시되어 분석 중 XSS를 방지합니다. |
| 성능 | HTML 문자열만 파싱하며, 이미지, CSS, 폰트에 대한 네트워크 요청이 발생하지 않습니다. |
| 탄력성 | 브라우저는 잘못된 HTML을 관대하게 처리합니다. DOMParser는 실제 브라우저처럼 닫히지 않은 태그를 처리하므로, 스크레이퍼가 깨진 페이지에서도 충돌하지 않습니다. |
라이브 데모
직접 사용해 보세요: NasajTools – Meta Tag Analyzer
URL을 입력하세요(예: github.com) 하면 DOMParser 추출을 실시간으로 확인할 수 있습니다.
Source: …
성능 고려 사항
테스트 중에 2 MB+ 파일을 제공하는 레거시 사이트와 같은 대용량 HTML 페이지를 만나게 되었습니다. UI가 반응성을 유지하도록 두 가지 최적화를 적용했습니다:
1. 요청 중단
프록시 측에서 3초 제한 시간을 엄격히 설정했습니다. SEO 봇은 보통 그보다 오래 기다리지 않으므로, 그 시점에 중단하는 것이 현실적입니다.
2. Content‑Length 검사 및 Head‑Only 파싱
메타 태그는 거의 항상 <head> 내부에 위치합니다. HTML 문자열이 안전 임계값을 초과하면 DOMParser에 전달하기 전에 100 KB(또는 </head>가 있으면 그까지)만 잘라 사용합니다.
// Optimization: Only parse the head if the file is massive
const MAX_SIZE = 100_000; // 100 KB
if (rawHtml.length > MAX_SIZE) {
// Cut off after the closing </head> tag to keep it valid
const headEnd = rawHtml.indexOf('</head>');
if (headEnd !== -1) {
rawHtml = rawHtml.substring(0, headEnd + 7); // include '</head>'
}
}
이 절단 전략은 테스트 중 저사양 모바일 기기에서 처리 시간을 크게 단축시켰습니다.
Source: https://nasajtools.com/tools/seo/meta-tag-analyzer.html
TL;DR
- CORS → 서버리스 프록시로 해결합니다.
- HTML parsing → 정규식 사용을 피하고 네이티브
DOMParser를 사용하세요. - Performance → 긴 요청은 중단하고, 페이로드가 클 경우
<head>만 파싱합니다.
한 번 실행해 보세요, 그러면 몇 줄의 순수 JavaScript만으로도 신뢰할 수 있고, 안전하며 빠른 SEO 메타‑태그 분석기를 구현할 수 있다는 것을 확인할 수 있습니다. 🚀
클라이언트‑사이드 스크래퍼나 분석기를 만들고자 할 때 도움이 되길 바랍니다!