Elasticsearch & MySQL Rivering & MeCab-Ko

Development / Elasticsearch / MySQL / MeCab-ko / MeCab / 은전한닢

사실 ES & MeCab-Ko 조합을 수없이 세팅했던 것 같은데, 이번에 새로 AWS로 이전하면서 새로 또 세팅을 해야해서.. 기왕 하는거 글로 남기면서 해볼까 한다. 세팅 다 끝나면 이미지 꼭 떠놔야지. (Docker로는 언제 하지..?)

  1. 나는 Ubuntu x64 환경이고, 딱히 빌드를 직접 하고픈 마음이 없기 때문에 패키지 관리자를 통해 설치를 할 예정이다. 단, 리버링을 위해 사용하고자 하는 elasticsearch-jdbc 플러그인이 ES 버전 의존성이 있기 때문에, 글을 쓰고 있는 2015년 10월 말 현재 지원 가능한 가장 최신 버전인 1.7.2를 설치하기로 한다. (서로 버전이 안맞으면 절대 리버링이 안된다!)

  2. 여기를 참고해서 패키지 관리자에 ES Repository를 추가한다. (기본 Ubuntu apt-get 레포에는 ES가 없다!)

    $ wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
    $ echo "deb http://packages.elastic.co/elasticsearch/1.7/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-1.7.list
    $ sudo apt-get update
    

    자 이제 우리가 원하는 1.7.2를 깔아보자.

    $ sudo apt-get install elasticsearch=1.7.2
    
  3. http://주소:9200/을 때리면 "You Know, for Search."가 반겨줄거라 생각했지만.. 아 깜빡했다. 자바를 안깔았다. ㅎㅎ.. ES에서는 Java8을 권장한다고 한다. 하지만 나는 OpenJDK6을 깔꺼다!

    $ sudo apt-get install default-jre
    $ sudo apt-get install default-jdk
    

    깔고 좀 기다리면(뭔가 초기 인덱싱 하는듯) http://주소:9200/에서 반가운 문구를 볼 수 있다. "You Know, for Search"

  4. 본 작업을 계속 진행하기 전에, 수월하게 ES를 다루기 위해 elasticsearch-HQ 플러그인을 깔자. 예전에는 head만 썼었는데, 보기 좋은 떡이 먹기도 좋다고.. 그냥 이뻐서 갈아탔다. 기능은 비슷비슷한 것 같다.

    $ cd /usr/share/elasticsearch/bin
    $ sudo ./plugin -install royrusso/elasticsearch-HQ
    

    http://주소:9200/_plugin/HQ/로 들어가면 확인할 수 있다.

  5. 좋다. 이제 다시 본론으로 돌아와, 먼저 한국어 형태소 분석기 부터 설치해보자. 우리가 설치할 플러그인은 은전한닢(MeCab-ko)이다. 먼저 엔진부터..

    $ sudo apt-get install gcc
    $ sudo apt-get install g++
    $ sudo apt-get install make
    
    
    $ wget https://bitbucket.org/eunjeon/mecab-ko/downloads/mecab-0.996-ko-0.9.2.tar.gz
    $ tar zxfv mecab-0.996-ko-0.9.2.tar.gz
    $ cd mecab-0.996-ko-0.9.2/
    $ ./configure
    $ make
    $ make check
    $ sudo make install
    
  6. 이제 MeCab-ko-dic(사전)을 설치해보자.

    $ wget https://bitbucket.org/eunjeon/mecab-ko-dic/downloads/mecab-ko-dic-2.0.1-20150920.tar.gz
    $ tar zxfv mecab-ko-dic-2.0.1-20150920.tar.gz
    $ cd mecab-ko-dic-2.0.1-20150920/
    $ ./configure
    $ make
    
    
    $ sudo apt-get install automake
    $ ./autogen.sh
    $ sudo ldconfig
    $ sudo make install
    

    mecab: error while loading shared libraries: libmecab.so.2: cannot open shared object file: No such file or directory이라는 괴상망측한 에러가 발생하면 꼭 중간에 sudo ldconfig를 해주기 바라며, make install 때에 뭔가 부족한데.. 싶으면 automake 설치와 ./autogen.sh를 해주면 말끔하게 해결된다.

    $ mecab -d /usr/local/lib/mecab/dic/mecab-ko-dic을 실행하여 아무 한국말이나 입력해서 분석이 잘 되면 은전한닢 설치 끝~

  7. 이제 자바로 만들어진 Elasticsearch에서 mecab-ko 플러그인을 사용하기 위해 라이브러리들을 설치해주자.

    $ wget https://bitbucket.org/eunjeon/mecab-java/downloads/mecab-java-0.996.tar.gz
    $ tar zxvf mecab-java-0.996.tar.gz
    $ cd mecab-java-0.996/
    

    이 때, vi MakeFile로 파일을 열어서, INCLUDE=/usr/lib/jvm/default-java/include로 고쳐준다. (Java 설치 환경마다 디렉토리가 다르니까!) 그리고 $(CXX) -O3 -c -fpic $(TARGET)_wrap.cxx $(INC)$(CXX) -O1 -c -fpic $(TARGET)_wrap.cxx $(INC)로 빌드 최적화 옵션을 고쳐준다.(우리가 OpenJDK를 설치한 댓가이다ㅎㅎ) 이후에 다시 빌드하고, 결과물을 복사한다.

    $ make
    $ sudo cp libMeCab.so /usr/local/lib
    $ sudo cp MeCab.jar /usr/local/lib
    
  8. 자 이제 막판! 실질적인 플러그인(mecab-ko-lucene-analyzer)을 설치해보자.

    $ wget https://bitbucket.org/eunjeon/mecab-ko-lucene-analyzer/downloads/elasticsearch-analysis-mecab-ko-0.17.0.zip
    $ cd /usr/share/elasticsearch/bin
    $ sudo ./plugin --install analysis-mecab-ko=0.17.0 --url file:///<아까파일받은디렉토리>/elasticsearch-analysis-mecab-ko-0.17.0.zip
    
  9. ES 설정에서 우리가 여태 실컷 설치한 라이브러리들을 참조할 수 있게 해주자. /etc/elasticsearch/elasticsearch.yml을 열어, 아무 줄이나 좋으니 java.library.path: /usr/local/lib를 추가해주자.

    /etc/init.d/elasticsearch를 열어

    DAEMON_OPTS="-d -p $PID_FILE --default.config=$CONF_FILE --default.path.home=$ES_HOME --default.path.logs=$LOG_DIR --default.path.data=$DATA_DIR --default.path.work=$WORK_DIR --default.path.conf=$CONF_DIR"
    

    부분을

    DAEMON_OPTS="-Djava.library.path=/usr/local/lib -d -p $PID_FILE --default.config=$CONF_FILE --default.path.home=$ES_HOME --default.path.logs=$LOG_DIR --default.path.data=$DATA_DIR --default.path.work=$WORK_DIR --default.path.conf=$CONF_DIR"
    

    로 바꿔주자. 우리는 세련되게(?) 데몬으로 실행시키니까.

  10. 설치 끝! 테스트를 해보자!! 테스트용 가짜 인덱스를 하나 만들고, 이 인덱스의 Analyzer, Tokenizer를 은전한닢으로 만들어 샘플을 하나 보내보는 것이다. (내 로컬 컴퓨터에서 해보면 된다.)

    $ ES='http://<ES가설치된서버주소>:9200'
    $ ESIDX='eunjeon_test'
    
    
    $ curl -XPUT $ES/$ESIDX/ -d '{
      "settings": {
        "index": {
          "analysis": {
            "analyzer": {
              "korean_index": {
                "type": "custom",
                "tokenizer": "mecab_ko_standard_tokenizer"
              },
              "korean_query": {
                "type": "custom",
                "tokenizer": "korean_query_tokenizer"
              }
            },
            "tokenizer": {
              "korean_query_tokenizer": {
                "type": "mecab_ko_standard_tokenizer",
                "compound_noun_min_length": 100
              }
            }
          }
        }
      }
    }'
    
    
    $ curl -XGET "$ES/$ESIDX/_analyze?analyzer=korean_query&amp;pretty" -d '아버지가방에들어가신다'
    

    은전한닢이 똑똑한건, '아버지가방에가방에들어가신다'에 대한 분석을 진짜 뜻인 '아버지가 방에 들어가신다'로 분석해주기 때문이라고 생각한다ㅎㅎ.. 다른 형태소 분석기들은 '아버지 가방에 들어가신다'의 느낌으로 분석해주는 경우가 많다고 들었다. 여튼..! 여기까지 했으면 ES와 MeCab-ko는 모두 설치가 완료된 것이다!! 이제 MySQL과 리버링을 해보자.

    여기까지 참고하면 좋은 문서들(은 내가 참고한 문서들) http://d2.naver.com/helloworld/273788
    http://develop.sunshiny.co.kr/1010
    http://guruble.com/?p=416

  11. 쓰다보니 글이 길어져가고 있다.. 헥헥. MySQL Rivering을 위해 elasticsearch-jdbc를 다운로드 받자. 예전에는 Elasticsearch에 Plug-in 형식으로 제공되었는데, 이제는 단일 Stand-alone 형식으로 제공되니 참고하면 좋다. (README도 안 읽고 예전 방식으로 하다가 삽질 엄청 했다.)

    $ wget http://xbib.org/repository/org/xbib/elasticsearch/importer/elasticsearch-jdbc/1.7.2.1/elasticsearch-jdbc-1.7.2.1-dist.zip
    $ unzip elasticsearch-jdbc-1.7.2.1-dist.zip 
    

    다음은 Mysql Connector/J를 까는것. 하지만 친절하게도 아까 받은 zip 파일 내부에 JAVA용 MySQL Connector JAR 파일이 들어있으므로 패스해도 좋다. 만약 최신 버전이 필요하다면 여기서 다운로드 받은 뒤, jar 파일을 lib 디렉토리 안에 두면 된다.

  12. 실제 리버링을 하기 위해 bin디렉토리 안에 예제 쉘 스크립트들을 보자. 리버링을 위한 상세한 Query Option들은 내가 여기서 주구장창 설명하는 것 보다 RTFM하는 것이 좋을 것 같다ㅎ.ㅎ.. 여기서 중요한 점은, 인덱스 생성시에 아까 우리가 설정한 은전한닢 Tokenizer를 잊지 말아야한다는 것이다. (열심히 깔아놓고는 나중에 질의 할 때 오잉 왜 한국어가 인덱싱이 안되어있지? 하는 경우가 종종 있다.) PUT으로 보내는 JSON 데이터(jdbc의 경우 index_settings->index) 안에

            "analysis": {
              "analyzer": {
                "korean_index": {
                  "type": "custom",
                  "tokenizer": "mecab_ko_standard_tokenizer"
                },
                "korean_query": {
                  "type": "custom",
                  "tokenizer": "korean_query_tokenizer"
                }
              },
              "tokenizer": {
                "korean_query_tokenizer": {
                  "type": "mecab_ko_standard_tokenizer",
                  "compound_noun_min_length": 100
                }
              }
            }
    

    그리고

    "type_mapping": {
        "<TYPE명>":{
            "_all": {
                "analyzer": "korean_index"
            }
        }
    }
    

    를 꼭 같이 담아서 보내자.

    검색할 때에도 query_string 객체 안에 {"analyzer": "korean_query"}를 담거나, URL Parameter에 http://<주소>:9200/<INDEX>/_search?q=<검색어>&analyzer=korean_query와 같이 꼭 analyzer를 명시해서 검색할 수 있도록 하자.

  13. 짠! 이제 HQ로 돌아가(혹은 curl 등으로) 실제 쿼리를 날려서 확인해보면 리버링이 순식간에 잘 되었음을 알 수 있다. 나 같은 경우에는 성능 이슈를 위해, is_rivered 컬럼을 만들어놓고, 리버링 된 데이터를 마킹하고 있다. (무결성 따위..)

자 이제 이미지 떰프뜨자!! (글 다 쓰고 Publish 하려니 고새 Elasticsearch 2.0 GA 버전이 릴리즈 되었다고 한다..ㅎㅎㅎ 것 참..)

Share on : Twitter, Facebook or Google+