← 모두의 툴

XML 파서는 왜 HTML보다 깐깐한가(well-formed vs valid)

가이드 · 2026.08.24 최종 확인

닫히지 않은 태그가 있는 HTML 파일을 브라우저에 열면 화면은 대부분 멀쩡하게 뜹니다. 반면 같은 실수를 XML 파일에서 저지르면 파서가 그 자리에서 처리를 멈추고 오류를 던집니다. 둘 다 태그 기반 마크업 언어인데 왜 이렇게 다르게 반응할까요. 답은 취향이 아니라 스펙 자체에 있습니다. 이 가이드는 그 차이가 어디서 오는지, 그리고 "well-formed"와 "valid"라는 서로 다른 두 개념이 왜 헷갈리는지 구조적으로 짚어봅니다.

1. HTML 파서의 관대함: error recovery는 스펙에 명시된 기능이다

HTML5 파싱 스펙(WHATWG HTML Living Standard)은 잘못된 마크업을 만났을 때 파서가 어떻게 "복구"해야 하는지를 상세히 규정합니다. 태그가 안 닫혀 있으면 암묵적으로 닫아주고, 순서가 어긋난 태그는 트리 구조 규칙에 따라 재배치하며, 알 수 없는 태그는 무시하고 넘어갑니다. 이건 브라우저가 특별히 착해서가 아니라, 웹 초창기부터 문법이 엉망인 페이지가 워낙 많았던 현실을 반영해 "깨져도 최대한 보여준다"는 것 자체가 표준 동작으로 못박혔기 때문입니다.

2. XML 스펙의 fatal error 강제: well-formed 위반 시 파서는 멈춰야 한다

XML 1.0 스펙은 정반대 방향으로 설계됐습니다. 문서가 well-formed 규칙(모든 태그가 올바르게 열리고 닫힘, 속성값은 따옴표로 감쌈, 루트 요소는 정확히 하나)을 위반하면 파서는 이를 fatal error로 처리하고 그 지점에서 처리를 중단해야 한다고 명시합니다. 관대하게 복구해서 계속 진행하는 선택지 자체가 스펙상 존재하지 않습니다. XML은 데이터 교환 포맷으로 설계됐기 때문에, 애매하게 복구해서 계속 파싱하면 서로 다른 파서가 서로 다른 결과를 낼 위험이 있고, 그건 데이터 포맷으로서는 치명적이라고 본 것입니다.

정리: HTML 파서의 관대함은 "구현체 재량"이 아니라 스펙이 요구하는 표준 동작이고, XML 파서의 엄격함도 마찬가지로 스펙이 강제하는 표준 동작입니다. 두 언어는 애초에 다른 목적(문서 렌더링 vs 데이터 교환)으로 설계됐고, 그 목적 차이가 파싱 철학의 차이로 이어진 것입니다.

3. well-formed와 valid는 다른 층위의 개념이다

여기서 자주 섞이는 두 단어를 구분할 필요가 있습니다. well-formed는 XML 문법 규칙(태그 짝, 속성 인용 부호, 단일 루트 등) 자체를 지켰는지를 말합니다. 이건 어떤 XML 문서든 예외 없이 지켜야 하는 최소 조건입니다. valid는 그보다 한 단계 위의 개념으로, DTD나 XSD 같은 스키마가 정의한 "이 문서에는 어떤 요소가 어떤 순서로 와야 하는지"까지 만족하는지를 말합니다. well-formed하지 않은 문서는 애초에 파싱조차 안 되지만, well-formed하면서도 valid하지 않은 문서는 얼마든지 있을 수 있습니다(문법은 맞지만 스키마가 요구하는 필수 요소가 빠졌다든지).

구분검사 대상위반 시 결과
well-formedXML 1.0 기본 문법(태그 짝, 인용부호, 단일 루트)파서가 fatal error로 즉시 중단
validDTD/XSD가 정의한 요소·속성·순서 규칙스키마 검증 실패(별도 검증기 필요)

4. 실제 도구는 어디까지 검사하는가

이 구분이 실무에서 왜 중요하냐면, "XML 검증"이라는 말이 well-formed 체크만 뜻하는지 valid까지 포함하는지에 따라 도구의 범위가 완전히 달라지기 때문입니다. 예를 들어 XML 검증기는 브라우저 내장 DOMParserparseFromString(xml, 'application/xml')를 호출해 parsererror 요소가 생기는지를 확인하는 방식으로 동작합니다. 이건 well-formed 여부만 확인하는 것이고, DTD나 XSD 스키마를 별도로 로드해 요소 구조까지 검증하는 valid 체크는 하지 않습니다. 즉 "well-formed는 통과했지만 valid는 아닌" 문서도 이 도구에서는 "유효한 XML"로 표시됩니다 — 이건 도구의 한계가 아니라, well-formed 검증기의 정상적인 정의된 동작 범위입니다.

예시: 아래 문서는 well-formed지만(모든 태그가 짝이 맞음), sitemap.xml의 XSD 스키마가 요구하는 <loc> 필수 요소가 빠져 있어 valid하지는 않습니다.

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><lastmod>2026-08-24</lastmod></url></urlset>

DOMParser 기반 검증기는 이 문서를 "유효"라고 표시합니다 — well-formed 여부만 보기 때문입니다. 스키마 위반까지 잡으려면 XSD 인식 검증기가 별도로 필요합니다.

5. XHTML이 특히 엄격한 이유

이 원칙이 실전에서 가장 자주 부딪히는 지점이 XHTML입니다. HTML5 문서는 HTML 파서로 처리되어 오류가 있어도 대부분 렌더링되지만, application/xhtml+xml로 서빙되는 XHTML 문서는 브라우저가 XML 파서로 처리합니다. 그래서 XHTML에서는 태그 하나만 안 닫혀도 페이지 전체가 빈 화면에 오류 메시지만 뜨는 "Yellow Screen of Death" 현상이 벌어집니다. 같은 마크업이라도 서버가 어떤 MIME 타입으로 응답하느냐에 따라 파서의 관용도가 완전히 달라지는 셈입니다.

자주 묻는 질문

Q. well-formed만 확인하고 valid는 왜 확인 안 하나요?

valid 검증은 DTD나 XSD 같은 스키마 파일을 별도로 참조해야 하고, 스키마 자체가 없는 문서(사용자가 임의로 작성한 설정 파일 등)도 많기 때문입니다. 반면 well-formed 검증은 문서 자체만으로 판단 가능해 범용적으로 쓸 수 있습니다.

Q. DOMParser의 parsererror는 어떻게 감지하나요?

parseFromString()이 파싱에 실패하면 반환된 문서 안에 <parsererror> 요소가 삽입됩니다. 이 요소의 존재 여부로 well-formed인지 판단하는 것이 브라우저 기반 XML 검증 도구의 표준적인 방식입니다.

Q. HTML5는 왜 이렇게 관대하게 설계됐나요?

웹 초창기에 문법이 엉망인 페이지가 이미 대량으로 존재했고, 이를 깨뜨리지 않으면서 브라우저 간 동작을 통일하기 위해 HTML5 스펙이 "오류 복구 알고리즘"을 표준화했습니다. 즉 관대함 자체가 상호운용성을 위한 설계 선택입니다.

Q. JSON도 XML처럼 엄격한가요?

네, JSON도 문법 오류가 있으면 파서가 즉시 실패하는 strict 방식입니다. 쉼표 하나만 잘못돼도 전체가 파싱 실패로 처리되는 점에서 XML의 well-formed 강제와 비슷한 철학을 공유합니다.