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

22012
2026년 08월 08일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22012 division by zero 는?

PostgreSQL 에러 코드 22012, division by zero는 SQL 연산 중 분모(나누는 값)가 0이 되었을 때 발생하는 오류입니다. 이 에러는 SQLSTATE 22012로 분류되며, 정수 나눗셈(/), 모듈로 연산(%), 그리고 집계 함수나 윈도우 함수 내부에서도 발생할 수 있습니다. 예상치 못한 데이터 값이나 잘못된 쿼리 설계로 인해 운영 환경에서 갑작스럽게 나타나는 경우가 많아, DBA와 개발자 모두 반드시 숙지해야 할 에러입니다.


주요 발생 원인

  • 직접적인 0으로 나누기 (리터럴 또는 컬럼 값이 0인 경우)

가장 흔한 원인은 특정 컬럼의 값이 0인 행을 필터링하지 않고 나눗셈 연산에 사용하는 경우입니다. 예를 들어 판매 데이터에서 단위 수량(quantity)이 0인 경우 총액을 단위 수량으로 나누면 즉시 에러가 발생합니다. 개발 환경에서는 테스트 데이터가 잘 정제되어 있어 발견되지 않다가, 실운영 데이터에서 예외 값이 유입될 때 처음 발생하는 패턴이 매우 흔합니다.

  • 집계 함수 및 윈도우 함수에서의 0 나누기

SUM(), COUNT(), AVG() 같은 집계 함수의 결과값을 분모로 사용할 때, 특정 그룹의 집계 결과가 0이 되는 경우 에러가 발생합니다. 예를 들어 특정 카테고리에 속하는 데이터가 전혀 없어 COUNT(*)가 0이 되는 상황, 혹은 SUM()이 음수와 양수가 상쇄되어 0이 되는 경우도 포함됩니다. 윈도우 함수(OVER())에서도 파티션 내 합계가 0일 때 동일한 문제가 발생하므로 각별한 주의가 필요합니다.

  • 동적 쿼리 또는 애플리케이션 로직에서의 변수 미검증

ORM이나 애플리케이션 레이어에서 사용자 입력값 또는 계산된 값을 SQL 쿼리에 바인딩할 때, 해당 값이 0인지 검증하지 않고 분모로 사용하는 경우가 있습니다. 특히 비율 계산, 퍼센트 계산, 환율 변환 등의 비즈니스 로직에서 자주 발생하며, 입력 유효성 검사가 누락된 경우 데이터베이스 레벨에서 에러가 터지게 됩니다. 이는 단순한 쿼리 문제가 아니라 애플리케이션 아키텍처 차원의 방어 로직 부재 문제입니다.


해결 방법

원인 1: 직접적인 0으로 나누기 해결

NULLIF() 함수를 활용하면 분모가 0일 때 NULL을 반환하게 하여 에러 대신 NULL로 처리할 수 있습니다.

-- 문제가 되는 쿼리
SELECT total_amount / quantity AS unit_price
FROM sales;

-- NULLIF를 사용한 안전한 쿼리
-- quantity가 0이면 NULL을 반환하여 division by zero 방지
SELECT total_amount / NULLIF(quantity, 0) AS unit_price
FROM sales;

-- NULL 대신 기본값(0)을 반환하려면 COALESCE와 함께 사용
SELECT COALESCE(total_amount / NULLIF(quantity, 0), 0) AS unit_price
FROM sales;

-- CASE 문을 이용한 명시적 처리 (가독성 중심)
SELECT 
    CASE 
        WHEN quantity = 0 THEN NULL
        ELSE total_amount / quantity
    END AS unit_price
FROM sales;

원인 2: 집계 함수에서의 0 나누기 해결

-- 문제가 되는 집계 쿼리
SELECT 
    category,
    SUM(revenue) / COUNT(*) AS avg_revenue
FROM orders
GROUP BY category;

-- NULLIF로 집계 결과가 0인 경우 처리
SELECT 
    category,
    SUM(revenue) / NULLIF(COUNT(*), 0) AS avg_revenue
FROM orders
GROUP BY category;

-- 윈도우 함수에서의 안전한 나눗셈
SELECT 
    employee_id,
    department_id,
    salary,
    salary / NULLIF(SUM(salary) OVER (PARTITION BY department_id), 0) AS salary_ratio
FROM employees;

-- 특정 그룹의 합계가 0이 될 수 있는 경우
SELECT 
    product_id,
    monthly_sales,
    COALESCE(
        monthly_sales / NULLIF(SUM(monthly_sales) OVER (PARTITION BY product_id), 0),
        0
    ) AS contribution_ratio
FROM product_sales;

원인 3: 동적 쿼리에서의 안전한 처리

-- PostgreSQL 함수로 안전한 나눗셈 래퍼 만들기
CREATE OR REPLACE FUNCTION safe_divide(
    numerator   NUMERIC,
    denominator NUMERIC,
    default_val NUMERIC DEFAULT NULL
)
RETURNS NUMERIC AS $$
BEGIN
    IF denominator IS NULL OR denominator = 0 THEN
        RETURN default_val;
    END IF;
    RETURN numerator / denominator;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- 함수 사용 예제
SELECT 
    order_id,
    safe_divide(total_price, item_count) AS avg_item_price,
    safe_divide(total_price, item_count, 0) AS avg_item_price_default_zero
FROM orders;

-- 데이터 검증 후 처리 (WHERE 절로 0 제외)
SELECT total_amount / quantity AS unit_price
FROM sales
WHERE quantity IS NOT NULL AND quantity <> 0;

예방 방법

  • NULLIF()를 나눗셈 연산의 표준으로 채택하기

팀 내 SQL 코딩 컨벤션에 나눗셈 연산 시 반드시 NULLIF(분모, 0) 패턴을 사용하도록 규정하세요. 코드 리뷰 체크리스트에 “나눗셈 연산에 NULLIF 적용 여부”를 포함시키고, 정적 분석 도구나 SQL 린터를 도입하여 / 연산자 사용 시 자동으로 경고가 뜨도록 설정하는 것을 권장합니다. 또한 safe_divide()와 같은 공통 래퍼 함수를 팀 공유 라이브러리에 등록하여 재사용성을 높이면 실수를 크게 줄일 수 있습니다.

  • 데이터 품질 제약 조건 및 테스트 데이터 관리 강화

분모로 사용되는 컬럼에 CHECK (column_name > 0) 제약 조건을 추가하거나, 0이 되면 안 되는 컬럼에 대해 데이터 입력 시점부터 유효성 검사를 적용하세요. 또한 단위 테스트 및 통합 테스트에 경계값(0, NULL, 음수) 케이스를 반드시 포함시켜 개발 단계에서 에러를 조기에 발견하는 체계를 구축하는 것이 중요합니다.

-- 테이블 생성 시 CHECK 제약 조건으로 예방
CREATE TABLE sales (
    id          SERIAL PRIMARY KEY,
    product_id  INT NOT NULL,
    quantity    INT NOT NULL CHECK (quantity > 0),  -- 0 방지
    total_price NUMERIC(12, 2) NOT NULL
);

-- 기존 테이블에 제약 조건 추가
ALTER TABLE sales
ADD CONSTRAINT chk_quantity_positive CHECK (quantity > 0);

관련 에러

  • 22003 numeric_value_out_of_range: 나눗셈 결과값이 데이터 타입의 허용 범위를 초과할 때 발생합니다. division by zero 수정 후 결과값 범위도 함께 점검하세요.
  • 22004 null_value_not_allowed: NULLIF()를 사용하여 0을 NULL로 처리했을 때, 해당 컬럼이 NOT NULL 제약이 있다면 이 에러가 연쇄적으로 발생할 수 있습니다.
  • 42883 undefined_function: 커스텀 safe_divide() 함수를 생성하지 않고 호출하면 발생하며, 공유 함수 라이브러리 관리 시 주의가 필요합니다.
  • 22P02 invalid_text_representation: 문자열로 전달된 값을 숫자로 캐스팅하는 과정에서 실패하면 발생하며, 동적 쿼리에서 타입 검증 누락 시 division by zero와 함께 자주 발생합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기