PostgreSQL · 2026-01-13

PostgreSQL Full Text Search 설정과 튜닝

PostgreSQL 전체 텍스트 검색 설정과 성능 최적화를 위한 실무 구성과 튜닝 요소를 정리한 기술 설명서

작성일 : 2026-01-13 ㆍ 작성자 : 관리자
post
목차

개요

PostgreSQL의 Full Text Search(FTS)는 대용량 텍스트에서 효율적인 검색을 가능하게 한다. 본문에서는 기본 구성부터 tsvector 활용 예제, 인덱스 설계, 쿼리 최적화와 운영상 고려사항까지 단계별로 설명한다. 처음 접하는 개발자도 따라하기 쉬운 흐름으로 구성되며 실무 적용에 초점을 둔다.

기초 개념

tsvector와 tsquery

tsvector는 텍스트를 정규화한 역색인 형태의 데이터 타입이다. 반대로 tsquery는 사용자가 입력하는 검색어를 표현한다. 이 둘을 결합해 일치 여부와 랭킹을 산출한다. 이 과정에서 불용어(stop words)와 형태소 처리(dictionary)가 중요한 역할을 한다.

형태소 사전과 언어 설정

Postgres는 여러 언어의 텍스트 파서를 제공한다. 적절한 언어를 지정하면 어근 추출과 불용어 제거가 정확해진다. 예를 들어 한국어는 기본 지원이 제한적이므로 외부 확장(예: pgroonga, nori 등)을 고려해야 한다.

설정과 구현

테이블과 tsvector 컬럼 추가 예제

실무에서는 쿼리 비용을 줄이기 위해 tsvector를 물리 컬럼으로 유지하고 트리거로 갱신하는 방식이 일반적이다. 아래는 기본적인 예제이다.

CREATE TABLE articles (
  id serial PRIMARY KEY,
  title text,
  body text,
  tsv tsvector
);

-- tsvector를 자동 갱신하는 함수
CREATE FUNCTION articles_tsv_trigger() RETURNS trigger AS $$
begin
  new.tsv := to_tsvector('english', coalesce(new.title,'') || ' ' || coalesce(new.body,''));
  return new;
end
$$ LANGUAGE plpgsql;

CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
  ON articles FOR EACH ROW EXECUTE FUNCTION articles_tsv_trigger();

-- GIN 인덱스 생성
CREATE INDEX idx_articles_tsv ON articles USING GIN(tsv);

tsvector postgres 예제: 쿼리

검색 쿼리는 to_tsquery 또는 plainto_tsquery를 사용한다. 랭킹 함수 ts_rank_cd로 결과를 정렬하면 유의미한 순위를 얻을 수 있다.

SELECT id, title, ts_rank_cd(tsv, query) AS rank
FROM articles, to_tsquery('english','database & performance') query
WHERE tsv @@ query
ORDER BY rank DESC
LIMIT 10;

인덱스와 성능

GIN vs GiST

일반적으로 GIN 인덱스가 Full Text Search에 더 적합하다. GIN은 검색 성능이 우수하지만 인덱스 빌드와 업데이트가 느리다. 반대로 GiST는 업데이트가 빠르나 검색 성능은 낮다. 업데이트 빈도가 높다면 트레이드오프를 고려해야 한다.

부분 인덱스와 조건부 인덱스

데이터 특성에 따라 부분 인덱스를 사용하면 저장 공간과 검색 비용을 절감할 수 있다. 예를 들어 공개 게시물만 검색 대상이라면 WHERE 조건을 추가한 인덱스를 생성한다.

쿼리 튜닝 전략

  • plainto_tsquery 대신 websearch_to_tsquery로 사용자 입력을 자연스럽게 해석
  • 불필요한 컬럼 조회를 줄여 네트워크 비용 절감
  • 필요 시 ts_rank_cd의 가중치(중요도)를 사용해 title과 body의 상대적 중요도 조정

가중치 예제

UPDATE articles SET tsv =
  setweight(to_tsvector('english', coalesce(title,'')), 'A') ||
  setweight(to_tsvector('english', coalesce(body,'')), 'B');

SELECT id, title, ts_rank_cd(tsv, query) AS rank
FROM articles, to_tsquery('english','performance') query
WHERE tsv @@ query
ORDER BY rank DESC;

운영 및 유지관리

인덱스 bloat와 통계 최신화가 성능에 큰 영향을 준다. 정기적인 VACUUM, ANALYZE와 필요 시 REINDEX를 계획한다. 대량 입력 작업 후에는 인덱스 재작성이나 일괄 갱신 정책을 적용하면 좋다.

모니터링 포인트

  • 빈번한 HOT 업데이트 여부
  • 인덱스 크기와 디스크 IO 패턴
  • 쿼리 플랜에서의 인덱스 사용 유무

확장과 대안

한국어와 같은 교착어는 외부 확장(예: pg_jieba, pgroonga)으로 처리 성능과 정확도를 높일 수 있다. 또한 대규모 검색에는 Elasticsearch와의 연동을 검토해도 좋다. 단, 데이터 일관성 및 운영 복잡도가 증가하므로 목적에 맞는 선택이 필요하다.

정리

Postgres Full Text Search 설정은 적절한 언어 설정, tsvector 컬럼 사용, 알맞은 인덱스 선택, 그리고 쿼리 레벨의 튜닝이 핵심이다. 운영 단계에서는 정기적인 유지관리와 모니터링이 성능 유지에 결정적 역할을 한다. 위 예제와 원칙을 바탕으로 환경에 맞는 최적화를 단계적으로 적용하면 실무에서 안정적인 텍스트 검색 성능을 확보할 수 있다.

postgres full text search 설정 tsvector postgres 예제 postgres 텍스트 검색 최적화 Postgres FTS GIN 인덱스 tsquery 사용법 텍스트 검색 튜닝 인덱스 유지관리