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

22019
2026년 10월 15일 | DBMS Error 가이드

이 글에서 다루는 내용

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

22019 invalid escape character 는?

PostgreSQL 에러 코드 22019는 LIKE, ILIKE, SIMILAR TO 등의 패턴 매칭 연산자에서 이스케이프 문자를 잘못 지정했을 때 발생하는 에러입니다. SQL 표준에서는 패턴 매칭 시 와일드카드 문자(%, _)를 리터럴로 사용하기 위해 이스케이프 문자를 지정할 수 있는데, 이 이스케이프 문자가 단일 문자가 아니거나 잘못된 형식으로 지정되면 이 에러가 발생합니다. 실무에서는 동적 쿼리를 생성하거나 애플리케이션에서 사용자 입력값을 그대로 SQL에 삽입할 때 자주 마주치는 에러입니다.

주요 발생 원인

  • ESCAPE 절에 두 글자 이상의 문자열을 지정한 경우

LIKE 또는 ILIKE 연산자의 ESCAPE 절은 반드시 단 하나의 문자만 허용합니다. 두 글자 이상의 문자열을 이스케이프 문자로 지정하면 PostgreSQL은 즉시 22019 에러를 발생시킵니다. 예를 들어 ESCAPE '\\'와 같이 두 글자를 전달하는 경우가 대표적인 실수입니다.

  • 빈 문자열('')을 ESCAPE 절에 지정한 경우

이스케이프 문자로 빈 문자열을 사용하려고 시도할 경우에도 22019 에러가 발생합니다. 일부 개발자들은 이스케이프 기능을 비활성화하려는 의도로 빈 문자열을 전달하는데, PostgreSQL은 이를 허용하지 않습니다. 이런 경우에는 별도의 방법으로 처리해야 합니다.

  • 애플리케이션 레이어에서 동적으로 생성된 잘못된 이스케이프 문자

Python, Java, Node.js 등의 애플리케이션에서 사용자 입력값이나 변수를 이용해 동적으로 SQL 쿼리를 구성할 때, 이스케이프 처리 로직의 버그로 인해 다중 문자 또는 비정상적인 값이 ESCAPE 절에 전달되는 경우가 많습니다. 특히 백슬래시(\) 처리 방식이 언어마다 다르기 때문에 이런 문제가 자주 발생합니다.

해결 방법

원인 1: ESCAPE 절에 두 글자 이상 지정한 경우

잘못된 쿼리와 올바른 쿼리를 비교해 보겠습니다.

-- ❌ 잘못된 예시: 두 글자 이스케이프 문자 지정
SELECT *
FROM products
WHERE product_name LIKE '%50\%off%' ESCAPE '\\';
-- ERROR: 22019: invalid escape character

-- ✅ 올바른 예시: 단일 문자 이스케이프 지정
SELECT *
FROM products
WHERE product_name LIKE '%50\%off%' ESCAPE '\';

-- ✅ 다른 단일 문자를 이스케이프로 사용하는 예시
SELECT *
FROM products
WHERE product_name LIKE '%50!%off%' ESCAPE '!';

원인 2: 빈 문자열을 ESCAPE에 지정한 경우

이스케이프를 비활성화하고 싶다면, ESCAPE 절을 아예 제거하거나 패턴을 재설계해야 합니다.

-- ❌ 잘못된 예시: 빈 문자열 이스케이프
SELECT *
FROM users
WHERE username LIKE '%admin%' ESCAPE '';
-- ERROR: 22019: invalid escape character

-- ✅ 올바른 예시: ESCAPE 절 생략 (기본 이스케이프 문자 '\' 사용)
SELECT *
FROM users
WHERE username LIKE '%admin%';

-- ✅ 이스케이프가 필요 없는 경우 단순 패턴 사용
SELECT *
FROM users
WHERE username LIKE '%admin%';

-- ✅ SIMILAR TO를 사용하는 경우에도 동일하게 적용
SELECT *
FROM users
WHERE username SIMILAR TO '%(admin|root)%';

원인 3: 동적 쿼리에서 이스케이프 문자 처리

애플리케이션에서 동적으로 쿼리를 생성할 때는 파라미터 바인딩과 전처리 함수를 활용해야 합니다.

-- ✅ PostgreSQL 함수를 이용한 안전한 LIKE 패턴 생성 예시
CREATE OR REPLACE FUNCTION safe_like_pattern(input_text TEXT)
RETURNS TEXT AS $$
BEGIN
    -- % 와 _ 와 \ 문자를 이스케이프 처리
    RETURN replace(replace(replace(input_text, '\', '\\'), '%', '\%'), '_', '\_');
END;
$$ LANGUAGE plpgsql;

-- 함수 사용 예시
SELECT *
FROM products
WHERE product_name LIKE '%' || safe_like_pattern('50% off') || '%' ESCAPE '\';

-- ✅ 동적 쿼리에서 단일 문자 검증 후 사용
DO $$
DECLARE
    v_escape_char TEXT := '\';
    v_pattern TEXT := '%hello\%world%';
BEGIN
    -- 이스케이프 문자가 단일 문자인지 검증
    IF length(v_escape_char) <> 1 THEN
        RAISE EXCEPTION '이스케이프 문자는 반드시 단일 문자여야 합니다.';
    END IF;

    -- 동적 쿼리 실행
    EXECUTE format(
        'SELECT * FROM logs WHERE message LIKE %L ESCAPE %L',
        v_pattern,
        v_escape_char
    );
END;
$$;

-- ✅ 준비된 구문(Prepared Statement) 사용 예시
PREPARE search_products (text) AS
    SELECT product_id, product_name
    FROM products
    WHERE product_name LIKE $1 ESCAPE '\';

EXECUTE search_products('%notebook%');
DEALLOCATE search_products;

실무 디버깅 팁

에러가 발생한 쿼리에서 ESCAPE 절의 실제 값을 확인하는 방법입니다.

-- 이스케이프 문자의 길이 확인
SELECT length('\') AS single_char_length;      -- 결과: 1 (정상)
SELECT length('\\') AS double_char_length;     -- 결과: 2 (에러 발생 원인)
SELECT length('') AS empty_char_length;        -- 결과: 0 (에러 발생 원인)

-- 안전한 패턴 매칭 함수 예시
CREATE OR REPLACE FUNCTION safe_search(
    p_table_name TEXT,
    p_column_name TEXT,
    p_search_term TEXT
)
RETURNS SETOF RECORD AS $$
DECLARE
    v_safe_pattern TEXT;
    v_query TEXT;
BEGIN
    -- 특수문자 이스케이프 처리
    v_safe_pattern := '%' ||
        replace(replace(replace(p_search_term, '\', '\\'), '%', '\%'), '_', '\_')
        || '%';

    v_query := format(
        'SELECT * FROM %I WHERE %I LIKE %L ESCAPE %L',
        p_table_name,
        p_column_name,
        v_safe_pattern,
        '\'
    );

    RETURN QUERY EXECUTE v_query;
END;
$$ LANGUAGE plpgsql;

예방 방법

  • 이스케이프 문자 유효성 검사 함수를 공통 라이브러리로 관리하기

프로젝트 공통 유틸리티 레이어에 LIKE 패턴 생성 함수를 중앙화하여, 모든 개발자가 동일한 안전한 함수를 사용하도록 강제하는 것이 좋습니다. 위에서 작성한 safe_like_pattern() 함수처럼 특수문자 이스케이프 처리와 단일 문자 검증 로직을 하나의 함수로 캡슐화하면, 개별 쿼리에서 실수할 가능성을 크게 줄일 수 있습니다. ORM을 사용하는 경우에도 Raw Query를 직접 작성할 때만큼은 반드시 이 함수를 경유하도록 팀 내 코딩 컨벤션으로 규정하세요.

  • SQL 정적 분석 도구 및 코드 리뷰 체크리스트 활용

pgTAP, SQLFluff 같은 SQL 정적 분석 도구를 CI/CD 파이프라인에 통합하면 배포 전 단계에서 잘못된 이스케이프 문자 사용을 사전에 탐지할 수 있습니다. 또한 코드 리뷰 체크리스트에 “LIKE/ILIKE/SIMILAR TO 사용 시 ESCAPE 절의 값이 단일 문자인지 확인” 항목을 명시적으로 추가하여, 팀 전체가 이 에러를 인지하고 예방할 수 있는 문화를 만드는 것이 중요합니다.

관련 에러

  • 22025 (invalid_escape_sequence): 이스케이프 문자 자체는 올바르게 지정되었지만, 패턴 내에서 이스케이프 시퀀스가 잘못 사용된 경우 발생합니다. 예를 들어 ESCAPE '\'를 지정했지만 패턴 끝에 \가 홀로 남아있는 경우입니다.
  • 2201B (invalid_regular_expression): SIMILAR TO나 regexp_match() 등 정규식 기반 함수에서 정규식 패턴이 잘못된 경우 발생하며, 패턴 매칭 관련 에러와 함께 자주 등장합니다.
  • 42601 (syntax_error): 동적 쿼리 생성 시 이스케이프 문자 처리 실수로 인해 SQL 구문 자체가 깨지는 경우, 22019보다 먼저 42601이 발생할 수 있습니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기