2026년 06월 14일 | DBMS Error 가이드
이 글에서 다루는 내용
22P03 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
22P03 invalid binary representation 는?
PostgreSQL 에러 코드 22P03 invalid binary representation은 데이터를 바이너리 형식으로 전송하거나 변환하는 과정에서 해당 값이 올바른 바이너리 표현 형식을 따르지 않을 때 발생합니다. 주로 클라이언트 애플리케이션이 PostgreSQL 서버로 바이너리 프로토콜을 통해 데이터를 전달하거나, COPY 명령어의 바이너리 모드를 사용하거나, bytea 타입 등의 바이너리 데이터를 잘못된 형식으로 입력할 때 나타납니다. 이 에러는 데이터 타입의 내부 바이너리 포맷이 PostgreSQL의 기대값과 불일치할 때 서버가 해당 데이터를 파싱하지 못하고 즉시 오류를 반환하는 상황에서 발생합니다.
주요 발생 원인
1. COPY 명령어의 바이너리 모드에서 잘못된 데이터 포맷 사용
PostgreSQL의 COPY ... WITH (FORMAT BINARY) 명령어는 엄격한 바이너리 파일 포맷을 요구합니다. 바이너리 COPY 파일은 고정된 헤더(11바이트 시그니처 + 플래그 필드 + 헤더 확장 영역)를 반드시 포함해야 하며, 이를 누락하거나 잘못 구성한 파일을 로드하려 하면 즉시 이 에러가 발생합니다. 특히 텍스트 모드로 생성된 덤프 파일을 바이너리 모드로 불러오려 할 때 흔히 발생하는 실수입니다.
2. bytea 타입에 잘못된 형식의 이진 문자열 입력
bytea 컬럼에 데이터를 삽입할 때 PostgreSQL은 기본적으로 hex 형식(\x로 시작)이나 escape 형식을 지원합니다. 잘못된 16진수 문자열이나 올바르지 않은 이스케이프 시퀀스를 입력하면 서버가 바이너리 표현을 해석하지 못하고 이 에러를 반환합니다. 애플리케이션에서 바이트 배열을 문자열로 변환하는 과정에서 인코딩 처리가 미흡할 경우 자주 발생합니다.
3. 클라이언트 드라이버의 바이너리 프로토콜 불일치 또는 버전 차이
JDBC, libpq, psycopg2 등의 드라이버가 바이너리 프로토콜을 사용하여 데이터를 전송할 때, 드라이버 버전과 PostgreSQL 서버 버전 간의 내부 데이터 표현 방식이 맞지 않으면 이 에러가 발생할 수 있습니다. 특히 사용자 정의 타입(Composite Type, Domain 등)이나 배열 타입을 바이너리 모드로 전송할 경우 직렬화/역직렬화 과정에서 불일치가 생기기 쉽습니다.
해결 방법
원인 1 해결: COPY 바이너리 모드 문제 수정
텍스트 형식으로 된 파일을 바이너리 모드로 읽으려 했다면, 올바른 포맷을 명시하거나 텍스트 모드로 전환하세요.
-- 잘못된 예시: 텍스트 파일을 바이너리로 로드 시도 (에러 발생)
-- COPY my_table FROM '/tmp/data.txt' WITH (FORMAT BINARY);
-- 올바른 예시 1: 텍스트 포맷으로 명시
COPY my_table FROM '/tmp/data.txt' WITH (FORMAT TEXT, DELIMITER ',');
-- 올바른 예시 2: CSV 형식으로 명시
COPY my_table FROM '/tmp/data.csv' WITH (FORMAT CSV, HEADER true);
-- 바이너리 파일을 올바르게 생성하고 로드하는 예시
-- (덤프 시)
COPY my_table TO '/tmp/data.bin' WITH (FORMAT BINARY);
-- (복원 시)
COPY my_table FROM '/tmp/data.bin' WITH (FORMAT BINARY);
-- 현재 테이블의 데이터 포맷 확인
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'my_table';
원인 2 해결: bytea 데이터 형식 교정
bytea 타입에 올바른 형식으로 데이터를 삽입해야 합니다.
-- 잘못된 예시: 올바르지 않은 hex 문자열 (에러 발생 가능)
-- INSERT INTO file_storage (data) VALUES ('\xZZFF'); -- 유효하지 않은 hex 문자 Z
-- 올바른 예시 1: hex 형식 (PostgreSQL 기본, \x 접두어 사용)
INSERT INTO file_storage (file_name, data)
VALUES ('example.bin', '\xDEADBEEF');
-- 올바른 예시 2: escape 형식
INSERT INTO file_storage (file_name, data)
VALUES ('example2.bin', E'\\001\\002\\003');
-- bytea_output 설정 확인 및 변경
SHOW bytea_output;
SET bytea_output = 'hex'; -- 또는 'escape'
-- 문자열을 bytea로 안전하게 변환
SELECT convert_to('Hello, PostgreSQL!', 'UTF8')::bytea;
-- hex 문자열 검증 후 삽입하는 안전한 방법
DO $$
DECLARE
v_hex TEXT := 'DEADBEEF';
BEGIN
-- 유효한 hex 문자열인지 확인
IF v_hex ~ '^[0-9A-Fa-f]*$' AND length(v_hex) % 2 = 0 THEN
INSERT INTO file_storage (file_name, data)
VALUES ('validated.bin', decode(v_hex, 'hex'));
RAISE NOTICE '삽입 성공';
ELSE
RAISE EXCEPTION '유효하지 않은 hex 문자열: %', v_hex;
END IF;
END;
$$;
-- encode/decode 함수로 안전하게 변환
SELECT encode(data, 'hex') FROM file_storage; -- bytea → hex 문자열
SELECT decode('DEADBEEF', 'hex'); -- hex 문자열 → bytea
원인 3 해결: 드라이버 바이너리 프로토콜 비활성화 또는 업그레이드
드라이버 수준에서 바이너리 프로토콜 전송을 비활성화하거나 텍스트 모드로 전환합니다.
-- 특정 세션에서 문제가 되는 타입의 캐스팅 확인
SELECT oid, typname, typtype, typcategory
FROM pg_type
WHERE typname IN ('bytea', 'json', 'jsonb', 'uuid');
-- 사용자 정의 타입이나 도메인의 바이너리 I/O 함수 확인
SELECT t.typname,
p_in.proname AS binary_input_func,
p_out.proname AS binary_output_func
FROM pg_type t
LEFT JOIN pg_proc p_in ON t.typreceive = p_in.oid
LEFT JOIN pg_proc p_out ON t.typsend = p_out.oid
WHERE t.typtype = 'c' -- composite types
ORDER BY t.typname;
-- 임시 해결: 텍스트 캐스팅을 통해 우회
SELECT val::text::integer FROM some_table; -- 바이너리 대신 텍스트 경로 강제
-- pg_stat_activity로 문제 세션 확인
SELECT pid, usename, application_name, client_addr, state, query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start;
예방 방법
1. 바이너리 데이터 처리 시 인코딩/디코딩 함수를 표준화하여 사용
애플리케이션 코드에서 바이너리 데이터를 처리할 때는 반드시 PostgreSQL에서 제공하는 encode(), decode() 함수를 활용하거나, 드라이버에서 제공하는 표준 바이너리 직렬화 메서드를 사용하세요. 임의의 문자열 연결이나 수동 변환 로직은 바이너리 표현 불일치를 유발하는 주요 원인이므로, 팀 내 코딩 컨벤션으로 표준 함수 사용을 강제하는 것이 바람직합니다.
2. COPY 작업 시 포맷을 명시적으로 지정하고, CI/CD 파이프라인에서 데이터 유효성 검사 자동화
COPY 명령어를 사용할 때는 반드시 FORMAT TEXT, FORMAT CSV, FORMAT BINARY 중 하나를 명시적으로 기술하여 혼동을 방지하세요. 또한 데이터 마이그레이션이나 ETL 파이프라인에서 바이너리 데이터를 처리할 경우, 스테이징 환경에서의 자동 유효성 검사 쿼리를 CI/CD에 포함시켜 운영 환경 반영 전에 포맷 오류를 사전에 차단하는 것이 좋습니다.
관련 에러
22000data_exception: 바이너리 표현 에러를 포함하는 상위 카테고리 에러로, 데이터 값 관련 다양한 예외의 부모 클래스입니다.22P02invalid_text_representation: 텍스트 형식의 값이 특정 데이터 타입으로 변환될 수 없을 때 발생하며,22P03의 텍스트 버전에 해당합니다. 예를 들어'abc'::integer시도 시 발생합니다.22021character_not_in_repertoire: 지정된 인코딩에서 표현할 수 없는 문자를 사용하려 할 때 발생하며, 바이너리와 텍스트 인코딩 경계에서 함께 나타날 수 있습니다.42804datatype_mismatch: 클라이언트가 바이너리 프로토콜로 잘못된 타입의 데이터를 전송할 경우 함께 나타날 수 있는 에러입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.