XML 포맷 도구
XML 포맷팅이란?
XML(eXtensible Markup Language)은 데이터를 저장하고 전송하기 위한 확장 가능한 마크업 언어입니다. XML 포맷팅 도구는 압축된 XML 데이터를 들여쓰기 정돈되고 읽기 쉬운 형식으로 변환하며, 구문 강조, 오류 감지 및 데이터 검증 기능을 제공합니다. 실제 데이터나 코드베이스에 적용할 때는 파서, 테스트, 프로젝트 규칙으로 결과를 다시 확인하는 것이 중요합니다.
사용 방법
사용 방법
- 왼쪽 입력란에 XML 데이터를 붙여넣거나 직접 입력하세요
- 들여쓰기 크기를 선택하세요 (2칸, 4칸 또는 탭)
- '포맷'을 클릭해 정리하거나 '축소'를 클릭해 공백을 제거하세요
- 결과가 오른쪽에 구문 강조와 함께 표시됩니다
- '복사' 또는 '다운로드'를 클릭하여 결과를 저장하세요
XML 참고사항
- 포맷팅은 공백만 변경할 뿐 문서 의미는 바꾸지 않지만, 텍스트 노드와 혼합 콘텐츠 문서에서는 공백이 여전히 중요할 수 있습니다.
- 구문 분석에 실패하면 닫히지 않은 태그, 잘못된 중첩, 중복된 속성, 이스케이프되지 않은 앰퍼샌드 등의 문자를 확인하세요.
활용 사례
` 같은 자체 닫기 축약형(SGML 기능으로 XML 1.0 §3.1에서 허용)은 그대로 보존되므로, XHTML이나 RSS 안에 포함되는 HTML 보이드 요소는 슬래시를 유지해야 합니다. HTML5 파서에서 `
`으로 변경하면 렌더링 결과가 달라질 수 있습니다. CDATA 섹션(리터럴 `]]>` 종료자 규칙 포함)도 `&` 엔티티로 이스케이프하지 않고 그대로 유지됩니다.
기술 원리
XML 포맷팅은 W3C XML 1.0(제5판) 권고안에 기반합니다. 파싱은 `new DOMParser().parseFromString(src, 'application/xml')`(또는 `text/xml`)을 통해 이루어지며, 사양에 정의된 7가지 생성 규칙(Element, Attr, Text, CDATASection, Comment, ProcessingInstruction, DocumentType)과 일치하는 노드를 가진 Document를 반환합니다. HTML과 달리 XML 파서는 엄격합니다: 태그 불일치, 이스케이프되지 않은 `&`, 중복 속성은 파싱을 중단하고 DOMParser는 줄과 열 정보를 포함하는 `<parsererror>` 요소를 반환합니다. 서버 측 등가물로는 libxml2(`xmllint --format`), Python의 `xml.etree.ElementTree`, Java의 StAX/SAX, .NET의 `XmlReader`가 있습니다. 프린터는 DOM을 노드 단위로 직렬화합니다: 각 요소는 depth*indent 공백으로 자체 줄에 열리고, 자식은 depth+1로 재귀하며, 닫는 태그는 여는 태그에 정렬되고, 빈 요소는 사양 §3.1에서 `<foo></foo>`와 의미상 동일하다고 선언하는 자체 닫기 축약형 `<foo/>`로 축소됩니다. 5개의 미리 정의된 엔티티는 텍스트와 속성 값에서 항상 재인코딩됩니다: `&` `<` `>` `"` `'`. CDATA 섹션(`<![CDATA[ ... ]]>`)은 엔티티 인코딩이 필요한 콘텐츠를 위한 명시적 이스케이프 해치이므로 충실히 보존됩니다. §2.7에 따라 종료자 `]]>`는 CDATA 블록 안에 올 수 없으며 파서가 이를 강제합니다. `<?xml-stylesheet?>` 같은 처리 지시문과 `<?xml version="1.0" encoding="UTF-8"?>` XML 선언은 문서 프롤로그에 유지됩니다. DOCTYPE 선언은 단일 문자열로 라운드트립됩니다. 두 가지 미묘한 차이가 포맷터 복잡성의 대부분을 차지합니다. 첫째, 혼합 콘텐츠 — 텍스트와 자식 요소를 모두 포함하는 요소(예: `<p>Hello <b>world</b>!</p>`) — 는 문서 정보 집합을 변경하지 않고는 재들여쓰기할 수 없습니다. 이러한 컨텍스트의 모든 공백 문자는 중요한 Text 노드이기 때문입니다. 포맷터는 요소에 비공백 Text 자식이 있는지 스캔하여 혼합 콘텐츠를 감지하고 해당 하위 트리에 대해 단일 줄 직렬화로 전환합니다. 둘째, 네임스페이스 선언(`xmlns`, `xmlns:prefix`)은 처음 선언된 요소에 남아 있어야 합니다. 이를 이동하면 범위가 변경됩니다. 속성 순서는 사양에 따라 정규화되지 않으므로, 대부분의 포맷터는 선행 `xmlns:*` 선언을 보존하면서 알파벳 정렬을 적용합니다. 파싱과 직렬화는 문서 길이에 대해 O(n)이며, 매우 큰 피드는 일반적으로 DOM을 메모리에 구축하는 대신 SAX를 통해 스트리밍합니다.
- 사양: W3C XML 1.0 제5판(REC-xml-20081126); DOM은 `DOMParser().parseFromString(src, 'application/xml')`로 구축되며, 서버 측에서는 libxml2 또는 `xmllint --format`와 동등합니다.
- 설계상 엄격: 태그 불일치, 이스케이프되지 않은 `&`/`<`, 중복 속성 또는 유효하지 않은 문자는 `<parsererror>` 요소를 트리거합니다. HTML의 관대한 복구는 적용되지 않습니다.
- 텍스트와 속성 값에서 재인코딩되는 5개의 미리 정의된 엔티티: `&` `<` `>` `"` `'`. 숫자 문자 참조(예: ` `)는 있는 그대로 보존됩니다.
- 자체 닫기 `<foo/>`와 `<foo></foo>`는 §3.1에 따라 의미상 동일합니다. CDATA 섹션은 충실히 보존되며 종료자 `]]>`를 포함할 수 없습니다.
- 혼합 콘텐츠(텍스트 + 자식 요소)는 정보 집합을 변경하지 않고는 재들여쓰기할 수 없습니다. 프린터는 중요한 공백을 감지하여 해당 하위 트리를 인라인으로 직렬화합니다.
- 네임스페이스 선언(`xmlns`, `xmlns:prefix`)은 처음 선언된 요소에 유지됩니다. 이를 이동하면 범위가 변경됩니다. 속성 순서는 정규화되지 않으므로, 안정적인 정렬(xmlns 먼저, 그다음 알파벳 순)이 일반적입니다.
- 복잡도: DOM 기반 도구의 경우 O(n) 파싱 및 O(n) 직렬화; 대용량 문서는 SAX/StAX(Python의 xml.sax, Java의 javax.xml.stream)를 통해 스트리밍하여 전체 트리를 메모리에 로드하지 않습니다.
예시
기본 요소
<!-- 입력 (한 줄) -->
<book><title>XML Guide</title><author>Jane Doe</author><year>2024</year></book>
<!-- 출력 (2칸 들여쓰기) -->
<book>
<title>XML Guide</title>
<author>Jane Doe</author>
<year>2024</year>
</book>속성 포함
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<book id="b001" lang="en" available="true">
<title>Effective XML</title>
<price currency="USD">29.99</price>
</book>
</catalog>네임스페이스와 CDATA를 포함한 중첩 구조
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns:GetUser xmlns:ns="https://example.com/api">
<ns:UserId>10086</ns:UserId>
<ns:Script>
<![CDATA[ if (a < b && b > 0) { return true; } ]]>
</ns:Script>
</ns:GetUser>
</soap:Body>
</soap:Envelope>자주 묻는 질문
이 도구는 무엇을 하나요?
중첩된 요소에 들여쓰기를 적용하고 각 요소를 한 줄씩 배치하며 닫는 태그를 정렬해 XML을 보기 좋게 정리합니다. 한 줄로 들어온 SOAP 응답, RSS 피드, 설정 파일 등 XML 페이로드를 살펴볼 때 유용합니다.
스키마에 맞춰 검증해 주나요?
아니요. 입력한 well-formed XML을 형식만 정리할 뿐입니다. 스키마(XSD, DTD, RELAX NG) 검증은 별도 도구가 필요합니다. 태그 불일치나 닫는 괄호 누락 같은 well-formedness 오류는 알려주지만 페이지가 직접 고쳐주지는 않습니다.
속성 순서가 유지되나요?
네. XML 속성 순서는 명세상 의미가 없지만, 예기치 못한 변경을 막기 위해 원래 순서를 그대로 보존합니다. CDATA 섹션, 주석, 처리 명령(processing instruction)도 그대로 유지됩니다.
공백은 어떻게 처리되나요?
요소 사이 공백은 정규화되어 한 줄에 하나의 요소가 들여쓰기와 함께 표시됩니다. 텍스트 내용 안의 공백은 의미가 있을 수 있으므로 기본적으로 보존됩니다. xml:space='preserve' 속성이 지정된 곳은 그대로 존중합니다.
XML을 압축(minify)할 수도 있나요?
일부 빌드는 요소 간 공백을 제거하는 minify 모드를 제공합니다. 다만 텍스트 내용이나 xml:space='preserve' 영역의 공백은 보존되어야 한다는 점에 주의하세요. 풍부한 텍스트가 포함된 XML이라면 변환 전후를 비교 검증하는 것이 좋습니다.
XML이 업로드되나요?
아니요. 파싱과 포맷팅은 브라우저 내장 DOMParser와 XMLSerializer를 통해 브라우저에서 실행됩니다. 어떤 정보도 전송되지 않습니다.
XML 네임스페이스는요?
네임스페이스 선언(xmlns)과 접두사가 붙은 요소/속성은 입력된 그대로 포맷팅됩니다. 중첩된 요소에서 같은 네임스페이스를 다시 선언한 경우도 그대로 보존됩니다(검증기에 따라 신경 쓰는 곳도 있고 아닌 곳도 있습니다).