데이터베이스는 몇 가지나 알고 계신가요?" 이 질문에 MySQL, Oracle, MongoDB, Redis 등을 떠올리셨다면, 오늘 또 하나의 강력한 도구를 리스트에 추가할 시간입니다. 바로 검색 기능을 갖춘 NoSQL 데이터베이스이자 검색 엔진인 OpenSearch입니다.
오늘날 데이터는 엄청난 속도와 양, 그리고 다양한 형태로 생성됩니다. 기존 관계형 데이터베이스는 정형 데이터 처리에 강점을 보이지만, 대량의 비정형 데이터를 효율적으로 검색하고 분석하는 데는 한계가 있죠. OpenSearch는 이러한 현대 데이터 환경의 요구에 부응하며, 강력한 검색 기능을 중심으로 다양한 서비스에서 핵심적인 역할을 수행하고 있습니다.
이 글에서는 OpenSearch의 기본 개념과 핵심 기능인 Analyzer, Elasticsearch와의 관계, 클러스터 아키텍처, 그리고 한국어 처리에 특화된 Nori 분석기까지 깊이 있게 살펴보고, 실제 기업들이 어떻게 OpenSearch를 활용하여 검색 서비스를 구축하는지 그 여정을 따라가 보겠습니다.
OpenSearch는 단순히 데이터를 저장하는 것을 넘어, 저장된 데이터를 빠르고 정교하게 검색하는 데 특화된 오픈소스 NoSQL 데이터베이스이자 검색 엔진입니다.
OpenSearch vs. RDBMS 용어 비교:
OpenSearch | RDBMS | 설명 |
---|---|---|
Index | Table (테이블) | 데이터 문서(Document)들의 논리적인 집합. |
Document | Row (행) | Index에 저장되는 개별 데이터 단위. JSON 객체 형태. |
Field | Column (열) | Document 내의 각 키-값 쌍에서 키에 해당. 데이터의 속성. |
Mapping | Schema (스키마) | Index 내 Document들의 구조 정의. 각 Field의 데이터 타입, 분석 방식 등을 설정. |
OpenSearch는 기본적으로 분산 시스템으로 설계되어 높은 가용성과 확장성을 제공합니다. 여러 대의 서버(노드)가 모여 하나의 클러스터(Cluster)를 구성하고, 데이터는 이 클러스터 내에 분산되어 저장 및 처리됩니다.
etcd
와 유사한 내부 메커니즘을 통해 다른 노드들과 동기화됩니다.🤔 꼬리 질문: OpenSearch 클러스터 설계 시 샤드 수와 레플리카 수는 어떻게 결정하는 것이 좋을까요? 너무 많거나 적게 설정했을 때 발생할 수 있는 문제점은 무엇일까요?
OpenSearch가 뛰어난 검색 기능을 제공할 수 있는 비결 중 하나는 바로 Analyzer입니다. Analyzer는 데이터를 저장(색인)하거나 검색할 때, 입력된 텍스트를 일정한 규칙에 따라 의미 있는 작은 단위인 토큰(Token)으로 분리하고 가공하는 역할을 합니다. 이 과정을 통해 검색의 정확도와 효율성을 크게 높일 수 있습니다.
데이터 저장부터 검색까지의 흐름 (Analyzer 중심):
text
타입으로 지정된 Field의 내용은 설정된 Analyzer를 통해 여러 개의 토큰으로 분리되고 가공된 후, 역색인(Inverted Index) 구조로 저장됩니다.예제: 책 검색 서비스 구현을 위한 Analyzer 활용
(이하 Analyzer 예제 설명은 이전 답변과 거의 동일하게 유지하되, 문맥상 필요한 부분만 수정합니다. 제공해주신 내용이 매우 상세하고 좋아서 핵심을 유지하는 것이 좋다고 판단됩니다.)
대량의 책 데이터를 OpenSearch에 적재하여 검색 서비스를 만든다고 가정하고, 다음과 같은 검색 요구사항이 있습니다.
1. 인덱스 생성 및 매핑 정의 (예시):
PUT /book_example_v2 // 인덱스 이름 변경 (가독성)
{
"mappings": {
"properties": {
"bookName": {
"type": "text",
"analyzer": "my_book_name_analyzer"
},
"author": {
"type": "keyword"
},
"publishDate": {
"type": "date"
}
}
},
"settings": {
"analysis": {
"analyzer": {
"my_book_name_analyzer": {
"type": "custom",
"char_filter": [ "html_strip", "remove_special_chars" ],
"tokenizer": "my_ngram_tokenizer",
"filter": [ "lowercase", "trim" ]
}
},
"char_filter": {
"remove_special_chars": {
"type": "pattern_replace",
"pattern": "[^a-zA-Z0-9가-힣\\s]",
"replacement": ""
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "ngram",
"min_gram": 2, "max_gram": 5,
"token_chars": [ "letter", "digit" ]
}
}
}
}
}
2. 데이터 인덱싱 과정 (Analyzer의 역할):
(Analyzer 처리 순서: Character Filters → Tokenizer → Token Filters)
html_strip
(HTML 태그 제거), remove_special_chars
(사용자 정의 특수문자 제거).my_ngram_tokenizer
(N-gram 방식).lowercase
(소문자 변환), trim
(공백 제거).3. 인덱싱된 데이터 검색:
GET /book_example_v2/_search
{
"query": {
"match": {
"bookName": "java"
}
}
}
검색 결과에는 연관도 점수(_score
)가 포함되어 BM25 알고리즘 등에 의해 계산된 순서대로 문서가 반환됩니다.
기본적으로 제공되는 OpenSearch(및 Elasticsearch)의 Standard Analyzer는 공백을 기준으로 단어를 분리하므로, 한국어처럼 조사가 붙고 띄어쓰기가 불규칙한 교착어에는 적합하지 않습니다. 예를 들어 "오픈서치검색엔진"이라는 텍스트는 Standard Analyzer로는 "오픈서치검색엔진"이라는 하나의 토큰으로만 분석될 가능성이 높아, "오픈서치"나 "검색엔진"으로 검색했을 때 원하는 결과를 얻기 어렵습니다.
이러한 문제를 해결하기 위해 한국어 형태소 분석기가 필요하며, OpenSearch에서는 Nori (노리) 분석기를 공식적으로 지원합니다.
Nori 분석기 설정 예시 (인덱스 생성 시):
PUT /korean_example
{
"settings": {
"analysis": {
"analyzer": {
"my_korean_analyzer": { // 사용자 정의 Nori 분석기
"type": "custom",
"tokenizer": "nori_tokenizer",
"filter": [
"nori_pos_filter_useful_nouns", // 명사 위주 필터 (예시)
"lowercase"
]
}
},
"tokenizer": { // Nori 토크나이저 사용
"nori_tokenizer": {
"type": "nori_tokenizer",
"decompound_mode": "mixed", // 복합 명사 분해 방식 (discard, mixed, none)
"user_dictionary_rules": [ // 사용자 사전 규칙 (필요시)
"c++", "C#.NET", "씨쁠쁠", "오픈서치", "엘라스틱서치"
]
}
},
"filter": {
"nori_pos_filter_useful_nouns": { // 사용자 정의 Nori 품사 필터
"type": "nori_part_of_speech",
"stoptags": [ // 제외할 품사 태그 (예: 조사, 어미 등)
"E", "J", "SC", "SF", "SP", "SSC", "SSO", "SY", "UNA", "UNKNOWN", "VSV", "VA", "VCP", "VCN"
// 필요에 따라 명사(NNG, NNP 등)만 남기도록 stoptags 조정
]
}
}
}
},
"mappings": {
"properties": {
"korean_title": {
"type": "text",
"analyzer": "my_korean_analyzer", // 색인 시 사용할 분석기
"search_analyzer": "my_korean_analyzer" // 검색 시 사용할 분석기 (일반적으로 동일하게 설정)
}
}
}
}
Nori 분석기를 사용하면 "오픈서치로 검색하기"와 같은 문장을 "오픈서치", "검색" 등의 의미 있는 명사 토큰으로 분리하여 색인함으로써, 한국어 검색의 정확도와 재현율을 크게 향상시킬 수 있습니다.
🤔 꼬리 질문: 한국어 처리 시 Nori 분석기의
decompound_mode
설정(mixed, discard, none)은 각각 어떤 차이가 있으며, 어떤 경우에 어떤 설정을 사용하는 것이 유리할까요? 사용자 사전은 어떤 경우에 특히 유용하게 사용될 수 있을까요?
지금까지 OpenSearch의 기본 개념부터 Elasticsearch와의 관계, 클러스터 아키텍처, 핵심 기능인 Analyzer의 활용법, 그리고 한국어 처리를 위한 Nori 분석기까지 폭넓게 살펴보았습니다. OpenSearch는 단순한 데이터 저장을 넘어, 강력하고 유연한 검색 기능을 제공함으로써 다양한 서비스에 핵심적인 가치를 더하는 중요한 기술입니다.
Analyzer를 어떻게 설계하고 활용하느냐에 따라 검색 결과의 품질과 사용자 경험이 크게 달라질 수 있으며, 안정적이고 효율적인 색인 파이프라인 구축은 대규모 데이터를 다루는 현대 서비스의 필수 과제입니다. 이 글이 OpenSearch를 이해하고 실제 서비스에 적용하는 데 있어 유용한 정보를 제공했기를 바랍니다.
읽어주셔서 감사합니다!