2026년 10월 24일 | DBMS Error 가이드
이 글에서 다루는 내용
2200T 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2200T invalid xml processing instruction 는?
PostgreSQL 에러 코드 2200T는 XML 처리 명령어(Processing Instruction, PI)가 유효하지 않은 형식으로 작성되었을 때 발생하는 에러입니다. XML 처리 명령어는 형식으로 구성되며, XML 문서 내에서 애플리케이션에 특별한 지시를 전달하는 역할을 합니다. PostgreSQL의 XML 데이터 타입이나 XML 관련 함수(xmlpi(), xpath(), XMLPARSE() 등)를 사용할 때, 처리 명령어의 타겟 이름이나 데이터가 XML 표준 규격을 위반하면 이 에러가 트리거됩니다.
이 에러는 특히 xmlpi() 함수를 사용하여 XML 처리 명령어를 직접 생성하거나, 외부 시스템으로부터 유입된 비표준 XML 데이터를 PostgreSQL에 삽입하려 할 때 자주 발생합니다. XML 표준(W3C)에 따르면 처리 명령어의 타겟 이름은 xml(대소문자 구분 없이)로 시작할 수 없으며, 유효한 XML 이름 규칙을 따라야 합니다.
주요 발생 원인
1. 처리 명령어 타겟 이름이 ‘xml’로 시작하는 경우
XML 1.0 표준에 따르면, 처리 명령어의 타겟 이름은 xml, XML, Xml 등 대소문자 조합과 관계없이 ‘xml’로 시작할 수 없습니다. 이는 W3C XML 표준이 해당 접두사를 예약어로 지정해 두었기 때문이며, PostgreSQL은 이 표준을 엄격하게 준수합니다. 많은 개발자들이 처리 명령어에 xml-stylesheet처럼 ‘xml’로 시작하는 이름을 사용하려다 이 에러를 마주하게 됩니다.
2. 처리 명령어 데이터에 ‘?>’ 문자열이 포함된 경우
XML 처리 명령어는 ?> 시퀀스로 종료되기 때문에, 처리 명령어의 데이터(content) 부분에 ?>가 포함되면 XML 파서가 명령어를 조기 종료된 것으로 인식하거나 전체 구조가 무효한 것으로 판단합니다. 이런 상황은 주로 프로그래밍 코드나 특수 문자열을 XML 처리 명령어 데이터로 직접 삽입할 때 발생하며, 개발자가 데이터 이스케이프 처리를 누락한 경우 흔히 나타납니다.
3. 타겟 이름이 유효한 XML Name 규칙을 위반한 경우
XML 이름(Name)은 문자(letter) 또는 언더스코어(_)로 시작해야 하며, 이후에는 문자, 숫자, 하이픈(-), 점(.), 언더스코어(_)만 포함할 수 있습니다. 타겟 이름이 숫자로 시작하거나, 공백을 포함하거나, 허용되지 않는 특수 문자를 사용하는 경우 2200T 에러가 발생합니다. 외부 API나 레거시 시스템으로부터 받은 XML 데이터에서 이 규칙을 어기는 경우가 실무에서 상당히 흔합니다.
해결 방법
원인 1 해결: ‘xml’로 시작하는 타겟 이름 수정
xmlpi() 함수를 사용할 때 타겟 이름이 ‘xml’로 시작하지 않도록 변경해야 합니다.
-- 에러 발생 예시: 타겟 이름이 'xml'로 시작
SELECT xmlpi(name "xml-stylesheet", 'type="text/css" href="style.css"');
-- ERROR: invalid XML processing instruction
-- DETAIL: XML processing instruction target name cannot be "xml".
-- 올바른 해결 방법: 다른 타겟 이름 사용
SELECT xmlpi(name "stylesheet", 'type="text/css" href="style.css"');
-- 결과: <?stylesheet type="text/css" href="style.css"?>
-- 실무 예제: XML 문서 생성 시 올바른 처리 명령어 포함
SELECT xmlroot(
xmlelement(
name "document",
xmlelement(name "title", '블로그 포스트'),
xmlelement(name "content", 'PostgreSQL XML 에러 해결 가이드')
),
version '1.0',
standalone yes
);
원인 2 해결: 처리 명령어 데이터의 ‘?>’ 문자열 제거 또는 대체
처리 명령어 데이터에 ?> 시퀀스가 포함되지 않도록 데이터를 전처리해야 합니다.
-- 에러 발생 예시: 데이터에 '?>' 포함
SELECT xmlpi(name "myapp", 'config data ?> end');
-- ERROR: invalid XML processing instruction
-- 해결 방법 1: 문제 시퀀스를 다른 표현으로 대체
SELECT xmlpi(name "myapp", replace('config data ?> end', '?>', '? >'));
-- 결과: <?myapp config data ? > end?>
-- 해결 방법 2: 입력 데이터 검증 함수 생성
CREATE OR REPLACE FUNCTION safe_xmlpi(target_name text, pi_data text)
RETURNS xml AS $$
DECLARE
cleaned_data text;
BEGIN
-- '?>' 시퀀스 제거 및 치환
cleaned_data := replace(pi_data, '?>', '? >');
-- 타겟 이름 검증
IF lower(target_name) LIKE 'xml%' THEN
RAISE EXCEPTION '처리 명령어 타겟 이름은 xml로 시작할 수 없습니다: %', target_name;
END IF;
RETURN xmlpi(name "placeholder", cleaned_data);
END;
$$ LANGUAGE plpgsql;
-- 함수 사용 예시
SELECT safe_xmlpi('myprocessor', 'action="update" version="1.0"');
원인 3 해결: 유효하지 않은 타겟 이름 교정
외부 데이터의 타겟 이름을 검증하고 정규화하는 로직을 추가합니다.
-- 에러 발생 예시: 숫자로 시작하는 타겟 이름
SELECT xmlpi(name "1invalidname", 'data="value"');
-- ERROR: invalid XML processing instruction
-- 해결 방법: 데이터 삽입 전 검증 절차 추가
DO $$
DECLARE
target_name text := '1invalidname';
pi_data text := 'data="value"';
result xml;
BEGIN
-- 타겟 이름 유효성 검사
IF target_name ~ '^[0-9]' THEN
-- 접두사를 추가하여 유효한 이름으로 변환
target_name := 'pi_' || target_name;
RAISE NOTICE '타겟 이름을 수정했습니다: %', target_name;
END IF;
IF lower(target_name) LIKE 'xml%' THEN
RAISE EXCEPTION '타겟 이름이 xml로 시작합니다. 수정이 필요합니다.';
END IF;
-- 안전한 이름으로 처리 명령어 생성 (동적 SQL 사용)
EXECUTE format('SELECT xmlpi(name %I, %L)', target_name, pi_data) INTO result;
RAISE NOTICE '생성된 XML PI: %', result;
END $$;
-- XML 데이터 삽입 시 유효성 검사를 포함한 테이블 설계
CREATE TABLE xml_documents (
id SERIAL PRIMARY KEY,
content xml NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
-- 유효한 XML만 삽입하는 예시
INSERT INTO xml_documents (content)
VALUES (
XMLPARSE(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?>
<?myapp action="process"?>
<root>
<item>데이터</item>
</root>')
);
-- XMLPARSE를 통한 외부 XML 데이터 유효성 검사
CREATE OR REPLACE FUNCTION validate_and_insert_xml(raw_xml text)
RETURNS INTEGER AS $$
DECLARE
parsed_xml xml;
new_id integer;
BEGIN
BEGIN
parsed_xml := XMLPARSE(DOCUMENT raw_xml);
EXCEPTION
WHEN invalid_xml_processing_instruction THEN
RAISE EXCEPTION 'XML 처리 명령어가 유효하지 않습니다. 입력 데이터를 확인하세요: %', SQLERRM;
WHEN invalid_xml_content THEN
RAISE EXCEPTION 'XML 내용이 유효하지 않습니다: %', SQLERRM;
END;
INSERT INTO xml_documents (content) VALUES (parsed_xml) RETURNING id INTO new_id;
RETURN new_id;
END;
$$ LANGUAGE plpgsql;
예방 방법
1. XML 입력 데이터에 대한 애플리케이션 레벨 사전 검증 구현
데이터베이스에 XML 데이터를 저장하기 전에 애플리케이션 레벨에서 XML 유효성을 먼저 검증하는 것이 가장 효과적인 예방책입니다. 특히 외부 API, 사용자 입력, 레거시 시스템으로부터 XML 데이터를 받을 때는 반드시 처리 명령어 타겟 이름이 XML 표준을 준수하는지, 데이터에 ?> 시퀀스가 포함되어 있는지 등을 체크하는 전처리 레이어를 두어야 합니다. PostgreSQL의 XMLPARSE() 함수를 트랜잭션 내에서 먼저 테스트 실행하고, 성공 시에만 실제 삽입을 진행하는 패턴도 권장됩니다.
-- 예방을 위한 XML 검증 함수
CREATE OR REPLACE FUNCTION is_valid_xml(input_text text)
RETURNS boolean AS $$
BEGIN
PERFORM XMLPARSE(DOCUMENT input_text);
RETURN true;
EXCEPTION
WHEN OTHERS THEN
RETURN false;
END;
$$ LANGUAGE plpgsql;
-- 사용 예시
SELECT is_valid_xml('<?xml version="1.0"?><?myapp valid="true"?><root/>');
-- 결과: true
SELECT is_valid_xml('<?xml version="1.0"?><?xml-invalid?><root/>');
-- 결과: false
2. CHECK 제약 조건 및 트리거를 활용한 데이터베이스 레벨 방어
테이블 수준에서 XML 데이터의 무결성을 보장하기 위해 CHECK 제약 조건이나 BEFORE INSERT/UPDATE 트리거를 활용하면, 잘못된 XML이 데이터베이스에 저장되는 것을 원천 차단할 수 있습니다.
-- XML 컬럼 검증 트리거 생성
CREATE OR REPLACE FUNCTION trg_validate_xml()
RETURNS TRIGGER AS $$
BEGIN
-- XML 처리 명령어 패턴 검사
IF NEW.content::text ~ '<\?[Xx][Mm][Ll]' AND
NEW.content::text !~ '<\?xml version' THEN
RAISE EXCEPTION '유효하지 않은 XML 처리 명령어가 감지되었습니다. (에러코드: 2200T)';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER validate_xml_before_insert
BEFORE INSERT OR UPDATE ON xml_documents
FOR EACH ROW EXECUTE FUNCTION trg_validate_xml();
관련 에러
2200S(invalid_xml_comment): XML 주석이 올바르지 않은 형식일 때 발생합니다.--로 끝나거나, 주석 내에--가 포함된 경우 트리거됩니다.2200N(invalid_xml_content): XML 문서 전체의 내용이 well-formed XML 표준을 충족하지 못할 때 발생하며,2200T와 함께 XML 처리 관련 에러 그룹을 형성합니다.2200M(invalid_xml_document): XML 문서가 유효하지 않을 때 발생하는 에러로, DTD 또는 스키마 유효성 검사 실패 시 나타납니다.22000(data_exception): XML 관련 에러들의 상위 카테고리로, XML 데이터 처리 중 발생하는 다양한 데이터 예외의 부모 에러 코드입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.