GIN을 만드느 기준

김영준·2026년 4월 20일

멜로미

목록 보기
13/13

난 문자열을 검색할 예정이기에 문자열을 나누는 기준을 알아보겠다.

1. trigram

2. tsvector

[1] trigram

: 세글자씩 잘라서 역색인 구조로 만들기

자료 저장이든 검색이든 앞에 공백 두개, 뒤에 공백 하나를 넣음
"개발의 신이 될거다"
->
" 개"
" 개발"
"개발의"
...
"될거다"
"거다 "
까지 저장된다는 것.

[공식 문서]

pg_trgm ignores non-word characters (non-alphanumerics) when extracting trigrams from a string. Each word is considered to have two spaces prefixed and one space suffixed when determining the set of trigrams contained in the string. For example, the set of trigrams in the string “cat” is “ c”, “ ca”, “cat”, and “at ”. The set of trigrams in the string “foo|bar” is “ f”, “ fo”, “foo”, “oo ”, “ b”, “ ba”, “bar”, and “ar ”.

[2] tsvector

: 토큰으로 잘라서 역색인 구조로 만들기

토큰이란?

의미를 가진 최소 단위

무엇을 토큰으로 볼지는 토크나이저가 정함

1단계 - 띄어쓰기 기준으로 나누기

2단계 - 조사나 be동사 같은거 없앰 [규칙 기반 파서]

PostgreSQL의 ts_parse가 실제로 이렇게 동작함. 23가지 토큰 타입을 구분

"apple is good"
 ↑
 왼쪽부터 한 글자씩 읽음

글자별 추적
ts_parse는 상태머신이야. 현재 상태를 들고 있다가, 다음 글자 보고 상태를 바꿈.
시작: 상태 = INIT

1. 'a' 읽음

INIT 상태 + 알파벳 글자 → "아, 영문 단어 시작이네"
상태 전환: INIT → IN_ASCIIWORD
버퍼에 'a' 저장
토큰 확정은 아직 안 함 (계속 이어질 수 있으니까)

2. 'p' 읽음

IN_ASCIIWORD 상태 + 알파벳 → "계속 단어 중"
상태 유지: IN_ASCIIWORD
버퍼: "ap"

3. 'p' 읽음

상태 유지: IN_ASCIIWORD
버퍼: "app"

4. 'l' 읽음

버퍼: "appl"

5. 'e' 읽음

버퍼: "apple"

6. ' ' (공백) 읽음

IN_ASCIIWORD 상태 + 공백 → "어, 단어 끝났네"
토큰 확정! → {token: "apple", tokid: 1 (ASCIIWORD)}
상태 전환: IN_ASCIIWORD → IN_BLANK
버퍼에 공백 저장

7. (다음 글자 'i' 읽기 전에) 공백도 토큰임

IN_BLANK 상태에서 공백 아닌 글자('i')를 만남
토큰 확정! → {token: " ", tokid: 12 (BLANK)}
상태 전환: IN_BLANK → IN_ASCIIWORD

8. 'i' 처리 (7번에서 이미 읽은 글자)

버퍼: "i"

9. 's' 읽음

버퍼: "is"

10. ' ' 읽음

토큰 확정! → {token: "is", tokid: 1 (ASCIIWORD)}
상태: IN_BLANK

11. 'g' 읽음

공백 토큰 확정! → {token: " ", tokid: 12 (BLANK)}
상태: IN_ASCIIWORD
버퍼: "g"

12~14. 'o', 'o', 'd' 읽음

버퍼: "good"

15. EOF (문자열 끝)

토큰 확정! → {token: "good", tokid: 1 (ASCIIWORD)}
파싱 종료


최종 결과
sqlSELECT * FROM ts_parse('default', 'apple is good');

 tokid |  token  |  description
-------+---------+---------------
     1 | apple   |  ASCIIWORD
    12 | (공백)   |  BLANK  
     1 | is      |  ASCIIWORD
    12 | (공백)   |  BLANK
     1 | good    |  ASCIIWORD
총 5개의 토큰으로 분해됨 (단어 3개 + 공백 2개).

3단계 - 사전 기반

running -> run으로 변환

위 과정으로 토큰을 나눔.

근데 문제 ! 이게 영어만 가능하다는거. 물론 한글 가능하지. 띄어쓰기 기준으로 나누고 가능해. 근데 한글은 단어 옆에 조사가 붙어있음. 프로그램은 이걸 조사로 인식할 방법이 없음. 그래서 한글은 지원 안하기에 이건 앞으로도 사용 안할 것임

profile
개발의 신이 될거다

0개의 댓글