콘텐츠로 이동

(KO) PostgreSQL 국제화·텍스트 검색 — 섹션 개요

목차

이 서브카테고리의 주제는 PostgreSQL이 문자열의 바이트를 저장하는 것 너머에서 하는 일이다. 로케일 아래에서 텍스트를 정렬하고 대소문자를 변환하는 방법, 문자열이 어떤 인코딩으로 표현되어 있고 인코딩 사이를 어떻게 변환하는 방법, 그리고 문서를 검색 가능한 형태로 바꾸는 방법이 핵심이다. 세 개의 모듈 문서가 이 세 계층을 각각 담당한다.

  • 콜레이션 제공자 — 로케일 의존 연산 전체를 뒷받침하는 추상화다. COLLATE 절, lower(), LIKE/정규식, text 컬럼 인덱스 — 이 모두는 콜레이션 OID를 단일 pg_locale_t 핸들로 해석하고 그 핸들로 직접 호출한다. 핸들은 실제 비교를 수행하는 제공자가 libc인지 ICU인지 아니면 PG17에서 추가된 builtin 제공자인지를 숨긴다.
  • 인코딩(utils/mb) — 데이터베이스별 서버 인코딩, 인코딩 간 변환 함수 행렬(클라이언트↔서버), 백엔드 나머지가 호출하는 멀티바이트 문자열 기본 연산이다.
  • 전문 검색(tsearch)tsvector/tsquery 타입, 문서를 어휘소로 정규화하는 파서+사전 텍스트 검색 설정, 그리고 쿼리와 벡터를 매칭하는 연산자다.

명확한 경계 — 이 섹션이 다루지 않는 것.

  • 데이터 타입 기계가 아니다. text/varchar 저장, TOAST 압축, varlena 헤더, 모든 문자열 함수가 사용하는 fmgr 호출 규약은 base-infra에 속한다. 이 섹션은 문자열이 이미 Datum으로 존재한다는 전제 아래, 그 문자열에 어떤 로케일·인코딩·검색 의미가 적용되는지를 다룬다.
  • GIN 접근 방법 자체가 아니다. 전문 검색은 GIN의 가장 중요한 클라이언트다. tsvector는 GIN extractValue/extractQuery 지원 함수와 기본 연산자 클래스를 제공한다. 그러나 GIN 인덱스 구조, 포스팅 리스트, 대기 목록/fast-update 경로는 storage-engine(postgres-gin.md)이 담당한다. 이 문서는 경계를 짚을 뿐 그것을 넘지 않는다.
  • 패턴 매칭 실행이나 플래너의 인덱스 선택이 아니다. LIKE/SIMILAR TO/정규식 평가와 선택도는 query-processing에 있다. 이 섹션이 담당하는 것은 그 평가가 대소문자 판별과 문자 분류를 위해 참조하는 로케일 핸들뿐이다.
  • 식별자와 SQL 텍스트의 파싱이나 정규화가 아니다. 그것은 query-processing의 스캐너/파서 영역이다. 여기서의 인코딩은 데이터 경로(client_encoding ↔ server_encoding)에 관한 것이지 렉서에 관한 것이 아니다.

이 경계 중 하나를 넘는 질문이 생기면, 해당 모듈 문서가 이웃 문서를 명시하고 안내한다.

세 모듈은 같은 바이트 위에 얹힌 독립적인 계층이며, 단일 파이프라인이 아니다. 각 모듈은 백엔드의 서로 다른 호출자가 참조한다. 아래 다이어그램은 각 모듈을 호출하는 주체와 두 개의 외부 경계(아래의 base-infra, 옆의 storage-engine GIN)를 보여 준다.

flowchart TB
  subgraph CALLERS["백엔드 호출자 (다른 서브카테고리)"]
    CMP["비교 / 정렬 / 인덱스 빌드<br/>(varstr_cmp, str_tolower, LIKE, regex)"]
    WIRE["클라이언트 I/O<br/>(client_encoding ↔ server_encoding)"]
    FTS["to_tsvector / to_tsquery / @@<br/>(텍스트 검색 연산자)"]
  end

  subgraph SEC["i18n-text 서브카테고리"]
    COLL["postgres-collation-providers.md<br/>pg_locale_t 핸들 + collate vtable<br/>(libc / ICU / builtin)"]
    ENC["postgres-encoding.md<br/>utils/mb: 서버 인코딩,<br/>변환 행렬, mb 문자열 연산"]
    TS["postgres-full-text-search.md<br/>tsvector/tsquery, 파서 +<br/>사전 (텍스트 검색 설정)"]
  end

  CMP --> COLL
  WIRE --> ENC
  FTS --> TS

  COLL -. "ctype 연산은 인코딩 필요<br/>(char ↔ wchar)" .-> ENC
  TS -. "어휘화 / 대소문자 변환은<br/>로케일 + 인코딩 사용" .-> COLL
  TS -. "어휘화는 인코딩 사용" .-> ENC

  subgraph BASE["base-infra (아래)"]
    DT["text / varlena 데이터 타입<br/>fmgr 호출 규약"]
  end
  COLL --> DT
  ENC --> DT
  TS --> DT

  subgraph STORE["storage-engine (옆 경계)"]
    GIN["postgres-gin.md<br/>GIN 접근 방법"]
  end
  TS -. "extractValue / extractQuery<br/>(tsvector opclass)" .-> GIN

다이어그램에서 두 가지를 읽어 두면 나머지가 명확해진다. 첫째, 콜레이션과 인코딩은 독립적이면서도 결합되어 있다는 점이다. 인코딩은 한 문자가 어디서 끝나고 다음 문자가 어디서 시작하는지를 알려 주며, libc ctype 경로가 필요로 하는 charwchar 변환도 제공한다. 콜레이션은 그 문자들을 어떻게 정렬하고 대소문자를 변환할지를 알려 준다. builtin과 ICU 제공자는 자체 유니코드 테이블을 갖고 있어 바이트/코드포인트 경계 파악에만 인코딩을 의존하고 의미 해석에는 의존하지 않는다. 둘째, 전문 검색은 두 계층 위에 앉는다는 점이다. 문서를 어휘소로 만드는 과정(사전 lexize)에서 대소문자 변환을 위해 로케일을, 문자 경계를 위해 인코딩을 참조하며, 그 결과물을 GIN이 인덱싱한다.

다른 두 모듈이 의존하는 추상화를 먼저 읽고, 그다음 바이트 계층, 마지막으로 두 계층 위에 앉는 소비자 순으로 읽는다.

  1. postgres-collation-providers.md — 여기서 시작한다. pg_locale_t 핸들과 collate_methods vtable은 인코딩의 ctype 경로와 전문 검색의 대소문자 변환이 모두 참조하는 공유 어휘다. PG≤16에서 넘어온 독자라면 예상치 못했을 세 제공자 분리(libc / ICU / builtin)도 여기서 설명한다.
  2. postgres-encoding.md — 바이트 계층이다. 짧고 독립적이다. 서버 인코딩 대 클라이언트 인코딩, 변환 함수 행렬, 인코딩 이름/wchar 테이블이 src/common에 사는 이유(프론트엔드 도구와 공유)를 다룬다.
  3. postgres-full-text-search.md — 마지막으로 읽는다. 앞의 두 계층을 묶는 소비자이고, 옆으로는 GIN(postgres-gin.md, storage-engine)까지 뻗는다. 인덱스 절반의 이야기까지 보고 싶다면 GIN 문서를 나란히 읽는다.

아래 모듈 문서들은 아직 존재하지 않을 수 있다. 요약은 예측적이다.

모듈 문서범위 한 줄 요약
postgres-collation-providers.mdpg_locale.cpg_locale_t 핸들과 collate_methods vtable: 콜레이션 OID가 제공자(COLLPROVIDER_LIBC 'c' / COLLPROVIDER_ICU 'i' / COLLPROVIDER_BUILTIN 'b')로 해석되는 방법, pg_locale_{libc,icu,builtin}.c로 디스패치되는 pg_strcoll/pg_strxfrm/대소문자 매핑 진입점, 결정적/비결정적 콜레이션, collate_is_c/ctype_is_c 빠른 경로, 콜레이션 버전 추적, CREATE COLLATION(collationcmds.c).
postgres-encoding.mdutils/mb: 데이터베이스별 서버 인코딩, client_encodingpg_do_encoding_conversion(mbutils.c, conv.c, conversion_procs 테이블)으로 연결되는 변환 함수 행렬, 멀티바이트 문자열 기본 연산, src/common과의 분리(encnames.c: 인코딩 이름, wchar.c: 프론트엔드 도구와 공유하는 인코딩별 mblen/verify/charwchar 테이블).
postgres-full-text-search.mdtsearch: tsvector/tsquery 타입과 연산자, 텍스트 검색 설정(파서 — wparser_def.c — 와 사전 체인 — dict_*, spell.c), to_tsvector/to_tsquery의 어휘화 및 정규화 방식, 랭킹(tsrank.c), GIN 통합(tsginidx.cextractValue/extractQuery, GiST용 tsgistidx.c).
  • postgres-overview-base-infra.md — 바로 아래 계층이다. text/varlena 데이터 타입, fmgr 호출 규약, 그리고 이 섹션이 기술하는 콜레이션 핸들과 mb 변환을 호출하는 utils/adt의 문자열 함수들을 담당한다. “text Datum이 무엇인가”는 base-infra에서, “그것에 어떤 로케일/인코딩 규칙이 적용되는가”는 이 섹션에서 읽는다.
  • postgres-overview-storage-engine.md — 옆 경계다. 거기 있는 postgres-gin.md가 전문 검색의 대표 클라이언트인 GIN 접근 방법을 담당한다. 이 섹션에서 기술하는 tsvector 연산자 클래스와 extract* 지원 함수는 GIN의 제네릭 extract/consistent 프레임워크에 꽂힌다.
  • postgres-overview-query-processing.md — 두 곳에서 맞닿는다. LIKE/정규식 평가와 선택도 추정이 대소문자/문자 분류를 위해 콜레이션 핸들을 참조하며, 스캐너/파서는 이 섹션의 데이터 경로 인코딩과 나란히 SQL 텍스트 인코딩을 처리한다.
  • postgres-overview-system-catalog.mdpg_collation, pg_conversion, pg_ts_config/pg_ts_dict/pg_ts_parser가 여기서 다루는 세 모듈이 읽는 카탈로그 행이다. 카탈로그 레이아웃과 캐시는 그 섹션이 담당하고, 그 행으로 키를 찾는 런타임 동작은 이 섹션이 담당한다.