본문 바로가기

Lucene

Lucene 3.0 TokenStream과 AttributeSource. - 1 -

루씬이 버전업 되면서 바뀐 부분 중 하나가 이 부분인 것 같습니다.
이전에는 Tokenizer나 TokenFilter 클래스를 만들 때 TokenStream 클래스를 상속받아 만들고
이 TokenStream의 next 메서드를 사용해서 얻어지는 Token을 가지고
데코레이터 패턴으로 적용 된 Filter들이 Token을 처리하는 방식이었습니다.

예를 들어서,

Analyzer의 tokenStream 메서드가 위와 같이 정의되어 있다고 하고
분석해야 할 문장이 "검색엔진 개발자" 라고 했을 때
추출 되는 Token을 얻어내기 위해서 next 메서드를 실행했었습니다. 즉,


대략 위와 같은 방식이었죠.
next 메서드가 실행 되면 제일 상위의 Tokenizer에서 "검색엔진,(0,4)" 라는 Token을 만들어서 리턴하고
그것을 받아서 다음 Filter의 next 메서드에서 Token에서 원하는 작업을 하고
(뭐 검색엔진을 검색+엔진으로 분리하여 리턴한다던가..)
그 Token을 또 다음 Filter가 받아서 작업하는 방식이었습니다.

그런데 이번에 Analyzer를 lucene 3.0 버전으로 바꾸다보니
앞선 포스트에 잠깐 언급했던 것 처럼 이 가장 핵심이라고 할 수 있는
Token next() 메서드가 없어졌습니다. 그리고, boolean incrementToken() 이라는 메서드가 생겼습니다.
게다가 리턴타입이 boolean 입니다.

필터가 앞선 필터(즉, TokenStream)으로 부터 추출되는 Token을 받아야 자기 작업을 할텐데
리턴 타입이 boolean이니 이걸 어떻게 하라는건가 싶었습니다.

3.0 버전에서는 예전의 next() 메서드를 대신 전부 incrementToken() 메서드로 대체가 되었습니다.

그럼 3.0 버전에서는 어떻게 필터와 Tokenizer가 동작할까요..

이전버전에 있던 (3.0에도 있지만) Token 클래스는 문장을 나타내는 term과 위치정보를 나타내는 start/end offset
그리고 위치 이동에 대한 정보인 positionIncremental 또 Term의 타입을 지정 할 수 있는 Type을 그 속성으로 가지고 있었습니다.

이 속성들이 Attribute라는 클래스를 상속한 속성 클래스들로 전부 빠져나왔습니다.
즉,

이런식으로 ...
그래서, 이전에 Token에 넣어주던 정보들을 저 속성들에 넣어주게 됩니다.
그러면, 어떻게 각 필터와 Tokenizer가 저 값들을 공유하여 자신들의 작업 (동의어추출,stemming,복합명사 추출등)을
할 수 있는 것일까요..?

Lucene 3.0 (혹은 그 이전버전 부터인지..)에서는 TokenStream 클래스가 AttributeSource라는 클래스를 상속받고 있습니다.
AttributeSource는 내부적으로 Attribute들을 가지고 있고요.. 즉, 위에 나열된 저런 속성들을 가지고 있습니다.
결국 모든 필터들이 TokenStream을 상속받고 있기 때문에
저 AttributeSource를 사용해서 원하는 값들을 공유 할 수 있게 됩니다.

조금 자세하게 살펴보면
일반적으로 가장 앞단에서 Term을 잘라내는 Tokenizer를 살펴보면
생성자에서 아래와 같은 일을 하도록 정의 되어 있습니다.


addAttribute 메서드는 AttributeSource 클래스에 정의되어있는 메서드로
Attribute Class를 자기 속성에 add하고, 만약에 이미 있는 Attribute라면 그 Attribute를 return 하는 메서드입니다.
Tokenizer가 가장 앞단에서 실행 되므르 위 문장에 의해서 TermAttribute와 OffsetAttribute, TypeAttribute가 AttributeSource에
추가 될 것입니다.

그리고, 해당 Tokenizer가 incrementToken()메서드에서
읽어들인 문장에서 Term을 잘라내고나서는

해당 속성값을 Attribute에 넣어주고 true를 리턴하게 됩니다.

그렇게 되면 다음 필터에서는 저 AttributeSource의 Attribute들을 얻어 낼 수 있다면
앞에서 동작하는 Filter나 Tokenizer의 결과 값을 사용 할 수 있게 되는 것 입니다.

그럼 어떻게 얻어낼까요?

바로 addAttribute 혹은 getAttribute 메서드를 통해 얻어낼 수 있습니다.

 - 계속 -