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

22021
2026년 10월 12일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22021 character not in repertoire 는?

PostgreSQL 에러 코드 22021 (character not in repertoire)은 데이터베이스가 특정 문자 인코딩 레퍼토리(repertoire)에서 지원하지 않는 문자를 처리하려 할 때 발생합니다. 쉽게 말해, 현재 데이터베이스 또는 컬럼의 인코딩 설정으로는 표현할 수 없는 문자가 삽입되거나 변환될 때 이 에러가 트리거됩니다. 특히 다국어 데이터를 다루는 시스템, 레거시 데이터베이스 마이그레이션, 또는 외부 시스템으로부터 데이터를 수신하는 ETL 파이프라인 환경에서 자주 목격됩니다.


주요 발생 원인

1. 클라이언트 인코딩과 서버 인코딩 불일치

가장 흔한 원인입니다. 클라이언트(애플리케이션 또는 psql)가 UTF-8로 데이터를 전송하는데 서버의 데이터베이스가 LATIN1 또는 SQL_ASCII와 같은 제한된 인코딩으로 설정되어 있을 경우, UTF-8에서만 표현 가능한 멀티바이트 문자(예: 한국어, 이모지, 아랍 문자 등)를 대상 인코딩으로 변환하지 못해 에러가 발생합니다. 이 상황은 client_encoding과 server_encoding이 서로 다를 때 PostgreSQL의 내부 변환 과정에서 충돌이 일어나는 것으로 이해할 수 있습니다.

2. SQL_ASCII 인코딩 데이터베이스에 비 ASCII 문자 삽입

SQL_ASCII로 생성된 데이터베이스는 사실상 인코딩 검증을 수행하지 않는 “바이트 통과(passthrough)” 모드로 동작하지만, 특정 상황(예: 변환 함수 사용, COPY 명령, 또는 일부 드라이버)에서는 비 ASCII 바이트 시퀀스를 처리할 때 22021 에러를 유발할 수 있습니다. 레거시 시스템에서 마이그레이션된 데이터베이스나 오래된 설정을 그대로 유지하는 시스템에서 특히 자주 발생합니다.

3. convert() 또는 convert_to() 함수 사용 시 인코딩 변환 실패

convert('문자열', 'UTF8', 'LATIN1')처럼 명시적으로 인코딩 변환을 수행하는 SQL 함수를 사용할 때, 원본 문자가 대상 인코딩에 존재하지 않으면 바로 22021 에러가 발생합니다. 예를 들어 한글, 중국어, 이모지 등은 LATIN1 인코딩의 레퍼토리에 포함되어 있지 않기 때문에 변환 자체가 불가능합니다. 이 원인은 코드 내에서 명시적으로 인코딩 변환을 호출하는 경우에 한정되므로, 에러 발생 지점을 추적하기 비교적 쉬운 편입니다.


해결 방법

원인 1 해결: 클라이언트 인코딩 설정 확인 및 조정

먼저 현재 데이터베이스 및 클라이언트 인코딩을 확인합니다.

-- 현재 서버 인코딩 및 클라이언트 인코딩 확인
SHOW server_encoding;
SHOW client_encoding;

-- 데이터베이스별 인코딩 확인
SELECT datname, pg_encoding_to_char(encoding) AS encoding
FROM pg_database;

클라이언트 인코딩을 서버 인코딩에 맞게 세션 단위로 조정합니다.

-- 세션 내 클라이언트 인코딩을 UTF8로 강제 설정
SET client_encoding TO 'UTF8';

-- 또는 연결 시 psql 옵션으로 지정
-- psql -U postgres -d mydb --set=client_encoding=UTF8

만약 데이터베이스 자체를 UTF-8로 다시 생성해야 한다면 아래와 같이 합니다.

-- UTF-8 인코딩으로 새 데이터베이스 생성
CREATE DATABASE mydb_utf8
    ENCODING 'UTF8'
    LC_COLLATE 'ko_KR.UTF-8'
    LC_CTYPE 'ko_KR.UTF-8'
    TEMPLATE template0;

원인 2 해결: SQL_ASCII 데이터베이스 문제 우회 또는 마이그레이션

SQL_ASCII 데이터베이스에서 문제가 발생한 경우, 임시 우회 방법으로 bytea 타입을 활용하거나 데이터를 바이트 단위로 처리할 수 있습니다.

-- 비 ASCII 데이터를 bytea로 저장하여 인코딩 검증 우회
INSERT INTO legacy_table (raw_data)
VALUES (convert_to('한글 데이터', 'UTF8')::bytea);

-- 저장된 bytea 데이터를 다시 텍스트로 변환
SELECT convert_from(raw_data, 'UTF8') FROM legacy_table;

-- SQL_ASCII DB에서 UTF-8 DB로 데이터 마이그레이션 시
-- pg_dump에 --no-encoding 또는 명시적 인코딩 지정
-- pg_dump -U postgres -d old_db --encoding=UTF8 -f dump.sql

원인 3 해결: 인코딩 변환 함수 사용 시 안전 처리

convert() 계열 함수 사용 전에 변환 가능 여부를 검증하거나, 변환 실패 시 대체 값을 반환하도록 예외 처리를 구현합니다.

-- 안전한 인코딩 변환 함수 래퍼 예제
CREATE OR REPLACE FUNCTION safe_convert_to(
    input_text TEXT,
    target_encoding NAME
) RETURNS BYTEA AS $$
BEGIN
    RETURN convert_to(input_text, target_encoding);
EXCEPTION
    WHEN character_not_in_repertoire THEN
        -- 변환 실패 시 NULL 반환 또는 로그 처리
        RAISE WARNING 'Encoding conversion failed for input: %', left(input_text, 50);
        RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- 사용 예시
SELECT safe_convert_to('Hello 안녕하세요', 'LATIN1');

-- 특수 문자 제거 후 변환하는 방법
SELECT convert_to(
    regexp_replace('Hello 안녕하세요', '[^\x00-\x7F]', '', 'g'),
    'LATIN1'
);

예방 방법

1. 데이터베이스 생성 시 UTF-8 인코딩을 표준으로 강제화

모든 신규 데이터베이스는 반드시 UTF8 인코딩으로 생성하는 것을 팀 내 표준으로 정착시켜야 합니다. PostgreSQL 템플릿 데이터베이스(template1)를 UTF-8로 미리 설정해 두면 별도 지정 없이도 항상 UTF-8 데이터베이스가 생성됩니다. 또한 애플리케이션 레벨의 DB 연결 설정에도 client_encoding=UTF8을 명시적으로 포함시켜 클라이언트-서버 인코딩 불일치를 원천 차단하세요.

-- postgresql.conf 또는 ALTER SYSTEM으로 기본 클라이언트 인코딩 설정
ALTER SYSTEM SET client_encoding = 'UTF8';
SELECT pg_reload_conf();

2. 데이터 입력 전 인코딩 유효성 검사 로직 구현

ETL 파이프라인이나 외부 데이터 수신 로직에서 데이터베이스에 삽입하기 전 반드시 인코딩 유효성을 검증하는 단계를 추가하세요. PostgreSQL의 pg_client_encoding() 함수와 정규식을 조합하거나, 애플리케이션 레이어(Python의 chardet, Java의 ICU4J 등)에서 사전 검증을 수행하면 런타임 에러를 사전에 방지할 수 있습니다.

-- 텍스트가 유효한 UTF-8인지 간접 검증하는 방법
-- (bytea를 통한 라운드트립 검증)
DO $$
DECLARE
    test_input TEXT := '테스트 문자열 🎉';
BEGIN
    -- 정상 케이스: 변환 성공
    PERFORM convert_to(test_input, 'UTF8');
    RAISE NOTICE 'Valid UTF-8 string confirmed.';
EXCEPTION
    WHEN character_not_in_repertoire THEN
        RAISE EXCEPTION 'Invalid encoding detected in input data.';
END;
$$;

관련 에러

  • 22000 (data_exception): 22021의 상위 카테고리 에러로, 데이터 관련 다양한 예외의 부모 클래스입니다.
  • 22P05 (untranslatable_character): 문자를 서버 인코딩으로 변환할 수 없을 때 발생하며, 22021과 매우 유사한 맥락에서 등장합니다. 클라이언트에서 서버로 전송 중 변환 불가 문자가 있을 때 주로 이 코드가 사용됩니다.
  • 42809 / 42P18: 잘못된 인코딩 이름을 지정했을 때 발생하는 에러로, 인코딩 관련 설정 작업 중 함께 마주치는 경우가 많습니다.
  • 08P01 (protocol_violation): 일부 드라이버에서 인코딩 협상 실패 시 프로토콜 레벨 에러로 나타나는 경우가 있어 22021과 혼동될 수 있습니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기