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

42725
2026년 09월 15일 | DBMS Error 가이드

이 글에서 다루는 내용

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

42725 ambiguous function 란?

PostgreSQL 에러 코드 42725ambiguous function, 즉 “모호한 함수 호출”을 의미합니다. 이 에러는 함수를 호출할 때 전달된 인자(argument)의 타입이 여러 함수 시그니처와 동시에 매칭될 수 있어 PostgreSQL이 어떤 함수를 실행해야 할지 결정하지 못할 때 발생합니다. 주로 함수 오버로딩(overloading)이 많이 사용된 환경이나 암묵적 타입 변환(implicit type casting)이 복잡하게 얽힌 상황에서 자주 목격됩니다.


주요 발생 원인

1. 동일 이름의 함수가 여러 시그니처로 오버로딩된 경우

PostgreSQL은 같은 이름의 함수를 인자 타입만 다르게 하여 여러 개 등록(오버로딩)하는 것을 허용합니다. 문제는 함수 호출 시 전달한 인자가 integernumeric 처럼 암묵적으로 변환 가능한 두 타입 모두와 호환될 때, PostgreSQL의 함수 결정 알고리즘이 유일한 후보를 선택하지 못하고 에러를 발생시킨다는 점입니다.

예를 들어 아래처럼 두 함수가 존재한다고 가정해 봅니다.

CREATE FUNCTION calculate(p_val integer) RETURNS integer AS $$
    SELECT p_val * 2;
$$ LANGUAGE SQL;

CREATE FUNCTION calculate(p_val numeric) RETURNS numeric AS $$
    SELECT p_val * 2.5;
$$ LANGUAGE SQL;

-- 아래 호출은 42725 에러 발생: 2는 integer? numeric? 모호함
SELECT calculate(2);

2라는 리터럴은 integernumeric 모두로 해석될 수 있기 때문에 PostgreSQL은 어느 함수를 실행해야 할지 결정하지 못합니다.


2. 사용자 정의 함수가 내장(built-in) 함수와 충돌하는 경우

사용자가 length, substring, round 등 PostgreSQL 내장 함수와 동일한 이름으로 새로운 함수를 생성하면, 호출 시 내장 함수와 사용자 정의 함수 모두가 후보에 오르게 됩니다. 특히 인자 타입이 암묵적으로 변환 가능한 경우 PostgreSQL은 최적의 후보를 선별하지 못하고 42725 에러를 냅니다.

-- 사용자가 내장 함수와 동일한 이름으로 함수 생성
CREATE FUNCTION round(p_val double precision) RETURNS double precision AS $$
    SELECT floor(p_val + 0.6);
$$ LANGUAGE SQL;

-- 내장 round(double precision)와 사용자 정의 round(double precision) 충돌
SELECT round(3.7::double precision);
-- ERROR: 42725: function round(double precision) is not unique

3. 스키마 검색 경로(search_path)에 동일 함수가 여러 스키마에 존재하는 경우

search_path에 등록된 여러 스키마에 동일한 이름과 시그니처(또는 암묵적으로 호환 가능한 시그니처)를 가진 함수가 각각 존재하는 경우에도 이 에러가 발생할 수 있습니다. 대규모 멀티 테넌트 환경이나 여러 팀이 동일 데이터베이스를 공유하는 경우에 특히 빈번하게 나타납니다.

-- search_path: public, tenant_a
-- public 스키마에 calculate(integer) 존재
-- tenant_a 스키마에도 calculate(integer) 존재

SET search_path = public, tenant_a;
SELECT calculate(100);
-- ERROR: 42725: function calculate(integer) is not unique

해결 방법

원인 1 해결: 명시적 캐스팅(Explicit Casting)으로 타입을 특정

함수 호출 시 인자에 명시적으로 타입을 지정하여 PostgreSQL이 유일한 후보를 선택할 수 있도록 합니다.

-- integer 버전 명시적 호출
SELECT calculate(2::integer);

-- numeric 버전 명시적 호출
SELECT calculate(2::numeric);

-- CAST 문법 사용
SELECT calculate(CAST(2 AS integer));
SELECT calculate(CAST(2 AS numeric));

원인 2 해결: 스키마를 포함한 전체 함수 경로 명시 또는 함수 삭제

사용자 정의 함수가 내장 함수와 충돌하는 경우, 충돌을 일으키는 사용자 함수를 삭제하거나 스키마를 명시적으로 지정하여 호출합니다.

-- 스키마를 명시하여 내장 함수 직접 호출
SELECT pg_catalog.round(3.7::double precision);

-- 사용자 정의 함수 호출
SELECT public.round(3.7::double precision);

-- 충돌하는 사용자 정의 함수 삭제 (권장)
DROP FUNCTION public.round(double precision);

원인 3 해결: search_path를 명확히 설정하거나 스키마 한정 호출

-- 특정 스키마를 우선하도록 search_path 조정
SET search_path = tenant_a, public;

-- 또는 스키마를 명시하여 모호성 제거
SELECT public.calculate(100);
SELECT tenant_a.calculate(100);

-- 세션 수준이 아닌 함수/역할 수준으로 search_path 고정 (권장)
ALTER FUNCTION my_function() SET search_path = tenant_a, public;
ALTER ROLE my_role SET search_path = tenant_a, public;

함수 후보 목록 확인 쿼리

어떤 함수들이 후보로 등록되어 있는지 확인하는 방법입니다.

-- 동일 이름의 함수 목록 조회
SELECT
    n.nspname AS schema_name,
    p.proname AS function_name,
    pg_catalog.pg_get_function_arguments(p.oid) AS arguments,
    pg_catalog.pg_get_function_result(p.oid) AS return_type
FROM pg_catalog.pg_proc p
JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE p.proname = 'calculate'   -- 함수 이름으로 변경
ORDER BY n.nspname, p.proname;

예방 방법

1. 함수 오버로딩 시 명확한 타입 정책 수립 및 문서화

오버로딩 함수를 설계할 때는 각 버전이 암묵적 변환 없이도 명확히 구분되는 타입을 인자로 받도록 설계해야 합니다. 팀 내에서 함수 네이밍 컨벤션과 허용 오버로딩 범위를 문서화하고, 가능하면 text, integer, numeric, bigint 등 암묵적 변환 관계가 복잡한 타입 조합은 피하는 것이 좋습니다. 또한 내장 함수와 동일한 이름의 사용자 정의 함수 생성은 반드시 코드 리뷰를 거치도록 프로세스를 수립하세요.

-- 나쁜 예: 암묵적 변환으로 충돌 가능
CREATE FUNCTION process(val integer) RETURNS text ...;
CREATE FUNCTION process(val bigint)  RETURNS text ...;

-- 좋은 예: 타입 명확화 또는 함수명 분리
CREATE FUNCTION process_integer(val integer) RETURNS text ...;
CREATE FUNCTION process_bigint(val bigint)   RETURNS text ...;

2. search_path를 역할(Role) 및 함수 단위로 고정 관리

전역 search_path 변경은 예측하기 어려운 부작용을 낳습니다. 대신 역할(Role) 수준 또는 함수 수준에서 search_path를 고정하여 어느 스키마의 함수가 우선 호출될지 명시적으로 제어하는 것이 실무 베스트 프랙티스입니다.

-- 역할 수준에서 search_path 고정
ALTER ROLE app_user SET search_path = app_schema, public;

-- 함수 수준에서 search_path 고정 (보안 및 명확성 확보)
CREATE OR REPLACE FUNCTION my_business_logic()
RETURNS void
LANGUAGE plpgsql
SET search_path = app_schema, public
AS $$
BEGIN
    -- 이 함수 내에서는 항상 app_schema의 함수가 우선 호출됨
    PERFORM calculate(100);
END;
$$;

관련 에러

| 에러 코드 | 이름 | 설명 |

|———–|——|——|

| 42883 | undefined_function | 함수가 존재하지 않거나 인자 타입이 전혀 맞지 않을 때 발생. 42725와 반대 상황으로, 후보가 0개일 때 나타남 |

| 42P13 | invalid_function_definition | 함수 정의 자체가 잘못된 경우 발생 |

| 42846 | cannot_coerce | 타입 변환이 불가능한 경우 발생하며, 명시적 캐스팅 시도 중 마주칠 수 있음 |

| 42804 | datatype_mismatch | 반환 타입이나 컬럼 타입이 맞지 않을 때 발생하며, 함수 오버로딩 수정 과정에서 동반될 수 있음 |

42725 에러는 결국 PostgreSQL의 강력한 타입 시스템과 함수 오버로딩 기능이 교차하는 지점에서 발생하는 에러입니다. 명시적 타입 캐스팅, 스키마 한정 호출, 그리고 명확한 함수 설계 정책으로 대부분의 상황을 예방하고 빠르게 해결할 수 있습니다.


DBMS 에러 코드 시리즈

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

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

댓글 남기기