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

22002
2026년 10월 19일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22002 null value no indicator parameter 는?

PostgreSQL 에러 코드 22002는 null value no indicator parameter라는 메시지로, 호스트 변수(host variable)에 NULL 값이 반환되었지만 해당 NULL을 처리할 인디케이터 변수(indicator variable)가 선언되지 않았을 때 발생합니다. 주로 Embedded SQL(ECPG) 환경이나 ODBC/JDBC 드라이버를 통해 C, C++ 등의 언어로 PostgreSQL과 통신할 때 나타나는 에러입니다. 데이터베이스 칼럼에서 NULL을 읽어올 때 애플리케이션 측에서 이를 처리할 준비가 되어 있지 않으면 런타임 오류로 이어지며, 데이터 무결성 문제로 발전할 수 있습니다.


주요 발생 원인

1. Embedded SQL(ECPG)에서 인디케이터 변수 누락

가장 흔한 원인으로, C 언어 기반의 ECPG 코드에서 FETCH 또는 SELECT INTO 시 NULL 가능성이 있는 컬럼에 대해 인디케이터 변수를 선언하지 않은 경우입니다. PostgreSQL은 NULL 값을 호스트 변수에 직접 매핑할 수 없기 때문에 인디케이터 변수가 반드시 필요합니다. 특히 NOT NULL 제약이 없는 컬럼을 조회할 때 이 문제가 빈번하게 발생합니다.

2. 애플리케이션의 NOT NULL 가정과 실제 데이터 불일치

개발 단계에서는 특정 컬럼에 항상 값이 있다고 가정하고 NULL 처리 로직을 생략한 경우입니다. 운영 환경에서 데이터가 쌓이면서 예상치 못한 NULL 값이 입력되거나, 조인(JOIN) 결과로 NULL이 생성될 때 에러가 발생합니다. 특히 LEFT JOIN 이후 오른쪽 테이블의 컬럼을 호스트 변수로 받을 때 자주 나타납니다.

3. 스키마 변경 후 기존 코드와의 불일치

운영 중인 데이터베이스에서 기존에 NOT NULL이었던 컬럼의 제약 조건을 제거하거나, 새로운 nullable 컬럼을 추가했을 때 기존 애플리케이션 코드가 이를 반영하지 못한 경우입니다. 스키마 마이그레이션 후 전체 코드베이스를 검토하지 않으면 특정 쿼리 경로에서만 에러가 발생하여 발견이 늦어지는 경향이 있습니다.


해결 방법

원인 1 해결: 인디케이터 변수 추가 (ECPG)

ECPG 코드에서 인디케이터 변수를 선언하고, 각 NULL 가능 컬럼에 인디케이터를 연결해야 합니다.

-- 잘못된 예: 인디케이터 변수 없이 NULL 가능 컬럼 조회
EXEC SQL BEGIN DECLARE SECTION;
    char emp_name[100];
    int  emp_salary;
EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT name, salary
         INTO :emp_name, :emp_salary
         FROM employees
         WHERE id = 1;
-- NULL이 존재하면 22002 에러 발생!


-- 올바른 예: 인디케이터 변수(indicator variable) 추가
EXEC SQL BEGIN DECLARE SECTION;
    char emp_name[100];
    int  emp_salary;
    short ind_name;    -- 인디케이터 변수: NULL이면 -1, 아니면 0
    short ind_salary;  -- 인디케이터 변수
EXEC SQL END DECLARE SECTION;

EXEC SQL SELECT name, salary
         INTO :emp_name  INDICATOR :ind_name,
              :emp_salary INDICATOR :ind_salary
         FROM employees
         WHERE id = 1;

-- 이후 애플리케이션 코드에서 NULL 여부 체크
-- if (ind_name == -1) { /* name is NULL */ }
-- if (ind_salary == -1) { /* salary is NULL */ }

원인 2 해결: COALESCE로 NULL을 기본값으로 치환

쿼리 단계에서 NULL이 반환되지 않도록 COALESCE 또는 NULLIF를 활용해 기본값을 제공하는 방법입니다.

-- LEFT JOIN 결과에서 NULL 방지 예시
SELECT
    e.id,
    e.name,
    COALESCE(d.department_name, 'Unknown')   AS department_name,
    COALESCE(e.salary, 0)                    AS salary,
    COALESCE(e.bonus, 0)                     AS bonus
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;

-- 집계 함수와 함께 사용하는 경우
SELECT
    department_id,
    COALESCE(SUM(salary), 0)    AS total_salary,
    COALESCE(AVG(bonus), 0.0)   AS avg_bonus
FROM employees
GROUP BY department_id;

-- NULLIF를 이용해 0을 NULL로, 다시 COALESCE로 안전하게 처리
SELECT
    product_id,
    COALESCE(NULLIF(stock_count, 0), -1) AS safe_stock
FROM products;

원인 3 해결: 스키마 변경 후 점검 쿼리 실행

스키마 마이그레이션 후 nullable 컬럼의 현황을 빠르게 파악하는 쿼리입니다.

-- 특정 테이블에서 NULL을 허용하는 컬럼 목록 조회
SELECT
    table_name,
    column_name,
    data_type,
    is_nullable,
    column_default
FROM information_schema.columns
WHERE table_schema = 'public'
  AND is_nullable = 'YES'
ORDER BY table_name, ordinal_position;

-- NULL 값이 실제로 존재하는지 확인하는 동적 검사 예시 (employees 테이블)
SELECT
    COUNT(*) FILTER (WHERE name IS NULL)    AS null_name_count,
    COUNT(*) FILTER (WHERE salary IS NULL)  AS null_salary_count,
    COUNT(*) FILTER (WHERE bonus IS NULL)   AS null_bonus_count
FROM employees;

-- NULL 허용 컬럼에 기본값 설정으로 향후 NULL 방지
ALTER TABLE employees
    ALTER COLUMN bonus SET DEFAULT 0;

-- 기존 NULL 데이터 일괄 업데이트
UPDATE employees
SET bonus = 0
WHERE bonus IS NULL;

예방 방법

1. 모든 호스트 변수에 인디케이터 변수를 기본으로 선언하는 코딩 표준 수립

ECPG나 Pro*C 계열의 Embedded SQL을 사용하는 프로젝트에서는 NOT NULL 제약이 걸린 컬럼이라도 습관적으로 인디케이터 변수를 함께 선언하는 팀 코딩 표준을 만드는 것이 좋습니다. 이는 향후 스키마 변경 시 발생할 수 있는 사이드 이펙트를 방지하고, 코드 리뷰에서도 빠르게 검토할 수 있게 합니다. CI/CD 파이프라인에 정적 분석 도구를 연동하여 인디케이터 없는 호스트 변수 사용을 자동으로 검출하는 것을 권장합니다.

2. 데이터베이스 설계 단계에서 NULL 허용 여부를 명시적으로 문서화

테이블 설계 시 각 컬럼의 NULL 허용 여부를 ERD와 데이터 딕셔너리에 반드시 명시하고, 애플리케이션 개발자가 이를 참조하도록 프로세스를 수립해야 합니다. DDL 스크립트에도 컬럼별 주석(COMMENT ON COLUMN)을 활용해 NULL의 비즈니스적 의미를 명확히 기록하면 유지보수 시 혼란을 줄일 수 있습니다.

-- 컬럼에 명시적 주석 추가 예시
COMMENT ON COLUMN employees.bonus IS
    'nullable: 미지급인 경우 NULL, 지급 완료는 양수 값. 애플리케이션에서 반드시 NULL 처리 필요';

COMMENT ON COLUMN employees.department_id IS
    'nullable: 부서 미배정 직원의 경우 NULL 가능. LEFT JOIN 사용 시 COALESCE 처리 권장';

관련 에러

  • 22001 (string_data_right_truncation): 문자열 데이터가 대상 컬럼의 최대 길이를 초과할 때 발생하며, 호스트 변수 크기 관련 문제로 22002와 함께 ECPG 환경에서 자주 언급됩니다.
  • 22003 (numeric_value_out_of_range): 숫자 데이터가 대상 변수의 범위를 벗어날 때 발생합니다. 인디케이터 없이 NULL을 숫자형 변수에 매핑 시 함께 나타날 수 있습니다.
  • 22000 (data_exception): 22002를 포함한 데이터 예외 에러의 상위 클래스 코드로, 데이터 조작 시 발생하는 다양한 런타임 예외를 포괄합니다.
  • 42804 (datatype_mismatch): 호스트 변수와 컬럼의 데이터 타입이 일치하지 않을 때 발생하며, NULL 처리 문제와 함께 ECPG 코드 점검 시 동시에 확인해야 할 에러입니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기