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

22022
2026년 10월 13일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22022 indicator overflow 는?

PostgreSQL 에러 코드 22022는 indicator overflow 에러로, 주로 ECPG(Embedded C for PostgreSQL) 또는 ODBC/JDBC 드라이버를 통해 데이터베이스와 통신할 때 호스트 변수의 인디케이터(indicator) 변수가 표현할 수 있는 범위를 초과하는 경우 발생합니다. 인디케이터 변수는 NULL 값이나 데이터 잘림(truncation) 여부를 클라이언트 애플리케이션에 전달하는 역할을 하는데, 이 변수가 담을 수 없을 만큼 큰 값이 반환되거나, 잘린 데이터의 크기가 인디케이터의 최대 표현 범위를 넘어설 때 이 에러가 발생합니다. 실무에서는 대용량 문자열이나 바이너리 데이터를 소형 버퍼 변수에 매핑하려 할 때 자주 마주치게 됩니다.


주요 발생 원인

1. 인디케이터 변수의 데이터 타입 범위 초과

ECPG 또는 Pro*C 스타일의 임베디드 SQL에서 인디케이터 변수는 보통 short (2바이트 정수) 타입으로 선언됩니다. short 타입의 최대값은 32,767인데, 반환되는 데이터의 실제 길이가 이 값을 초과하면 인디케이터 변수가 해당 값을 저장하지 못하고 overflow가 발생합니다. 예를 들어 수만 자의 텍스트 데이터를 short 인디케이터로 처리하려 할 때 이 문제가 발생합니다.

2. 버퍼 크기보다 큰 데이터 수신 시 잘림(Truncation) 정보 전달 실패

PostgreSQL이 클라이언트 버퍼보다 더 큰 데이터를 반환할 때, 드라이버는 인디케이터 변수에 원래 데이터 크기를 기록하여 애플리케이션이 데이터가 잘렸음을 인지하도록 합니다. 그런데 원래 데이터의 크기가 인디케이터 변수의 최대 범위(예: short의 경우 32,767)보다 크면, 이 크기 정보 자체를 저장할 수 없어 overflow 에러가 발생하게 됩니다. 특히 TEXT, VARCHAR, BYTEA 컬럼에 매우 큰 값이 저장되어 있을 때 빈번하게 나타납니다.

3. ODBC/JDBC 드라이버 설정 또는 버전 불일치

오래된 버전의 ODBC 드라이버나 잘못 설정된 JDBC 드라이버를 사용하면 인디케이터 처리 로직에 버그가 존재할 수 있습니다. 드라이버가 PostgreSQL 서버로부터 받은 데이터 크기를 올바르게 변환하지 못하거나, 내부 버퍼 관리가 비효율적으로 구현된 경우에도 이 에러가 발생할 수 있습니다. 드라이버 버전과 PostgreSQL 서버 버전 간의 호환성 문제도 중요한 원인 중 하나입니다.


해결 방법

원인 1 해결: 인디케이터 변수 타입을 더 큰 정수형으로 변경

ECPG 코드에서 인디케이터 변수를 short 대신 int 또는 long으로 선언하여 더 넓은 범위의 값을 수용하도록 변경합니다.

-- ECPG 예제: 인디케이터 변수 타입 변경
-- 변경 전 (문제 발생 가능)
EXEC SQL BEGIN DECLARE SECTION;
    char description[100];
    short description_ind;  -- 최대 32,767까지만 표현 가능
EXEC SQL END DECLARE SECTION;

-- 변경 후 (권장)
EXEC SQL BEGIN DECLARE SECTION;
    char description[65536];
    int description_ind;  -- int로 변경하여 더 큰 범위 수용
EXEC SQL END DECLARE SECTION;

-- 데이터 조회 시 인디케이터 변수와 함께 사용
EXEC SQL SELECT description INTO :description :description_ind
    FROM products
    WHERE product_id = 1001;

원인 2 해결: 데이터 크기를 미리 제한하거나 서버 사이드에서 트리밍

쿼리 레벨에서 반환 데이터의 크기를 미리 제한하면 인디케이터 overflow를 원천 차단할 수 있습니다.

-- 방법 1: LEFT() 함수로 반환 길이 제한
SELECT
    product_id,
    LEFT(description, 32000) AS description,  -- 32,767 미만으로 제한
    LENGTH(description) AS original_length     -- 원본 길이는 별도 컬럼으로 확인
FROM products
WHERE product_id = 1001;

-- 방법 2: SUBSTRING() 으로 필요한 부분만 추출
SELECT
    product_id,
    SUBSTRING(large_text_column FROM 1 FOR 10000) AS partial_text
FROM large_data_table
WHERE id = 42;

-- 방법 3: 데이터 길이 검사 후 처리 분기
SELECT
    product_id,
    CASE
        WHEN LENGTH(description) > 32000
            THEN LEFT(description, 32000) || '...[truncated]'
        ELSE description
    END AS safe_description
FROM products;

원인 3 해결: 드라이버 업그레이드 및 연결 파라미터 조정

ODBC나 JDBC 드라이버를 최신 버전으로 업그레이드하고, 드라이버의 버퍼 설정을 검토합니다.

-- PostgreSQL 서버에서 현재 연결 드라이버 정보 확인
SELECT
    application_name,
    client_addr,
    state,
    query
FROM pg_stat_activity
WHERE datname = current_database();

-- 드라이버 버전 확인을 위한 연결 정보 조회
SELECT version();  -- PostgreSQL 서버 버전 확인

-- JDBC 연결 시 defaultRowFetchSize 설정 확인 (Java 애플리케이션)
-- jdbc:postgresql://localhost:5432/mydb?defaultRowFetchSize=100&prepareThreshold=5

-- 큰 오브젝트 데이터 처리 시 스트리밍 방식 활용 (Large Object)
SELECT lo_get(large_object_oid) FROM my_large_object_table WHERE id = 1;

-- 또는 largeobject API를 통한 청크 단위 읽기
SELECT lo_get(large_object_oid, 0, 32000) AS chunk_1
FROM my_large_object_table WHERE id = 1;

예방 방법

1. 스키마 설계 단계에서 컬럼 길이 적절히 제한하기

대용량 텍스트가 반드시 필요하지 않은 컬럼에는 TEXT 대신 길이 제한이 있는 VARCHAR(n)을 사용하고, 제약 조건(CHECK CONSTRAINT)을 통해 데이터 길이를 데이터베이스 수준에서 관리합니다.

-- 권장: 컬럼 길이 제약 조건 명시
CREATE TABLE products (
    product_id   SERIAL PRIMARY KEY,
    name         VARCHAR(255) NOT NULL,
    description  VARCHAR(10000),  -- 명시적 길이 제한
    summary      VARCHAR(500),
    CONSTRAINT chk_description_length CHECK (LENGTH(description) <= 10000)
);

-- 기존 테이블에 체크 제약 추가
ALTER TABLE products
    ADD CONSTRAINT chk_summary_length
    CHECK (LENGTH(summary) <= 500);

2. 애플리케이션 레이어에서 데이터 크기 검증 및 모니터링

애플리케이션 코드에서 데이터를 INSERT/UPDATE 하기 전에 길이 검증 로직을 추가하고, 운영 중에는 컬럼별 최대 데이터 크기를 주기적으로 모니터링하여 잠재적 overflow 위험을 사전에 탐지합니다.

-- 모니터링: 각 컬럼의 실제 최대 데이터 길이 주기적 점검
SELECT
    'description' AS column_name,
    MAX(LENGTH(description)) AS max_length,
    AVG(LENGTH(description))::INT AS avg_length,
    COUNT(*) FILTER (WHERE LENGTH(description) > 30000) AS risky_rows
FROM products

UNION ALL

SELECT
    'summary',
    MAX(LENGTH(summary)),
    AVG(LENGTH(summary))::INT,
    COUNT(*) FILTER (WHERE LENGTH(summary) > 30000)
FROM products;

관련 에러

  • 22001 (string_data_right_truncation): 문자열 데이터가 대상 컬럼의 최대 길이를 초과하여 잘릴 때 발생하며, 22022와 함께 대용량 데이터 처리 시 자주 동반됩니다.
  • 22003 (numeric_value_out_of_range): 숫자 값이 대상 데이터 타입의 범위를 초과할 때 발생하며, 인디케이터 overflow와 유사한 범위 초과 문제입니다.
  • 22007 (invalid_datetime_format): 날짜/시간 데이터 변환 오류로, 클라이언트-서버 간 데이터 타입 불일치 문제라는 점에서 22022와 원인 맥락이 유사합니다.
  • 22P02 (invalid_text_representation): 텍스트를 특정 데이터 타입으로 변환하는 데 실패할 때 발생하며, 드라이버 데이터 변환 문제와 연관될 수 있습니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기