2026년 08월 16일 | DBMS Error 가이드
이 글에서 다루는 내용
22001 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
22001 string data right truncation 는?
PostgreSQL 에러 코드 22001, string data right truncation은 문자열 데이터를 특정 컬럼에 삽입하거나 업데이트할 때, 해당 데이터의 길이가 컬럼에 정의된 최대 길이를 초과할 경우 발생하는 에러입니다. 쉽게 말해, VARCHAR(10)으로 정의된 컬럼에 11자 이상의 문자열을 넣으려 할 때 PostgreSQL이 데이터를 자르는 대신 에러를 발생시키는 것입니다. 이 에러는 애플리케이션 개발 초기보다는 실제 운영 환경에서 예상치 못한 입력값이 들어올 때 더 자주 마주치게 되며, 데이터 무결성을 지키기 위한 PostgreSQL의 엄격한 타입 검사 결과입니다.
주요 발생 원인
1. 컬럼 길이 정의가 실제 데이터보다 짧게 설정된 경우
가장 흔한 원인으로, 테이블 설계 시점에는 충분해 보였던 컬럼 크기가 서비스가 성장하면서 부족해지는 경우입니다. 예를 들어, 사용자 이름을 VARCHAR(20)으로 설계했는데, 외국 사용자의 긴 이름이나 특수 명칭이 입력될 때 발생합니다. 특히 글로벌 서비스로 확장할 때 이 문제가 빈번하게 터집니다.
2. 외부 시스템 연동 또는 마이그레이션 시 데이터 불일치
다른 데이터베이스(MySQL, Oracle, MSSQL 등)에서 PostgreSQL로 데이터를 마이그레이션하거나, 외부 API에서 데이터를 받아 저장할 때 발생합니다. 원본 시스템의 컬럼 타입이나 데이터 유효성 검사 기준이 PostgreSQL과 다를 수 있으며, 특히 MySQL의 경우 기본 설정에서 문자열을 자동으로 잘라버리는(sql_mode에 따라) 경우가 있어 마이그레이션 후 PostgreSQL에서 에러가 처음 터지는 경우가 많습니다.
3. 애플리케이션 레이어의 유효성 검사 누락
백엔드 코드에서 입력값의 길이 검증 없이 사용자 입력을 그대로 데이터베이스에 전달할 때 발생합니다. 특히 프리페어드 스테이트먼트(Prepared Statement)를 사용하더라도 길이 검증은 별도로 처리해야 하며, 폼 필드의 maxlength 속성을 제거하거나 API를 직접 호출하는 경우 이 방어선이 뚫릴 수 있습니다.
해결 방법
원인 1 해결: 컬럼 길이 확장
현재 컬럼의 최대 길이를 확인하고, 필요에 따라 늘려주는 것이 가장 직접적인 해결책입니다.
-- 현재 테이블의 컬럼 정의 확인
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name = 'username';
-- 컬럼 길이 확장 (다운타임 없이 가능 - PostgreSQL은 VARCHAR 확장 시 테이블 재작성 불필요)
ALTER TABLE users
ALTER COLUMN username TYPE VARCHAR(100);
-- 만약 길이 제한 자체가 불필요하다면 TEXT 타입으로 변경
ALTER TABLE users
ALTER COLUMN username TYPE TEXT;
> 실무 팁: PostgreSQL에서 VARCHAR(n)의 길이를 늘리는 것은 테이블 잠금 없이 즉시 적용됩니다. 반면 줄이거나 다른 타입으로 변경 시에는 전체 테이블 스캔이 발생하므로 대용량 테이블에서는 주의가 필요합니다.
원인 2 해결: 마이그레이션 전 데이터 사전 검증 및 클렌징
-- 마이그레이션 전 초과 데이터 탐지 쿼리
SELECT id, username, LENGTH(username) AS len
FROM source_users
WHERE LENGTH(username) > 20
ORDER BY len DESC;
-- 데이터 잘라서 임시 저장 (마이그레이션 시 임시 방편)
INSERT INTO users (id, username, email)
SELECT id,
LEFT(username, 20), -- 20자로 강제 절단
email
FROM source_users;
-- 또는 SUBSTRING 사용
INSERT INTO users (id, username)
SELECT id, SUBSTRING(username FROM 1 FOR 20)
FROM source_users;
> 주의: 데이터를 자르는 것은 임시 방편입니다. 반드시 원본 데이터를 별도로 백업하고, 비즈니스 로직 상 데이터 손실이 허용되는지 확인한 후 진행하세요.
원인 3 해결: 데이터베이스 레벨에서 길이 초과 데이터 사전 차단
애플리케이션에서 검증이 누락되더라도 DB 레벨에서 방어할 수 있도록 CHECK 제약 조건을 추가하거나, 트리거를 활용합니다.
-- CHECK 제약 조건으로 길이 검증 강화
ALTER TABLE users
ADD CONSTRAINT chk_username_length
CHECK (LENGTH(username) <= 50);
-- 에러 대신 자동으로 잘라주는 트리거 (신중하게 사용)
CREATE OR REPLACE FUNCTION truncate_username()
RETURNS TRIGGER AS $$
BEGIN
IF LENGTH(NEW.username) > 50 THEN
-- 운영 로그 테이블에 원본 기록 후 자르기
INSERT INTO truncation_log (table_name, column_name, original_value, truncated_at)
VALUES ('users', 'username', NEW.username, NOW());
NEW.username := LEFT(NEW.username, 50);
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_truncate_username
BEFORE INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION truncate_username();
-- 현재 데이터 중 길이 초과 항목 확인
SELECT id, username, LENGTH(username) AS actual_length
FROM users
WHERE LENGTH(username) > 50;
에러 발생 시 즉각 진단 쿼리
-- 어떤 컬럼이 문제인지 빠르게 파악
SELECT
c.column_name,
c.character_maximum_length,
MAX(LENGTH(t.col_value)) AS max_actual_length
FROM information_schema.columns c
-- 실제 사용 시에는 동적 SQL 또는 pg_catalog 뷰 활용 권장
WHERE c.table_name = 'your_table'
AND c.character_maximum_length IS NOT NULL;
-- pg_catalog를 활용한 VARCHAR 컬럼 전체 조회
SELECT
a.attname AS column_name,
pg_catalog.format_type(a.atttypid, a.atttypmod) AS data_type
FROM pg_catalog.pg_attribute a
JOIN pg_catalog.pg_class c ON a.attrelid = c.oid
WHERE c.relname = 'users'
AND a.attnum > 0
AND NOT a.attisdropped
AND a.atttypmod > 0;
예방 방법
1. 설계 단계에서 여유 있는 컬럼 길이 정책 수립 및 TEXT 타입 적극 활용
실무에서 가장 효과적인 예방책은 불필요하게 짧은 VARCHAR(n) 대신 TEXT 타입을 적극 활용하는 것입니다. PostgreSQL에서 TEXT와 VARCHAR는 내부적으로 동일한 스토리지 메커니즘을 사용하므로 성능 차이가 없습니다. 길이 제한이 비즈니스 규칙상 반드시 필요한 경우(예: 전화번호, 우편번호 등)에만 VARCHAR(n)을 사용하고, 그 외에는 TEXT를 기본값으로 채택하는 팀 컨벤션을 만들어 두세요. 또한 신규 컬럼 추가 시 예상 최대 길이의 2배 이상으로 여유를 두는 것을 권장합니다.
2. CI/CD 파이프라인에 데이터 길이 검증 테스트 통합
애플리케이션 배포 파이프라인에 경계값 테스트(Boundary Test)를 포함시켜, 각 컬럼의 최대 허용 길이에 대한 자동화된 테스트를 반드시 실행하도록 합니다. pgTAP과 같은 PostgreSQL 전용 테스트 프레임워크를 활용하거나, 애플리케이션 레이어의 단위 테스트에서 DB 스키마의 character_maximum_length를 읽어와 동적으로 검증하는 방식을 도입하세요. 이를 통해 스키마 변경이나 데이터 소스 변경 시 배포 전에 문제를 사전에 감지할 수 있습니다.
관련 에러
- 22000 (data exception): 22001의 상위 카테고리 에러로, 데이터 관련 일반적인 예외를 포괄합니다.
- 22P02 (invalid_text_representation): 문자열을 숫자나 날짜 등 다른 타입으로 변환할 때 형식이 맞지 않을 경우 발생하며, 타입 캐스팅 시 함께 발생하는 경우가 많습니다.
- 23514 (check_violation): CHECK 제약 조건 위반으로, 위에서 제안한
chk_username_length같은 제약을 추가한 후 위반 시 발생합니다. - 42804 (datatype_mismatch): 잘못된 타입의 데이터를 삽입할 때 발생하는 에러로, 마이그레이션 작업 시 22001과 함께 자주 등장합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.