2026년 06월 20일 | DBMS Error 가이드
이 글에서 다루는 내용
2203G 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2203G sql json item cannot be cast to target type 는?
PostgreSQL 에러 코드 2203G는 SQL/JSON 경로 표현식(SQL/JSON path expression)을 사용할 때, JSON 데이터 내의 특정 항목을 목표 데이터 타입으로 변환(캐스팅)할 수 없을 때 발생합니다. 예를 들어, JSON 필드에 저장된 문자열 값을 INTEGER나 DATE 타입으로 직접 변환하려 할 때, 해당 값이 변환 규칙에 맞지 않으면 이 에러가 발생합니다. 이 에러는 PostgreSQL 12 이상에서 jsonb_path_query, jsonb_path_value, @?, @@ 연산자 등 SQL/JSON 기능을 활용하는 쿼리에서 주로 나타납니다.
주요 발생 원인
1. 숫자로 변환할 수 없는 문자열 값이 JSON에 포함된 경우
JSON 필드 안에 숫자처럼 보이지만 실제로는 숫자가 아닌 값(예: "abc", "N/A", "12px")이 저장되어 있을 때, 이를 INTEGER 또는 NUMERIC 타입으로 캐스팅하려 하면 에러가 발생합니다. SQL/JSON 경로 함수는 런타임에 타입 변환을 시도하므로, 쿼리 작성 시점이 아닌 실행 시점에 이 문제가 드러나는 경우가 많습니다.
2. 날짜/시간 형식이 맞지 않는 값을 DATE 또는 TIMESTAMP로 변환 시도
JSON 데이터 내 날짜 문자열이 ISO 8601 표준(YYYY-MM-DD)이 아닌 다른 형식(예: "31/12/2023", "Dec 31, 2023")으로 저장되어 있을 때 문제가 발생합니다. PostgreSQL의 SQL/JSON 경로 표현식은 날짜 변환에 있어 ISO 8601 형식을 기본으로 사용하기 때문에, 형식이 다르면 변환 자체가 실패합니다.
3. 배열 또는 객체를 스칼라 타입으로 직접 캐스팅 시도
JSON 배열([1, 2, 3])이나 JSON 객체({"key": "value"})를 INTEGER, TEXT 같은 단일 스칼라 타입으로 직접 변환하려 할 때도 이 에러가 발생합니다. SQL/JSON 경로 표현식은 배열이나 객체 전체를 스칼라 값으로 자동 변환하지 않으므로, 반드시 경로 표현식으로 특정 요소를 먼저 선택해야 합니다.
해결 방법
원인 1 해결: 문자열 숫자 변환 오류 처리
jsonb_path_query 사용 시 try 키워드 또는 조건 분기를 활용하여 변환 실패를 안전하게 처리합니다.
-- 문제가 되는 쿼리 예시
SELECT jsonb_path_query('{"amount": "abc"}', '$.amount.integer()');
-- ERROR: 2203G: sql json item cannot be cast to target type
-- 해결책 1: jsonb_path_query_first 와 예외 처리를 활용
SELECT
CASE
WHEN jsonb_typeof(data->'amount') = 'number'
THEN (data->>'amount')::INTEGER
ELSE NULL
END AS safe_amount
FROM (
SELECT '{"amount": "abc"}'::jsonb AS data
) sub;
-- 해결책 2: try 수식을 사용한 안전한 변환 (PostgreSQL 14+)
SELECT jsonb_path_query_first(
'{"amount": "123"}',
'strict $.amount.integer()'
);
-- 정상 동작 예시
SELECT jsonb_path_query('{"amount": 123}', '$.amount.integer()');
-- 결과: 123
원인 2 해결: 날짜 형식 표준화
JSON 데이터에 날짜를 저장할 때는 ISO 8601 형식을 사용하고, 비표준 형식의 경우 to_date() 함수를 활용합니다.
-- 문제가 되는 쿼리 예시 (비표준 날짜 형식)
SELECT jsonb_path_query(
'{"event_date": "31/12/2023"}',
'$.event_date.date()'
);
-- ERROR: 2203G: sql json item cannot be cast to target type
-- 해결책 1: ISO 8601 형식으로 저장된 경우 정상 동작
SELECT jsonb_path_query(
'{"event_date": "2023-12-31"}',
'$.event_date.date()'
);
-- 결과: "2023-12-31"
-- 해결책 2: 비표준 형식은 꺼내서 PostgreSQL 함수로 변환
SELECT to_date(data->>'event_date', 'DD/MM/YYYY') AS converted_date
FROM (
SELECT '{"event_date": "31/12/2023"}'::jsonb AS data
) sub;
-- 해결책 3: 변환 전 형식 검증 추가
SELECT
CASE
WHEN data->>'event_date' ~ '^\d{4}-\d{2}-\d{2}$'
THEN (data->>'event_date')::DATE
ELSE NULL
END AS safe_date
FROM (
SELECT '{"event_date": "2023-12-31"}'::jsonb AS data
) sub;
원인 3 해결: 배열/객체에서 스칼라 값 올바르게 추출
-- 문제가 되는 쿼리 예시 (배열을 직접 integer로 변환 시도)
SELECT jsonb_path_query('{"scores": [10, 20, 30]}', '$.scores.integer()');
-- ERROR: 2203G: sql json item cannot be cast to target type
-- 해결책 1: 배열의 특정 인덱스 요소를 지정하여 변환
SELECT jsonb_path_query(
'{"scores": [10, 20, 30]}',
'$.scores[0].integer()'
);
-- 결과: 10
-- 해결책 2: 배열의 모든 요소를 integer로 변환
SELECT jsonb_path_query(
'{"scores": [10, 20, 30]}',
'$.scores[*].integer()'
);
-- 결과: 10, 20, 30 (각각)
-- 해결책 3: unnest를 활용한 배열 전개
SELECT (elem)::INTEGER AS score
FROM jsonb_array_elements_text('{"scores": [10, 20, 30]}'::jsonb->'scores') AS elem;
예방 방법
1. JSON 데이터 저장 시 스키마 검증(Schema Validation) 적용
JSON 데이터를 테이블에 삽입하기 전에 CHECK 제약 조건이나 트리거를 활용하여 데이터 타입과 형식을 사전에 검증하는 것이 중요합니다. 특히 날짜 필드는 ISO 8601 형식 준수 여부를, 숫자 필드는 실제 숫자 값인지 여부를 반드시 확인해야 합니다.
-- CHECK 제약 조건으로 JSON 필드 형식 검증 예시
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
data JSONB NOT NULL,
CONSTRAINT chk_amount_is_number
CHECK (jsonb_typeof(data->'amount') = 'number'),
CONSTRAINT chk_order_date_format
CHECK (
data->>'order_date' IS NULL OR
data->>'order_date' ~ '^\d{4}-\d{2}-\d{2}$'
)
);
-- 삽입 테스트
INSERT INTO orders (data) VALUES ('{"amount": 100, "order_date": "2024-01-15"}'); -- 성공
INSERT INTO orders (data) VALUES ('{"amount": "abc", "order_date": "2024-01-15"}'); -- 실패
2. SQL/JSON 경로 표현식 사용 시 strict 모드와 에러 억제 활용
lax 모드(기본값)와 strict 모드의 차이를 이해하고, 프로덕션 쿼리에서는 jsonb_path_query_first 또는 jsonb_path_exists로 값의 존재 여부를 먼저 확인한 후 변환을 진행하는 패턴을 습관화하세요.
-- 안전한 JSON 값 추출 패턴 (프로덕션 권장)
SELECT
CASE
WHEN jsonb_path_exists(data, '$.amount') AND jsonb_typeof(data->'amount') = 'number'
THEN jsonb_path_query_first(data, '$.amount.integer()')::INTEGER
ELSE NULL
END AS safe_integer_amount
FROM your_table;
관련 에러
22023(invalid_parameter_value): SQL/JSON 경로 표현식 자체가 잘못된 파라미터를 포함할 때 발생합니다.22P02(invalid_text_representation):::INTEGER,::DATE등의 일반 PostgreSQL 캐스팅에서 변환 불가 문자열이 있을 때 발생하며,2203G와 유사한 상황에서 나타날 수 있습니다.2203F(sql_json_array_not_found): SQL/JSON 경로 표현식이 배열을 기대하는데 배열이 아닌 값이 반환될 때 발생합니다.2203W(sql_json_scalar_required): SQL/JSON 연산이 스칼라 값을 필요로 하는데 배열 또는 객체가 반환될 때 발생하며, 원인 3과 밀접하게 연관됩니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.