PostgreSQL Full-Text Search — 한국어 검색 구현
데이터베이스 내에서 텍스트 데이터를 효율적으로 검색하는 기능은 현대 애플리케이션의 핵심 요구사항 중 하나입니다. 사용자들은 특정 키워드나 문구를 통해 원하는 정보를 빠르게 찾기를 기대하며, 이는 서비스의 사용자 경험을 좌우하는 중요한 요소입니다. PostgreSQL은 강력한 Full-Text Search (FTS) 기능을 내장하고 있어 이러한 요구사항을 충족시킬 수 있습니다. 하지만 한국어는 영어와 달리 띄어쓰기와 형태소 분석의 중요성이 커, 단순한 방법으로는 정확한 검색 결과를 얻기 어렵습니다.
이 포스트에서는 PostgreSQL의 Full-Text Search 기본 개념을 소개하고, 한국어 검색의 특수성을 이해한 뒤, N-gram 기반의 pg_bigm 확장을 활용하여 PostgreSQL에서 한국어 검색을 구현하는 실전적인 방법을 단계별로 안내합니다. 또한, N-gram 방식의 한계점과 더 나은 한국어 검색을 위한 대안까지 함께 논의하여 개발자들이 프로젝트에 최적의 검색 솔루션을 선택할 수 있도록 돕고자 합니다.
PostgreSQL Full-Text Search 기본 개념
PostgreSQL의 Full-Text Search는 단순히 LIKE 연산자를 사용하는 것보다 훨씬 정교하고 빠르며 유연한 텍스트 검색 기능을 제공합니다. 이는 대량의 텍스트 데이터에서 관련성이 높은 결과를 효율적으로 찾아내기 위해 설계되었습니다.
검색의 중요성 및 PostgreSQL FTS 소개
검색 기능은 전자상거래 사이트의 상품 검색, 블로그나 뉴스 사이트의 기사 검색, 문서 관리 시스템의 내용 검색 등 거의 모든 서비스에서 필수적입니다. 단순히 WHERE column LIKE %keyword%와 같은 쿼리는 인덱스를 활용하기 어렵고, 부분 일치 검색만 가능하며, 대량의 데이터에서는 성능 저하를 초래합니다. 또한, 동의어 처리, 복수형 처리, 불용어(stop word) 제거 등 고급 검색 기능을 제공하기 어렵습니다.
PostgreSQL FTS는 이러한 문제를 해결하기 위해 다음과 같은 기능을 제공합니다:
- 언어별 사전(dictionary) 지원: 단어를 표준화된 형태로 변환(스테밍, 렉셈화)합니다.
- 불용어(stop word) 처리: 은, 는, 이, 가, and, the와 같이 검색에 의미 없는 단어를 제거합니다.
- 랭킹(ranking): 검색 결과의 관련성을 점수로 매겨 가장 관련성이 높은 문서를 우선적으로 보여줍니다.
- GIN (Generalized Inverted Index) 인덱스: 검색 성능을 극적으로 향상시킵니다.
ts_vector와 ts_query 이해하기
PostgreSQL FTS의 핵심은 ts_vector와 ts_query라는 두 가지 특별한 데이터 타입입니다.
ts_vector: 검색 대상이 되는 문서(텍스트 데이터)를 특수한 형태로 변환한 것입니다.to_tsvector함수를 사용하여 텍스트를ts_vector로 변환할 때, 텍스트는 다음과 같은 과정을 거칩니다:- 파싱(Parsing): 텍스트를 단어 단위로 분리합니다.
- 토큰화(Tokenization): 분리된 단어들을 토큰으로 만듭니다.
- 사전 처리(Dictionary Processing): 각 토큰에 대해 언어별 사전(예:
english,simple)을 적용하여 불용어를 제거하고, 단어를 기본 형태(lexeme)로 변환합니다. 예를 들어, "running", "ran", "runs"는 모두 "run"이라는 렉셈으로 변환될 수 있습니다. - 위치 정보 저장: 각 렉셈이 원본 텍스트에서 나타났던 위치 정보를 함께 저장합니다. 이는 랭킹 계산에 사용됩니다.
sqlSELECT to_tsvector(english, The quick brown fox jumps over the lazy dog); -- 결과: brown:3 dog:9 fox:4 jump:5 lazy:8 quick:2위 예시에서 The, over, the는 불용어로 제거되었고, jumps는 jump로 스테밍되었습니다.
ts_query: 사용자가 입력한 검색어를 특수한 형태로 변환한 것입니다.to_tsquery함수를 사용하여 검색어를ts_query로 변환할 때, 검색어는ts_vector와 유사한 과정을 거치지만, 논리 연산자(&AND,|OR,!NOT,<->NEAR)를 포함할 수 있습니다.sqlSELECT to_tsquery(english, fox & dog); -- 결과: fox & dog SELECT to_tsquery(english, quick | brown); -- 결과: quick | brown
ts_vector와 ts_query는 @@ 연산자를 사용하여 일치 여부를 검사합니다.
SELECT to_tsvector(english, The quick brown fox jumps over the lazy dog) @@ to_tsquery(english, fox & dog);
-- 결과: t (true)
SELECT to_tsvector(english, The quick brown fox jumps over the lazy dog) @@ to_tsquery(english, cat);
-- 결과: f (false)
GIN 인덱스의 역할
대량의 텍스트 데이터에서 ts_vector를 효율적으로 검색하려면 인덱스가 필수적입니다. PostgreSQL FTS는 GIN (Generalized Inverted Index) 인덱스를 사용합니다. GIN 인덱스는 각 렉셈을 키로 하고, 해당 렉셈을 포함하는 문서의 목록을 값으로 가지는 역색인(inverted index) 구조를 가집니다.
예를 들어, "fox"라는 렉셈이 문서 1, 5, 10에 나타난다면, GIN 인덱스는 "fox" -> [문서 1, 문서 5, 문서 10]과 같이 저장합니다. 이렇게 하면 특정 렉셈이 포함된 문서를 빠르게 찾아낼 수 있어 검색 성능이 크게 향상됩니다.
-- 예시 테이블 생성
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT,
content TEXT,
search_vector TSVECTOR
);
-- search_vector 컬럼에 GIN 인덱스 생성
CREATE INDEX idx_documents_search_vector ON documents USING GIN (search_vector);
search_vector 컬럼은 트리거를 사용하여 title과 content 컬럼이 변경될 때 자동으로 업데이트되도록 구성하는 것이 일반적입니다.
-- search_vector 업데이트 함수
CREATE FUNCTION update_document_search_vector() RETURNS TRIGGER AS $$
BEGIN
NEW.search_vector = to_tsvector(english, NEW.title || || NEW.content);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 트리거 생성
CREATE TRIGGER trg_update_document_search_vector
BEFORE INSERT OR UPDATE ON documents
FOR EACH ROW EXECUTE FUNCTION update_document_search_vector();
한국어 검색의 특수성 및 도전 과제
PostgreSQL의 기본 FTS 기능은 영어와 같은 서구권 언어에 최적화되어 있습니다. 그러나 한국어는 언어적 특성 때문에 이를 그대로 적용하기 어렵습니다.
형태소 분석의 필요성
한국어는 교착어(膠着語, agglutinative language)로, 어근에 접사나 어미, 조사가 붙어 단어의 의미나 문법적 기능을 나타냅니다. 예를 들어 "사과"라는 명사에 "를", "가", "는", "도" 등의 조사가 붙어 "사과를", "사과가", "사과는", "사과도" 등 다양한 형태로 변화합니다. 또한, 동사 "먹다"는 "먹고", "먹어서", "먹으니", "먹습니다" 등 수많은 형태로 활용됩니다.
이러한 특성 때문에 단순한 띄어쓰기나 어간 추출 방식만으로는 정확한 검색이 어렵습니다. 예를 들어 사용자가 "사과"라고 검색했을 때, "사과를 먹었다", "사과가 맛있다"와 같은 문서를 찾으려면, "사과를"과 "사과가"에서 "사과"라는 핵심 형태소를 추출해내야 합니다. 이 과정을 **형태소 분석(Morphological Analysis)**이라고 합니다.
PostgreSQL의 기본 FTS는 한국어 형태소 분석 기능을 내장하고 있지 않아, "사과"와 "사과를"을 다른 단어로 인식하게 됩니다. 이는 검색 정확도를 크게 떨어뜨리는 요인입니다.
N-gram 방식 vs. 형태소 분석 방식
한국어와 같은 CJK(중국어, 일본어, 한국어) 언어의 검색을 구현하는 방식은 크게 두 가지로 나눌 수 있습니다.
| 특징 | N-gram 방식 (예: `pg_bigm`, `pg_trgm`) | 형태소 분석 방식 (예: Elasticsearch Nori 플러그인, MeCab) |
|---|---|---|
| **작동 원리** | 텍스트를 N개의 문자 단위로 잘라 토큰을 생성 (예: 2-gram이면 "사과" -> "사", "과") | 텍스트를 의미 있는 최소 단위(형태소)로 분리하고 품사를 분석 (예: "사과를" -> "사과"(명사), "를"(조사)) |
| **장점** | - 구현이 비교적 간단하고 빠름 - 띄어쓰기 오류나 오타에도 강인함 - 특정 언어에 종속되지 않음 | - 검색 정확도가 높음 (의미 기반 검색) - 불필요한 토큰 제거로 검색 결과의 노이즈 감소 - 동의어 처리 등 고급 기능 구현 용이 |
| **단점** | - 의미 단위가 아닌 글자 단위 분리로 인해 불필요한 토큰 생성 - 검색 결과의 정확도가 떨어질 수 있음 - 인덱스 크기가 커질 수 있음 | - 형태소 분석기의 성능에 의존 - 형태소 분석 사전 구축 및 유지보수 비용 - 띄어쓰기 오류에 취약할 수 있음 |
| **적합한 경우** | - 간단하고 빠른 검색이 필요한 경우 - 띄어쓰기 오류가 잦은 사용자 입력 검색 - 개발 비용 및 복잡성을 최소화하고 싶은 경우 | - 높은 검색 정확도와 의미 기반 검색이 필수적인 경우 - 대규모 텍스트 데이터 검색 - 복잡한 검색 요구사항 (예: 특정 품사 검색) |
PostgreSQL에서 형태소 분석 기반의 한국어 FTS를 직접 구현하는 것은 매우 복잡하며, 외부 형태소 분석기를 연동해야 합니다. 이 포스트에서는 PostgreSQL 확장 기능 중 비교적 쉽게 적용할 수 있는 N-gram 기반의 pg_bigm을 사용하여 한국어 검색을 구현하는 방법을 중점적으로 다룹니다.
PostgreSQL에서 한국어 검색 구현 전략
PostgreSQL에서 한국어 검색을 구현하는 가장 현실적인 방법 중 하나는 N-gram 기반의 확장을 사용하는 것입니다. 여기서는 pg_bigm 확장을 소개하고 이를 활용한 구현 방법을 설명합니다.
1. pg_bigm 소개 및 활용
pg_bigm은 CJK(중국어, 일본어, 한국어) 언어를 포함한 모든 언어에 대해 텍스트를 바이그램(bigram, 2-gram) 단위로 분할하여 Full-Text Search를 가능하게 하는 PostgreSQL 확장입니다. 바이그램은 텍스트를 두 글자씩 묶어 토큰으로 만드는 방식입니다. 예를 들어 "안녕하세요"는 "안녕", "녕하", "하세", "세요"와 같이 분할됩니다.
pg_bigm은 GIN 인덱스를 지원하여 대용량 텍스트에서도 빠른 검색을 제공하며, 띄어쓰기 오류나 부분 일치 검색에 강하다는 장점이 있습니다. 형태소 분석만큼 정확하지는 않지만, 구현이 간단하고 성능이 우수하여 많은 한국어 검색 요구사항을 충족시킬 수 있습니다.
2. pg_bigm 설치 및 활성화
pg_bigm 확장을 사용하려면 먼저 PostgreSQL 서버에 설치해야 합니다. 대부분의 Linux 배포판에서는 PostgreSQL 개발 패키지(postgresql-server-dev-XX 또는 postgresql-contrib-XX)에 포함되어 있거나 별도로 설치할 수 있습니다.
설치 과정 (Ubuntu/Debian 기준):
# PostgreSQL contrib 패키지 설치
sudo apt update
sudo apt install postgresql-contrib-14 # 사용하는 PostgreSQL 버전에 맞게 변경 (예: 14)
PostgreSQL 내부에서 확장 활성화:
psql 클라이언트에 접속하여 다음 명령어를 실행합니다.
CREATE EXTENSION pg_bigm;
3. 테이블 및 데이터 준비
pg_bigm을 사용하여 검색할 테이블과 데이터를 준비합니다.
-- 검색 대상이 될 문서 테이블 생성
CREATE TABLE articles (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- 샘플 데이터 삽입
INSERT INTO articles (title, content) VALUES
(PostgreSQL 한국어 검색 구현 가이드, 이 문서는 PostgreSQL에서 한국어 Full-Text Search를 구현하는 방법을 설명합니다. 형태소 분석과 N-gram 방식을 비교하며 pg_bigm 확장을 활용한 실전 예제를 제공합니다.),
(데이터베이스 성능 최적화 전략, PostgreSQL 데이터베이스의 성능을 최적화하기 위한 다양한 전략들을 소개합니다. 인덱스 튜닝, 쿼리 최적화, 파티셔닝 등 심화된 내용을 다룹니다.),
(코드픽 기술 블로그 소개, 코드픽 기술 블로그는 다양한 개발 기술 트렌드와 실전 팁을 공유합니다. 최신 기술 동향과 실무에 유용한 정보를 얻어가세요.),
(한국어 자연어 처리의 도전 과제, 한국어는 교착어 특성 때문에 자연어 처리(NLP) 분야에서 많은 도전 과제를 안고 있습니다. 형태소 분석, 개체명 인식, 의존 구문 분석 등 다양한 기술이 필요합니다.),
(PostgreSQL Full-Text Search 활용, PostgreSQL의 Full-Text Search 기능을 활용하여 빠르고 정확한 텍스트 검색 시스템을 구축하는 방법을 알아봅니다. 기본적인 ts_vector와 ts_query 개념부터 GIN 인덱스까지 다룹니다.);
4. GIN 인덱스 생성
pg_bigm은 GIN 인덱스를 사용하여 검색 성능을 최적화합니다. 검색 대상이 되는 컬럼(여기서는 title과 content)에 GIN 인덱스를 생성해야 합니다. pg_bigm은 gin_bigm_ops라는 연산자 클래스를 제공합니다.
-- title 컬럼에 pg_bigm GIN 인덱스 생성
CREATE INDEX idx_articles_title_bigm ON articles USING GIN (title gin_bigm_ops);
-- content 컬럼에 pg_bigm GIN 인덱스 생성
CREATE INDEX idx_articles_content_bigm ON articles USING GIN (content gin_bigm_ops);
-- 여러 컬럼을 합쳐서 검색할 경우, 가상 컬럼 또는 생성된 컬럼에 인덱스 생성
-- 예시: title과 content를 합친 텍스트에 대한 인덱스 (실제 사용 시 검색 필드를 합쳐서 쿼리)
-- CREATE INDEX idx_articles_fulltext_bigm ON articles USING GIN ((title || || content) gin_bigm_ops);
-- 위 방식은 인덱스 생성 시점에 합쳐진 텍스트를 저장하지 않으므로, 더 효율적인 방법은 다음과 같습니다.
-- 1. Generated Column 사용 (PostgreSQL 12+)
ALTER TABLE articles ADD COLUMN full_text_search_bigm TEXT GENERATED ALWAYS AS (title || || content) STORED;
CREATE INDEX idx_articles_fulltext_bigm ON articles USING GIN (full_text_search_bigm gin_bigm_ops);
-- 2. 또는 트리거를 사용하여 별도의 컬럼에 저장 (PostgreSQL 11 이하)
-- ALTER TABLE articles ADD COLUMN full_text_search_bigm TEXT;
-- CREATE FUNCTION update_article_bigm_text() RETURNS TRIGGER AS $$
-- BEGIN
-- NEW.full_text_search_bigm = NEW.title || || NEW.content;
-- RETURN NEW;
-- END;
-- $$ LANGUAGE plpgsql;
-- CREATE TRIGGER trg_update_article_bigm_text
-- BEFORE INSERT OR UPDATE ON articles
-- FOR EACH ROW EXECUTE FUNCTION update_article_bigm_text();
-- CREATE INDEX idx_articles_fulltext_bigm ON articles USING GIN (full_text_search_bigm gin_bigm_ops);
위 예시에서는 full_text_search_bigm이라는 Generated Column을 사용하여 title과 content를 합친 텍스트에 인덱스를 생성했습니다. 이렇게 하면 검색 쿼리 시 title과 content를 각각 검색하는 대신 하나의 컬럼만 검색하여 효율성을 높일 수 있습니다.
5. 검색 쿼리 실행
pg_bigm은 % 연산자를 사용하여 텍스트 검색을 수행합니다. 이 연산자는 GIN 인덱스를 활용합니다.
-- 한국어 검색이라는 키워드로 검색
SELECT id, title, content
FROM articles
WHERE full_text_search_bigm LIKE %한국어 검색%;
-- pg_bigm의 LIKE 연산자는 GIN 인덱스를 사용하지 않으므로, 성능이 좋지 않습니다.
-- pg_bigm의 핵심은 % 연산자입니다.
-- 한국어 검색 키워드로 검색 (pg_bigm의 % 연산자 사용)
SELECT id, title, content
FROM articles
WHERE full_text_search_bigm % 한국어 검색;
-- PostgreSQL 또는 데이터베이스를 포함하는 문서 검색
SELECT id, title, content
FROM articles
WHERE full_text_search_bigm % PostgreSQL OR full_text_search_bigm % 데이터베이스;
-- PostgreSQL과 한국어를 모두 포함하는 문서 검색 (AND 조건)
SELECT id, title, content
FROM articles
WHERE full_text_search_bigm % PostgreSQL AND full_text_search_bigm % 한국어;
pg_bigm은 show_bigm() 함수를 제공하여 특정 텍스트가 어떻게 바이그램으로 분해되는지 확인할 수 있습니다.
SELECT show_bigm(안녕하세요);
-- 결과: {안녕,녕하,하세,세요}
SELECT show_bigm(한국어 검색);
-- 결과: {한국,국어, 검색}
이 바이그램들이 GIN 인덱스에 저장되어 검색 시 일치하는 바이그램을 찾아냅니다. 예를 들어 WHERE full_text_search_bigm % 한국어 검색 쿼리는 한국, 국어, 검색 바이그램 중 하나라도 포함하는 문서를 찾아냅니다.
6. 검색 결과 및 성능 분석
EXPLAIN ANALYZE를 사용하여 쿼리의 실행 계획과 성능을 분석할 수 있습니다. GIN 인덱스가 제대로 사용되는지 확인하는 것이 중요합니다.
EXPLAIN ANALYZE SELECT id, title, content
FROM articles
WHERE full_text_search_bigm % 한국어 검색;
EXPLAIN ANALYZE 결과에서 Index Scan using idx_articles_fulltext_bigm on articles와 같은 항목이 보인다면 GIN 인덱스가 성공적으로 사용되고 있음을 의미합니다. 만약 Seq Scan이 나타난다면 인덱스가 없거나, 쿼리가 인덱스를 활용하지 못하는 방식으로 작성되었을 가능성이 높습니다.
N-gram 기반 검색의 한계와 보완
pg_bigm을 이용한 N-gram 기반 검색은 구현이 간단하고 띄어쓰기 오류에 강하다는 장점이 있지만, 다음과 같은 한계점을 가집니다.
정확도 문제 (오버매칭, 언더매칭)
- 오버매칭 (Over-matching): N-gram은 의미 단위가 아닌 글자 단위로 텍스트를 분리하기 때문에, 원치 않는 결과가 검색될 수 있습니다. 예를 들어, "바나나"를 검색했을 때 "바다"와 "나비"가 포함된 문서가 바이그램 "바"와 "나" 때문에 검색될 수 있습니다. 이는 "바"와 "나"가 "바나나"의 일부이기 때문입니다.
- 언더매칭 (Under-matching): 검색어가 특정 형태소의 일부로만 존재하고 바이그램으로 분리될 때 의미가 약해지는 경우, 정확한 문서가 누락될 수 있습니다. 예를 들어 "아이폰"을 검색했을 때 "아이폰15"와 같은 단어가 "아이", "이폰", "폰1" 등으로 분리되어, "아이폰"이라는 단어의 의미가 희석될 수 있습니다.
이러한 문제들은 특히 짧은 검색어에서 두드러지며, 검색 결과의 관련성을 저하시킬 수 있습니다.
형태소 분석 기반 검색 시스템과의 비교
높은 검색 정확도와 의미 기반의 고급 검색 기능이 필요한 경우, 형태소 분석 기반의 검색 시스템을 고려해야 합니다. 대표적인 예시로는 Elasticsearch와 Solr가 있습니다.
- Elasticsearch (Nori 플러그인): Elasticsearch는 분산 검색 엔진으로, 한국어 형태소 분석을 위한 Nori 플러그인을 제공합니다. Nori는 Mecab-ko를 기반으로 하여 높은 정확도로 한국어를 형태소 단위로 분석하고, 이를 기반으로 인덱싱 및 검색을 수행합니다. 이를 통해 동의어 처리, 품사 기반 검색, 복합 명사 분해 등
pg_bigm으로는 어려운 정교한 검색 기능을 구현할 수 있습니다. - 외부 형태소 분석기 연동: PostgreSQL 자체에서 형태소 분석을 직접 수행하기는 어렵지만, 애플리케이션 레벨에서 MeCab-ko, Okt (Open Korean Text)와 같은 외부 형태소 분석 라이브러리를 사용하여 텍스트를 미리 분석한 뒤, 분석된 형태소들을 PostgreSQL의
ts_vector에 저장하는 방식으로 구현할 수 있습니다. 이 경우,ts_vector의simple설정을 사용하여 형태소들을 그대로 저장하고 검색하는 방식입니다. 하지만 이 방법은 데이터 전처리 과정이 복잡하고,ts_vector의 사전 기능을 제대로 활용하기 어렵다는 단점이 있습니다.
언제 pg_bigm을 선택하고, 언제 외부 솔루션을 고려해야 할까요?
pg_bigm선택:- 구현이 간단하고 빠른 검색 응답 속도가 중요한 경우
- 띄어쓰기 오류나 오타에 강한 검색이 필요한 경우
- 높은 수준의 의미론적 정확도보다는 빠른 부분 일치 검색이 우선인 경우
- 기존 PostgreSQL 인프라를 최대한 활용하고 싶을 때
외부 형태소 분석 기반 솔루션 (Elasticsearch 등) 고려:
- 검색 결과의 정확도가 매우 중요하며, 의미 기반 검색이 필수적인 경우
- 동의어 처리, 유의어 확장, 품사 필터링 등 고급 검색 기능이 필요한 경우
- 대규모 데이터와 복잡한 검색 요구사항을 가진 시스템
- 분산 환경에서의 확장성과 고가용성이 필요한 경우
FAQ (자주 묻는 질문)
Q1: pg_bigm 외에 PostgreSQL에서 한국어 검색을 위한 다른 방법은 없나요?
A1: pg_bigm 외에 pg_trgm이라는 N-gram 기반 확장도 있습니다. pg_trgm은 주로 영어의 Trigram(3-gram)에 최적화되어 있지만, CJK 언어에도 사용할 수는 있습니다. 그러나 pg_bigm이 CJK 언어에 더 적합하게 설계되었으며, 특히 바이그램(2-gram)을 사용하여 텍스트 길이가 짧은 한국어 단어에 더 효과적일 수 있습니다. 또한, 앞서 언급했듯이, 애플리케이션 레벨에서 MeCab-ko, Okt 등 외부 형태소 분석기를 사용하여 텍스트를 전처리한 후, 그 결과(형태소)를 PostgreSQL의 일반 텍스트 컬럼에 저장하고 LIKE 연산자나 ts_vector의 simple 설정을 이용해 검색하는 방식도 가능합니다. 하지만 이 방법은 직접적인 PostgreSQL FTS 확장 활용보다는 복잡합니다.
Q2: pg_bigm 검색 성능을 더 개선할 수 있는 방법은 무엇인가요?
A2: pg_bigm의 성능을 개선하기 위한 몇 가지 방법이 있습니다.
GIN인덱스 활용: 가장 중요합니다. 검색 대상 컬럼에 반드시CREATE INDEX ... USING GIN (column_name gin_bigm_ops);형태로GIN인덱스를 생성해야 합니다.- Generated Column 또는 트리거 사용: 여러 컬럼(예:
title과content)을 합쳐서 검색해야 할 경우, 이들을 합친 텍스트를 별도의 Generated Column(PostgreSQL 12 이상)이나 트리거를 통해 업데이트되는 컬럼에 저장하고, 그 컬럼에GIN인덱스를 생성하는 것이 효율적입니다. - 검색어 길이 제한: 너무 짧은 검색어(예: 한 글자)는
pg_bigm의 바이그램 특성상 많은 결과를 반환하고 인덱스 효율을 떨어뜨릴 수 있습니다. 애플리케이션 레벨에서 최소 검색어 길이를 제한하는 것이 좋습니다. - 하드웨어 최적화:
GIN인덱스는 디스크 공간을 많이 차지하고, 쓰기 작업 시 오버헤드가 있을 수 있습니다. 빠른 디스크(SSD), 충분한 메모리, 적절한shared_buffers및work_mem설정 등 PostgreSQL 서버의 하드웨어 및 설정 튜닝도 중요합니다.
Q3: ts_vector를 사용한 Full-Text Search와 pg_bigm의 차이점은 무엇인가요?
A3:
ts_vector기반 FTS: 언어별 사전을 사용하여 단어를 렉셈(기본형)으로 변환하고 불용어를 제거하는 등 의미 기반의 정교한 검색을 목표로 합니다. 영어와 같은 언어에 매우 효과적입니다. 한국어의 경우, 내장된 형태소 분석기가 없어 직접 사용하기 어렵습니다.pg_bigm: 텍스트를 N-gram(주로 바이그램) 단위로 분해하여 글자 단위의 부분 일치 검색을 수행합니다. 언어의 의미론적 분석보다는 텍스트의 패턴 매칭에 가깝습니다. 한국어와 같이 형태소 분석이 복잡한 언어에서 비교적 쉽게 부분 일치 검색을 구현할 수 있습니다. 띄어쓰기나 오타에 강하다는 장점이 있습니다.
두