목록 보기
검색엔진의 Analyzer, 형태소분석기 ≠ 토크나이저
기타

검색엔진의 Analyzer, 형태소분석기 ≠ 토크나이저

요기요
요기요
2024년 5월 27일

안녕하세요, 요기요 Search Platform 팀의 정승한입니다. 저희 팀은 요기요에서 검색과 관련된 모든 시스템을 관리하고 있으며, 사용자가 입력한 키워드에 가장 적합한 가게와 메뉴를 찾아주는 역할을 하고있습니다. 요기요에서 처음으로 선보이는 검색 관련 테크 블로그인 만큼, 이번 글에서는 가장 기본적인 주제인 사용자의 입력 키워드를 분석하는 방법에 대해 소개하고자합니다. 이러한 역할을 담당하는 검색엔진의 Analyzer라는 모듈을 살펴보고, 이와 관련하여 형태소분석기, 토크나이저 등이 어떻게 구별되는지 설명드리겠습니다. 검색엔진이란? 검색엔진이 처음이시라면, 먼저 검색엔진이 무엇인지 부터 이해하는 것이 중요합니다. 검색엔진은 역색인 데이터 구조를 사용함으로써 결과물을 빠르게찾아주는프로그램입니다. 여기서 역색인이란? 서적 뒤에 나오는 찾아보기, 색인, 또는 Index라고 표시된 부분을 떠올리시면 됩니다. 이 부분은 각 단어마다 해당 단어가 등장하는 페이지 번호를 기록해 놓은것입니다. 도서에서 쉽게 찾아볼 수 있는 색인(Index) 페이지 검색엔진도 이와 같은 데이터 구조를 이용하여, 주어진 용어가 포함된 문서를 빠르게 찾을 수 있습니다. 예를들어, 치킨이라는 단어가 포함된 문서가 10쪽과 17쪽에있다 라는 식으로말입니다. 이러한 역색인 구조를 만들기 위해서는 치킨과 같은 용어들을 추출할 수 있어야 합니다. 검색엔진에서는 이러한 용어들을 Term이라고 부릅니다. Term은 Token과는 조금 다른 의미를 가지는데, 이에 대해서는 뒤에서 자세히설명하겠습니다. Term을 뽑아내기 까지의 여정,Analysis 원문에서 Term을 추출하기까지는 다양한 과정을 거치게 됩니다. 이 모든 과정을 검색엔진에서는 Analysis(분석)이라고 부르며, 이를 수행하는 모듈을 Analyzer(분석기)라고 합니다. Analysis 과정은 크게 3단계로나뉩니다. Character-Filtering Tokenizing Token-Filtering Character-Filtering Character-Filtering은 이름 그대로 글자(character) 단위로 제거하거나 변경이 필요한 부분을 처리하는 과정입니다. 예를 들어, 영어 알파벳에는 여러 변형이 존재합니다. 같은 a도 á, à, â, ä, å 등 다양한 형태가 있습니다. 사장님들이 정말로 이런 알파벳을 사용할까 싶지만, 실제로 cafe를 café로 표기하는 경우가 종종있습니다. 하지만 대부분의 사용자는 café가 아닌 cafe로 검색할 것입니다. 이런 경우, Character-Filtering을 통해 가게명이나 메뉴명에 사용된 알파벳을 모두 일반적인 알파벳 문자(ASCII 알파벳)로 변경할 수 있습니다. 이를 통해 검색의 일관성과 정확성을 높일 수있습니다. 이 외에도 정규표현식을 이용해 특정 패턴의 문자(열)을 삭제하거나 변경할 수 있습니다. 예를 들어, 요기요 메뉴 리스트의 색인 원본에는 각 메뉴 이름 뒤에 세미콜론()을 기준으로 메뉴 ID가 추가된 경우가있습니다. 이러한 경우, 원본 데이터에서 메뉴ID를 제거하지 않고도 Character-Filtering을 통해 불필요한 메뉴ID가 색인되는 것을 막을 수 있습니다. 이 과정을 통해 메뉴 이름만을 색인하여사용합니다. Character-Filtering에 대해 더 자세히 알고 싶으시면, 아래 대표적인 검색엔진 서비스들의 Character filter 레퍼런스를 참고하시면좋습니다. CharFilters Character filters reference | Elasticsearch Guide [8.13] | Elastic Tokenizing Tokenizing은 Character-Filtering을 통해 정제된 원문에서 Token을 추출하는 과정입니다. 사용하는 Tokenizer에 따라 Token을 추출하는 방식이 달라집니다. 우리는 오픈소스 <은전한닢> 프로젝트에서 제공하는 MeCabKoTokenizer를 사용합니다. 이 Tokenizer는 내부적으로 mecab-ko 형태소 분석기를 사용하여 이름이 붙여졌습니다. 이 Tokenizer의 Token을 추출하는 과정을 따라가면, Tokenizer와 형태소 분석기가 어떻게 구분되는지 알 수 있을것입니다. MeCabKoTokenizer는 총 3단계로구성됩니다. 형태소 분석단계 어절 형성단계 토큰화 단계 형태소 분석단계 형태소 분석은 원문을 형태소 단위로 쪼개는 과정입니다. 앞으로의 과정을 설명하기 위해 떡복이참잘하는집이라는 가게명을 예시로 사용하겠습니다. 이 가게명을 형태소 분석하면 아래의 형태소들로나뉩니다. 어절 형성단계 어절 형성 단계에서는 형태소들을 하나씩 가져와 어절을 만듭니다. 여기서 어절이란 학창 시절 국어 시간에 배운 띄어쓰기 단위를의미합니다. 아래에 단계별로 설명드리겠습니다. [] + 떡볶이 현재 첫 어절이 없기 때문에 아무것도 따질 필요 없이, 첫 형태소 떡볶이가 들어갑니다. 단, 여기서 떡볶이는 복합명사라서 떡과 볶이로 분리된 후에들어갑니다. [떡, 볶이] + 참 현재 어절의 끝 형태소 볶이 뒤에 참이 붙어서 어절이 되는지 확인하는 단계입니다. 하지만 명사(볶이) 뒤에 부사(참)가 붙을 수 없으므로 최종적으로 첫 어절은 [떡, 볶이]로 끝납니다. 참은 다음 어절의 처음으로 들어가게 됩니다.[참] [참] + 잘하- 부사 뒤에 동사가 붙을 수 없습니다. 마찬가지로 [참]으로 두 번째 어절이 끝납니다. 잘하-는 다음 어절의 처음으로 들어가게 됩니다.[잘하-] [잘하-] + -는 -는은 동사 뒤에 붙을 수 있는 어미로서 어절 구성에들어갑니다. [잘하-, -는] + 집 집은 명사로 어미 뒤에 붙을 수 없습니다. [잘하-, -는]이 세 번째 어절이 되고, [집]은 혼자서 네 번째 어절이됩니다. 이렇게 해서 최종적으로 4개의 어절이완성됩니다. [떡, 볶이] + [참] + [잘하-, -는] +[집] 토큰화 단계 드디어 토큰을 만드는 단계입니다. 위에서 만들어진 각 어절들에서 필요한 토큰을뽑아냅니다. [떡, 볶이] 떡과 볶이가 토큰으로 뽑힙니다. 단, 이 어절에는 이전 어절 형성 단계에서 복합명사가 있다는 표시를 해놓았습니다. 그래서 복합명사 전체인 떡볶이도 토큰으로 포함됩니다. → [ 떡, 떡볶이, 볶이] [참] 간단하게 참이 토큰으로 뽑힙니다. →[참] [잘하-, -는] 잘하-는 토큰에 포함되지만 -는은 포함되지 않습니다. 왜냐하면 실질적 형태소가 아니기 때문입니다. 실질적 형태소란 뜻(의미)를 가지는 형태소를 말하며, 어미인 -는은 뜻이 없기 때문에 토큰이 될 수 없습니다. 그러나 -는이 쓸모 없는 것은 아닙니다. 한 어절에 형태소가 여러 개인 경우, 항상 어절 전체가 하나의 토큰으로 포함됩니다. 여기서 어절 전체는 잘하는입니다. 어미 -는을 형태소 분석기로 뽑아낸 이유가 여기에 있습니다. → [잘하-,잘하는] [ 집 ] 간단하게 집이 토큰으로 뽑힙니다. →[집] 최종적으로 MeCabKoTokenizer의 토크나이징 결과는 아래와같습니다. [ 떡, 떡볶이, 볶이, 참, 잘하-, 잘하는, 집] 가장 간단하게 설명하기 위해 위처럼 1차원으로 표현했지만, 사실 이 Tokenizer의 결과는 1차원이 아닌 그래프구조입니다. 위 그래프가 무슨 의미인가 하면 문장의 시작(SOS) 지점에서 문장의 끝(EOS)까지의 모든 경로로 만들어지는 토큰 배열들이 해당 원문을 토크나이징 할 수 있는 모든 결과라는의미입니다. 위 그래프에서의 경로들로 만들어질 수 있는 모든 토큰 배열의 경우의 수는 다음과4가지입니다. 떡 + 볶이 + 참 + 잘하- +집 떡 + 볶이 + 참 + 잘하는 +집 떡볶이 + 참 + 잘하- +집 떢볶이 + 참 + 잘하는 +집 이러한 경우의 수가 나뉘는 이유는 토큰들 사이에 동의성(synonymy)이 있기 때문입니다. 떡볶이라는 하나의 덩어리 토큰은 떡과 볶이라는 두 개의 토큰과 동의 관계이며, 어간으로만 이루어진 잘하- 토큰과 어미까지 붙은 잘하는 토큰도 동의 관계에있습니다. 이러한 동의 관계의 토큰이 필요한 이유는 다음과 같습니다. 예를 들어, 떡과 볶이라는 복합명사의 부분 토큰까지 색인할 수 있으면, 사용자가 떡볶이뿐만 아니라 떡 또는 볶이만으로 검색해도 해당 가게가 검색 결과에 나타날 수 있습니다. 또한 잘하-를 색인하게 되면, 어간 잘하-로 시작하는 모든 어절들, 예를 들어 잘하려는, 잘할려는, 잘하겠는 등과 같은 키워드로도 검색이가능합니다. 물론, 이러한 동의 토큰이 항상 필요한 것은 아닙니다. 요기요 검색에서는 이러한 동형 토큰을 필요에 따라 추가하거나 제거하여 검색 품질을 높이고 있습니다. 예를 들어, 찜하다라는 키워드로 검색했을 때, 명사 찜과, -하다가 붙은 어절 찜하다가 동의 관계에 있기 때문에 찜을 파는 모든 가게가 검색 결과에 나오는 경우가있었습니다. 찜하다로 검색 시 모든 찜과 매칭되어 검색되어지는모습 그러나 찜하다라고 검색한 사용자의 의도는 찜하다-역삼점 같은 가게를 찾는다는 니즈가 거의 분명하기 때문에 찜하다 가게만 노출되는 것이 맞다고 판단하여, 찜하다 토큰만을 채택하도록 Tokenizer를 커스텀하여 검색의 정확성을높였습니다. 개선 후 찜하다가 존재하는 가게만 검색되어지는모습 이제 형태소분석기와 토크나이저의 차이를 충분히 이해할 수 있으실 겁니다. 요약하자면, 형태소분석기는 단순히 원문을 형태소 단위로 disjoint 하게 쪼개는 과정까지의 역할이고, 토크나이저는 이 과정을 포함하여, 적절히 합치거나 지우는 추가 작업을 하여 사용자의 의도에 맞는 토큰을만들어줍니다. Token-Filtering Analysis의 마지막 단계인 Token-Filtering는, 문자(열) 단위로 처리하던 Character-Filter와는 약간 다르게, 토큰의 단위로 처리가 이루어집니다. 왜냐하면 Tokenizing 단계를 거쳤기 때문에 이제는 모든 입력이 token 단위이기때문입니다. 가장 대표적인 token-filter는 동의어-필터(synonym-filter)입니다. 위 예시 떡볶이참잘하는집을 떡뽀끼로도 검색되게 하려면 떡뽀끼 토큰이 추가로 필요하게 됩니다. 이때 떡볶이와 떡뽀끼가 동의어 관계라고 동의어-필터에 등록을 해주면 떡뽀끼 토큰을추가해줍니다. 이렇게 동의어 처리를 하면 떡뽀끼로도 떡볶이를 검색할 수 있게됩니다. 이 밖에도 토큰을 결합해주는 Shingle-Filter, 각 토큰 내에서 n-gram 토큰을 뽑아주는 N-gram-Filter, 필요 없는 토큰을 제거해주는 Stop-Filter 등이 있습니다. 이러한 token-filter들은 사용자가 순서를 결정하여 여러 개를 순차적으로 적용할 수 있습니다. 다양한 token-filter가 있으니 검색 엔진들의 레퍼런스 문서를 참고하시면좋습니다. Filters Token filter reference | Elasticsearch Guide [8.13] | Elastic 마무리 이렇게 Analysis의 모든 과정을 거쳐 최종적으로 나오는 token들이 바로 검색에서 활용되는 term이 되는 것입니다. 오늘의 내용을 잘 이해하셨다면, 제목의 형태소 분석기 ≠ 토크나이저의 의미를 잘 캐치하셨을 것이라생각됩니다. 검색엔진의 Analysis 과정을 이해하지 못하면, “term들을 뽑아내는 것은 토크나이저이고 이는 형태소 분석기”라고 단순하게 생각하기 쉽습니다. 이러한 분들을 위해 오늘의 내용을 다음과 같이 요약할 수있습니다. 형태소 분석기 ⊆토크나이저 토큰은 tokenizing과 이후 단계에서 생성되는 입출력단위 term은 최종토큰 끝까지 정독해 주신 분들께 감사드리고, 다음에 검색엔진 Analysis와 관련된 이야기로, “요기요 검색에서 형태소분석기의 한계와 극복”에 대한 소재로 찾아뵙겠습니다. 검색엔진의 Analyzer, 형태소분석기 ≠ 토크나이저 was originally published in YOGIYO Tech Blog - 요기요 기술블로그 on Medium, where people are continuing the conversation by highlighting and responding to this story.

댓글 0

댓글을 작성하려면 로그인이 필요합니다.

댓글을 불러오는 중...