XML이 잘못됐다고 나올 때, 화면에 안 보이는 원인 다섯 가지
태그는 멀쩡해 보이는데 파서가 거부하는 경우가 있습니다. 닫히지 않은 태그부터 인코딩 선언까지, 눈으로 찾기 어려운 원인을 정리했습니다.
최종 수정일 읽는 데 약 4분
핵심 요약
- XML은 태그를 반드시 닫아야 하고 대소문자도 정확히 일치해야 합니다.
- 앰퍼샌드와 부등호는 그대로 쓸 수 없고 정해진 표기로 바꿔야 합니다.
- 파일 맨 앞의 인코딩 선언과 실제 저장 인코딩이 다르면 한글이 깨집니다.
- 오류가 가리키는 위치보다 그 앞에서 열린 채 남은 태그를 먼저 찾아야 합니다.
설정 파일이나 응답 데이터를 열어 고쳤는데 XML이 유효하지 않다는 오류가 납니다. 태그를 훑어봐도 짝이 맞는 것 같고, 알려준 줄에는 이상한 것이 없습니다.
그 자리만 봐서는 찾기 어렵습니다. 결론부터 말하면 XML 파서는 HTML과 달리 사소한 오류도 보정하지 않고, 문제 원인은 대개 오류가 표시된 지점보다 앞에 있습니다.
파서가 보정해 주지 않습니다
브라우저는 HTML을 관대하게 다룹니다. 태그를 닫지 않아도, 대소문자를 섞어 써도 알아서 해석합니다.
XML은 정반대입니다. 규칙을 하나라도 어기면 전체를 거부합니다. 부분적으로 읽어주는 동작이 없습니다.
그래서 HTML을 다루던 습관으로 XML을 쓰면 걸립니다. 그리고 파서는 앞에서부터 읽어 나가다 더 진행할 수 없는 지점에서 멈추므로, 표시되는 위치가 실제 원인보다 뒤인 경우가 많습니다. 앞쪽에서 태그를 닫지 않았다면 파일 끝에 가서야 문제가 드러납니다.
눈으로 찾기 어려운 다섯 가지
첫째, 닫히지 않은 태그입니다. 내용이 없는 태그는 슬래시로 닫아야 합니다. HTML에서 닫지 않아도 되던 태그들이 여기서 걸립니다.
둘째, 대소문자 불일치입니다. 여는 태그와 닫는 태그의 철자가 대소문자까지 정확히 같아야 합니다. 한 글자만 달라도 다른 태그로 취급됩니다.
셋째, 특수문자를 그대로 넣은 경우입니다. 앰퍼샌드와 부등호는 XML에서 의미가 정해진 문자라 값에 그대로 쓸 수 없습니다. 주소에 들어간 앰퍼샌드가 가장 흔한 사례입니다.
넷째, 속성값의 따옴표입니다. 속성값은 반드시 따옴표로 감싸야 하고, 문서 편집기에서 붙여넣으면 모양이 기울어진 따옴표가 섞여 들어옵니다.
다섯째, 인코딩 선언과 실제 저장의 불일치입니다. 맨 앞 선언에는 UTF-8이라고 적혀 있는데 파일이 다른 방식으로 저장돼 있으면 한글이 깨집니다.
| 증상 | 실제 원인 | 확인 방법 |
|---|---|---|
| 파일 끝에서 오류 | 앞에서 태그를 안 닫음 | 여는 태그와 닫는 태그 개수 비교 |
| 특정 태그에서 멈춤 | 대소문자 불일치 | 철자를 그대로 대조 |
| 주소가 들어간 값에서 오류 | 앰퍼샌드를 그대로 씀 | 특수 표기로 교체 |
| 속성 부근에서 오류 | 따옴표 모양이 다름 | 곧은 따옴표로 일괄 교체 |
| 한글만 깨짐 | 인코딩 불일치 | 선언과 저장 방식 확인 |
| 첫 글자에서 오류 | 앞에 보이지 않는 문자 | 다른 편집기로 열어 확인 |
| 주석 안에서 오류 | 주석에 하이픈 두 개 연속 | 하이픈 정리 |
마지막 줄은 드물지만 원인을 짐작하기 가장 어렵습니다. 주석 안에 하이픈이 두 번 연속으로 들어가면 규칙 위반입니다.
원인을 좁혀 가는 순서
- 정렬을 먼저 돌립니다. 코드 포맷터에서 XML을 정리하면 오류 위치가 표시되고, 통과하면 계층이 눈에 보이게 정리됩니다.
- 표시된 위치의 앞을 봅니다. 그 줄이 아니라 위쪽에서 열린 채 남은 태그를 찾습니다.
- 태그 개수를 셉니다. 같은 이름의 여는 태그와 닫는 태그 수가 맞는지 확인합니다.
- 앰퍼샌드를 검색합니다. 값 안에 그대로 들어간 것이 있으면 교체합니다.
- 따옴표를 일괄 교체합니다. 기울어진 따옴표를 곧은 따옴표로 바꿉니다.
- 그래도 안 되면 반으로 나눠 좁힙니다. 앞쪽 절반만 남겨 검사하며 문제 구간을 줄여 갑니다.
6번은 파일이 클 때 특히 빠릅니다. 몇 번만 반복하면 범위가 확 줄어듭니다.
문법은 통과했는데 처리에서 실패할 때
| 상황 | 문법 | 실제 문제 |
|---|---|---|
| 필수 항목이 빠짐 | 정상 | 받는 쪽에서 오류 |
| 태그 이름의 대소문자가 다름 | 정상 | 값을 못 찾음 |
| 숫자를 문자열처럼 넣음 | 정상 | 형 변환 실패 |
| 계층 구조가 기대와 다름 | 정상 | 읽기 실패 |
| 이름공간 선언이 빠짐 | 경우에 따라 정상 | 해석 불가 |
포맷터는 문법만 봅니다. 받는 쪽이 기대하는 구조와 맞는지는 별도로 확인해야 합니다.
XML을 고칠 때 시간이 새는 지점
HTML 습관으로 씁니다. 닫지 않은 태그, 따옴표 없는 속성값은 HTML에서는 넘어가도 XML에서는 오류입니다.
표시된 줄만 반복해서 봅니다. 원인은 대개 그 앞에 있습니다.
앰퍼샌드를 눈으로 찾습니다. 검색 기능으로 한 번에 찾는 편이 확실합니다.
인코딩을 확인하지 않습니다. 한글만 깨지는 증상은 문법이 아니라 인코딩 문제입니다.
정렬을 먼저 해보지 않습니다. 자동 정렬은 문제 여부를 즉시 알려주고 통과하면 구조 파악도 쉬워집니다.
닫히지 않은 태그부터 찾으세요
XML 오류의 대부분은 태그가 열린 채 남아 있거나 특수문자를 그대로 넣은 경우입니다.
정렬을 먼저 돌리고, 표시된 위치에서 위로 거슬러 올라가고, 앰퍼샌드와 따옴표를 검색으로 확인하세요. 한글만 깨진다면 그건 문법이 아니라 인코딩 쪽입니다.
자주 묻는 질문
HTML은 되는데 XML은 왜 안 되나요?
브라우저는 HTML의 사소한 오류를 알아서 보정해 주지만 XML 파서는 보정하지 않습니다. 닫지 않은 태그 하나, 대소문자 하나가 달라도 전체를 거부합니다. HTML 습관대로 쓰면 XML에서 걸립니다.
앰퍼샌드를 그냥 쓰면 안 되나요?
안 됩니다. 앰퍼샌드는 특수 표기의 시작을 알리는 문자라 값에 그대로 넣으면 파서가 뒤따르는 글자를 표기 이름으로 읽으려다 실패합니다. 부등호도 태그의 시작과 끝으로 해석되므로 그대로 쓸 수 없습니다.
한글이 물음표나 깨진 글자로 나옵니다.
문법 오류가 아니라 인코딩 문제입니다. 파일 맨 앞의 선언이 UTF-8이라고 적혀 있는데 실제 저장은 다른 방식이라면 글자가 어긋납니다. 편집기에서 파일 인코딩을 확인하고 선언과 맞추세요.
정렬이 되면 문제가 없는 건가요?
문법이 맞다는 뜻일 뿐입니다. 받는 쪽이 기대하는 구조와 다르거나 필수 항목이 빠져 있으면 문법은 통과해도 처리에서 실패합니다. 문법 검사와 구조 검사는 별개입니다.