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

22021
2026년 08월 08일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22021 character not in repertoire 는?

PostgreSQL 에러 코드 22021 character not in repertoire는 데이터베이스가 처리하려는 문자열에 현재 설정된 문자 인코딩 체계(character repertoire)에 포함되지 않는 문자가 존재할 때 발생합니다. 쉽게 말해, 데이터베이스나 특정 컬럼에서 허용하지 않는 문자를 삽입하거나 변환하려 할 때 PostgreSQL이 이를 거부하며 던지는 오류입니다. 주로 클라이언트 인코딩과 서버 인코딩 간의 불일치, 또는 SQL_ASCII 인코딩 환경에서 멀티바이트 문자를 다룰 때 빈번하게 나타납니다.


주요 발생 원인

  • 클라이언트-서버 인코딩 불일치

가장 흔한 원인입니다. 클라이언트 애플리케이션이 UTF-8로 문자를 전송하는데, 서버의 데이터베이스가 SQL_ASCII 또는 LATIN1 등의 인코딩으로 설정되어 있을 경우 멀티바이트 한글, 일본어, 아랍어 같은 문자를 정상적으로 수용하지 못합니다. 예를 들어, 한국어 애플리케이션 서버가 UTF-8 문자열을 SQL_ASCII 데이터베이스에 INSERT하려 하면 이 에러가 즉시 발생합니다.

  • SQL_ASCII 데이터베이스에서의 멀티바이트 문자 처리

PostgreSQL에서 SQL_ASCII는 사실상 “인코딩 검사를 하지 않겠다”는 의미이지만, 내부적으로 특정 함수나 연산을 수행할 때 문자 레퍼토리 검사가 이루어질 수 있습니다. SQL_ASCII 데이터베이스에서 to_tsvector(), regexp_replace(), upper(), lower() 같은 문자 처리 함수를 멀티바이트 문자에 적용하면 이 에러가 발생할 수 있습니다. 이는 레거시 시스템에서 특히 자주 마주치는 문제입니다.

  • 잘못된 client_encoding 세션 파라미터 설정

애플리케이션 연결 시 client_encoding이 실제 데이터의 인코딩과 다르게 설정되면 PostgreSQL은 내부 변환 과정에서 변환 불가능한 문자를 만나게 됩니다. 예를 들어, 실제 데이터는 EUC-KR로 인코딩되어 있는데 세션의 client_encoding이 UTF-8로 설정된 경우, 또는 그 반대의 경우에도 이 에러가 트리거될 수 있습니다. JDBC나 psycopg2 같은 드라이버에서 인코딩 옵션을 누락하거나 잘못 지정하는 경우가 많습니다.


해결 방법

원인 1: 클라이언트-서버 인코딩 불일치 해결

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

-- 현재 데이터베이스 인코딩 확인
SELECT pg_encoding_to_char(encoding), datname
FROM pg_database
WHERE datname = current_database();

-- 현재 세션의 클라이언트 인코딩 확인
SHOW client_encoding;

-- 세션 수준에서 클라이언트 인코딩 강제 설정 (서버 인코딩과 맞춤)
SET client_encoding = 'UTF8';

데이터베이스 자체를 재생성해야 한다면 아래와 같이 올바른 인코딩으로 새 데이터베이스를 만들어야 합니다.

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

원인 2: SQL_ASCII 환경에서의 문자 처리 우회

SQL_ASCII 데이터베이스에서 멀티바이트 문자를 처리해야 한다면, convert_from() 또는 encode()/decode() 함수를 활용하거나 바이트 처리 방식으로 우회합니다.

-- 문제가 되는 쿼리 예시 (SQL_ASCII DB에서 에러 발생 가능)
-- SELECT upper(some_column) FROM my_table;

-- 우회 방법 1: 바이트 변환 후 처리
SELECT convert_from(some_column::bytea, 'UTF8')
FROM my_table;

-- 우회 방법 2: 특정 컬럼에서 문자 인코딩을 명시적으로 지정하여 캐스팅
SELECT encode(convert_to(some_text, 'UTF8'), 'escape')
FROM my_table;

-- 우회 방법 3: 텍스트 검색 함수 사용 시 설정 명시
SELECT to_tsvector('simple', some_column)
FROM my_table;

원인 3: 세션 client_encoding 파라미터 수정

애플리케이션 연결 직후 또는 postgresql.conf / pg_hba.conf 레벨에서 인코딩을 통일합니다.

-- 연결 직후 인코딩 강제 맞춤
SET client_encoding TO 'UTF8';

-- 특정 유저의 기본 인코딩 설정 (이후 연결부터 자동 적용)
ALTER ROLE myapp_user SET client_encoding = 'UTF8';

-- 특정 데이터베이스 수준에서 기본 인코딩 설정
ALTER DATABASE myapp_db SET client_encoding = 'UTF8';

-- 현재 설정 전체 확인
SELECT name, setting, context
FROM pg_settings
WHERE name IN ('client_encoding', 'server_encoding');

즉각적인 데이터 정제가 필요한 경우

기존 데이터에 문제 있는 문자가 포함되어 있다면 아래처럼 정제할 수 있습니다.

-- 유효하지 않은 UTF-8 바이트 시퀀스 제거 (PostgreSQL 9.x+)
UPDATE my_table
SET problematic_column = regexp_replace(
    convert_from(
        regexp_replace(
            encode(problematic_column::bytea, 'hex'),
            '(..)',
            E'\\\\x\\1',
            'g'
        )::bytea,
        'UTF8'
    ),
    '[^\u0009\u000A\u000D\u0020-\uD7FF\uE000-\uFFFD]',
    '',
    'g'
)
WHERE problematic_column IS NOT NULL;

-- 안전하게 변환 가능 여부 먼저 테스트
SELECT id, problematic_column,
       length(problematic_column) AS original_len,
       octet_length(problematic_column) AS byte_len
FROM my_table
WHERE octet_length(problematic_column) > length(problematic_column);

예방 방법

  • 데이터베이스 생성 시 반드시 UTF-8 인코딩과 적절한 로케일을 지정하라

모든 신규 PostgreSQL 데이터베이스는 ENCODING = 'UTF8'TEMPLATE = template0을 명시하여 생성하는 것을 팀 규칙으로 정착시켜야 합니다. SQL_ASCII는 인코딩 검사를 우회하는 것처럼 보이지만 오히려 예측 불가능한 에러를 유발하는 시한폭탄이므로 실무에서는 절대 사용하지 않는 것이 좋습니다. CI/CD 파이프라인의 DB 마이그레이션 스크립트에 인코딩 검증 단계를 포함시키면 더욱 안전합니다.

“`sql

— 팀 표준 DB 생성 템플릿

CREATE DATABASE production_db

WITH OWNER = db_owner

ENCODING = ‘UTF8’

LC_COLLATE = ‘en_US.UTF-8’

LC_CTYPE = ‘en_US.UTF-8’

TEMPLATE = template0

CONNECTION LIMIT = 200;

“`

  • 애플리케이션 레벨에서 연결 직후 인코딩을 명시적으로 설정하고 모니터링하라

JDBC, psycopg2, node-postgres 등 모든 드라이버에서 연결 문자열에 인코딩을 명시하고, ALTER ROLE을 통해 사용자 수준 기본값을 설정해두면 개별 연결의 설정 누락으로 인한 문제를 원천 차단할 수 있습니다. 또한 운영 환경의 로그 레벨(log_min_messages)을 적절히 설정하여 인코딩 변환 경고를 조기에 포착하는 모니터링 체계를 갖추는 것이 중요합니다.


관련 에러

  • 22000 data_exception: 22021의 상위 카테고리 에러로, 데이터 값 관련 다양한 예외를 포괄합니다.
  • 22P05 untranslatable_character: 특정 문자를 목표 인코딩으로 변환할 수 없을 때 발생하며, 22021과 매우 유사한 상황에서 나타납니다.
  • 42809 wrong_object_type: 인코딩 관련 함수에 잘못된 타입의 객체를 전달할 때 발생할 수 있습니다.
  • 08P01 protocol_violation: 클라이언트가 서버와 완전히 다른 인코딩으로 통신을 시도할 때 프로토콜 수준에서 발생하는 연관 에러입니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기