2026년 09월 12일 | DBMS Error 가이드
이 글에서 다루는 내용
42704 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
42704 undefined object 는?
PostgreSQL 에러 코드 42704는 “undefined object”로, 사용자가 참조하거나 삭제하려는 데이터베이스 객체(인덱스, 제약조건, 타입, 연산자, 캐스트 등)가 존재하지 않을 때 발생합니다. 단순히 테이블이나 컬럼이 없는 경우(42P01, 42703)와는 다르게, 이 에러는 주로 인덱스, 연산자 클래스, 사용자 정의 타입, 캐스트, 텍스트 검색 구성 등 메타 객체(meta object) 를 대상으로 할 때 나타납니다. 특히 마이그레이션 스크립트, 배포 자동화, 롤백 작업 중에 빈번하게 발생하며, 존재 여부를 확인하지 않고 DROP 또는 ALTER 구문을 실행할 때 트리거됩니다.
주요 발생 원인
- 존재하지 않는 인덱스 또는 제약조건을 DROP하려는 경우
가장 흔한 원인입니다. 배포 스크립트나 마이그레이션 도구에서 특정 인덱스나 제약조건이 이미 삭제되었거나 처음부터 생성되지 않은 상태에서 DROP INDEX 또는 ALTER TABLE ... DROP CONSTRAINT 구문을 실행하면 이 에러가 발생합니다. 특히 여러 환경(개발, 스테이징, 운영)에서 스키마 동기화가 제대로 되지 않은 경우에 자주 나타납니다.
- 존재하지 않는 사용자 정의 타입(Custom Type), 연산자(Operator), 캐스트(Cast)를 참조하는 경우
CREATE FUNCTION이나 CREATE TABLE 구문 내에서 사용자 정의 타입 또는 연산자를 참조할 때, 해당 객체가 아직 생성되지 않았거나 다른 스키마에 위치하고 있으면 42704 에러가 발생합니다. 특히 search_path 설정이 잘못되어 있거나 객체가 다른 스키마에 존재하는 경우 찾지 못하는 경우가 많습니다.
- 텍스트 검색(Full-Text Search) 구성 객체가 없는 경우
to_tsvector(), to_tsquery() 함수 또는 CREATE INDEX USING GIN 구문에서 텍스트 검색 구성(Text Search Configuration)을 명시적으로 지정할 때, 해당 구성이 데이터베이스에 존재하지 않으면 42704 에러가 발생합니다. 예를 들어 'korean' 또는 사용자 정의 구성을 참조했으나 설치되지 않은 경우가 이에 해당합니다.
해결 방법
1. 인덱스 DROP 시 IF EXISTS 사용
인덱스가 존재하지 않을 때 발생하는 에러를 방지하려면 IF EXISTS 옵션을 반드시 사용하세요.
-- 에러 발생 예시
DROP INDEX idx_users_email;
-- ERROR: 42704: index "idx_users_email" does not exist
-- 해결 방법: IF EXISTS 사용
DROP INDEX IF EXISTS idx_users_email;
-- 제약조건(Constraint) 삭제 시
ALTER TABLE users DROP CONSTRAINT IF EXISTS uq_users_email;
-- 인덱스 존재 여부 확인 후 처리
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'users'
AND indexname = 'idx_users_email'
) THEN
DROP INDEX idx_users_email;
RAISE NOTICE 'Index idx_users_email dropped successfully.';
ELSE
RAISE NOTICE 'Index idx_users_email does not exist, skipping.';
END IF;
END;
$$;
2. 사용자 정의 타입 및 연산자 존재 확인
사용자 정의 타입을 사용하기 전에 pg_type 카탈로그를 통해 존재 여부를 확인하세요.
-- 에러 발생 예시: 존재하지 않는 타입 사용
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
status order_status_enum -- 타입이 없으면 42704 발생
);
-- 해결 방법: 타입 존재 여부 먼저 확인
SELECT typname, typtype
FROM pg_type
WHERE typname = 'order_status_enum'
AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public');
-- 타입이 없다면 먼저 생성
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_type
WHERE typname = 'order_status_enum'
AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
) THEN
CREATE TYPE public.order_status_enum AS ENUM ('pending', 'processing', 'completed', 'cancelled');
RAISE NOTICE 'Type order_status_enum created.';
ELSE
RAISE NOTICE 'Type order_status_enum already exists.';
END IF;
END;
$$;
-- 이후 테이블 생성
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
status public.order_status_enum NOT NULL DEFAULT 'pending'
);
3. 텍스트 검색 구성 확인 및 수정
-- 에러 발생 예시: 존재하지 않는 텍스트 검색 구성 사용
SELECT to_tsvector('korean', '안녕하세요 PostgreSQL');
-- ERROR: 42704: text search configuration "korean" does not exist
-- 현재 설치된 텍스트 검색 구성 목록 확인
SELECT cfgname, cfgparser::text
FROM pg_ts_config
ORDER BY cfgname;
-- 기본 제공 구성으로 대체 (한국어는 별도 확장 필요)
SELECT to_tsvector('simple', 'hello postgresql full text search');
-- 사용자 정의 텍스트 검색 구성 생성 예시
CREATE TEXT SEARCH CONFIGURATION public.my_korean_config (COPY = simple);
-- GIN 인덱스에 올바른 구성 적용
CREATE INDEX idx_articles_fts
ON articles
USING GIN (to_tsvector('simple', title || ' ' || body));
-- 세션 기본 텍스트 검색 구성 설정
SET default_text_search_config = 'pg_catalog.simple';
4. search_path 설정 문제로 인한 객체 미인식 해결
-- search_path 확인
SHOW search_path;
-- 특정 스키마의 객체가 보이지 않을 때
SET search_path TO public, myschema, pg_catalog;
-- 또는 연결 시 기본값으로 설정
ALTER ROLE myuser SET search_path TO public, myschema;
-- 스키마를 명시적으로 지정하여 참조
DROP INDEX IF EXISTS myschema.idx_products_name;
DROP TYPE IF EXISTS myschema.my_custom_type;
예방 방법
- 모든 DDL 스크립트에
IF EXISTS/IF NOT EXISTS패턴을 표준화하세요
마이그레이션 스크립트, 롤백 스크립트, 배포 자동화 파이프라인에서 DROP 구문을 사용할 때는 항상 IF EXISTS를 붙이는 것을 팀 코딩 컨벤션으로 정착시키세요. Flyway, Liquibase 등의 마이그레이션 도구를 사용하더라도, 내부 SQL 스크립트에서 이 패턴을 철저히 적용하면 환경 간 스키마 불일치로 인한 장애를 예방할 수 있습니다. 또한 CI/CD 파이프라인에서 마이그레이션 스크립트를 운영 환경 적용 전 스테이징 환경에서 반드시 검증하는 절차를 마련하세요.
pg_catalog시스템 카탈로그를 활용한 사전 검증 루틴을 구축하세요
배포 전 pg_indexes, pg_constraint, pg_type, pg_operator, pg_ts_config 등의 시스템 카탈로그 뷰를 조회하여 필요한 객체가 존재하는지 확인하는 헬스체크 스크립트를 작성하고, 이를 배포 파이프라인에 통합하세요. 특히 멀티 스키마 환경에서는 search_path를 명시적으로 고정하고, 객체를 참조할 때 항상 스키마 이름을 prefix로 붙이는 습관을 들이면 42704 에러를 근본적으로 줄일 수 있습니다.
관련 에러
- 42P01 (undefined_table): 존재하지 않는 테이블을 참조할 때 발생하며, 42704와 유사하지만 테이블 객체에 특화된 에러입니다.
- 42703 (undefined_column): 존재하지 않는 컬럼을 참조할 때 발생합니다.
- 42883 (undefined_function): 존재하지 않는 함수를 호출하거나 인자 타입이 맞지 않는 함수를 호출할 때 발생합니다.
- 42P02 (undefined_parameter): 준비된 구문(Prepared Statement)에서 파라미터가 정의되지 않았을 때 발생합니다.
- 3F000 (invalid_schema_name): 존재하지 않는 스키마를 참조할 때 발생하며, search_path 문제와 함께 42704를 유발하는 경우가 많습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.