2026년 08월 20일 | DBMS Error 가이드
이 글에서 다루는 내용
2200S 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2200S invalid xml comment 는?
PostgreSQL 에러 코드 2200S (invalid_xml_comment)는 XML 데이터를 처리하는 과정에서 XML 주석 형식이 올바르지 않을 때 발생하는 에러입니다. XML 표준(W3C)에 따르면 XML 주석은 반드시 로 끝나야 하며, 주석 내부에 --(더블 하이픈)가 포함되거나 특정 형식을 위반할 경우 PostgreSQL의 XML 파서가 이 에러를 발생시킵니다. 주로 XMLPARSE(), XMLCOMMENT(), xml 타입 컬럼에 데이터를 삽입하거나 XML 관련 함수를 호출할 때 나타납니다.
주요 발생 원인
1. XML 주석 내부에 더블 하이픈(--) 포함
XML 표준에서는 주석 내부에 --(연속된 두 개의 하이픈)를 사용하는 것을 엄격히 금지하고 있습니다. 이는 XML 파서가 -->를 주석 종료 토큰으로 인식하는 방식 때문인데, 주석 내부에 --가 있으면 파서가 혼란을 일으켜 2200S 에러를 반환합니다. 특히 SQL 주석(--)에 익숙한 개발자들이 XML 주석에도 동일한 방식을 사용하다가 이 문제를 자주 겪습니다.
2. XMLCOMMENT() 함수에 유효하지 않은 문자열 전달
PostgreSQL의 XMLCOMMENT() 함수는 문자열을 받아 XML 주석으로 변환해 주는 함수인데, 이 함수에 --가 포함된 문자열이나 -로 끝나는 문자열을 전달하면 에러가 발생합니다. 함수 내부적으로 XML 표준 검증을 수행하기 때문에, 입력값에 대한 사전 검증 없이 사용자 입력값을 바로 함수에 넘기는 경우 이 에러가 빈번하게 발생합니다.
3. 외부 시스템에서 생성된 XML 데이터 직접 삽입
외부 API, 레거시 시스템, 또는 다른 데이터베이스에서 생성된 XML 데이터를 PostgreSQL의 xml 타입 컬럼에 그대로 삽입할 때 발생할 수 있습니다. 외부 시스템이 XML 표준을 느슨하게 적용하거나, 특정 변환 과정에서 잘못된 주석 형식이 포함된 XML이 생성될 수 있기 때문입니다. 이 경우 삽입 전 데이터 유효성 검사가 반드시 필요합니다.
해결 방법
원인 1 해결: 더블 하이픈 제거 또는 대체
주석 내부의 --를 제거하거나, 의미 전달이 필요하다면 다른 표현 방식으로 대체해야 합니다.
-- 잘못된 예시: 주석 내부에 -- 포함
SELECT XMLCOMMENT('이것은 잘못된 -- 주석입니다');
-- ERROR: invalid xml comment
-- 올바른 예시 1: 더블 하이픈 제거
SELECT XMLCOMMENT('이것은 올바른 주석입니다');
-- 결과: <!--이것은 올바른 주석입니다-->
-- 올바른 예시 2: 더블 하이픈을 단일 하이픈으로 대체
SELECT XMLCOMMENT('이것은 올바른 - 주석입니다');
-- 결과: <!--이것은 올바른 - 주석입니다-->
-- 애플리케이션 레벨에서 사전 치환 후 삽입하는 예시
SELECT XMLCOMMENT(
REPLACE('사용자 입력값 -- 포함된 텍스트', '--', '- -')
);
-- 결과: <!--사용자 입력값 - - 포함된 텍스트-->
원인 2 해결: XMLCOMMENT() 함수 입력값 사전 검증
XMLCOMMENT() 함수에 전달하는 값을 사전에 검증하는 함수를 만들어 활용하세요.
-- 안전한 XML 주석 생성 래퍼 함수
CREATE OR REPLACE FUNCTION safe_xmlcomment(p_text TEXT)
RETURNS XML AS $$
DECLARE
v_safe_text TEXT;
BEGIN
-- 더블 하이픈을 안전한 형태로 대체
v_safe_text := REPLACE(p_text, '--', '- -');
-- 끝이 하이픈으로 끝나는 경우 처리 (XML 표준 위반)
IF v_safe_text LIKE '%-' THEN
v_safe_text := v_safe_text || ' ';
END IF;
RETURN XMLCOMMENT(v_safe_text);
END;
$$ LANGUAGE plpgsql;
-- 사용 예시
SELECT safe_xmlcomment('이것은 안전한 -- 주석 처리 예시입니다-');
-- 결과: <!--이것은 안전한 - - 주석 처리 예시입니다- -->
-- 실제 테이블에 적용하는 예시
CREATE TABLE xml_documents (
id SERIAL PRIMARY KEY,
doc_name VARCHAR(100),
content XML
);
INSERT INTO xml_documents (doc_name, content)
VALUES (
'테스트 문서',
XMLPARSE(DOCUMENT '<?xml version="1.0"?>
<root>
<!--올바른 주석-->
<data>값</data>
</root>')
);
원인 3 해결: 외부 XML 데이터 삽입 전 유효성 검사
-- 외부 XML 데이터의 유효성을 검사하는 함수
CREATE OR REPLACE FUNCTION validate_and_insert_xml(
p_doc_name TEXT,
p_xml_text TEXT
)
RETURNS BOOLEAN AS $$
DECLARE
v_xml XML;
BEGIN
-- XML 파싱 시도 (에러 발생 시 EXCEPTION으로 이동)
v_xml := XMLPARSE(DOCUMENT p_xml_text);
-- 유효한 경우 삽입
INSERT INTO xml_documents (doc_name, content)
VALUES (p_doc_name, v_xml);
RETURN TRUE;
EXCEPTION
WHEN invalid_xml_comment THEN
RAISE NOTICE '유효하지 않은 XML 주석이 포함된 데이터입니다: %', p_doc_name;
RETURN FALSE;
WHEN OTHERS THEN
RAISE NOTICE 'XML 처리 중 오류 발생: % - %', SQLSTATE, SQLERRM;
RETURN FALSE;
END;
$$ LANGUAGE plpgsql;
-- 사용 예시: 유효하지 않은 XML 삽입 시도
SELECT validate_and_insert_xml(
'외부 데이터',
'<?xml version="1.0"?>
<root>
<!-- 잘못된 -- 주석 -->
<data>값</data>
</root>'
);
-- NOTICE: 유효하지 않은 XML 주석이 포함된 데이터입니다: 외부 데이터
-- 결과: false
-- 유효한 XML 삽입 시도
SELECT validate_and_insert_xml(
'정상 데이터',
'<?xml version="1.0"?>
<root>
<!--올바른 주석-->
<data>값</data>
</root>'
);
-- 결과: true
예방 방법
1. 애플리케이션 레벨에서 XML 입력값 사전 정제 파이프라인 구축
XML 데이터가 데이터베이스에 도달하기 전에 애플리케이션 레벨(Java, Python, Node.js 등)에서 반드시 XML 주석 유효성 검사를 수행하는 파이프라인을 구축하세요. 사용자 입력이나 외부 시스템으로부터 받은 XML 데이터는 신뢰할 수 없다고 가정하고, 더블 하이픈 치환, 주석 끝 하이픈 처리 등의 정제 로직을 공통 유틸리티로 만들어 모든 XML 처리 흐름에 적용하는 것이 좋습니다. 이렇게 하면 에러가 데이터베이스 레벨까지 전파되는 것을 원천 차단할 수 있습니다.
2. CHECK 제약 조건 및 트리거를 활용한 DB 레벨 방어
-- 트리거를 이용한 XML 데이터 자동 정제
CREATE OR REPLACE FUNCTION sanitize_xml_comment_trigger()
RETURNS TRIGGER AS $$
BEGIN
-- xml 컬럼이 NULL이 아닌 경우에만 처리
IF NEW.content IS NOT NULL THEN
-- XML을 텍스트로 변환하여 검사 후 재파싱
BEGIN
NEW.content := XMLPARSE(
DOCUMENT regexp_replace(
NEW.content::TEXT,
'--(?!>)', -- --> 앞의 -- 는 제외하고 나머지 -- 치환
'- -',
'g'
)
);
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION '유효하지 않은 XML 주석 형식입니다. 데이터를 확인하세요.';
END;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_sanitize_xml_before_insert
BEFORE INSERT OR UPDATE ON xml_documents
FOR EACH ROW
EXECUTE FUNCTION sanitize_xml_comment_trigger();
관련 에러
- 2200N (invalid_xml_content): XML 전체 구조가 유효하지 않을 때 발생하며, 2200S와 함께 XML 데이터 처리 시 자주 짝으로 등장합니다.
- 2200M (invalid_xml_document): 올바른 XML 문서 형식(예: XML 선언, 루트 엘리먼트)을 갖추지 않았을 때 발생합니다.
- 2200T (invalid_xml_processing_instruction): XML 처리 지시자(Processing Instruction)의 형식이 잘못되었을 때 발생합니다.
- 22000 (data_exception): 위 XML 관련 에러들의 상위 카테고리 에러로, XML 외에도 다양한 데이터 형식 문제 시 발생합니다.
이 에러들은 모두 22 계열의 데이터 예외(Data Exception) 범주에 속하므로, XML 처리 로직에서는 해당 계열 에러 전체를 포괄적으로 핸들링하는 것이 안정적인 운영에 도움이 됩니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.