XML Diff: 온라인에서 두 XML 파일 비교
두 XML 문서를 붙여넣고, 포맷하고, 나란히 비교하세요. Pretty-print, 검증, namespace 인식 하이라이트가 내장되어 있습니다.
XML diff 도구란?
두 XML 문서를 비교하기 위한 무료 브라우저 내 도구입니다. 왼쪽에 예전 pom.xml을, 오른쪽에 새 것을 붙여넣으면 변경 사항이 요소 단위로 드러납니다. 어떤 데이터도 기기 밖으로 나가지 않습니다.
diff 자체는 문자 단위이고, 검증은 브라우저의 네이티브 DOMParser를 거칩니다. 각 패널의 Format 버튼은 일관된 들여쓰기로 XML을 다시 흘려 정렬합니다. 라이브 검증은 입력하는 동안 잘못된 마크업, 짝이 맞지 않는 태그, 깨진 엔티티 참조를 표시합니다.
코드 리뷰에서 4,000줄짜리 Spring application context를 열어 class 속성이 바뀐 단 하나의 bean을 찾으려 한 적이 있다면, 이 도구가 몇 초 안에 거기로 데려다줍니다. 일반 산문이라면 텍스트 diff 도구가 적합합니다. 키/값 쌍의 구조화된 데이터라면 JSON diff가 객체 재정렬을 XML보다 깔끔하게 처리합니다.
diff가 실제로 작동하는 방식
diff는 문자 단위로 실행되고, 그 다음 의미 기반의 후처리 단계가 하이라이트를 옮겨 무작위 구두점이 아니라 태그 이름, 속성, 텍스트 내용 위에 놓이도록 합니다. 추가는 오른쪽 패널에 초록, 삭제는 왼쪽 패널에 빨강으로 나타납니다.
XML에는 명세가 짚어 놓은 몇 가지 특이점이 있고, 두 파일을 텍스트로 비교할 때 모두 문제를 일으킵니다. XML 1.0 명세는 요소의 속성 순서가 의미가 없다고 말하므로, 파서에게 <img src="a.png" alt="x"/>와 <img alt="x" src="a.png"/>는 같습니다. 그래도 텍스트 diff는 자리 바꿈을 표시합니다. 구조 비교 없이는 근본적인 해결책이 없습니다. 실용적인 우회 방법은 양쪽을 같은 도구로 포맷해 속성 순서를 안정시키는 것입니다.
namespace는 또 한 겹을 더합니다. 같은 URI를 서로 다른 prefix에 바인딩한 두 문서는 Namespaces in XML 1.0에 따라 동등하지만, 텍스트 diff는 모든 ns1: 대 ns2:의 교체를 변경으로 칠합니다. 양쪽을 포맷하고, 한쪽의 prefix를 맞춘 다음 다시 diff를 돌리세요. namespace와 속성 순서를 diff 전에 정규화하는 파이프라인이 필요하다면 XSLT 3.0이나 Canonical XML에 따른 정규화 단계를 살펴보세요.
세 단계로 XML 비교하기
텍스트 패널 둘, diff 하나. 가입도, 업로드도, 서버 왕복도 없습니다.
- 1
XML을 붙여넣거나 업로드
왼쪽에 예전 XML, 오른쪽에 새 XML을 붙여넣으세요. 또는 어느 쪽이든 업로드를 눌러 .xml, .pom, .config, .svg 파일을 직접 불러오세요. 샘플 버튼은 작은 pom.xml 예제로 양쪽 패널을 채웁니다. 도구가 어떻게 동작하는지 먼저 보고 싶을 때 사용하세요.
- 2
공정한 비교를 위해 양쪽을 포맷
각 패널의 Format을 누르면 일관된 들여쓰기와 줄바꿈으로 정렬됩니다. 이렇게 공백이 정규화되어, Windows CRLF 파일 대 Unix LF 파일에서 오는 포맷 잡음이 아니라 진짜 내용 변경에 diff가 집중합니다. DOMParser가 문서를 well-formed로 받아들이면 검증 배지가 초록으로 바뀝니다.
- 3
diff 읽기
삭제는 왼쪽에 빨간 하이라이트로, 추가는 오른쪽에 초록 하이라이트로 표시됩니다. 어느 쪽이든 스크롤하면 다른 쪽이 따라갑니다. 각 헤더의 변경 카운트는 요소 이름, 속성 값, 텍스트 내용에 걸쳐 diff가 찾은 서로 다른 편집 수를 알려줍니다.
XML diff가 적합한 경우
pom.xml 의존성 업그레이드 검토
Dependabot PR 하나가 Maven 좌표 15개를 한 번에 올립니다. 예전 pom.xml을 새 것과 붙여 실제 업그레이드를 확인하세요: spring-boot-starter-web이 3.1.5에서 3.2.1로, jackson-databind가 2.15.3에서 2.16.0으로, 그리고 새로운 micrometer-registry-prometheus 의존성이 추가되었다는 식으로요. diff가 버전 점프를 분명히 보여주므로 승인 전에 changelog와 대조해 점검할 수 있습니다.
Spring application context XML 차이
리팩터링 후 서비스가 실패하기 시작할 때, 원인은 보통 applicationContext.xml에서 class 속성이나 생성자 인자가 바뀐 단 하나의 bean입니다. 잘 동작하던 리비전을 HEAD와 붙여 보세요. class="com.acme.OldDataSource"와 class="com.acme.HikariDataSource"의 교체가 즉시 표면에 떠오르고, 주변의 <property> 태그가 어떤 설정이 함께 옮겨졌는지 알려줍니다.
SOAP 요청과 응답 본문 비교
어제까지 동작하던 SOAP 통합이 오늘은 Fault를 반환합니다. 패킷 로거나 WireMock 녹화에서 두 envelope를 캡처해 diff에 넣으면 문제 요소가 튀어나옵니다: <currencyCode>가 USD에서 누락된 요소로 바뀌었거나, 상위 서비스가 soap:Envelope의 namespace 선언을 조용히 바꾼 것처럼요. 나란히 보지 않고 800줄짜리 XML에서 이걸 찾는 건 사실상 불가능합니다.
AndroidManifest.xml 권한 감사
릴리스 전에, AndroidManifest.xml을 이전 태그와 diff해 권한 누수를 잡으세요. 서드파티 SDK 업데이트와 함께 슬쩍 들어온 새 <uses-permission android:name="android.permission.READ_CONTACTS"/>는 정확히 Play Store 검수에서 걸리는 종류입니다. diff는 <intent-filter> 요소와 android:exported 플래그 변경도 드러내는데, 이는 보안 검토에서 자주 보는 지점입니다.
RSS 또는 Atom 피드 스키마 변경 추적
소스가 RSS 2.0에서 Atom 1.0으로 바뀌거나, 게시자가 새 <media:thumbnail> namespace를 추가해 피드 리더가 깨집니다. 동작하던 피드의 스냅샷을 저장해 두고 현재 피드와 diff하면 구조적 변경이 몇 초 만에 드러납니다. OPML 임포트나 채널 레벨 메타데이터가 요소 사이를 옮긴 podcast 피드도 같은 흐름입니다.
OOXML document.xml 차이
.docx는 그저 안에 XML이 든 zip입니다. 계약서의 두 버전을 풀어 word/document.xml에 diff를 돌리면, Word의 변경 추적 마크업에 가려지지 않은 실제 텍스트 편집이 보입니다. 패러리갈이 redline과 일치한다는 "깨끗한" 사본을 돌려보냈을 때 유용합니다. XML이 어떤 단락 요소가 옮겨졌고 어떤 run 단위 서식이 바뀌었는지 알려줍니다.
XML 빠른 참조
이 도구가 가장 자주 드러내는 파싱 경계 사례에 대한 짧은 치트시트입니다. 모두 W3C XML 명세에 근거합니다.
| Topic | What this tool does |
|---|
| 속성 순서 | XML 1.0 명세상 의미가 없습니다. 파서에게 <a x="1" y="2"/>는 <a y="2" x="1"/>와 같습니다. 텍스트 diff는 교체를 표시하므로, 양쪽을 포맷해 순서를 안정시키세요. |
|---|
| Namespace | URI에 바인딩되고 prefix로 별칭이 붙습니다. 같은 URI를 서로 다른 prefix에 바인딩한 두 문서는 동등합니다. Namespaces in XML 1.0 참고. |
|---|
| CDATA 섹션 | <![CDATA[ ... ]]>로 감싼 리터럴 텍스트. 파서는 그 안의 태그나 엔티티를 해석하지 않습니다. ]]> 시퀀스는 CDATA 블록 안에 나타날 수 없습니다. |
|---|
| 혼합 내용 | 요소는 텍스트, 자식 요소, 공백을 임의의 순서로 포함할 수 있습니다. <p>안녕 <b>세계</b>!</p>는 혼합 내용이고 거기서의 공백은 의미가 있습니다. |
|---|
| 주석 | <!-- 주석 -->. 내부에 --를 포함할 수 없습니다. 대부분의 프로세서가 제거하지만 이 diff에서는 텍스트로 보존됩니다. |
|---|
| 인코딩과 BOM | <?xml version="1.0" encoding="UTF-8"?>로 선언됩니다. UTF-8 BOM은 숨겨진 첫 글자로, 1행에서 한 글자짜리 유령 diff의 흔한 원인입니다. |
|---|
| XML 1.0 대 1.1 | 거의 모두가 XML 1.0을 사용합니다. 1.1 버전은 요소 내용에서 추가 Unicode 제어 문자를 지원하지만 실무에서는 거의 보이지 않습니다. |
|---|
| 엔티티 참조 | 내장 다섯 개: & < > ' ". 악센트 문자에 대한 é 같은 숫자 문자 참조도 유효합니다. 자기 종료형 <br/>과 명시적인 <br></br>은 동등합니다. |
|---|
XML diff: 자주 묻는 질문
XML 속성 재정렬이나 공백이 diff로 나타나나요?
네, 둘 다 나타납니다. 텍스트 diff는 줄 단위로 문자를 비교하므로, 재포맷이나 속성 재정렬, 요소 안의 공백은 문서가 논리적으로 동일해도 차이로 나타납니다. 양쪽 패널에서 먼저 Format을 누르면 diff가 진짜 내용 변경에 집중합니다. 자식이 깊게 중첩된 요소 트리에는 XSLT나 Canonical XML을 통한 구조 비교가 다음 단계지만, 이 도구는 그런 복잡함 없이 실무 XML 리뷰의 95%를 처리합니다.
요소의 속성 순서가 중요한가요?
아니요, XML 파서에게는 그렇지 않습니다. XML 1.0 명세는 속성 순서가 의미가 없다고 말하므로, <img src="a.png" alt="x"/>와 <img alt="x" src="a.png"/>는 같은 요소를 나타냅니다. 문자 diff는 원시 텍스트를 보기 때문에 재정렬을 표시합니다. 해결책은 diff 전에 같은 도구로 양쪽을 포맷해 속성 순서를 일관되게 만드는 것이거나, 파이프라인을 제어할 수 있다면 Canonical XML 정규화를 적용하는 것입니다.
XML namespace는 diff에 어떻게 영향을 주나요?
namespace는 URI 기반이지만, 문서 안에서는 짧은 prefix에 바인딩됩니다. http://maven.apache.org/POM/4.0.0을 서로 다른 prefix에 바인딩한 두 파일은 Namespaces in XML 명세에서 동등하지만, 텍스트 diff는 모든 prefix 교체를 변경으로 표시합니다. 실용적인 해결책은 두 파일을 포맷하고 양쪽에서 일치하는 prefix를 사용하는 것입니다. 자동화된 파이프라인에서는 Canonical XML 패스가 이를 정규화합니다.
CDATA 섹션이 있는 XML 파일도 diff할 수 있나요?
네. CDATA 섹션은 단지 파서에게 해석하지 말라고 지시한 텍스트 내용이므로, <![CDATA[<b>raw</b>]]>는 그 안의 문자 그대로 비교됩니다. 긴 CDATA 블록(script 태그, 임베디드 HTML, SQL)도 깔끔하게 diff됩니다. 한 가지 주의점은 CDATA 섹션 안에 ]]>를 둘 수 없다는 것입니다. 데이터에 그 시퀀스가 있다면 소스에서 두 개의 CDATA 블록으로 나누어야 하고, diff는 작성된 그대로 보여줍니다.
diff 대신 XSLT를 써야 할까요?
XSLT는 XML을 변환하거나 비교 전에 정규화(자식 정렬, 주석 제거, namespace 정규화)하고 싶을 때 사용합니다. 이 diff는 두 특정 파일 사이에 무엇이 바뀌었는지 보고 싶을 때 사용합니다. 둘은 보완적입니다: XSLT 사전 패스에 이 diff를 더한 조합은 잡음 많은 머신 생성 XML에 강력한 워크플로입니다. 대부분의 코드 리뷰 사용 사례(pom.xml, AndroidManifest, application context)에서는 diff만으로 충분합니다.
인코딩 선언이나 BOM이 비교에 영향을 주나요?
조금은 그렇습니다. <?xml version="1.0" encoding="UTF-8"?> 선언은 문서 텍스트의 일부이므로 UTF-8을 UTF-16으로 바꾸면 한 줄짜리 diff로 나타납니다. 맨 앞의 UTF-8 byte order mark(BOM)는 어떤 에디터는 제거하고 어떤 에디터는 유지하는 숨은 한 글자로, 유령 diff의 흔한 원인입니다. 두 파일이 똑같아 보이는데 diff가 1행 0번째 문자에서 변경을 보여주면 BOM을 의심하고 알려진 인코딩 설정으로 다시 저장해 보세요.
개인정보와 작동 방식
당신의 XML은 브라우저를 떠나지 않습니다. 파서, 포매터, diff 모두 사용자의 머신 위에서 로컬로 실행됩니다. 입력에 대한 분석, 로그, "도와주려는" 클라우드 왕복 같은 건 없습니다. 파싱과 검증은 브라우저의 네이티브 DOMParser를 사용하고, 따르는 명세는 W3C XML 1.0입니다. 포맷 자체에 대한 배경 자료는 Wikipedia에 있습니다.