2026년 08월 19일 | DBMS Error 가이드
이 글에서 다루는 내용
2200N 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2200N invalid xml content 는?
PostgreSQL 에러 코드 2200N: invalid xml content는 XML 데이터를 파싱하거나 저장하려 할 때, 입력된 문자열이 유효한 XML 형식을 갖추지 못한 경우 발생하는 에러입니다. 이 에러는 xml 타입 컬럼에 데이터를 INSERT/UPDATE하거나, XMLPARSE(), XMLROOT(), XMLELEMENT() 등 XML 관련 함수를 사용할 때 주로 마주치게 됩니다. PostgreSQL은 ISO SQL 표준에 따라 XML 유효성을 엄격하게 검사하기 때문에, 단 하나의 문법 오류나 인코딩 불일치만으로도 이 에러가 즉시 발생할 수 있습니다.
주요 발생 원인
1. XML 루트 엘리먼트 누락 또는 복수 루트 엘리먼트 존재
유효한 XML 문서(document)는 반드시 단 하나의 루트 엘리먼트를 가져야 합니다. 루트 엘리먼트가 없거나, 두 개 이상의 최상위 엘리먼트가 존재하는 경우 PostgreSQL XML 파서는 즉시 invalid xml content 에러를 반환합니다. 실무에서 외부 API로부터 받은 XML 응답을 그대로 저장하려 할 때 이 케이스가 가장 빈번하게 발생합니다.
2. 특수 문자 이스케이프 미처리 및 잘못된 인코딩
XML 내에서 &, <, >, ", ' 등의 특수 문자는 반드시 &, <, >, ", '로 이스케이프해야 합니다. 이를 누락한 채 원본 문자를 그대로 삽입하거나, 데이터베이스 인코딩(UTF-8)과 XML 선언부의 인코딩이 불일치할 경우 파서가 내용을 해석하지 못하고 에러를 발생시킵니다. 특히 레거시 시스템에서 EUC-KR 등의 인코딩으로 작성된 XML을 그대로 이관할 때 자주 문제가 됩니다.
3. 닫히지 않은 태그 및 잘못된 태그 중첩 구조
XML은 HTML과 달리 모든 태그가 반드시 닫혀야 하며, 태그의 중첩 순서도 올바르게 지켜져야 합니다. 와 같이 태그가 교차되거나, 처럼 닫힘 태그 없이 단독으로 사용되는 HTML 관행을 XML에 그대로 적용하면 파싱 에러가 발생합니다. 애플리케이션 개발자가 HTML 생성 로직과 XML 생성 로직을 혼용하는 환경에서 특히 자주 발생합니다.
해결 방법
원인 1 해결: 루트 엘리먼트 감싸기
복수 루트 또는 루트 없는 XML 조각(fragment)을 단일 래퍼 엘리먼트로 감싸서 유효한 문서 구조로 만들어야 합니다.
-- 잘못된 예: 루트 엘리먼트가 없는 XML 조각
SELECT XMLPARSE(DOCUMENT '<item>A</item><item>B</item>');
-- 에러: invalid xml content
-- 올바른 예: 단일 루트 엘리먼트로 감싸기
SELECT XMLPARSE(DOCUMENT '<items><item>A</item><item>B</item></items>');
-- 테이블에 저장할 때도 동일하게 적용
CREATE TABLE xml_data (
id SERIAL PRIMARY KEY,
data XML
);
-- 잘못된 INSERT (에러 발생)
-- INSERT INTO xml_data (data) VALUES ('<name>홍길동</name><age>30</age>');
-- 올바른 INSERT
INSERT INTO xml_data (data)
VALUES ('<person><name>홍길동</name><age>30</age></person>');
-- XMLPARSE를 활용한 명시적 검증 후 삽입
INSERT INTO xml_data (data)
VALUES (XMLPARSE(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?>
<person>
<name>홍길동</name>
<age>30</age>
</person>'));
원인 2 해결: 특수 문자 이스케이프 처리
애플리케이션에서 동적으로 XML을 생성할 경우 반드시 이스케이프 처리를 해야 합니다. PostgreSQL의 내장 함수를 활용하면 안전하게 처리할 수 있습니다.
-- 특수 문자가 포함된 데이터를 안전하게 XML로 변환
-- XMLELEMENT는 자동으로 특수 문자를 이스케이프 처리합니다
SELECT XMLELEMENT(
NAME "product",
XMLELEMENT(NAME "description", '가격 < 10,000원 & 부가세 포함')
);
-- 결과: <product><description>가격 < 10,000원 & 부가세 포함</description></product>
-- 잘못된 직접 문자열 삽입 (에러 발생)
-- SELECT XMLPARSE(DOCUMENT '<price>10 < 20</price>');
-- 올바른 이스케이프 처리
SELECT XMLPARSE(DOCUMENT '<price>10 < 20</price>');
-- 인코딩 선언 명시 (UTF-8 환경 권장)
SELECT XMLPARSE(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?>
<data>
<value>특수문자 & 테스트</value>
</data>');
-- 동적 XML 생성 시 XMLFOREST 활용
SELECT XMLFOREST(
'홍길동' AS name,
30 AS age,
'IT & 개발' AS department -- 자동 이스케이프
);
원인 3 해결: 태그 구조 검증 및 수정
기존 XML 데이터를 검증하고 문제 있는 레코드를 식별하는 쿼리를 활용하세요.
-- 기존 테이블에서 XML 유효성 검사를 통해 문제 레코드 식별
-- (text 타입으로 저장된 경우 xml 타입으로 캐스팅하여 검증)
CREATE TABLE raw_xml_staging (
id SERIAL PRIMARY KEY,
raw_data TEXT
);
-- 유효한 XML만 필터링하는 함수 생성
CREATE OR REPLACE FUNCTION is_valid_xml(p_text TEXT)
RETURNS BOOLEAN AS $$
BEGIN
PERFORM XMLPARSE(DOCUMENT p_text);
RETURN TRUE;
EXCEPTION
WHEN invalid_xml_content THEN
RETURN FALSE;
WHEN others THEN
RETURN FALSE;
END;
$$ LANGUAGE plpgsql;
-- 유효하지 않은 XML 레코드 조회
SELECT id, raw_data
FROM raw_xml_staging
WHERE NOT is_valid_xml(raw_data);
-- 올바른 태그 중첩 예시
SELECT XMLPARSE(DOCUMENT '
<order>
<items>
<item>
<name>노트북</name>
<quantity>1</quantity>
</item>
<item>
<name>마우스</name>
<quantity>2</quantity>
</item>
</items>
</order>');
예방 방법
1. 애플리케이션 레벨에서 XML 생성 시 전용 라이브러리 사용
XML을 문자열 직접 조합 방식으로 생성하는 것은 매우 위험합니다. Java의 JAXB, Python의 lxml, Node.js의 xmlbuilder2 등 XML 전용 라이브러리를 사용하면 특수 문자 이스케이프와 태그 구조가 자동으로 보장됩니다. DB에 저장하기 직전에 라이브러리의 유효성 검증 메서드를 반드시 호출하고, 검증 통과 후에만 INSERT/UPDATE를 수행하는 파이프라인을 구성하세요.
2. CHECK 제약 조건 및 트리거를 통한 DB 레벨 방어
데이터베이스 레벨에서도 XML 유효성 검증을 이중으로 적용하면 불량 데이터의 유입을 원천 차단할 수 있습니다.
-- xml 타입 컬럼은 자동으로 유효성 검사를 수행하므로,
-- text 타입으로 저장할 경우에는 아래와 같이 CHECK 제약 추가
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
CONSTRAINT chk_valid_xml CHECK (is_valid_xml(content))
);
-- 또는 처음부터 xml 네이티브 타입 사용 (권장)
CREATE TABLE documents_native (
id SERIAL PRIMARY KEY,
content XML -- 삽입 시 자동으로 XML 유효성 검사 수행
);
관련 에러
2200M: invalid XML document:XMLPARSE(DOCUMENT ...)에서 XML 선언 또는 DTD 구조가 잘못된 경우 발생하며,2200N과 유사하지만 문서 수준의 구조적 오류에 초점이 맞춰져 있습니다.22000: data exception: XML 처리 중 발생하는 일반적인 데이터 예외의 상위 카테고리로,2200N의 부모 에러 클래스입니다.42804: datatype mismatch: XML 타입이 기대되는 컬럼에 호환되지 않는 타입의 데이터를 삽입하려 할 때 발생하며, XML 관련 작업에서 함께 나타날 수 있습니다.22021: character not in repertoire: XML 문서 내에 현재 데이터베이스 인코딩에서 표현 불가능한 문자가 포함된 경우 발생하며, 인코딩 불일치 문제와 함께2200N을 동반하는 경우가 많습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.