2026년 07월 24일 | DBMS Error 가이드
이 글에서 다루는 내용
HV004 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
HV004 fdw invalid data type 는?
PostgreSQL에서 HV004: fdw invalid data type 에러는 Foreign Data Wrapper(FDW) 를 통해 외부 데이터 소스에 접근할 때, 외부 테이블의 컬럼 데이터 타입이 PostgreSQL 내부 타입과 호환되지 않거나 올바르게 매핑되지 않은 경우 발생합니다. 쉽게 말해, 외부 서버(Oracle, MySQL, CSV 파일 등)에서 정의된 데이터 타입을 PostgreSQL이 이해하거나 변환할 수 없을 때 나타나는 에러입니다. 이 에러는 주로 postgres_fdw, oracle_fdw, mysql_fdw, file_fdw 등 다양한 FDW 구현체에서 공통적으로 발생할 수 있으며, 외부 테이블(Foreign Table) 생성 시 또는 쿼리 실행 시점에 감지됩니다.
주요 발생 원인
- 외부 테이블 컬럼 타입과 실제 외부 소스 타입 불일치
가장 흔한 원인으로, CREATE FOREIGN TABLE 구문에서 선언한 PostgreSQL 데이터 타입이 실제 원격 데이터베이스 또는 파일의 데이터 타입과 맞지 않을 때 발생합니다. 예를 들어 Oracle의 NUMBER(10,2) 컬럼을 PostgreSQL Foreign Table에서 INTEGER로 선언하거나, MySQL의 TINYINT(1) 을 TEXT로 잘못 매핑하는 경우가 대표적입니다. FDW 드라이버는 데이터를 가져올 때 선언된 타입으로 캐스팅을 시도하며, 이 과정에서 변환 불가능한 타입이 발견되면 HV004 에러를 발생시킵니다.
- FDW 드라이버가 지원하지 않는 PostgreSQL 고유 데이터 타입 사용
PostgreSQL에는 UUID, JSONB, ARRAY, HSTORE, TSTZRANGE 등 다른 데이터베이스 시스템에서는 지원하지 않는 고유 타입들이 많습니다. 외부 테이블을 정의할 때 이러한 타입을 무분별하게 사용하면, FDW 드라이버가 원격 시스템으로부터 데이터를 수신한 뒤 해당 타입으로 변환하는 과정에서 실패할 수 있습니다. 특히 oracle_fdw나 mysql_fdw 같은 이기종 FDW에서는 타입 지원 범위가 제한적이므로, 드라이버 공식 문서에서 지원 타입 목록을 반드시 확인해야 합니다.
- FDW 버전 업그레이드 또는 원격 스키마 변경 후 타입 불일치
처음에는 정상적으로 동작하던 Foreign Table이 원격 데이터베이스의 스키마 변경(컬럼 타입 변경, 컬럼 추가/삭제) 이후 갑자기 HV004 에러를 발생시키는 경우가 있습니다. 또한 FDW 익스텐션을 업그레이드했을 때 내부 타입 매핑 규칙이 변경되어 기존에 허용되던 타입 조합이 더 이상 허용되지 않게 되는 상황도 발생합니다. 이런 경우에는 현재 Foreign Table의 컬럼 정의와 원격 테이블의 실제 컬럼 정의를 꼼꼼히 비교 검토해야 합니다.
해결 방법
원인 1 해결: 컬럼 타입 재정의
잘못 선언된 Foreign Table을 삭제하고 올바른 타입으로 재생성합니다.
-- 문제가 있는 Foreign Table 확인
SELECT attname, atttypid::regtype AS data_type
FROM pg_attribute
WHERE attrelid = 'public.foreign_orders'::regclass
AND attnum > 0;
-- 기존 Foreign Table 삭제
DROP FOREIGN TABLE IF EXISTS public.foreign_orders;
-- 올바른 타입으로 재생성 (Oracle NUMBER -> PostgreSQL NUMERIC)
CREATE FOREIGN TABLE public.foreign_orders (
order_id INTEGER,
customer_id INTEGER,
amount NUMERIC(10, 2), -- Oracle NUMBER(10,2) 에 대응
order_date TIMESTAMP, -- Oracle DATE 에 대응
status VARCHAR(20)
)
SERVER oracle_server
OPTIONS (schema 'SALES', table 'ORDERS');
-- 재생성 후 정상 조회 테스트
SELECT * FROM public.foreign_orders LIMIT 10;
원인 2 해결: 지원 타입으로 대체 및 캐스팅
FDW 드라이버가 지원하지 않는 타입 대신 호환 가능한 기본 타입을 사용하고, 뷰(View)에서 캐스팅합니다.
-- JSONB 대신 TEXT로 Foreign Table 정의
CREATE FOREIGN TABLE public.foreign_products (
product_id INTEGER,
product_name VARCHAR(200),
attributes TEXT, -- JSONB 대신 TEXT로 선언
created_at TIMESTAMP
)
SERVER mysql_server
OPTIONS (dbname 'inventory', table_name 'products');
-- 뷰를 통해 TEXT -> JSONB 변환 제공
CREATE OR REPLACE VIEW public.v_products AS
SELECT
product_id,
product_name,
attributes::JSONB AS attributes, -- 애플리케이션에는 JSONB로 제공
created_at
FROM public.foreign_products;
-- UUID 타입이 문제인 경우도 동일하게 TEXT 변환 후 캐스팅
CREATE FOREIGN TABLE public.foreign_users (
user_id TEXT, -- UUID 대신 TEXT
username VARCHAR(100),
email VARCHAR(200)
)
SERVER postgres_remote_server
OPTIONS (schema_name 'public', table_name 'users');
CREATE OR REPLACE VIEW public.v_users AS
SELECT
user_id::UUID AS user_id, -- 뷰에서 UUID로 캐스팅
username,
email
FROM public.foreign_users;
원인 3 해결: 원격 스키마 재임포트 및 Foreign Table 재동기화
IMPORT FOREIGN SCHEMA를 활용하여 원격 스키마 변경사항을 자동으로 반영합니다.
-- 현재 Foreign Table 정의 백업
SELECT
ft.ftrelid::regclass AS foreign_table,
fs.srvname AS server_name,
fto.ftoptions AS table_options
FROM pg_foreign_table ft
JOIN pg_foreign_server fs ON ft.ftserver = fs.oid
JOIN pg_class c ON ft.ftrelid = c.oid
LEFT JOIN pg_foreign_table fto ON ft.ftrelid = fto.ftrelid
WHERE c.relnamespace = 'public'::regnamespace;
-- 기존 Foreign Table 제거 후 스키마 재임포트
DROP FOREIGN TABLE IF EXISTS public.foreign_orders CASCADE;
-- IMPORT FOREIGN SCHEMA 로 자동 타입 매핑
IMPORT FOREIGN SCHEMA sales
LIMIT TO (orders, order_items, customers)
FROM SERVER oracle_server
INTO public;
-- 임포트된 테이블 컬럼 및 타입 확인
SELECT
column_name,
data_type,
character_maximum_length,
numeric_precision,
numeric_scale
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'orders'
ORDER BY ordinal_position;
-- FDW 익스텐션 버전 확인
SELECT extname, extversion
FROM pg_extension
WHERE extname LIKE '%fdw%';
진단 쿼리: 현재 FDW 설정 전체 확인
-- FDW, Server, User Mapping, Foreign Table 전체 현황 조회
SELECT
fs.srvname AS server_name,
ft.ftrelid::regclass AS foreign_table_name,
a.attname AS column_name,
t.typname AS column_type,
fto.ftoptions AS column_options
FROM pg_foreign_table ft
JOIN pg_foreign_server fs ON ft.ftserver = fs.oid
JOIN pg_attribute a ON a.attrelid = ft.ftrelid AND a.attnum > 0
JOIN pg_type t ON t.oid = a.atttypid
LEFT JOIN pg_attribute_options fto ON fto.attrelid = a.attrelid AND fto.attnum = a.attnum
ORDER BY fs.srvname, ft.ftrelid::regclass, a.attnum;
예방 방법
IMPORT FOREIGN SCHEMA적극 활용 및 정기 재동기화
Foreign Table을 수동으로 CREATE FOREIGN TABLE로 작성하기보다는, IMPORT FOREIGN SCHEMA 명령을 활용하여 PostgreSQL이 원격 스키마를 자동으로 읽어 타입을 매핑하도록 합니다. 원격 데이터베이스의 스키마가 변경될 가능성이 있다면, 정기적인 배포 파이프라인이나 스케줄러를 통해 Foreign Table을 재임포트하는 프로세스를 구축해 두는 것이 좋습니다. 또한 원격 스키마에 DDL 변경이 발생할 때 알림을 받을 수 있도록 원격 DB의 DDL 감사 로그나 이벤트 트리거를 설정하면 사전 대응이 가능합니다.
- 타입 호환성 매핑 문서화 및 CI/CD 파이프라인 검증 자동화
프로젝트 내에서 원격 시스템별 타입 매핑 표(예: Oracle ↔ PostgreSQL, MySQL ↔ PostgreSQL)를 문서로 유지 관리하고, 모든 팀원이 Foreign Table 정의 시 참조하도록 합니다. CI/CD 파이프라인에 Foreign Table 정의 변경 시 자동으로 SELECT 1 FROM foreign_table LIMIT 1 형태의 스모크 테스트를 포함시켜, 배포 전에 타입 불일치 문제를 조기에 발견할 수 있도록 자동화합니다. 이를 통해 운영 환경에서의 HV004 에러 발생 가능성을 크게 줄일 수 있습니다.
관련 에러
- HV000 (fdw error): FDW 관련 일반 에러의 상위 분류로, HV004를 포함한 모든 FDW 에러의 부모 에러 코드입니다.
- HV005 (fdw column name not found): 원격 테이블에서 Foreign Table에 정의된 컬럼명을 찾을 수 없을 때 발생하며, HV004와 함께 스키마 불일치 상황에서 자주 같이 나타납니다.
- HV021 (fdw invalid column number): 원격 테이블의 컬럼 번호가 잘못 참조될 때 발생하며, IMPORT FOREIGN SCHEMA 이후 스키마 변경 시 나타날 수 있습니다.
- 42804 (datatype mismatch): FDW와 직접 관련은 없지만, INSERT/SELECT 시 타입 불일치 상황에서 함께 나타날 수 있는 에러로, HV004와 혼동되는 경우가 있습니다.
- HV002 (fdw dynamic parameter value needed): FDW 옵션 파라미터 설정 오류 시 발생하며, Foreign Server 설정 문제와 함께 HV004를 동반하는 경우가 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.