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

2200F
2026년 10월 21일 | DBMS Error 가이드

이 글에서 다루는 내용

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

2200F zero length character string 란?

PostgreSQL 에러 코드 2200F는 zero_length_character_string 에러로, 길이가 0인 빈 문자열('')이 허용되지 않는 컨텍스트에서 사용될 때 발생합니다. 이 에러는 주로 정규표현식 함수, 특정 문자열 처리 함수, 또는 데이터 타입 변환 과정에서 빈 문자열을 입력값으로 전달할 때 트리거됩니다. 실무에서는 사용자 입력값을 충분히 검증하지 않은 채 데이터베이스 함수에 직접 전달할 때 자주 마주치게 되는 에러입니다.


주요 발생 원인

1. 정규표현식 함수에 빈 문자열 패턴 전달

regexp_match(), regexp_replace(), regexp_split_to_table() 등 PostgreSQL의 정규표현식 관련 함수는 패턴(pattern) 인자로 빈 문자열을 허용하지 않습니다. 애플리케이션에서 사용자가 검색어를 입력하지 않은 상태로 쿼리를 실행하거나, 변수 초기화가 제대로 이루어지지 않은 경우 이 문제가 발생합니다. 특히 동적 쿼리를 생성하는 ORM이나 쿼리 빌더를 사용하는 환경에서 빈 문자열이 패턴으로 넘어오는 상황이 빈번합니다.

2. similar_to 연산자 또는 LIKE 변형 함수에서 빈 패턴 사용

SQL 표준의 SIMILAR TO 연산자나 이와 유사한 패턴 매칭 연산에서 패턴이 빈 문자열일 경우에도 동일한 에러가 발생할 수 있습니다. 이 경우는 특히 동적 필터 조건을 생성하는 보고서(Report) 쿼리나 대시보드 시스템에서 사용자가 필터를 비워두었을 때 자주 나타납니다. 빈 필터 조건이 그대로 SQL 패턴으로 삽입되면서 에러가 발생하게 됩니다.

3. 사용자 정의 함수(UDF) 또는 저장 프로시저에서 입력값 미검증

PL/pgSQL로 작성된 함수 내부에서 인자로 받은 문자열을 별도의 NULL 또는 빈 문자열 검사 없이 바로 정규표현식이나 문자열 처리 함수에 전달할 때 발생합니다. 함수 계약(contract)에 입력 검증 로직이 없다면, 호출 측에서 빈 문자열을 넘기는 순간 에러가 런타임에 발생하게 됩니다. 이는 단위 테스트가 충분하지 않은 레거시 시스템에서 특히 자주 발견됩니다.


해결 방법

원인 1 해결: 정규표현식 함수 호출 전 빈 문자열 방어 처리

함수를 호출하기 전에 NULLIF() 또는 CASE WHEN 구문을 사용하여 빈 문자열을 안전하게 처리합니다.

-- 문제가 발생하는 쿼리
SELECT regexp_match(description, '') 
FROM products;
-- ERROR: 2200F: invalid regular expression: empty (sub)expression

-- 해결 방법 1: NULLIF를 사용하여 빈 문자열을 NULL로 변환
SELECT 
    product_id,
    CASE 
        WHEN NULLIF(:search_pattern, '') IS NULL THEN description
        ELSE regexp_match(description, :search_pattern)::text
    END AS result
FROM products;

-- 해결 방법 2: WHERE 조건으로 빈 문자열 필터링
SELECT regexp_match(description, :search_pattern)
FROM products
WHERE :search_pattern <> '' 
  AND :search_pattern IS NOT NULL;

-- 해결 방법 3: COALESCE와 NULLIF 조합으로 기본값 설정
SELECT regexp_match(description, COALESCE(NULLIF(:search_pattern, ''), '.*'))
FROM products;

원인 2 해결: SIMILAR TO 패턴 매칭에서 빈 패턴 방어

-- 문제가 발생하는 쿼리
SELECT * FROM orders WHERE order_code SIMILAR TO '';
-- ERROR: 2200F: zero_length_character_string

-- 해결 방법: 동적 필터에서 빈 문자열 조건 분기 처리
DO $$
DECLARE
    v_pattern TEXT := ''; -- 사용자 입력값이 비어있는 상황
BEGIN
    IF v_pattern IS NULL OR v_pattern = '' THEN
        -- 패턴이 없으면 전체 조회
        RAISE NOTICE '패턴이 비어있어 전체 결과를 반환합니다.';
        -- 실제 쿼리: SELECT * FROM orders;
    ELSE
        -- 패턴이 있을 때만 SIMILAR TO 적용
        RAISE NOTICE '패턴 적용: %', v_pattern;
        -- 실제 쿼리: SELECT * FROM orders WHERE order_code SIMILAR TO v_pattern;
    END IF;
END;
$$;

-- 함수로 캡슐화하여 재사용 가능하도록 만들기
CREATE OR REPLACE FUNCTION search_orders(p_pattern TEXT DEFAULT NULL)
RETURNS SETOF orders AS $$
BEGIN
    IF p_pattern IS NULL OR p_pattern = '' THEN
        RETURN QUERY SELECT * FROM orders;
    ELSE
        RETURN QUERY 
            SELECT * FROM orders 
            WHERE order_code SIMILAR TO p_pattern;
    END IF;
END;
$$ LANGUAGE plpgsql;

-- 안전하게 호출
SELECT * FROM search_orders('');      -- 전체 반환
SELECT * FROM search_orders('ORD%');  -- 패턴 적용

원인 3 해결: UDF 내부에 입력 검증 로직 추가

-- 문제가 있는 기존 함수
CREATE OR REPLACE FUNCTION extract_domain(p_email TEXT)
RETURNS TEXT AS $$
BEGIN
    -- 빈 문자열이 들어오면 에러 발생
    RETURN (regexp_match(p_email, '@(.+)$'))[1];
END;
$$ LANGUAGE plpgsql;

-- 개선된 함수: 입력값 검증 추가
CREATE OR REPLACE FUNCTION extract_domain_safe(p_email TEXT)
RETURNS TEXT AS $$
BEGIN
    -- NULL 또는 빈 문자열 검증
    IF p_email IS NULL OR p_email = '' THEN
        RAISE WARNING 'extract_domain_safe: 입력값이 NULL이거나 빈 문자열입니다.';
        RETURN NULL;
    END IF;
    
    -- 이메일 형식 기본 검증
    IF p_email NOT LIKE '%@%' THEN
        RAISE WARNING 'extract_domain_safe: 유효하지 않은 이메일 형식 - %', p_email;
        RETURN NULL;
    END IF;
    
    RETURN (regexp_match(p_email, '@(.+)$'))[1];
    
EXCEPTION
    WHEN sqlstate '2200F' THEN
        RAISE WARNING 'extract_domain_safe: zero_length_character_string 에러 발생 - 입력: %', p_email;
        RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- 테스트
SELECT extract_domain_safe('user@example.com');  -- 'example.com' 반환
SELECT extract_domain_safe('');                   -- NULL 반환, 경고 출력
SELECT extract_domain_safe(NULL);                 -- NULL 반환, 경고 출력

-- 예외 처리를 통한 에러 핸들링 예시
DO $$
BEGIN
    PERFORM regexp_match('test_string', '');
EXCEPTION
    WHEN sqlstate '2200F' THEN
        RAISE NOTICE '빈 정규표현식 패턴이 감지되었습니다. 기본 처리로 전환합니다.';
END;
$$;

예방 방법

1. 애플리케이션 레이어와 DB 레이어 이중 검증 전략 도입

데이터베이스에 쿼리를 전달하기 전, 애플리케이션 레이어에서 빈 문자열 여부를 반드시 확인하는 것이 첫 번째 방어선입니다. 더불어 PostgreSQL 함수나 저장 프로시저 내부에서도 CHECK 제약이나 입력 검증 블록을 추가하여 이중 방어 체계를 구축해야 합니다.

-- 도메인 레이어에서 재사용 가능한 검증 함수 생성
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 'VALIDATION_ERROR: % 필드는 빈 문자열이 허용되지 않습니다.', p_field_name
            USING ERRCODE = '22023';
    END IF;
    RETURN p_value;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- 실제 사용 예시
SELECT regexp_match(
    content, 
    validate_non_empty(:user_pattern, 'search_pattern')
)
FROM articles;

2. 통합 테스트에 빈 문자열 경계값 테스트 케이스 의무화

CI/CD 파이프라인에서 실행되는 데이터베이스 통합 테스트에 빈 문자열(''), NULL, 공백만 포함된 문자열(' ') 등의 경계값 테스트를 반드시 포함시켜야 합니다. pgTAP과 같은 PostgreSQL 전용 테스트 프레임워크를 활용하면 함수 단위로 경계값 케이스를 체계적으로 관리할 수 있습니다.

-- pgTAP을 이용한 경계값 테스트 예시
SELECT plan(4);

SELECT is(
    extract_domain_safe('user@example.com'),
    'example.com',
    '정상 이메일 처리 확인'
);

SELECT is(
    extract_domain_safe(''),
    NULL,
    '빈 문자열 입력 시 NULL 반환 확인'
);

SELECT is(
    extract_domain_safe(NULL),
    NULL,
    'NULL 입력 시 NULL 반환 확인'
);

SELECT is(
    extract_domain_safe('   '),
    NULL,
    '공백 문자열 입력 시 NULL 반환 확인'
);

SELECT * FROM finish();

관련 에러

  • 22001 (string_data_right_truncation): 문자열이 대상 컬럼의 최대 길이를 초과할 때 발생하며, 문자열 길이 관련 제약 에러라는 점에서 2200F와 유사한 맥락입니다.
  • 22P02 (invalid_text_representation): 텍스트를 다른 데이터 타입으로 변환할 때 형식이 잘못된 경우 발생하며, 빈 문자열을 INTEGER나 UUID 등으로 캐스팅할 때 함께 마주칠 수 있습니다.
  • 2201B (invalid_regular_expression): 정규표현식 패턴 자체가 문법적으로 잘못된 경우 발생하는 에러로, 빈 문자열 패턴 문제(2200F)와 함께 정규표현식 관련 에러로 묶어서 처리하는 것이 좋습니다.
  • 23502 (not_null_violation): NOT NULL 제약이 있는 컬럼에 NULL을 삽입할 때 발생하며, 빈 문자열을 NULLIF로 변환한 후 삽입할 때 연쇄적으로 발생할 수 있어 주의가 필요합니다.
DBMS 에러 코드 시리즈

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

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

댓글 남기기