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

22032
2026년 06월 17일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22032 invalid json text 는?

PostgreSQL 에러 코드 22032는 invalid json text로, JSON 형식이 올바르지 않은 문자열을 JSON 타입으로 파싱하거나 변환하려고 할 때 발생합니다. 이 에러는 json, jsonb 컬럼에 데이터를 삽입하거나 ::json, ::jsonb 캐스팅, 또는 json_, jsonb_ 함수를 사용할 때 입력값이 유효한 JSON 구조를 따르지 않을 경우 트리거됩니다. 애플리케이션에서 동적으로 JSON 문자열을 조합하거나 외부 API의 응답을 그대로 저장할 때 특히 자주 발생하는 실무 에러입니다.


주요 발생 원인

1. 잘못된 JSON 문법 (따옴표, 괄호, 쉼표 오류)

JSON 표준에서는 키(key)는 반드시 큰따옴표(")로 감싸야 하며, 배열과 객체의 괄호가 정확히 닫혀야 합니다. 작은따옴표를 사용하거나 마지막 항목 뒤에 불필요한 쉼표(trailing comma)를 넣는 실수가 매우 흔하며, 이는 JavaScript 스타일 객체 표기법과 혼동에서 비롯됩니다. 또한 중괄호 {} 또는 대괄호 []가 열렸지만 닫히지 않은 경우도 이 에러를 유발합니다.

2. NULL 또는 빈 문자열, 비JSON 텍스트를 JSON으로 캐스팅

애플리케이션 레이어에서 빈 문자열('')이나 NULL이 아닌 일반 텍스트(예: "hello", N/A, undefined)를 JSON 컬럼에 그대로 삽입하려 할 때 에러가 발생합니다. 특히 ORM이나 마이그레이션 스크립트에서 기본값을 설정하지 않거나 데이터 변환 로직 없이 레거시 데이터를 jsonb 컬럼으로 마이그레이션할 때 대량으로 발생할 수 있습니다.

3. 이스케이프 처리 누락 또는 인코딩 문제

JSON 문자열 내부에 이스케이프 처리 없이 큰따옴표(")나 역슬래시(\)가 포함되면 파서가 JSON 구조를 잘못 해석하게 됩니다. 또한 UTF-8이 아닌 인코딩의 특수문자가 포함되거나, 제어 문자(Control Character, ASCII 0~31)가 JSON 문자열 내에 직접 포함된 경우에도 유효하지 않은 JSON으로 판별됩니다.


해결 방법

원인 1 해결: JSON 문법 교정

잘못된 JSON 예제와 올바른 형태를 비교하고, jsonb_typeof 또는 캐스팅을 통해 사전 검증합니다.

-- 오류 발생 예시: 작은따옴표, trailing comma 사용
SELECT '{"name": ''Alice'', "age": 30,}'::jsonb;
-- ERROR:  invalid input syntax for type json

-- 올바른 JSON 형식
SELECT '{"name": "Alice", "age": 30}'::jsonb;

-- JSON 유효성 검사 함수 (PostgreSQL 16+)
SELECT pg_input_is_valid('{"name": "Alice", "age": 30}', 'jsonb');
-- 결과: true

SELECT pg_input_is_valid('{"name": ''bad''}', 'jsonb');
-- 결과: false

-- 삽입 전 유효성 검사 후 처리
DO $$
DECLARE
    v_input TEXT := '{"user": "bob", "score": 99}';
BEGIN
    IF pg_input_is_valid(v_input, 'jsonb') THEN
        INSERT INTO user_logs (data) VALUES (v_input::jsonb);
    ELSE
        RAISE WARNING 'Invalid JSON skipped: %', v_input;
    END IF;
END;
$$;

원인 2 해결: 빈 문자열 및 비JSON 텍스트 처리

삽입 전 값을 검사하여 빈 문자열은 NULL로, 유효하지 않은 텍스트는 래핑하거나 건너뜁니다.

-- 빈 문자열 삽입 시 에러 발생
SELECT ''::jsonb;
-- ERROR: invalid input syntax for type json

-- NULLIF를 활용하여 빈 문자열을 NULL로 처리
INSERT INTO api_responses (payload)
VALUES (NULLIF('', '')::jsonb);

-- 레거시 텍스트 데이터를 JSON 문자열로 안전하게 래핑
UPDATE legacy_table
SET json_col = to_jsonb(old_text_col)
WHERE json_col IS NULL;

-- 배치 마이그레이션 시 유효하지 않은 행 필터링
INSERT INTO new_table (id, data)
SELECT id, raw_json::jsonb
FROM old_table
WHERE pg_input_is_valid(raw_json, 'jsonb') = true;

-- 유효하지 않은 데이터 로그 남기기
INSERT INTO migration_errors (id, raw_data, error_time)
SELECT id, raw_json, NOW()
FROM old_table
WHERE pg_input_is_valid(raw_json, 'jsonb') = false;

원인 3 해결: 이스케이프 및 인코딩 처리

to_json() / to_jsonb() 함수를 활용하면 PostgreSQL이 자동으로 이스케이프 처리를 수행합니다.

-- 이스케이프 미처리로 에러 발생
SELECT '{"message": "He said "Hello""}'::jsonb;
-- ERROR: invalid input syntax for type json

-- to_jsonb()를 사용하면 자동 이스케이프 처리
SELECT to_jsonb('He said "Hello"'::text);
-- 결과: "He said \"Hello\""

-- 제어 문자 제거 후 JSON 변환
SELECT regexp_replace(raw_input, '[[:cntrl:]]', '', 'g')::jsonb
FROM (SELECT '{"msg": "line1\nline2"}' AS raw_input) t;

-- json_build_object 활용으로 안전한 JSON 생성
SELECT json_build_object(
    'user', '홍길동',
    'message', 'He said "안녕하세요"',
    'score', 98.5
);

-- 함수로 안전한 JSON 변환 래퍼 만들기
CREATE OR REPLACE FUNCTION safe_to_jsonb(p_text TEXT)
RETURNS JSONB AS $$
BEGIN
    RETURN p_text::jsonb;
EXCEPTION WHEN OTHERS THEN
    RETURN NULL;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- 사용 예
SELECT safe_to_jsonb('{"valid": true}');    -- 정상 반환
SELECT safe_to_jsonb('not a json');          -- NULL 반환

예방 방법

1. 애플리케이션 레벨에서 JSON 유효성 검증 후 DB에 전달

데이터베이스에 도달하기 전, 애플리케이션(Python의 json.dumps(), Node.js의 JSON.stringify(), Java의 Jackson 등)에서 반드시 직렬화된 JSON 문자열을 생성하여 전달해야 합니다. 수작업으로 JSON 문자열을 문자열 연산으로 조합하는 방식은 절대 지양하고, 항상 언어에서 제공하는 JSON 직렬화 라이브러리를 사용하는 것이 원칙입니다. PostgreSQL 16 이상 환경에서는 pg_input_is_valid() 함수를 CHECK 제약 또는 트리거에 활용하여 DB 레벨에서도 이중으로 방어할 수 있습니다.

-- CHECK 제약 조건으로 유효하지 않은 JSON 원천 차단
ALTER TABLE api_logs
ADD CONSTRAINT chk_valid_payload
CHECK (payload IS NULL OR pg_input_is_valid(payload::text, 'jsonb'));

2. json 타입 대신 jsonb 타입 사용 및 컬럼 기본값 명확히 지정

jsonb 타입은 저장 시 파싱 및 검증을 수행하므로 잘못된 JSON이 저장되는 것을 원천 차단합니다. 또한 JSON 컬럼의 기본값을 '{}'::jsonb 또는 '[]'::jsonb와 같이 명시적으로 설정하면 빈 값 삽입으로 인한 에러를 예방할 수 있습니다. 데이터 마이그레이션이나 ETL 파이프라인에서는 항상 스테이징 테이블을 TEXT 타입으로 먼저 적재한 후, 검증된 데이터만 JSONB 컬럼으로 이동하는 2단계 전략을 권장합니다.

-- 안전한 테이블 설계 예시
CREATE TABLE user_profiles (
    id          SERIAL PRIMARY KEY,
    user_id     INT NOT NULL,
    metadata    JSONB NOT NULL DEFAULT '{}',
    settings    JSONB NOT NULL DEFAULT '{"theme": "light", "lang": "ko"}',
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

관련 에러

  • 22P02 (invalid_text_representation): JSON 외에도 integer, boolean 등 다른 타입 변환 실패 시 발생하는 유사한 형식 오류 에러입니다.
  • 22P05 (untranslatable_character): 데이터베이스 인코딩으로 변환할 수 없는 문자가 포함된 경우 발생하며, JSON 내 특수문자 처리와 함께 자주 동반됩니다.
  • 23502 (not_null_violation): JSON 컬럼에 NOT NULL 제약이 있을 때 NULL 또는 빈 값을 삽입하려는 경우 함께 발생할 수 있습니다.
  • 42883 (undefined_function): 잘못된 타입의 인수를 JSON 함수에 전달했을 때 발생하며, 22032와 함께 JSON 처리 오류의 대표적인 연관 에러입니다.
DBMS 에러 코드 시리즈

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

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

댓글 남기기