2026년 06월 12일 | DBMS Error 가이드
이 글에서 다루는 내용
22001 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
22001 string data right truncation 는?
PostgreSQL 에러 코드 22001, string data right truncation은 문자열 데이터를 특정 컬럼에 저장하려 할 때, 해당 데이터의 길이가 컬럼에 정의된 최대 길이를 초과할 경우 발생하는 에러입니다. 예를 들어 VARCHAR(10)으로 정의된 컬럼에 11자 이상의 문자열을 삽입하거나 업데이트하려 할 때 PostgreSQL은 이 에러를 발생시키며 트랜잭션을 중단합니다. 이 에러는 데이터 무결성을 지키기 위한 PostgreSQL의 엄격한 타입 검사 메커니즘의 일부로, 일부 다른 DBMS와 달리 PostgreSQL은 데이터를 자동으로 잘라내지 않고 명시적으로 에러를 반환합니다.
주요 발생 원인
1. 컬럼 길이 정의보다 긴 데이터 삽입/업데이트
가장 빈번하게 발생하는 원인으로, 애플리케이션 레이어에서 유효성 검사 없이 사용자 입력값을 그대로 데이터베이스에 저장하려 할 때 주로 발생합니다. 예를 들어 회원가입 폼에서 이름 필드를 VARCHAR(20)으로 정의했지만 외국인 이름이나 특수 케이스로 인해 20자를 초과하는 이름이 들어올 수 있습니다. 또한 외부 API 연동 시 예상보다 긴 응답 데이터가 반환되어 저장 과정에서 에러가 발생하는 경우도 매우 흔합니다.
2. 스키마 변경 없이 비즈니스 요구사항 변경
서비스가 성장하면서 초기에 설계된 컬럼 길이가 새로운 비즈니스 요구사항을 수용하지 못하는 경우가 많습니다. 예를 들어 초기에는 국내 전화번호만 저장하던 컬럼이 국제 전화번호도 저장해야 하는 요구사항이 생기거나, 상품 이름의 최대 글자 수 제한이 완화되는 등의 변화가 생길 때 스키마를 업데이트하지 않으면 이 에러가 발생합니다. 스키마 변경이 배포 일정과 맞지 않을 경우 운영 환경에서 갑작스럽게 에러가 터지는 상황이 발생할 수 있습니다.
3. 데이터 마이그레이션 또는 ETL 과정에서의 불일치
다른 시스템이나 데이터베이스에서 데이터를 이관할 때, 원본 시스템과 대상 시스템의 컬럼 정의가 다를 경우 이 에러가 발생합니다. 특히 MySQL, Oracle 등에서 PostgreSQL로 마이그레이션할 때 각 DBMS의 데이터 타입 크기 정의 방식 차이로 인해 예기치 않은 데이터 잘림 문제가 발생할 수 있습니다. 대용량 데이터 마이그레이션 중 이 에러가 발생하면 전체 배치 작업이 중단될 수 있어 사전 데이터 검증이 반드시 필요합니다.
해결 방법
원인 1 해결: 컬럼 길이 확인 및 확장
먼저 현재 테이블의 컬럼 정의를 확인하고, 필요 시 컬럼 크기를 조정합니다.
-- 컬럼 정의 확인
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name = 'full_name';
-- 컬럼 길이 확장 (데이터 손실 없이 길이 늘리기 가능)
ALTER TABLE users
ALTER COLUMN full_name TYPE VARCHAR(100);
-- 변경 후 확인
SELECT column_name, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name = 'full_name';
원인 1 해결: 데이터 삽입 전 길이 검사
-- 삽입 전 데이터 길이 확인
INSERT INTO users (full_name, email)
SELECT full_name, email
FROM staging_users
WHERE LENGTH(full_name) <= 100;
-- 잘림 처리가 불가피한 경우 SUBSTRING 사용 (주의: 데이터 손실 발생)
INSERT INTO users (full_name, email)
VALUES (SUBSTRING('홍길동의아주긴이름이여기에들어갑니다', 1, 20), 'hong@example.com');
원인 2 해결: 스키마 마이그레이션
-- 트랜잭션 내에서 안전하게 스키마 변경
BEGIN;
-- 국제 전화번호 지원을 위한 컬럼 확장
ALTER TABLE customers
ALTER COLUMN phone_number TYPE VARCHAR(20);
-- 변경 내용 검증
SELECT column_name, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'customers'
AND column_name = 'phone_number';
COMMIT;
-- 길이 제약을 완전히 제거하려면 TEXT 타입으로 변경
ALTER TABLE products
ALTER COLUMN product_name TYPE TEXT;
원인 3 해결: 마이그레이션 전 데이터 사전 검증
-- 마이그레이션 전 길이 초과 데이터 탐지
SELECT
id,
full_name,
LENGTH(full_name) AS name_length,
100 AS column_limit
FROM staging_users
WHERE LENGTH(full_name) > 100
ORDER BY LENGTH(full_name) DESC;
-- 초과 건수 요약
SELECT
COUNT(*) AS total_rows,
SUM(CASE WHEN LENGTH(full_name) > 100 THEN 1 ELSE 0 END) AS over_limit_rows,
MAX(LENGTH(full_name)) AS max_name_length
FROM staging_users;
-- CAST를 활용한 타입 변환 시 에러 처리
DO $$
DECLARE
v_name TEXT := '매우 긴 이름 데이터가 여기에 들어갑니다 추가 텍스트';
BEGIN
BEGIN
INSERT INTO users (full_name) VALUES (v_name::VARCHAR(20));
EXCEPTION
WHEN string_data_right_truncation THEN
RAISE NOTICE '데이터 길이 초과: %, 길이: %', v_name, LENGTH(v_name);
-- 필요 시 잘라서 삽입하거나 로그 테이블에 기록
INSERT INTO migration_errors (original_data, error_message, created_at)
VALUES (v_name, 'string_data_right_truncation', NOW());
END;
END;
$$;
CHECK 제약 조건 추가로 사전 방어
-- CHECK 제약 조건으로 특정 비즈니스 규칙 적용
ALTER TABLE products
ADD CONSTRAINT chk_product_name_length
CHECK (LENGTH(product_name) BETWEEN 1 AND 200);
-- 도메인 타입을 활용한 재사용 가능한 제약 정의
CREATE DOMAIN short_text AS VARCHAR(50)
CHECK (VALUE IS NOT NULL AND LENGTH(VALUE) > 0);
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
category_name short_text
);
예방 방법
1. 컬럼 타입 설계 시 여유 있는 크기 설정 및 TEXT 타입 적극 활용
컬럼 크기를 처음부터 여유 있게 설정하거나, 길이 제한이 비즈니스적으로 불필요한 경우 VARCHAR(n) 대신 TEXT 타입을 사용하는 것을 권장합니다. PostgreSQL에서 TEXT와 VARCHAR는 내부적으로 동일한 스토리지를 사용하므로 성능 차이가 없으며, TEXT를 사용하면 이 에러 자체를 원천적으로 방지할 수 있습니다. 단, 길이 제한이 실질적인 비즈니스 규칙(예: 우편번호는 반드시 5자리)인 경우에는 VARCHAR(n) 또는 CHAR(n)을 유지하고, 그 외에는 TEXT를 기본 선택으로 사용하는 팀 내 컨벤션을 수립하는 것이 좋습니다.
2. 애플리케이션 레이어와 DB 레이어의 이중 유효성 검사 체계 구축
애플리케이션 레이어에서만 유효성 검사를 하는 것은 충분하지 않으며, 데이터베이스 레이어에서도 제약 조건을 통해 방어적으로 설계해야 합니다. 아래와 같이 PostgreSQL 함수나 트리거를 활용하면 모든 경로(직접 SQL, ORM, 배치 등)에서 들어오는 데이터를 일관되게 검사할 수 있습니다. 또한 CI/CD 파이프라인에 스키마 유효성 검사 및 데이터 길이 테스트를 포함시켜 배포 전에 문제를 사전에 감지하는 자동화 체계를 구축하는 것이 장기적으로 운영 안정성을 높이는 최선의 방법입니다.
-- 트리거를 활용한 자동 유효성 검사 예시
CREATE OR REPLACE FUNCTION validate_user_data()
RETURNS TRIGGER AS $$
BEGIN
IF LENGTH(NEW.full_name) > 100 THEN
RAISE EXCEPTION 'full_name이 최대 길이(100자)를 초과했습니다. 현재 길이: %', LENGTH(NEW.full_name);
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_validate_user_before_insert
BEFORE INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION validate_user_data();
관련 에러
- 22000 (data_exception): 22001의 상위 에러 클래스로, 데이터 관련 모든 예외의 부모 카테고리입니다.
- 22P02 (invalid_text_representation): 잘못된 텍스트 형식으로 타입 캐스팅 시 발생하는 에러로, 데이터 마이그레이션 중 함께 자주 등장합니다.
- 23514 (check_violation): CHECK 제약 조건 위반 에러로, 길이 제한을 CHECK로 구현했을 때 발생할 수 있습니다.
- 42804 (datatype_mismatch): 데이터 타입 불일치 에러로, 잘못된 타입 캐스팅 시 22001과 함께 발생하는 경우가 있습니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.