2026년 08월 17일 | DBMS Error 가이드
이 글에서 다루는 내용
22024 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
22024 unterminated c string 는?
PostgreSQL 에러 코드 22024 (unterminated_c_string) 은 C 언어 스타일의 문자열 리터럴이 제대로 종료되지 않았을 때 발생하는 에러입니다. 주로 이스케이프 시퀀스가 잘못 처리되거나, 문자열 내부에 null 바이트(\0)가 포함되어 문자열 파싱이 비정상적으로 종료될 때 나타납니다. 데이터 마이그레이션, 외부 시스템 연동, 또는 바이너리 데이터를 텍스트 컬럼에 삽입하는 과정에서 자주 마주치는 에러입니다.
주요 발생 원인
1. 이스케이프 시퀀스 처리 오류 (Escape Sequence Mishandling)
PostgreSQL에서 E'' 형식의 이스케이프 문자열을 사용할 때, 백슬래시(\) 뒤에 유효하지 않은 문자가 오거나 문자열이 백슬래시로 끝나는 경우 이 에러가 발생합니다. 특히 외부 애플리케이션에서 동적으로 SQL을 생성할 때, 이스케이프 처리를 빠뜨리면 서버가 문자열의 끝을 인식하지 못해 22024 에러를 던집니다. 예를 들어, 파일 경로나 정규 표현식 문자열을 그대로 SQL에 삽입할 때 흔히 발생합니다.
2. null 바이트(Null Byte) 포함 데이터 삽입
PostgreSQL의 text, varchar 타입은 C 언어의 문자열 처리 방식에 기반하기 때문에 null 바이트(\x00, \0)를 문자열의 끝으로 인식합니다. 바이너리 데이터나 인코딩이 잘못된 외부 데이터를 텍스트 컬럼에 삽입하려 할 때, 데이터 중간에 null 바이트가 포함되어 있으면 파서가 문자열이 끝났다고 판단하여 이 에러를 발생시킵니다. 특히 레거시 시스템이나 타 DBMS에서 데이터를 마이그레이션할 때 자주 등장합니다.
3. 잘못된 클라이언트 라이브러리 또는 드라이버의 문자열 인코딩 처리
JDBC, psycopg2, libpq 등 클라이언트 드라이버에서 문자열을 올바르게 파라미터 바인딩하지 않고 문자열을 직접 연결(concatenation)하여 쿼리를 생성할 때 발생할 수 있습니다. 특히 멀티바이트 문자(한국어, 일본어, 중국어 등)를 포함한 데이터를 처리할 때 클라이언트 인코딩과 서버 인코딩이 불일치하면 파싱 도중 문자열이 비정상적으로 종료됩니다. 드라이버 버전이 오래되었거나 client_encoding 설정이 잘못된 경우에도 나타납니다.
해결 방법
원인 1: 이스케이프 시퀀스 처리 오류 해결
이스케이프 문자열을 사용할 때는 E'' 접두사와 함께 백슬래시를 이중으로 작성하거나, 달러 따옴표($$)를 사용해 이스케이프를 완전히 피하는 방법을 권장합니다.
-- 잘못된 예시 (에러 발생)
SELECT E'C:\Users\name\'; -- 백슬래시로 끝나 unterminated c string 에러 발생
-- 올바른 예시 1: 백슬래시 이중 이스케이프
SELECT E'C:\\Users\\name\\';
-- 올바른 예시 2: 달러 따옴표 사용 (이스케이프 불필요)
SELECT $$C:\Users\name\$$;
-- 실무 예시: 정규식 패턴 안전하게 삽입
SELECT * FROM logs
WHERE message ~ $$\d{3}-\d{4}$$;
-- 함수에서 달러 따옴표 활용
CREATE OR REPLACE FUNCTION get_windows_path()
RETURNS text AS $$
BEGIN
RETURN 'C:\Program Files\PostgreSQL\';
END;
$$ LANGUAGE plpgsql;
원인 2: null 바이트 포함 데이터 처리
null 바이트가 포함된 데이터는 삽입 전에 반드시 제거하거나 bytea 타입으로 변환하여 저장해야 합니다.
-- null 바이트 포함 여부 확인
SELECT id, length(content), position(chr(0) in content) AS null_byte_pos
FROM raw_data
WHERE content LIKE '%' || chr(0) || '%';
-- null 바이트 제거 후 삽입 (replace 활용)
INSERT INTO clean_data (content)
SELECT replace(content, chr(0), '')
FROM raw_data;
-- null 바이트 제거 업데이트
UPDATE my_table
SET text_column = replace(text_column, chr(0), '')
WHERE text_column LIKE '%' || chr(0) || '%';
-- 바이너리 데이터는 bytea 타입으로 저장
CREATE TABLE binary_storage (
id serial PRIMARY KEY,
raw_content bytea -- 바이너리 데이터에 적합한 타입
);
INSERT INTO binary_storage (raw_content)
VALUES (decode('48656C6C6F00576F726C64', 'hex')); -- null 바이트 포함 가능
-- 마이그레이션 시 데이터 검증 함수 활용
CREATE OR REPLACE FUNCTION sanitize_text(input text)
RETURNS text AS $$
BEGIN
RETURN replace(input, chr(0), '');
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- 검증 함수 적용하여 안전하게 삽입
INSERT INTO target_table (col1)
SELECT sanitize_text(col1)
FROM source_table;
원인 3: 클라이언트 인코딩 불일치 해결
클라이언트와 서버의 인코딩을 일치시키고, 반드시 파라미터 바인딩을 사용해야 합니다.
-- 현재 서버 및 클라이언트 인코딩 확인
SHOW server_encoding;
SHOW client_encoding;
-- 클라이언트 인코딩 명시적 설정
SET client_encoding TO 'UTF8';
-- 세션 시작 시 인코딩 확인 및 설정
SELECT pg_client_encoding();
-- 인코딩 변환 함수 활용
SELECT convert_from(
convert_to('안녕하세요', 'UTF8'),
'UTF8'
);
-- 잘못된 방식: 문자열 직접 연결 (SQL Injection + 인코딩 문제)
-- 애플리케이션 코드에서 절대 사용 금지
-- query = "SELECT * FROM users WHERE name = '" + user_input + "'"
-- 올바른 방식: 파라미터 바인딩 (psycopg2 예시 주석)
-- cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
-- PostgreSQL에서 인코딩 오류 데이터 식별
SELECT id, encode(convert_to(content, 'UTF8'), 'hex') AS hex_content
FROM my_table
WHERE octet_length(content) != length(content);
예방 방법
1. 항상 파라미터 바인딩(Prepared Statement)을 사용하고 입력 데이터를 사전 검증하라
SQL 쿼리를 동적으로 생성할 때 문자열 직접 연결 방식은 절대 사용하지 말고, 드라이버가 제공하는 파라미터 바인딩을 반드시 활용하세요. 또한 외부에서 유입되는 데이터는 DB에 삽입하기 전에 null 바이트 포함 여부, 인코딩 유효성을 반드시 검사하는 유효성 검증 레이어를 두는 것이 중요합니다.
-- 입력 데이터 사전 검증 트리거 예시
CREATE OR REPLACE FUNCTION validate_no_null_bytes()
RETURNS trigger AS $$
BEGIN
IF NEW.content LIKE '%' || chr(0) || '%' THEN
RAISE EXCEPTION 'null byte detected in content column';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_validate_content
BEFORE INSERT OR UPDATE ON my_table
FOR EACH ROW EXECUTE FUNCTION validate_no_null_bytes();
2. 문자열 리터럴 대신 달러 따옴표와 표준 따옴표를 일관되게 사용하라
복잡한 문자열이나 함수/프로시저 본문을 작성할 때는 이스케이프 오류를 원천 차단하기 위해 달러 따옴표($$ 또는 $tag$)를 일관되게 사용하세요. standard_conforming_strings 파라미터를 on으로 설정하여 백슬래시가 이스케이프 문자로 처리되지 않도록 하는 것도 좋은 방법입니다.
-- standard_conforming_strings 확인 및 설정
SHOW standard_conforming_strings;
-- postgresql.conf 또는 세션 레벨에서 설정
SET standard_conforming_strings = on;
-- on 설정 시 백슬래시는 이스케이프 문자로 처리되지 않음
SELECT 'C:\Users\name'; -- 그대로 출력됨
관련 에러
- 22021 (character_not_in_repertoire): 지정된 인코딩에서 표현할 수 없는 문자를 삽입할 때 발생하며, 22024와 함께 인코딩 관련 에러로 자주 등장합니다.
- 22P02 (invalid_text_representation): 텍스트를 특정 타입으로 변환할 때 형식이 맞지 않아 발생하며, 잘못된 데이터 형식 삽입 시 22024와 유사한 상황에서 나타납니다.
- 42601 (syntax_error): 이스케이프 처리 오류로 인해 SQL 문법 자체가 깨지는 경우 22024 대신 42601로 리포트되기도 합니다.
- 22000 (data_exception): 22024의 상위 에러 카테고리로, 데이터 값 관련 예외의 일반 분류입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.