2026년 10월 14일 | DBMS Error 가이드
이 글에서 다루는 내용
2201E 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2201E invalid argument for logarithm 는?
PostgreSQL 에러 코드 2201E는 로그(logarithm) 함수에 유효하지 않은 인수(argument)가 전달되었을 때 발생하는 에러입니다. 수학적으로 로그 함수는 양수(0보다 큰 값)에 대해서만 정의되므로, 0이나 음수를 입력값으로 사용하면 이 에러가 발생합니다. PostgreSQL의 LOG(), LOG(base, x), LN() 함수 등을 사용할 때 입력 데이터에 0이나 음수가 포함되어 있으면 쿼리가 즉시 중단되며 해당 에러 메시지를 반환합니다.
주요 발생 원인
- 0 또는 음수를 로그 함수의 인수로 직접 전달
가장 흔한 원인으로, 개발자가 데이터의 범위를 충분히 검토하지 않고 LOG() 또는 LN() 함수를 적용할 때 발생합니다. 예를 들어 매출 데이터나 측정값 컬럼에 0 또는 음수가 포함되어 있는데, 이를 그대로 로그 함수에 넣는 경우입니다. 특히 데이터 정합성이 완벽하지 않은 레거시 시스템에서 자주 목격됩니다.
- 집계 결과 또는 계산된 컬럼의 값이 0 또는 음수로 산출되는 경우
단순 컬럼 값이 아니라, SUM(), AVG(), 또는 산술 연산의 결과를 로그 함수의 인수로 사용할 때 예상치 못하게 0이나 음수가 나오는 경우입니다. 예를 들어 반품 수량이 판매 수량보다 많아 잔여 수량이 음수가 되거나, 특정 그룹의 합계가 0이 되는 비즈니스 케이스에서 발생할 수 있습니다. 이 경우 개별 레코드를 검토했을 때는 문제가 없어 보이지만, 집계 후에 문제가 드러나기 때문에 디버깅이 어렵습니다.
- LOG(base, x) 형태에서 밑(base)이 유효하지 않은 값인 경우
LOG(base, x) 함수에서는 인수 x뿐만 아니라 밑(base)도 양수이고 1이 아닌 값이어야 합니다. 밑이 1이면 로그가 정의되지 않고, 0이나 음수도 마찬가지입니다. 동적으로 밑 값을 계산하거나 사용자 입력을 그대로 사용하는 경우, 이 조건을 위반하여 에러가 발생할 수 있습니다.
해결 방법
원인 1 해결: NULLIF 또는 CASE 문으로 유효하지 않은 값 처리
0이나 음수를 NULL로 변환하거나, 조건을 걸어 로그 함수 적용 대상을 필터링합니다.
-- 방법 1: NULLIF를 사용하여 0을 NULL로 변환 (음수는 별도 처리 필요)
SELECT
product_id,
LOG(NULLIF(sales_amount, 0)) AS log_sales
FROM sales
WHERE sales_amount > 0;
-- 방법 2: CASE 문으로 조건 분기 처리
SELECT
product_id,
CASE
WHEN sales_amount > 0 THEN LOG(sales_amount)
ELSE NULL
END AS log_sales
FROM sales;
-- 방법 3: GREATEST 함수로 최솟값을 양수로 보정 (도메인 지식 기반)
-- 주의: 비즈니스 로직에 맞는 경우에만 사용
SELECT
product_id,
LOG(GREATEST(sales_amount, 0.0001)) AS log_sales
FROM sales;
원인 2 해결: 집계 결과에 대한 안전한 로그 적용
-- 집계 후 결과에 안전하게 로그 적용
SELECT
category_id,
SUM(quantity) AS total_quantity,
CASE
WHEN SUM(quantity) > 0 THEN LOG(SUM(quantity))
ELSE NULL
END AS log_total_quantity
FROM order_items
GROUP BY category_id;
-- 서브쿼리를 활용한 방법 (가독성 향상)
SELECT
category_id,
total_quantity,
CASE
WHEN total_quantity > 0 THEN LOG(total_quantity)
ELSE NULL
END AS log_total_quantity
FROM (
SELECT
category_id,
SUM(quantity) AS total_quantity
FROM order_items
GROUP BY category_id
) agg;
원인 3 해결: LOG(base, x) 밑(base) 유효성 검증
-- 밑(base)과 인수(x) 모두 유효성 검사
SELECT
value_column,
base_column,
CASE
WHEN base_column > 0
AND base_column <> 1
AND value_column > 0
THEN LOG(base_column, value_column)
ELSE NULL
END AS safe_log_result
FROM calculation_table;
-- 에러 발생 예시와 수정 예시 비교
-- 에러 발생 (base = 1, 수학적으로 정의 불가)
-- SELECT LOG(1, 100); -- ERROR: 2201E
-- 수정된 쿼리
SELECT
CASE
WHEN 1 > 0 AND 1 <> 1 AND 100 > 0
THEN LOG(1, 100)
ELSE NULL
END AS safe_result;
-- 결과: NULL (안전하게 처리)
에러 재현 및 확인 방법
-- 에러 재현 (실제 실행 시 2201E 에러 발생)
-- SELECT LN(0); -- ERROR: invalid argument for logarithm
-- SELECT LN(-1); -- ERROR: invalid argument for logarithm
-- SELECT LOG(0); -- ERROR: invalid argument for logarithm
-- SELECT LOG(10, -5); -- ERROR: invalid argument for logarithm
-- 문제가 있는 데이터 사전 탐색
SELECT COUNT(*) AS problematic_rows
FROM your_table
WHERE your_column <= 0;
-- 문제 행 상세 조회
SELECT *
FROM your_table
WHERE your_column <= 0
LIMIT 100;
예방 방법
- CHECK 제약조건 또는 뷰(View)로 데이터 입력 단계에서 유효성 보장
로그 함수를 자주 사용하는 컬럼에는 테이블 정의 시 CHECK 제약조건을 추가하여 0이나 음수가 저장되지 않도록 원천 차단합니다. 만약 기존 테이블 구조를 변경하기 어렵다면, 안전한 로그 계산을 제공하는 뷰(View)를 생성하여 응용 프로그램이 뷰를 통해 데이터를 조회하도록 유도합니다.
“`sql
— CHECK 제약조건 추가 예시
ALTER TABLE sales
ADD CONSTRAINT chk_sales_amount_positive
CHECK (sales_amount > 0);
— 안전한 뷰 생성 예시
CREATE OR REPLACE VIEW v_safe_log_sales AS
SELECT
product_id,
sales_amount,
CASE
WHEN sales_amount > 0 THEN LOG(sales_amount)
ELSE NULL
END AS log_sales_amount
FROM sales;
“`
- 쿼리 작성 시 방어적 프로그래밍 패턴 적용
로그 함수를 사용하는 모든 쿼리에서 CASE WHEN ... > 0 THEN LOG(...) ELSE NULL END 패턴을 팀 내 코딩 컨벤션으로 채택합니다. 또한 배포 전 단계에서 대상 컬럼의 최솟값을 MIN() 함수로 확인하는 사전 검증 쿼리를 CI/CD 파이프라인에 포함시키면 운영 환경에서의 에러 발생을 사전에 차단할 수 있습니다.
“`sql
— 배포 전 데이터 검증 쿼리 예시
DO $$
DECLARE
min_val NUMERIC;
BEGIN
SELECT MIN(sales_amount) INTO min_val FROM sales;
IF min_val <= 0 THEN
RAISE EXCEPTION ‘데이터 검증 실패: sales_amount에 0 또는 음수 값이 존재합니다. 최솟값: %’, min_val;
END IF;
RAISE NOTICE ‘데이터 검증 성공: 최솟값 = %’, min_val;
END;
$$;
“`
관련 에러
- 2201F
invalid argument for power function: 거듭제곱 함수(POWER())에 유효하지 않은 인수가 전달될 때 발생합니다. 예를 들어 음수의 소수 지수를 계산하려 할 때 나타납니다. - 2201G
invalid argument for width bucket function:WIDTH_BUCKET()함수에서 범위 설정이 잘못되었을 때 발생하며, 수학적 함수의 도메인 제한 에러라는 점에서 2201E와 맥락을 같이합니다. - 22012
division by zero: 0으로 나누기를 시도할 때 발생하며, 로그 함수의 0 입력과 유사하게 수학적으로 정의되지 않는 연산에서 비롯됩니다. 두 에러 모두 입력 값의 유효 범위 확인 부재에서 기인하는 경우가 많습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.