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

2200G
2026년 08월 15일 | DBMS Error 가이드

이 글에서 다루는 내용

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

2200G most specific type mismatch 는?

PostgreSQL 에러 코드 2200G: most specific type mismatch는 SQL/XML 또는 타입 계층 구조에서 가장 구체적인(most specific) 타입이 서로 일치하지 않을 때 발생하는 에러입니다. 주로 XML 타입 처리, 사용자 정의 타입(UDT), 또는 복합 타입(composite type)을 다루는 쿼리에서 타입 간의 불일치가 있을 때 트리거됩니다. 이 에러는 PostgreSQL이 타입 결정 과정에서 명확한 단일 타입을 식별할 수 없거나, 서로 다른 타입 체계를 가진 값들이 하나의 컨텍스트에서 충돌할 때 나타납니다.


주요 발생 원인

1. XMLFOREST / XMLELEMENT 등 XML 함수에서의 타입 불일치

PostgreSQL의 XML 관련 함수(XMLFOREST, XMLELEMENT, XMLAGG 등)는 입력값의 타입에 매우 민감합니다. 서로 다른 타입의 값을 동일한 XML 노드 집합으로 구성하려 할 때, 각 값의 “가장 구체적인 타입”이 통일되지 않으면 이 에러가 발생합니다. 예를 들어, INTEGERTEXT가 혼재된 상태로 XMLFOREST를 사용하면 PostgreSQL은 가장 구체적인 공통 타입을 결정하지 못해 에러를 던집니다.

2. UNION / UNION ALL 쿼리에서 복합 타입의 불일치

UNION 또는 UNION ALL을 사용할 때, 각 SELECT 절에서 반환되는 컬럼의 타입이 정확히 일치하지 않고 타입 계층 구조 상에서도 호환되지 않는 경우 이 에러가 발생할 수 있습니다. 특히 사용자 정의 도메인 타입(domain type)이나 복합 타입이 포함된 경우, PostgreSQL은 두 타입 중 어느 것이 더 구체적인지 판단하지 못해 에러를 발생시킵니다. 이는 단순한 암묵적 형변환(implicit cast)으로 해결되지 않을 수 있어 명시적 캐스팅이 필요합니다.

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

PostgreSQL은 함수 오버로딩을 지원하여 같은 이름의 함수를 여러 타입 시그니처로 정의할 수 있습니다. 그러나 호출 시 전달된 인자의 타입이 여러 오버로딩 버전에 동시에 매칭될 수 있거나, 또는 가장 구체적인 타입으로 해석되는 경우가 명확하지 않을 때 2200G 에러가 발생합니다. 특히 서브타입 관계가 있는 사용자 정의 타입들 사이에서 이 문제가 자주 나타납니다.


해결 방법

원인 1: XML 함수에서의 타입 불일치 해결

명시적으로 각 값을 TEXT 또는 원하는 타입으로 캐스팅하여 XML 함수에 전달하면 해결됩니다.

-- 문제가 되는 쿼리 (INTEGER와 TEXT 혼재)
SELECT XMLFOREST(
    employee_id,        -- INTEGER 타입
    employee_name,      -- TEXT 타입
    salary              -- NUMERIC 타입
)
FROM employees;

-- 해결: 모든 값을 명시적으로 TEXT로 캐스팅
SELECT XMLFOREST(
    employee_id::TEXT AS "employeeId",
    employee_name::TEXT AS "employeeName",
    salary::TEXT AS "salary"
)
FROM employees;

-- 또는 CAST 함수 사용
SELECT XMLFOREST(
    CAST(employee_id AS TEXT) AS "employeeId",
    CAST(employee_name AS TEXT) AS "employeeName",
    CAST(salary AS TEXT) AS "salary"
)
FROM employees;

원인 2: UNION 쿼리에서 복합 타입 불일치 해결

각 SELECT 절의 컬럼 타입을 명시적으로 통일시켜 줍니다.

-- 문제가 되는 쿼리
SELECT id, name, created_at::DATE AS event_date FROM orders
UNION ALL
SELECT id, description, updated_at::TIMESTAMP AS event_date FROM products;
-- event_date 컬럼의 타입이 DATE vs TIMESTAMP로 불일치

-- 해결: 동일한 타입으로 명시적 캐스팅
SELECT id, name, created_at::TIMESTAMP AS event_date FROM orders
UNION ALL
SELECT id, description, updated_at::TIMESTAMP AS event_date FROM products;

-- 도메인 타입 불일치 예시 해결
-- 도메인 정의
CREATE DOMAIN positive_int AS INTEGER CHECK (VALUE > 0);
CREATE DOMAIN non_negative_int AS INTEGER CHECK (VALUE >= 0);

-- 문제: 두 도메인 타입이 UNION에서 충돌
-- 해결: 기본 타입으로 명시적 캐스팅
SELECT id::INTEGER, value::INTEGER FROM table_a
UNION ALL
SELECT id::INTEGER, quantity::INTEGER FROM table_b;

원인 3: 함수 오버로딩 모호성 해결

명시적 캐스팅으로 함수가 사용할 타입 시그니처를 정확히 지정합니다.

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

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

-- 문제: 모호한 타입으로 인한 에러 가능성
SELECT process_value(42);  -- 모호할 수 있음

-- 해결: 명시적 타입 캐스팅으로 정확한 오버로딩 버전 지정
SELECT process_value(42::INTEGER);   -- INTEGER 버전 명시
SELECT process_value(42::NUMERIC);   -- NUMERIC 버전 명시

-- 함수 호출 시 타입 불일치 확인 쿼리
SELECT proname, proargtypes::TEXT, prorettype::TEXT
FROM pg_proc
WHERE proname = 'process_value';

추가: XML 처리 시 전체 타입 검증 쿼리

-- 테이블 컬럼 타입 확인
SELECT column_name, data_type, udt_name
FROM information_schema.columns
WHERE table_name = 'your_table_name'
  AND table_schema = 'public'
ORDER BY ordinal_position;

-- XML 생성 전 타입 명시 안전 패턴
SELECT XMLELEMENT(
    NAME "employee",
    XMLFOREST(
        COALESCE(employee_id::TEXT, '') AS "id",
        COALESCE(employee_name, 'Unknown') AS "name",
        TO_CHAR(hire_date, 'YYYY-MM-DD') AS "hireDate",
        ROUND(salary, 2)::TEXT AS "salary"
    )
)
FROM employees
WHERE department_id = 10;

예방 방법

1. 타입 명시 코딩 컨벤션 수립 및 준수

팀 내에서 SQL 작성 시 암묵적 타입 변환에 의존하지 않고, 항상 명시적 캐스팅(::type 또는 CAST(value AS type))을 사용하는 컨벤션을 수립하세요. 특히 XML 함수, UNION 쿼리, 복합 타입을 다루는 코드에서는 모든 값의 타입을 명시적으로 선언하는 것을 규칙으로 정해 코드 리뷰 체크리스트에 포함시키는 것이 좋습니다. CI/CD 파이프라인에 pg_query 또는 pganalyze 같은 정적 분석 도구를 도입하면 배포 전 타입 불일치를 사전에 감지할 수 있습니다.

2. 통합 테스트 환경에서의 타입 검증 자동화

개발 환경과 프로덕션 환경 간의 타입 불일치를 방지하기 위해, 스키마 변경 시마다 자동화된 테스트를 실행하여 모든 쿼리의 반환 타입을 검증하는 체계를 마련하세요. pg_typeof() 함수를 활용한 단위 테스트를 작성하면 타입 불일치를 개발 단계에서 조기에 발견할 수 있습니다.

-- pg_typeof()를 활용한 타입 검증 예시
SELECT pg_typeof(employee_id) AS id_type,
       pg_typeof(salary) AS salary_type,
       pg_typeof(hire_date) AS date_type
FROM employees
LIMIT 1;

-- 예상 타입과 실제 타입 비교 검증
DO $$
DECLARE
    v_type TEXT;
BEGIN
    SELECT pg_typeof(salary)::TEXT INTO v_type
    FROM employees LIMIT 1;

    IF v_type != 'numeric' THEN
        RAISE EXCEPTION 'Type mismatch: expected numeric, got %', v_type;
    END IF;
    RAISE NOTICE 'Type validation passed: %', v_type;
END;
$$;

관련 에러

  • 22000 – data exception: 데이터 예외의 상위 분류로, 2200G는 이 카테고리 하위에 속합니다.
  • 42804 – datatype mismatch: 함수 인자나 연산자 피연산자의 타입이 맞지 않을 때 발생하며, 2200G와 유사하지만 더 일반적인 타입 불일치 에러입니다.
  • 42P18 – indeterminate datatype: 타입을 전혀 결정할 수 없을 때 발생하며, 2200G와 달리 타입 자체가 불명확한 경우입니다. NULL 리터럴만 사용하거나 타입 힌트가 전혀 없을 때 나타납니다.
  • 2200M – invalid XML document: XML 관련 처리에서 함께 발생할 수 있는 에러로, XML 함수 사용 시 2200G와 함께 주의해야 합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기