2026년 10월 28일 | DBMS Error 가이드
이 글에서 다루는 내용
2203G 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2203G sql json item cannot be cast to target type 는?
PostgreSQL 에러 코드 2203G (sql_json_item_cannot_be_cast_to_target_type)는 SQL/JSON 경로 표현식(Path Expression)을 사용할 때 JSON 데이터 내의 값을 지정한 대상 타입(target type)으로 형변환(cast)할 수 없을 때 발생합니다. 예를 들어 JSON 배열이나 객체 내부의 문자열 값을 INTEGER, DATE, BOOLEAN 등 특정 SQL 데이터 타입으로 변환하려 할 때 해당 값이 그 타입에 맞지 않으면 이 에러가 발생합니다. 주로 JSON_VALUE(), JSON_QUERY(), JSONB_PATH_QUERY() 등의 함수 또는 @?, @@ 연산자와 함께 사용하는 경로 표현식에서 자주 목격됩니다.
주요 발생 원인
- JSON 값이 대상 SQL 타입과 호환되지 않는 경우
가장 흔한 원인입니다. JSON 내부에 저장된 값이 문자열("abc")인데 이를 INTEGER나 NUMERIC으로 변환하려 할 때 발생합니다. JSON은 타입 제약이 느슨하기 때문에 숫자처럼 보이지 않는 문자열도 충분히 저장될 수 있으며, 이를 엄격한 SQL 타입으로 강제 변환하면 PostgreSQL은 이 에러를 던집니다. 특히 외부 API나 서드파티 시스템으로부터 수신한 JSON 데이터는 예상치 못한 값 형식을 포함하는 경우가 많습니다.
- JSON 경로 표현식에서 RETURNING 절의 타입 불일치
PostgreSQL 14 이후 도입된 JSON_VALUE() 함수는 RETURNING 절을 통해 반환 타입을 명시할 수 있습니다. 이때 경로가 가리키는 JSON 값이 RETURNING에 지정된 타입으로 자동 변환될 수 없을 경우 이 에러가 발생합니다. 예를 들어 RETURNING DATE를 지정했는데 실제 JSON 값이 "2024/13/45"처럼 유효하지 않은 날짜 형식이라면 PostgreSQL은 형변환을 거부합니다.
- JSONB 경로 함수의 strict 모드에서의 타입 불일치
jsonb_path_query(), jsonb_path_value() 등의 함수에서 strict 모드(strict $로 시작하는 경로)를 사용할 때, 경로가 반환하는 값이 예상 타입과 다르면 에러를 발생시킵니다. lax 모드와 달리 strict 모드는 타입 불일치에 관대하지 않기 때문에, 배열 언래핑(unwrapping)이나 타입 강제 변환 시 더 엄격하게 동작하여 예기치 않게 이 에러가 발생할 수 있습니다.
해결 방법
원인 1 해결: 형변환 전 값 유효성 검사 및 조건 처리
JSON_VALUE() 또는 jsonb_path_query()를 사용할 때, ON ERROR 절을 활용하거나 형변환 전에 값을 미리 검증하세요.
-- 문제가 되는 쿼리 예시
SELECT JSON_VALUE('{"age": "not_a_number"}', '$.age' RETURNING INTEGER);
-- 에러: sql json item cannot be cast to target type
-- 해결 방법 1: ON ERROR 절로 기본값 지정
SELECT JSON_VALUE(
'{"age": "not_a_number"}',
'$.age'
RETURNING INTEGER
NULL ON ERROR -- 에러 발생 시 NULL 반환
);
-- 해결 방법 2: DEFAULT 값 지정
SELECT JSON_VALUE(
'{"age": "not_a_number"}',
'$.age'
RETURNING INTEGER
DEFAULT -1 ON ERROR -- 에러 발생 시 -1 반환
);
-- 해결 방법 3: CASE 문과 jsonb 연산자로 유효성 검사 후 변환
SELECT
CASE
WHEN (data->>'age') ~ '^\d+$'
THEN (data->>'age')::INTEGER
ELSE NULL
END AS age_int
FROM (SELECT '{"age": "not_a_number"}'::jsonb AS data) t;
원인 2 해결: RETURNING 절 타입 맞추기 또는 TEXT로 먼저 받기
-- 문제가 되는 쿼리 예시
SELECT JSON_VALUE(
'{"birthday": "2024/13/45"}',
'$.birthday'
RETURNING DATE
);
-- 에러 발생
-- 해결 방법 1: TEXT로 먼저 받고 애플리케이션에서 처리
SELECT JSON_VALUE(
'{"birthday": "2024/13/45"}',
'$.birthday'
RETURNING TEXT
) AS birthday_text;
-- 해결 방법 2: TO_DATE 함수로 형식 맞춰 변환
SELECT TO_DATE(
JSON_VALUE('{"birthday": "2024-12-25"}', '$.birthday'),
'YYYY-MM-DD'
) AS birthday;
-- 해결 방법 3: NULL ON ERROR로 안전하게 처리
SELECT JSON_VALUE(
'{"birthday": "2024/13/45"}',
'$.birthday'
RETURNING DATE
NULL ON ERROR
) AS safe_birthday;
원인 3 해결: strict 모드 대신 lax 모드 사용 또는 경로 수정
-- 문제가 되는 쿼리 (strict 모드)
SELECT jsonb_path_query(
'{"scores": [1, 2, "three", 4]}',
'strict $.scores[*].integer()'
);
-- 에러: sql json item cannot be cast to target type
-- 해결 방법 1: lax 모드 사용 (기본값)
SELECT jsonb_path_query(
'{"scores": [1, 2, "three", 4]}',
'lax $.scores[*] ? (@ != "three")'
);
-- 해결 방법 2: 타입 필터링 적용
SELECT jsonb_path_query(
'{"scores": [1, 2, "three", 4]}',
'$.scores[*] ? (@.type() == "number")'
);
-- 해결 방법 3: jsonb_path_query_array로 배열 전체 안전 처리
SELECT jsonb_path_query_array(
'{"scores": [1, 2, 3, 4]}',
'$.scores[*] ? (@.type() == "number")'
) AS valid_scores;
-- 실무에서 자주 쓰는 패턴: 테이블 컬럼에서 안전하게 숫자 추출
SELECT
id,
jsonb_path_query_first(
payload,
'$.amount ? (@.type() == "number")'
)::text::numeric AS amount
FROM orders
WHERE jsonb_path_exists(payload, '$.amount ? (@.type() == "number")');
예방 방법
- JSON 데이터 입력 시 스키마 유효성 검사 적용
JSON 데이터를 테이블에 저장하기 전 CHECK 제약 조건이나 트리거를 통해 필수 필드의 타입을 검증하세요. PostgreSQL의 jsonb_path_exists() 또는 JSON Schema 검증 라이브러리를 활용하면 입력 단계에서 타입 불일치를 사전에 차단할 수 있습니다.
“`sql
— CHECK 제약 조건으로 amount 필드가 반드시 숫자임을 보장
ALTER TABLE orders
ADD CONSTRAINT chk_amount_is_number
CHECK (
payload->’amount’ IS NULL
OR jsonb_typeof(payload->’amount’) = ‘number’
);
“`
- JSON_VALUE 및 jsonb_path 함수 사용 시 항상 ON ERROR 절 또는 타입 필터 명시
운영 환경의 쿼리에서는 반드시 NULL ON ERROR 또는 DEFAULT 값 ON ERROR 절을 명시하고, 가능한 경우 ? (@.type() == "number") 같은 타입 필터를 경로에 포함시키세요. 이를 통해 예기치 못한 JSON 데이터 형식이 들어와도 쿼리가 중단되지 않고 안전하게 처리됩니다.
관련 에러
- 22032 (
invalid_json_text): JSON 문자열 자체가 유효하지 않은 형식일 때 발생합니다. - 22033 (
invalid_sql_json_subscript): JSON 배열 인덱스가 잘못된 타입이거나 범위를 벗어날 때 발생합니다. - 2203F (
sql_json_array_not_found): JSON 경로 표현식이 배열을 찾지 못할 때 발생합니다. - 2203H (
sql_json_object_not_found): JSON 경로에서 객체를 찾지 못할 때 발생합니다. - 2203W (
sql_json_scalar_required): JSON 경로가 스칼라 값을 기대하지만 배열/객체가 반환될 때 발생합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.