PostgreSQL 2200G 오류 원인과 해결 방법 완벽 가이드

2200G
2026년 06월 11일 | DBMS Error 가이드

이 글에서 다루는 내용

2200G 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

2200G most specific type mismatch 는?

PostgreSQL 에러 코드 2200G는 SQL 표준에서 정의된 “most specific type mismatch” 오류로, 주로 SQL/XML 또는 사용자 정의 타입(User-Defined Type, UDT) 계층 구조에서 타입 간의 불일치가 발생할 때 나타납니다. 이 에러는 특히 구조화된 타입(structured type)이나 복합 타입(composite type)을 다루는 함수 또는 프로시저에서 인자로 전달된 값의 타입이 기대하는 가장 구체적인(most specific) 타입과 맞지 않을 때 트리거됩니다. 실무에서는 복잡한 타입 계층을 활용하는 엔터프라이즈 애플리케이션이나 XML 처리 로직에서 주로 마주치게 됩니다.


주요 발생 원인

1. 복합 타입(Composite Type) 또는 도메인 타입 계층에서의 불일치

PostgreSQL에서 복합 타입이나 도메인 타입을 상속받는 구조를 사용할 때, 부모 타입 대신 자식 타입(또는 그 반대)을 전달하면 most specific type mismatch 에러가 발생할 수 있습니다. 예를 들어, 특정 함수가 정확히 하위 도메인 타입을 요구하는데 상위 베이스 타입을 넘겨주는 경우가 대표적입니다. 이 상황은 특히 타입 계층이 깊거나, 여러 레이어의 추상화를 거친 코드베이스에서 빈번하게 발생합니다.

2. XML 타입 처리 시 스키마 타입 불일치

PostgreSQL의 XML 관련 함수(예: XMLQUERY, XMLTABLE)를 사용할 때, XML 스키마에서 정의된 타입과 실제 전달되는 XML 데이터의 타입이 다를 경우 이 에러가 발생합니다. XML 스키마 검증 과정에서 요소(element)나 속성(attribute)의 파생 타입이 기대값과 맞지 않으면 PostgreSQL은 2200G를 반환합니다. 특히 복잡한 XSD 스키마를 사용하는 환경에서 타입 정의를 잘못 매핑하면 이 에러를 자주 보게 됩니다.

3. 함수 오버로딩(Function Overloading) 시 타입 해석 오류

PostgreSQL은 같은 이름의 함수를 다양한 파라미터 타입으로 오버로딩할 수 있는데, 이때 쿼리 플래너가 어떤 오버로딩 버전을 선택해야 할지 명확하지 않거나, 암묵적 형 변환(implicit cast)이 기대한 대로 이루어지지 않아 에러가 발생하기도 합니다. 특히 사용자 정의 타입과 내장 타입이 혼재된 환경에서, 함수에 전달되는 인자가 가장 구체적인 타입으로 해석되지 못할 때 이 에러가 트리거됩니다. 이런 경우 명시적 캐스팅(explicit casting)이나 함수 시그니처를 명확하게 지정하는 것이 해결책이 됩니다.


해결 방법

원인 1: 복합 타입 계층 불일치 해결

복합 타입을 정의하고 함수에서 사용할 때, 타입을 명시적으로 캐스팅하여 정확한 타입을 전달해야 합니다.

-- 복합 타입 정의 예시
CREATE TYPE base_address AS (
    street TEXT,
    city   TEXT
);

CREATE DOMAIN specific_address AS base_address;

-- 잘못된 예: base_address 를 specific_address 를 기대하는 함수에 전달
CREATE OR REPLACE FUNCTION process_address(addr specific_address)
RETURNS TEXT AS $$
BEGIN
    RETURN (addr).city;
END;
$$ LANGUAGE plpgsql;

-- 에러 발생 가능 케이스
SELECT process_address(ROW('123 Main St', 'Seoul')::base_address);

-- 올바른 해결 방법: 명시적 캐스팅으로 타입 일치
SELECT process_address(ROW('123 Main St', 'Seoul')::specific_address);

원인 2: XML 타입 처리 오류 해결

XML 데이터를 처리할 때 올바른 타입으로 명시적으로 캐스팅하거나, XMLCAST를 활용하여 타입 불일치를 방지할 수 있습니다.

-- XML 타입 처리 예시
-- 잘못된 예: XML 데이터를 잘못된 타입으로 전달
SELECT XMLQUERY('//name/text()' 
    PASSING '<root><name>PostgreSQL</name></root>'
    RETURNING CONTENT
);

-- XMLTABLE 사용 시 올바른 타입 명시
SELECT *
FROM XMLTABLE(
    '//employee'
    PASSING XMLPARSE(DOCUMENT '
        <employees>
            <employee>
                <id>1</id>
                <name>Kim</name>
                <salary>5000.00</salary>
            </employee>
        </employees>
    ')
    COLUMNS
        emp_id   INTEGER  PATH 'id',
        emp_name TEXT     PATH 'name',
        salary   NUMERIC  PATH 'salary'   -- 타입을 명확하게 지정
);

-- XML 값에 명시적 캐스팅 적용
SELECT XMLCAST(
    XMLQUERY('//salary/text()' 
        PASSING XMLPARSE(DOCUMENT '<data><salary>5000</salary></data>')
        RETURNING CONTENT
    ) AS NUMERIC
);

원인 3: 함수 오버로딩 타입 충돌 해결

함수 호출 시 명시적 캐스팅을 사용하거나, 함수 시그니처에 ::타입명을 붙여 PostgreSQL이 정확한 버전을 선택하도록 강제합니다.

-- 함수 오버로딩 예시
CREATE OR REPLACE FUNCTION calculate_value(val INTEGER)
RETURNS TEXT AS $$
BEGIN
    RETURN 'Integer: ' || val::TEXT;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION calculate_value(val NUMERIC)
RETURNS TEXT AS $$
BEGIN
    RETURN 'Numeric: ' || val::TEXT;
END;
$$ LANGUAGE plpgsql;

-- 모호한 호출 (에러 발생 가능)
SELECT calculate_value(100);

-- 명시적 캐스팅으로 정확한 버전 선택
SELECT calculate_value(100::INTEGER);
SELECT calculate_value(100::NUMERIC);

-- 사용자 정의 타입과 혼용 시 CAST 활용
CREATE DOMAIN positive_int AS INTEGER CHECK (VALUE > 0);

SELECT calculate_value(CAST(50 AS positive_int));

-- 타입 확인용 쿼리 (디버깅 시 유용)
SELECT pg_typeof(100::INTEGER) AS type_check;
SELECT pg_typeof(100::NUMERIC) AS type_check;

에러 추적 및 디버깅

에러 발생 시 어떤 타입이 사용되고 있는지 확인하는 쿼리를 활용하세요.

-- 현재 등록된 사용자 정의 타입 목록 확인
SELECT typname, typtype, typbasetype::regtype
FROM pg_type
WHERE typtype IN ('c', 'd')  -- c: composite, d: domain
  AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
ORDER BY typname;

-- 함수 시그니처 확인 (오버로딩 충돌 디버깅)
SELECT proname, pg_get_function_identity_arguments(oid) AS args, prorettype::regtype
FROM pg_proc
WHERE proname = 'your_function_name'
  AND pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public');

-- 암묵적 캐스트 가능 여부 확인
SELECT castsource::regtype, casttarget::regtype, castcontext
FROM pg_cast
WHERE castsource = 'INTEGER'::regtype
   OR casttarget = 'INTEGER'::regtype;

예방 방법

1. 명시적 타입 캐스팅 정책 수립

팀 내 SQL 코딩 컨벤션에 “타입이 불명확할 경우 반드시 명시적 캐스팅을 사용한다” 는 규칙을 포함하세요. 암묵적 형 변환에 의존하는 코드는 PostgreSQL 버전 업그레이드나 타입 시스템 변경 시 예기치 않은 에러를 유발할 수 있습니다. CI/CD 파이프라인에 SQL 린터(예: sqlfluff)를 도입하여 명시적 캐스팅이 없는 타입 혼용을 자동으로 감지하는 것을 권장합니다.

-- 나쁜 예 (암묵적 변환에 의존)
INSERT INTO orders (amount) VALUES (100);

-- 좋은 예 (명시적 캐스팅)
INSERT INTO orders (amount) VALUES (100::NUMERIC(10,2));

2. 복합 타입 및 도메인 타입 문서화와 정기적 검토

복잡한 타입 계층 구조를 사용하는 경우, 반드시 타입 정의와 그 계층 관계를 문서화하고 주기적으로 검토하세요. pg_type, pg_class, pg_attribute 시스템 카탈로그를 활용한 타입 감사(type audit) 스크립트를 정기적으로 실행하여 의도치 않은 타입 의존성을 미리 발견하는 것이 중요합니다.

-- 타입 계층 감사 쿼리 예시
SELECT
    n.nspname AS schema_name,
    t.typname AS type_name,
    CASE t.typtype
        WHEN 'c' THEN 'composite'
        WHEN 'd' THEN 'domain'
        WHEN 'e' THEN 'enum'
        ELSE t.typtype::TEXT
    END AS type_category,
    t.typbasetype::regtype AS base_type
FROM pg_type t
JOIN pg_namespace n ON t.typnamespace = n.oid
WHERE t.typtype IN ('c', 'd', 'e')
  AND n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schema_name, type_category, type_name;

관련 에러

  • 22000 (data_exception): 데이터 예외의 상위 카테고리 에러로, 2200G를 포함한 다양한 데이터 타입 관련 에러의 부모 에러 코드입니다.
  • 42804 (datatype_mismatch): 컬럼 또는 표현식의 데이터 타입이 기대하는 타입과 맞지 않을 때 발생하며, 2200G와 혼동하기 쉽습니다.
  • 42883 (undefined_function): 오버로딩된 함수에서 적합한 시그니처를 찾지 못할 때 발생하며, 타입 불일치로 인해 함께 나타나는 경우가 많습니다.
  • 2200M (invalid_xml_document): XML 처리 중 문서 구조가 잘못된 경우 발생하며, XML 타입 관련 에러 맥락에서 2200G와 함께 주의해야 할 에러입니다.

DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기