2026년 06월 13일 | DBMS Error 가이드
이 글에서 다루는 내용
2200F 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
2200F zero length character string 는?
PostgreSQL 에러 코드 2200F: zero_length_character_string은 길이가 0인 문자열, 즉 빈 문자열('')이 허용되지 않는 컨텍스트에서 사용될 때 발생하는 에러입니다. 주로 특정 내장 함수나 연산자가 입력값으로 최소 1자 이상의 문자열을 요구하는데, 빈 문자열이 전달될 경우 PostgreSQL 엔진이 이 에러를 발생시킵니다. 실무에서는 사용자 입력값을 충분히 검증하지 않고 그대로 SQL 함수에 전달하는 과정에서 빈번하게 발생하며, 특히 SIMILAR TO, LIKE, 정규식 관련 함수, 그리고 타입 캐스팅 과정에서 자주 마주치게 됩니다.
주요 발생 원인
1. 정규식(Regex) 함수에 빈 문자열 전달
PostgreSQL의 regexp_match(), regexp_replace(), regexp_split_to_table() 등의 정규식 함수는 내부적으로 패턴 문자열을 파싱하는 과정에서 빈 문자열을 유효한 입력으로 허용하지 않는 경우가 있습니다. 특히 일부 정규식 엔진 설정(ARE, ERE 모드)에서는 빈 패턴 자체가 의미 없는 표현으로 간주되어 에러를 유발합니다. 애플리케이션에서 사용자가 검색어를 입력하지 않고 폼을 제출했을 때 빈 문자열이 그대로 정규식 함수로 전달되는 상황이 대표적인 사례입니다.
2. SIMILAR TO 또는 패턴 매칭 연산에서 빈 패턴 사용
SQL 표준 패턴 매칭 연산자인 SIMILAR TO는 SQL 정규식 문법을 따르며, 빈 문자열을 패턴으로 받았을 때 내부 처리 로직에서 2200F 에러를 일으킬 수 있습니다. 이는 LIKE 연산자와는 다르게, SIMILAR TO가 더 엄격한 패턴 유효성 검사를 수행하기 때문입니다. 동적 쿼리를 생성하는 ORM이나 쿼리 빌더를 사용할 때 필터 값이 빈 문자열로 설정된 채 쿼리가 실행되면 이 문제가 나타납니다.
3. 타입 캐스팅 및 도메인(Domain) 제약 조건 위반
사용자 정의 도메인(Domain)이나 CHECK 제약 조건에서 빈 문자열을 명시적으로 금지하도록 설정되어 있는 경우, 빈 문자열을 해당 타입으로 캐스팅하거나 INSERT/UPDATE 시도 시 이 에러가 발생할 수 있습니다. 예를 들어, CREATE DOMAIN으로 생성된 비어있지 않은 문자열 타입에 빈 값을 삽입할 때 PostgreSQL이 내부 검증 단계에서 2200F를 반환합니다. 이는 데이터 무결성을 보장하는 설계에서 의도적으로 발생하는 에러이기도 하지만, 애플리케이션 레이어에서 사전 방어가 부족할 때 예기치 않은 장애로 이어집니다.
해결 방법
원인 1: 정규식 함수에 빈 문자열 전달 해결
함수를 호출하기 전에 NULLIF() 또는 CASE WHEN을 사용하여 빈 문자열을 NULL로 변환하거나 기본값으로 대체합니다.
-- 문제가 발생하는 쿼리 예시
SELECT regexp_match(email, ''); -- 2200F 에러 발생
-- 해결 방법 1: NULLIF로 빈 문자열을 NULL로 변환
SELECT regexp_match(email, NULLIF('', ''))
FROM users;
-- 패턴이 NULL이면 함수 자체가 NULL을 반환하므로 에러 방지
-- 해결 방법 2: CASE WHEN으로 빈 문자열 필터링
SELECT
CASE
WHEN :search_pattern = '' THEN NULL
ELSE regexp_match(email, :search_pattern)
END AS match_result
FROM users;
-- 해결 방법 3: 함수 래퍼(Wrapper) 생성
CREATE OR REPLACE FUNCTION safe_regexp_match(
input_text TEXT,
pattern TEXT
)
RETURNS TEXT[] AS $$
BEGIN
IF pattern IS NULL OR pattern = '' THEN
RETURN NULL;
END IF;
RETURN regexp_match(input_text, pattern);
END;
$$ LANGUAGE plpgsql;
-- 래퍼 함수 사용
SELECT safe_regexp_match(email, '') FROM users;
-- 에러 없이 NULL 반환
원인 2: SIMILAR TO 빈 패턴 해결
-- 문제가 발생하는 쿼리
SELECT * FROM products
WHERE product_name SIMILAR TO ''; -- 2200F 에러 발생
-- 해결 방법 1: 애플리케이션에서 빈 문자열 전달 시 조건 제거
-- 동적 쿼리 예시 (PL/pgSQL 프로시저 내부)
CREATE OR REPLACE FUNCTION search_products(p_pattern TEXT)
RETURNS TABLE(product_id INT, product_name TEXT) AS $$
BEGIN
IF p_pattern IS NULL OR p_pattern = '' THEN
-- 패턴이 없으면 전체 결과 반환
RETURN QUERY SELECT id, name FROM products;
ELSE
RETURN QUERY
SELECT id, name FROM products
WHERE name SIMILAR TO p_pattern;
END IF;
END;
$$ LANGUAGE plpgsql;
-- 사용 예시
SELECT * FROM search_products(''); -- 전체 반환, 에러 없음
SELECT * FROM search_products('%사과%'); -- 패턴 적용
-- 해결 방법 2: LIKE로 대체 (빈 문자열에 더 유연함)
SELECT * FROM products
WHERE product_name LIKE '%' || NULLIF('', '') || '%';
원인 3: 도메인/타입 제약 위반 해결
-- 문제 상황: 빈 문자열을 허용하지 않는 도메인 정의
CREATE DOMAIN non_empty_text AS TEXT
CHECK (VALUE IS NOT NULL AND length(trim(VALUE)) > 0);
-- 이 도메인을 사용하는 테이블
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
full_name non_empty_text,
email non_empty_text
);
-- 빈 문자열 삽입 시 에러 발생
INSERT INTO customers (full_name, email)
VALUES ('', 'test@example.com'); -- 에러!
-- 해결 방법 1: 삽입 전 유효성 검사 함수 생성
CREATE OR REPLACE FUNCTION safe_insert_customer(
p_name TEXT,
p_email TEXT
)
RETURNS VOID AS $$
BEGIN
IF p_name IS NULL OR trim(p_name) = '' THEN
RAISE EXCEPTION 'full_name은 비어 있을 수 없습니다.'
USING ERRCODE = '22023';
END IF;
IF p_email IS NULL OR trim(p_email) = '' THEN
RAISE EXCEPTION 'email은 비어 있을 수 없습니다.'
USING ERRCODE = '22023';
END IF;
INSERT INTO customers (full_name, email)
VALUES (trim(p_name), trim(p_email));
END;
$$ LANGUAGE plpgsql;
-- 올바른 사용
SELECT safe_insert_customer('홍길동', 'hong@example.com');
-- 해결 방법 2: 트리거를 이용한 자동 정제
CREATE OR REPLACE FUNCTION trim_and_validate()
RETURNS TRIGGER AS $$
BEGIN
NEW.full_name := trim(NEW.full_name);
NEW.email := trim(NEW.email);
IF NEW.full_name = '' OR NEW.email = '' THEN
RAISE EXCEPTION '빈 문자열은 허용되지 않습니다 (에러코드: 2200F)';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER validate_customer_data
BEFORE INSERT OR UPDATE ON customers
FOR EACH ROW EXECUTE FUNCTION trim_and_validate();
예방 방법
1. 입력값 검증 레이어를 데이터베이스 진입점에서 일원화
애플리케이션 레이어에만 의존하지 말고, PostgreSQL 함수나 트리거를 활용해 데이터베이스 레벨에서도 빈 문자열 검증을 수행하는 이중 방어 구조를 구축하세요. 아래와 같은 공통 검증 함수를 만들어 모든 관련 프로시저에서 재사용하면 일관성을 높일 수 있습니다.
-- 공통 입력값 검증 유틸리티 함수
CREATE OR REPLACE FUNCTION validate_non_empty(
p_value TEXT,
p_field_name TEXT DEFAULT 'value'
)
RETURNS TEXT AS $$
BEGIN
IF p_value IS NULL OR trim(p_value) = '' THEN
RAISE EXCEPTION '필드 [%]에 빈 문자열이 전달되었습니다. (SQLSTATE: 2200F)',
p_field_name
USING ERRCODE = '2200F';
END IF;
RETURN trim(p_value);
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- 사용 예시
SELECT validate_non_empty('', 'search_pattern');
-- ERROR: 필드 [search_pattern]에 빈 문자열이 전달되었습니다.
2. 동적 쿼리 생성 시 빈 문자열 조건 분기 처리
ORM이나 동적 SQL을 사용할 때 빈 문자열 파라미터는 조건 자체를 제거하거나 IS NOT NULL 조건으로 대체하는 패턴을 표준화하세요. 다음과 같이 PL/pgSQL 내에서 조건을 동적으로 구성하면 안전합니다.
-- 동적 필터 적용 시 빈 문자열 안전 처리 패턴
CREATE OR REPLACE FUNCTION search_with_filters(
p_name_pattern TEXT DEFAULT NULL,
p_status TEXT DEFAULT NULL
)
RETURNS TABLE(id INT, name TEXT, status TEXT) AS $$
DECLARE
v_query TEXT := 'SELECT id, name, status FROM orders WHERE 1=1';
BEGIN
-- 빈 문자열은 NULL과 동일하게 취급
p_name_pattern := NULLIF(trim(COALESCE(p_name_pattern, '')), '');
p_status := NULLIF(trim(COALESCE(p_status, '')), '');
IF p_name_pattern IS NOT NULL THEN
v_query := v_query || format(' AND name ILIKE %L', '%' || p_name_pattern || '%');
END IF;
IF p_status IS NOT NULL THEN
v_query := v_query || format(' AND status = %L', p_status);
END IF;
RETURN QUERY EXECUTE v_query;
END;
$$ LANGUAGE plpgsql;
관련 에러
22001: string_data_right_truncation— 문자열 데이터가 컬럼의 최대 길이를 초과할 때 발생하며,2200F와 반대 방향의 문자열 길이 관련 에러입니다.22P02: invalid_text_representation— 유효하지 않은 텍스트 형식을 특정 타입으로 변환할 때 발생하며, 빈 문자열 캐스팅 시 함께 나타날 수 있습니다.23514: check_violation— CHECK 제약 조건 위반 시 발생하며, 도메인 기반의 비어있지 않은 문자열 제약 조건 위반 시2200F대신 이 에러가 나타나기도 합니다.22023: invalid_parameter_value— 함수나 연산자에 잘못된 파라미터가 전달될 때 발생하며, 일부 PostgreSQL 버전에서는 빈 문자열 관련 에러가 이 코드로 리포팅되기도 합니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.