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

2200B
2026년 08월 09일 | DBMS Error 가이드

이 글에서 다루는 내용

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

2200B escape character conflict 는?

PostgreSQL 에러 코드 2200B: escape character conflictLIKE 또는 SIMILAR TO 패턴 매칭 연산에서 이스케이프 문자(escape character)가 서로 충돌하거나 잘못 지정되었을 때 발생합니다. 주로 LIKE 절에 ESCAPE 옵션을 사용할 때, 지정한 이스케이프 문자가 패턴 내의 와일드카드 문자(%, _)와 중복되거나, 표준 SQL 규격에서 허용하지 않는 방식으로 사용될 경우 이 에러가 트리거됩니다. 실무에서는 동적 SQL을 생성하거나 외부 입력값을 패턴 매칭에 활용할 때 특히 자주 마주치게 되는 에러입니다.


주요 발생 원인

  • ESCAPE 문자로 와일드카드 문자(%, _)를 지정한 경우

LIKE 패턴 매칭에서 ESCAPE 절에 % 또는 _를 이스케이프 문자로 직접 지정하면 충돌이 발생합니다. 이는 해당 문자들이 이미 패턴 매칭에서 특별한 의미를 가지고 있기 때문이며, PostgreSQL은 이 상황을 명시적으로 에러로 처리합니다. 표준 SQL 규격(ISO/IEC 9075)에서도 이스케이프 문자는 와일드카드 문자와 달라야 한다고 명시하고 있습니다.

  • 이스케이프 문자를 두 글자 이상으로 지정한 경우

ESCAPE 절에 지정하는 이스케이프 문자는 반드시 단일 문자(single character)여야 합니다. 실수로 두 글자 이상의 문자열을 이스케이프 문자로 넣을 경우, PostgreSQL은 이를 유효하지 않은 이스케이프 문자로 인식하여 에러를 발생시킵니다. 특히 동적 SQL 생성 시 변수 바인딩 과정에서 이런 실수가 빈번하게 발생합니다.

  • SIMILAR TO 연산자에서의 정규표현식 특수문자 충돌

SIMILAR TO는 SQL 표준 정규표현식을 지원하며, 이스케이프 문자가 정규표현식의 메타문자(|, *, +, ?, {, }, (, ), [, ])와 충돌할 때 예상치 못한 에러가 발생할 수 있습니다. 특히 애플리케이션 레이어에서 사용자 입력을 그대로 패턴에 삽입할 때, 이스케이프 처리 로직이 누락되면 이 에러가 발생하기 쉽습니다.


해결 방법

원인 1: 와일드카드 문자를 ESCAPE로 사용한 경우

잘못된 예시와 올바른 수정 방법입니다. %_를 이스케이프 문자로 사용하는 대신, \(백슬래시)나 !(느낌표) 등 중립적인 문자를 사용하세요.

-- ❌ 잘못된 예시: 와일드카드 문자를 ESCAPE 문자로 지정
SELECT *
FROM products
WHERE product_code LIKE '50%_off' ESCAPE '%';
-- ERROR: 2200B - escape character conflict

-- ✅ 올바른 예시: 중립적인 이스케이프 문자 사용 (예: '!')
SELECT *
FROM products
WHERE product_code LIKE '50!%_off' ESCAPE '!';
-- '50%_off' 라는 리터럴 문자열을 포함하는 행 검색

-- ✅ 백슬래시를 이스케이프 문자로 사용하는 예시
SELECT *
FROM products
WHERE product_code LIKE '50\%_off' ESCAPE '\';

원인 2: 이스케이프 문자가 두 글자 이상인 경우

-- ❌ 잘못된 예시: 두 글자 이스케이프 문자 지정
SELECT *
FROM orders
WHERE memo LIKE '%특별%할인%' ESCAPE '!!';
-- ERROR: 2200B - invalid escape string (must be a single character)

-- ✅ 올바른 예시: 단일 문자로 수정
SELECT *
FROM orders
WHERE memo LIKE '%특별\%할인%' ESCAPE '\';

-- ✅ 동적 SQL에서의 안전한 처리 예시 (PL/pgSQL)
DO $$
DECLARE
    v_escape_char CHAR(1) := '!';  -- 반드시 단일 문자 타입 사용
    v_pattern     TEXT;
    v_result      TEXT;
BEGIN
    -- 사용자 입력에서 특수문자를 이스케이프 처리
    v_pattern := '%' || replace(replace('50%_off', '%', '!%'), '_', '!_') || '%';

    SELECT product_name
    INTO v_result
    FROM products
    WHERE product_code LIKE v_pattern ESCAPE v_escape_char
    LIMIT 1;

    RAISE NOTICE '결과: %', v_result;
END;
$$;

원인 3: SIMILAR TO에서의 특수문자 충돌

-- ❌ 잘못된 예시: 정규표현식 메타문자와 충돌
SELECT *
FROM logs
WHERE message SIMILAR TO '%(error|warning)%' ESCAPE '|';
-- ERROR: 2200B - escape character conflict

-- ✅ 올바른 예시: 중립적인 이스케이프 문자 사용
SELECT *
FROM logs
WHERE message SIMILAR TO '%(error|warning)%' ESCAPE '\';

-- ✅ SIMILAR TO 대신 PostgreSQL 네이티브 정규식 연산자 사용 권장
SELECT *
FROM logs
WHERE message ~ '(error|warning)';

-- ✅ 복잡한 패턴에서는 regexp_like 또는 ~ 연산자 활용
SELECT *
FROM logs
WHERE message ~* 'error|warning';  -- 대소문자 무시

-- ✅ 이스케이프가 필요한 리터럴 검색은 LIKE로 단순화
SELECT *
FROM logs
WHERE message LIKE '%error%'
   OR message LIKE '%warning%';

보너스: 이스케이프 문자 유효성 사전 검증 함수

-- 안전한 LIKE 패턴 생성 함수
CREATE OR REPLACE FUNCTION safe_like_pattern(
    p_input      TEXT,
    p_escape     CHAR(1) DEFAULT '!'
)
RETURNS TEXT
LANGUAGE plpgsql
IMMUTABLE
AS $$
BEGIN
    -- 이스케이프 문자가 와일드카드와 동일한지 검증
    IF p_escape IN ('%', '_') THEN
        RAISE EXCEPTION '이스케이프 문자로 와일드카드(%%,_)를 사용할 수 없습니다. (2200B)';
    END IF;

    -- 입력 문자열에서 특수문자를 이스케이프 처리
    RETURN '%'
        || replace(
               replace(
                   replace(p_input, p_escape::TEXT, p_escape::TEXT || p_escape::TEXT),
               '%', p_escape::TEXT || '%'),
           '_', p_escape::TEXT || '_')
        || '%';
END;
$$;

-- 사용 예시
SELECT *
FROM products
WHERE product_code LIKE safe_like_pattern('50%_off') ESCAPE '!';
-- 내부적으로 '50!%!_off' 패턴으로 변환되어 실행됨

예방 방법

  • 이스케이프 문자를 상수로 정의하고 와일드카드와 분리하여 관리하세요

프로젝트 전체에서 일관된 이스케이프 문자를 사용하도록 애플리케이션 공통 유틸리티 함수나 PostgreSQL 함수로 표준화하는 것이 좋습니다. ! 또는 \를 조직 표준으로 정하고, 개발자가 임의로 %_를 이스케이프 문자로 사용하지 않도록 코드 리뷰 가이드라인에 명시하세요. 가능하면 위에서 정의한 safe_like_pattern() 같은 래퍼 함수를 통해서만 LIKE 패턴을 생성하도록 팀 컨벤션을 수립하세요.

  • 사용자 입력값은 반드시 파라미터 바인딩(Prepared Statement)과 이스케이프 처리를 병행하세요

SQL 인젝션 방어와 이스케이프 문자 충돌 방지를 동시에 해결하려면, 사용자 입력을 동적 패턴에 직접 삽입하는 대신 Prepared Statement와 서버 사이드 이스케이프 함수를 결합하여 사용하세요. PostgreSQL 14 이상에서는 pg_catalog 스키마의 문자열 함수를 활용하거나, 애플리케이션 ORM(예: SQLAlchemy, Hibernate)에서 제공하는 LIKE 이스케이프 유틸리티를 사용하는 것이 실무에서 가장 안전한 방법입니다.


관련 에러

  • 22025 (invalid_escape_sequence): 이스케이프 시퀀스 자체가 유효하지 않을 때 발생하며, 2200B와 함께 자주 등장합니다. 이스케이프 문자 뒤에 %, _, 이스케이프 문자 자체 외의 문자가 오면 발생합니다.
  • 2201B (invalid_regular_expression): SIMILAR TO 또는 regexp_* 함수에서 정규표현식 문법 자체가 잘못된 경우 발생하며, 복잡한 패턴 매칭에서 2200B와 혼동하기 쉽습니다.
  • 22000 (data_exception): 데이터 관련 예외의 상위 카테고리로, 2200B는 이 카테고리 하위에 속합니다. 에러 핸들링 시 SQLSTATE '22000'으로 상위 포착도 가능합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기