본문 바로가기

Lucene

[about Lucene] 루씬으로 검색엔진 개발하기 - Analyzer (1) -

앞에 데모 프로그램을 보셔서 아시겠지만
검색이라는 하나의 작업을 위해서는 
크게 색인과 검색이라는 2가지 프로세스를 거쳐야 합니다.

이중 색인과 검색에 모두 관여하는 것이 하나 있는데
그것이 바로 키워드 추출.. 즉, 흔히 이야기하는(하지만 너무나 어려운)
형태소분석입니다. (이후에는 키워드 추출이라고 하도록 하겠습니다.)

잠깐 루씬을 떠나서
검색이론에 대해서 이야기 해 보겠습니다.

흔히 검색에서 이야기하는 색인 파일은 대부분 "역색인(Inverted Index)" 구조로 되어있습니다.

이게 어떤 구조인가하면.... 책의 맨 뒤 부록에 나오는
"단어"를 기준으로 페이지를 나열한 형태의 색인 구조라고 보시면 됩니다.

나이키 - Doc1, Doc2, Doc3
운동화 - Doc1, Doc5
청바지 - Doc6, Doc7


이런식으로 키워드를 기준으로 그 키워드가 포함된 문서들을
정의해 놓은 형태입니다.

"나이키"라는 검색어가 들어오면 Doc1, Doc2, Doc3을 찾아서 화면에
보여주는 것이지요.

"나이키와 운동화"라는 검색어가 들어오면
"나이키"에 연결된 Doc1, Doc2, Doc3
"운동화"에 연결된 Doc1, Doc5 를 찾아서
And 연산으로 Doc1을 찾아서 결과로 보여주는 구조입니다.

Doc1, Doc2, Doc3
&
Doc1, Doc5
= Doc1 


물론 재검색의 Boolean 조건이 OR라면 Doc1, Doc2, Doc3, Doc5가 전부 보여질 것 입니다.

보시면 아시겠지만 "키워드" 기반의 검색에 최적화 된 구조라고 볼 수 있습니다.

이러한 색인구조에는 미리 스코어를 지정 해 둘 수
없는 구조이기 때문에 Ranking이 그만큼 중요해지는 구조이기도 합니다.

그리고, 위의 예만 보시더라도
Doc1~Doc7까지의 문서에서 나이키, 운동화, 청바지등 사용자들에게
혹은 비지니스안에서 의미가 있는 키워드를 추출해내는 것과
사용자가 입력한 키워드인 "나이키와 운동화"에서 "나이키", "운동화"를 추출해내는 것이
얼마나 중요한 작업인가도 알 수 있습니다.

이 키워드가 추출되지 않으면
검색을 할 수가 없는 것 입니다.

이것이 검색에 있어서 키워드 추출(형태소 분석)이고
이 역할을 해주는 것이 루씬의 Analyzer입니다.

사실 루씬으로 검색엔진을 만든다고 할 때
가장 먼저 부딫히게 되는 장벽이 바로 이 Analyzer의 구현이고
또 가장 어려운 부분중에 하나가 역시 이 Analyzer입니다.

검색이라는 그 행동 자체는
어디서나 동일하겠지만 (랭킹의 구현은 다르겠지요..) 키워드 추출이라는 것은
나라별로, 언어별로 심지어 비지니스(1)별로 원하는 추출 방식이 모두 다르고, 추출해야하는
방법도 모두 다르기 때문입니다.

본격적으로 들어가기전에 키워드 추출에 대해서 조금 더 살펴보도록 하겠습니다.

초반에는 문장에서 (혹은 웹 페이지에서) 의미있는 키워드라는 것이 대부분 "명사"에 한정되는 구조였습니다.
전반적으로 색인 대상이 되는 문서가 많지 않았기 때문에 문장에 들어있는 중요한 명사들만
추출해서 색인을 해도 큰 문제가 없었울 것 입니다.

하지만 요즘에는 이렇게 명사만을 추출하는 것은 
큰 의미가 없을 것 같습니다.(2)

"사랑합니다"라는 노래를 찾아보기 위해 구글에서 "사랑"이라는 키워드로 검색을 해보세요.

"사랑"이 들어간 무수한 페이지들이 나올 것 입니다. 정말로 내가 원하는 것을 찾기 위해서는
"사랑"이라는 단어 하나만으로는 많이 부족합니다. 

최근에는 단순히 키워드만을 추출하는 것이 아닌, 점점 자연어에 근접한 키워드로 검색이 가능하도록
해주는 것이 중요해지고 있습니다. 물론 이러한 수준까지 이번 프로젝트(?)를 통해서
구현하지는 못 할 것 입니다. 사실 형태소 분석도 구현하기가 아주 어려워요..--;
참고로 이수명님께서 만드신 루씬용 형태소 분석기가 있습니다.

이번에는 미리 만들어진 사전을 기반으로 하여
문장과 입력된 키워드로부터 단어를 추출하는 수준으로
구현을 해 볼 예정입니다.

그리고 또 하나는 색인 할 때의 키워드 추출과 검색어로 들어온 키워드를 분석 할 때에는
약간의 차이가 있어야 한다는 것 입니다.

Doc1 : "삼성은 우리나라에서 가장 큰 기업이다. 전자부문을 비롯하여...." 
Doc2 : "삼성전자는 이번에 갤럭시S를 발표하였다."


라는 두개의 문장이 있다고 가정을 해보겠습니다.

Doc1에서의 키워드는 "삼성" , "우리나라" , "기업", "전자", "부문", "전자부문" 등이..
Doc2에서의 키워드는 "삼성" , "전자", "삼성전자", "갤럭시S", "발표" 등이 나온다고 볼 수 있을 것 입니다.

이렇게 색인이 되어 있는 상태에서
한명의 사용자가 검색어로 "삼성전자"를 입력하였습니다.

위 문장에서 키워드가 추출된 결과를 참고해보면 "삼성전자"로부터 "삼성"+"전자"
추출이 되는 것이라고 생각해 볼 수 있습니다.
그렇다면, 사용자가 "삼성전자"와 관련된 문서를 찾고 싶어서 입력 한 검색어를 "삼성""전자"
분석하여 검색이 되도록 해야 할까요? 그렇다면 Doc1과 Doc2과 모두 검색이 될 것 입니다.

하지만, Doc1은 사실 삼성전자와는 별 관련이 없는 글입니다.

오히려 사용자가 입력한 "삼성전자"라는 검색어를 특별히 분석하지 않고
그대로 검색이 되도록 한다면 Doc2만이 검색이 될 것이고 이것이 더 좋은
결과 값이라고 생각이 될 수도 있습니다.

사실 이러한 부분은 recall(재현율)과 precision(정확도) 중 어느 곳에
더 비중을 두느냐 혹은 위와 같은 상황에서 아예 Doc1을 검색 결과에서 제외를 시킬 것이냐
Ranking으로 해결 할 것이냐등에 따라서 정답이 없는 이야기이지만
키워드 추출이라는 것이 단어를 무조건 많이 추출한다는 것이
답은 아니라는 것을 보여드리기 위해서 언급을 해보았습니다.

이번에 직접 구현 할 Analyzer에서는 위 기준에 맞춰서
색인용과 검색어 분석용으로 나누어 구현을 할 예정입니다.

작성을 하고 이번 포스트를 마무리 하려고 하니..
이번 내용에서는 루씬에 대해서는 전혀 내용이 없네요..--;

하지만 검색 엔진을 만든다고하면 반드시 꼭 집고 넘어가야 하는
부분이기도 합니다. 최근의 검색 엔진들은 자연어 검색도 지원해주고 있기 때문에
여기서 이야기된 많은 부분들은 이미 검색엔진이 태동 될 초창기때
모두 한번씩은 언급이 되었던 내용들이라고 생각합니다.

하지만 뒤따라가는 입장에서
이미 지나간 이슈라고 그냥 넘어 갈 수는 없겠죠..^^

다음 포스트에서 
루씬에서 구현되어 있는 Analyzer의 구조와 가장 간단한 Analyzer하나를 뜯어보고
이를 바탕으로 저희만의 "사전기반의 명사 추출" Analyzer를 
만들어 나가보도록 하겠습니다.

하루써서 하루 올리는 입장이라서
글 올라오는 속도가 매우 들쑥날쑥 할 것 같습니다. 보통 애 재우고나야 
앉아서 뭘 쓸 시간이 생겨서요...ㅎㅎ

이해부탁드릴게요..^^

그리고 저도 검색/루씬 초짜입니다. 또 구현된 소스를
보시다보면 구현 자체에 문제가 있을 수도 있습니다.

내용 중 오류나 잘못된 부분들이 있으면
언제든 말씀해주세요.

감사합니다.

(1) - 쇼핑몰에서의 키워드 추출과 포털에서의 키워드 추출이 완전히 같을 수는 없을 것 입니다.
(2) - 쇼핑몰등에서는 조금 다릅니다. 명사/모델명등 단어만 추출하는 것이 충분히 의미가 있을 수 있습니다. 
(3) - 이 카페에 가시면 관련 내용들을 보실 수 있습니다.