'Elastic/Elasticsearch'에 해당되는 글 385건

  1. 2013.02.01 Elasticsearch Build Case by NHN
  2. 2013.01.24 루씬 한국어형태소 분석기 lucene-core 3.2 에서 3.6 으로..
  3. 2013.01.23 루씬 2.4.3 Field options for term vectors
  4. 2013.01.23 루씬 한글형태소 분석기 로컬 테스트
  5. 2013.01.23 lucene kr analyzer flow
  6. 2013.01.22 lucene 튜토리얼
  7. 2013.01.22 elasticsearch 한국어 형태소분석기 분석의 이해 2
  8. 2013.01.22 stopwords, thesaurus ... 등등
  9. 2013.01.22 루씬 한국어 형태소 분석기 사전 구성 및 팁.
  10. 2013.01.22 한글 stopwords

Elasticsearch Build Case by NHN

Elastic/Elasticsearch 2013. 2. 1. 13:41

other tips

[How do i configure the routing]

        "routing" : {

            "required" : true,

            "path" : "indexType.user_uniq_id"

        }

[How do i configure the compression]

            "store" : {

                "compress" : {

                    "stored" : true,

                    "tv" : true

                }

            }

[How do i configure the customized analyzer]

            "analysis" : {

                "analyzer" : {

                    "kr_analyzer" : {

                        "type" : "custom",

                        "tokenizer" : "kr_tokenizer",

                        "filter" : ["trim", "kr_filter", "kr_synonym"]

                    },

                    "kr_analyzer" : {

                        "type" : "custom",

                        "tokenizer" : "kr_tokenizer",

                        "filter" : ["trim", "kr_filter", "kr_synonym"]

                    }

                },

                "filter" : {

                    "kr_synonym" : {

                        "type" : "synonym",

                        "synonyms_path" : "analysis/synonym.txt"

                    }

                }

            }

        }


[How do i disable the _all field]
    You can add some parameter.

    like this : {"include_in_all" : false}

[Fully Configurations]

curl -XPUT 'http://localhost:9200/index0' -d '{

    "settings" : {

        "number_of_shards" : 50,

        "number_of_replicas" : 1,

        "index" : {

            "refresh_interval" : "60s",

            "term_index_interval" : "1",

            "store" : {

                "compress" : {

                    "stored" : true,

                    "tv" : true

                }

            },

            "analysis" : {

                "analyzer" : {

                    "kr_analyzer" : {

                        "type" : "custom",

                        "tokenizer" : "kr_tokenizer",

                        "filter" : ["trim", "kr_filter", "kr_synonym"]

                    },

                    "kr_analyzer" : {

                        "type" : "custom",

                        "tokenizer" : "kr_tokenizer",

                        "filter" : ["trim", "kr_filter", "kr_synonym"]

                    }

                },

                "filter" : {

                    "kr_synonym" : {

                        "type" : "synonym",

                        "synonyms_path" : "analysis/synonym.txt"

                    }

                }

            }

        },

        "routing" : {

            "required" : true,

            "path" : "indexType.user_uniq_id"

        }

    },

    "mappings" : {

        "indexType" : {

            "properties" : {

                "docid" : { "type" : "string", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },

                "rm_seq" : { "type" : "long", "store" : "yes", "index" : "no", "include_in_all" : false },

                "rm_join_seq" : { "type" : "long", "store" : "yes", "index" : "no", "include_in_all" : false },

                "rm_title" : { "type" : "string", "store" : "yes", "index" : "analyzed", "term_vector" : "yes", "analyzer" : "kr_analyzer", "include_in_all" : false },

                "user_uniq_id" : { "type" : "string", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },

                "mb_nm" : { "type" : "string", "store" : "yes", "index" : "analyzed", "term_vector" : "yes", "analyzer" : "kr_analyzer", "include_in_all" : false },

                "mb_count" : { "type" : "integer", "store" : "yes", "index" : "no", "include_in_all" : false },

                "rm_ymdt" : { "type" : "date", "format" : "yyyyMMddHHmmss", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },

                "data_size" : { "type" : "long", "store" : "yes", "index" : "no", "include_in_all" : false },

                "msgs" : {

                    "properties" : {

                        "msg_seq" : { "type" : "long", "store" : "no", "index" : "no", "include_in_all" : false },

                        "msg" : { "type" : "string", "store" : "yes", "index" : "analyzed", "term_vector" : "yes", "analyzer" : "kr_analyzer", "include_in_all" : false },

                        "send_user_uniq_id" : { "type" : "string", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },

                        "send_user_nick_nm" : { "type" : "string", "store" : "yes", "index" : "not_analyzed", "term_vector" : "yes", "analyzer" : "kr_analyzer", "include_in_all" : false },

                        "recv_ymdt" : { "type" : "date", "format" : "yyyyMMddHHmmss", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },

                        "cfn_yn" : { "type" : "string", "store" : "no", "index" : "no", "include_in_all" : false },

                        "send_yn" : { "type" : "string", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false },

                        "msg_type" : { "type" : "integer", "store" : "yes", "index" : "not_analyzed", "include_in_all" : false }

                    }

                }

            }

        }

    }

}'


Original article is 
        http://helloworld.naver.com/helloworld/273788


NHN Business Platform 글로벌플래폼개발랩 이재익

elasticsearch는 Shay Banon이 Lucene을 바탕으로 개발한 분산 검색엔진입니다. 설치와 서버 확장이 매우 편리하기 때문에 개발하고 있는 시스템에 검색 기능이 필요하다면 elasticsearch를 적용하는 것을 권장하고 싶습니다. 분산 시스템이기 때문에 검색 대상 용량이 증가했을 때 대응하기가 무척 수월하다는 것이 장점입니다.

이 글에서는 참고 자료의 내용을 바탕으로 기본적인 elasticsearch의 설치와 사용법을 설명하고, 실제 서비스에 적용할 때 고려해야 할 사항을 정리했습니다.

elasticsearch의 특징

우선 관계형 데이터베이스에 익숙한 사람들을 위해 관계형 데이터베이스와 elasticsearch의 용어를 비교한 표를 참고 자료에서 인용했다.

표 1 관계형 데이터베이스와 elasticsearch 용어 비교

관계형 데이터베이스

elasticsearch

Database

Index

Table

Type

Row

Document

Column

Field

Schema

Mapping

Index

Everything is indexed

SQL

Query DSL

JSON 기반의 스키마 없는 저장소

elasticsearch는 검색엔진이지만, NoSQL처럼 사용할 수 있다. 데이터 모델을 JSON으로 사용하고 있어서, 요청과 응답을 모두 JSON 문서로 주고받고 소스 저장도 JSON 형태로 저장한다. 스키마를 미리 정의하지 않아도, JSON 문서를 넘겨주면 자동으로 인덱싱한다. 숫자나 날짜 등의 타입은 자동으로 매핑한다.

Multi-tenancy

elasticsearch는 multit-enancy를 지원한다. 하나의 elasticsearch 서버에 여러 인덱스를 저장하고, 여러 인덱스의 데이터를 하나의 쿼리로 검색할 수 있다. <예제 1>의 경우 날짜별로 인덱스를 분리해 로그를 저장하고 있고, 검색 시에는 검색 범위에 있는 날짜의 인덱스를 하나의 쿼리로 요청하고 있다.

예제 1 Multi-tenency 예제 쿼리

# log-2012-12-26 인덱스에 로그 저장
curl -XPUT http://localhost:9200/log-2012-12-26/hadoop/1 -d '{
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-26T14:12:12",
"host": host1",
"body": "org.apache.hadoop.hdfs.StateChange: DIR* NameSystem.completeFile"
}'

# log-2012-12-27 인덱스에 로그 저장
curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1 -d '{
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}'

# log-2012-12-26, log-2012-12-27 인덱스에 한번에 검색 요청
curl -XGET http://localhost:9200/ log-2012-12-26, log-2012-12-27/_search

확장성과 유연성

elasticsearch는 확장성과 유연성이 매우 뛰어나다. 플러그인을 이용해 기능을 확장할 수 있다. 예를 들어 Thrift 플러그인이나 Jetty 플러그인을 사용하면 전송 프로토콜을 변경할 수 있다. 필수 플러그인이라고 할 수 있는 BigDesk나 Head를 설치하면 elasticsearh 모니터링 기능을 사용할 수 있게 된다. <예제 2>에서 보는 것처럼 동적으로 복제본 개수를 조정할 수도 있다. 다만 샤드 수는 인덱스별로 고정돼 있어 수정이 불가능하므로 노드 수와 향후 서버 확장을 고려해 초기에 적절한 수를 할당해야 한다.

예제 2 설정 변경 쿼리

$ curl -XPUT http://localhost:9200/log-2012-12-27/ -d '{
"settings" : {
"number_of_shards" : 10,
"number_of_replicas" : 1
}
}'

분산 저장소

elasticsearch는 분산 검색엔진이다. 키에 따라 여러 샤드가 구성되는 방식으로 데이터를 분산한다. 인덱스는 각각의 샤드마다 구성된다. 각각의 샤드는 0개 이상의 복제본을 가진다. elasticsearch는 클러스터링을 지원하며 클러스터가 가동될 때 여러 노드 중 하나가 메타데이터 관리를 위한 마스터 노드로 선출된다. 마스터 노드가 다운되면 자동으로 클러스터 내의 다른 노드가 마스터가 된다. 노드 추가 또한 매우 간단하다. 같은 네트워크에 노드를 추가하는 경우 추가된 노드가 멀티캐스트를 이용해 자동으로 클러스터를 찾아 자신을 추가한다. 같은 네트워크를 이용하지 않을 경우 유니캐스트로 마스터 노드의 주소를 명시해 주어야 한다(참고 영상:http://youtu.be/l4ReamjCxHo).

설치하기

Quick Start

elasticsearch는 무설정 설치가 가능하다. <예제 3>에서 볼 수 있는 것 처럼 공식 홈페이지에서 파일을 내려 받아 압축을 해제하기만 하면 바로 실행해 볼 수 있다.

  1. 다운로드

$ wget http://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-0.20.4.tar.gz
$ tar xvzf elasticsearch-0.20.4.tar.gz

  1. 서버 실행

예제 3 설치 및 실행 명령

$ bin/elasticsearch -f

플러그인 설치

elasticsearch는 플러그인을 통해 쉽게 기능을 확장할 수 있다. 관리 기능을 추가하거나 Lucene의 Analyzer를 변경하고 기본 전송 모듈을 Netty에서 Jetty로 변경하는 것도 가능하다. <예제 4>는 플러그인을 설치하기 위한 명령어다. <예제 4>의 첫 번째와 두 번째 줄에서 보이는 'head'와 'bigdesk'는 elasticsearch 모니터링을 위한 필수 플러그인이므로 꼭 설치해서 기능을 확인해 보도록 하자. 설치 후 http://localhost:9200/plugin/head/http://localhost:9200/plugin/bigdesk/로 접속하면 웹 브라우저를 이용해 상태를 확인해 볼 수 있다.

예제 4 플러그인 설치

bin/plugin -install Aconex/elasticsearch -head
bin/plugin -install lukas-vlcek/bigdesk
bin/plugin -install elasticsearch/elasticsearch-transport-thrift/1.4.0
bin/plugin -url https://oss-es-plugins.s3.amazonaws.com/elasticsearch-jetty/elasticsearch-jetty-0.20.1.zip -install elasticsearch-jetty-0.20.1

주요 설정

간단한 기능 테스트에는 설정 변경이 필요 없으나, 성능 테스트를 하거나 실서비스에 적용할 때에는 기본 설정에 대한 몇 가지 변경이 필요하다. <예제 5>를 참고하면 초기 설정 파일(elasticsearch.yml)에서 변경해야 할 설정 내용이 무엇인지 알 수 있다.

예제 5 주요 설정(config/elasticsearch.yml)

# 클러스터를 식별하기 위한 이름이므로 유일성과 의미를 가진 이름을 사용하자
cluster.name: es-cluster

# 노드 이름은 자동으로 생성되지만 호스트명과 같이 클러스터 내에서 식별 가능한 이름을 활용하는 것이 좋다.
node.name: "es-node1"

# 기본값은 아래 두 값이 모두 true다. node.master는 노드가 마스터가 될 수 있지에 대한 설정이고, node.data는 데이터를 저장하는 노드인지에 대한 설정이다. 보통은 두 값을 true로 설정하면 되고, 클러스터의 규모가 큰 경우에는 3가지 종류의 노드를 구성하기 위해 이 값을 노드별로 조정해 설정한다. 자세한 사항은 토폴로지(topology) 설정에서 다시 설명하겠다.
node.master: true
node.data: true

# 샤드와 리플리카 수를 변경하는 설정이다. 아래 값은 기본값이다.
index.number_of_shards: 5
index.number_of_replicas: 1



#JVM의 스왑을 방지하려면 아래 설정 값을 true로 한다.
bootstrap.mlockall: true

# 클러스터 내의 각 노드의 상태 체크를 위한 타임아웃 값으로, 너무 작게 하면 노드가 클러스터에서 자주 이탈하는 문제가 발생할 수 있어 적절한 값을 설정한다. 기본값은 3초다.
discovery.zen.ping.timeout: 10s

# 기본값은 멀티캐스트를 사용하지만, 실환경에서는 다른 클러스터와 노드가 섞이는 위험이 발생할 수 있으므로 유니캐스트를 사용하고 두 번째 설정 값에 마스터가 될 수 있는 서버들의 목록을 나열하는 것이 좋다.
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]

REST API 사용하기

elasticsearch는 <예제 6>과 같은 형식의 REST API를 제공한다. 인덱스 생성과 삭제, 매핑 생성과 삭제, 검색, 설정 변경 등 대부분의 기능을 REST API를 통해 제공한다. REST API 이외에도 Java, Python, Ruby 등의 언어별 클라이언트도 제공하고 있다.

예제 6 REST API 형식

http://host:port/(index)/(type)/(action|id)

<예제 7>의 경우 날짜별로 인덱스를 분리하고, 프로젝트별로 타입을 나누어 관리하고 있다. 2012년 12월 27일에 hadoop이라는 프로젝트로 들어온 로그를 문서 단위로 생성하는 과정을 REST API를 사용해 수행하는 예다.

예제 7 REST API 사용 예

#문서 생성
curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1
curl -XGET http://localhost:9200/log-2012-12-27/hadoop/1
curl -XDELETE http://localhost:9200/log-2012-12-27/hadoop/1

#검색
curl -XGET http://localhost:9200/log-2012-12-27/hadoop/_search
curl -XGET http://localhost:9200/log-2012-12-27/_search
curl -XGET http://localhost:9200/_search

#인덱스 상태 보기
curl -XGET http://localhost:9200/log-2012-12-27/_status

문서와 인덱스 생성

<예제 8>에서처럼 요청을 보내면 인덱스와 타입이 정의돼 있지 않더라도 elasticsearch는 자동으로 log-2012-12-27 인덱스와 hadoop 타입을 생성한다. 자동으로 생성하지 않고 명시적으로 생성하려면 설정 파일에서 action.auto_create_index와 index.mapper.dynamic의 설정 값을 false로 명시해야 한다.

예제 8 문서 생성

# 요청
curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1 -d '{
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2 ",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}'

# 결과
{
"ok" : true,
"_index" : "log-2012-12-27",
"_type" : "hadoop",
"_id" : "1",
"_version" : 1
}

<예제 9>에서 보는 것처럼 타입을 문서에 포함해 요청할 수 있다.

예제 9 타입을 포함한 쿼리

curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1 -d '{
"hadoop" : {
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2 ",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}
}'

<예제 10>과 같이 ID 값을 생략하면 자동으로 ID를 생성하고 문서를 만든다. 요청 시 PUT 대신 POST 방식을 사용한 것에 주의하자.

예제 10 ID 없는 문서 생성 쿼리

# 요청
curl -XPOST http://localhost:9200/log-2012-12-27/hadoop/ -d '{
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2 ",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}'

# 결과
{
"ok" : true,
"_index" : "log-2012-12-27",
"_type" : "hadoop",
"_id" : "kgfrarduRk2bKhzrtR-zhQ",
"_version" : 1
}

문서 삭제

<예제 11>은 문서를 삭제하는 방법을 보여 주고 있다. DELETE 메서드를 사용해 log-2012-12-27 인덱스에서 타입이 hadoop이고 ID가 1인 문서를 삭제한다.

예제 11 문서 삭제 쿼리

# 요청
$ curl -XDELETE 'http://localhost:9200/log-2012-12-27/hadoop/1'

# 결과
{
"ok" : true,
"_index" : "log-2012-12-27",
"_type" : "hadoop",
"_id" : "1",
"found" : true
}

문서 가져오기

<예제 12>와 같이 GET 메서드를 사용하면 log-2012-12-27 인덱스에서 타입이 hadoop이고 ID가 1인 문서를 가져올 수 있다.

예제 12 문서를 가져오기 위한 쿼리

#요청
curl -XGET 'http://localhost:9200/log-2012-12-27/hadoop/1'

# 결과
{
"_index" : "log-2012-12-27",
"_type" : "hadoop",
"_id" : "1",
"_source" : {
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2 ",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}
}

검색

검색 API를 호출하면 elasticsearch는 검색 API를 실행한 후 질의 내용과 일치하는 검색 결과를 반환한다. <예제 13>에서 검색 API를 사용하는 예제를 볼 수 있다.

예제 13 검색 API 사용 예제 쿼리

# 특정 인덱스의 모든 타입
$ curl -XGET 'http://localhost:9200/log-2012-12-27/_search?q=host:host2'

# 특정 인덱스의 특정 타입
$ curl -XGET 'http://localhost:9200/log-2012-12-27/hadoop,apache/_search?q=host:host2'

# 모든 인덱스의 특정 타입
$ $ curl - XGET 'http://localhost:9200/_all/hadoop/_search?q=host:host2'

# 모든 인덱스와 타입
$ curl -XGET 'http://localhost:9200/_search?q=host:host2'

URI 요청을 사용한 검색 API

URI를 사용하면 <표 2>의 파라미터와 쿼리 스트링(Query String)으로 간단하게 검색할 수 있다. 모든 검색 옵션을 제공하지는 않으므로 주로 테스트 용도로 간편하게 사용할 때 유용하다.

표 2 주요 파라미터들

이름

설명

q

쿼리 스트링

default_operator

기본으로 사용할 연산자(AND 혹은 OR). 기본값은 OR.

fields

결과로 가져올 필드. 기본값은 '_source' 필드.

sort

정렬 방법(예: fieldName:asc/fieldName:desc)

timeout

검색 수행 타임아웃 값. 기본값은 무제한.

size

결과 값의 개수. 기본값은 10.

예제 14 URI 요청을 사용한 검색 쿼리

# 요청
$ curl -XGET 'http://localhost:9200/log-2012-12-27/hadoop/_search?q=host:host2'

# 결과
{
"_shards":{
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits":{
"total" : 1,
"hits" : [
{
"_index" : "log-2012-12-27",
"_type" : "hadoop",
"_id" : "1",
"_source" : {
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}
}
]
}
}

요청 바디(Request Body)를 사용한 검색 API

HTTP 바디를 사용할 경우 Query DSL을 사용해서 검색한다. Query DSL은 내용이 방대하므로 공식 사이트의 가이드 문서(http://www.elasticsearch.org/guide/reference/query-dsl/)를 참고하도록 하자.

예제 15 Query DSL을 사용한 검색

# 요청
$ curl -XPOST 'http://localhost:9200/log-2012-12-27/hadoop/_search' -d '{
"query" : {
"term" : { "host" : "host2" }
}
}
'

# 결과
{
"_shards":{
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits":{
"total" : 1,
"hits" : [
{
"_index" : "log-2012-12-27",
"_type" : "hadoop",
"_id" : "1",
"_source" : {
"projectName" : "hadoop",
"logType": "hadoop-log",
"logSource": "namenode",
"logTime":"2012-12-27T02:02:02",
"host": "host2",
"body": "org.apache.hadoop.hdfs.server.namenode.FSNamesystem"
}
}
]
}
}

Mapping

Put Mapping API

특정 타입에 매핑을 추가하려면 <예제 16>과 같은 형태로 정의할 수 있다.

예제 16 매핑을 등록하기 위한 쿼리

$ curl -XPUT 'http://localhost:9200/log-2012-12-27/hadoop/_mapping' -d '
{
"hadoop" : {
"properties" : {
"projectName" : {"type" : "string", "index" : "not_analyzed"},
"logType" : {"type" : "string", "index" : "not_analyzed"},
"logSource" : {"type" : "string", "index" : "not_analyzed"},
"logTime" : {"type" : "date"},
"host" : {"type" : "string", "index" : "not_analyzed"},
"body" : {"type" : "string"},
}
}
}
'

Get Mapping API

정의한 매핑 정보를 얻기 위해서 <예제 17>과 같은 형태의 쿼리를 사용할 수 있다.

예제 17 매핑을 얻어오기 위한 쿼리

$ curl -XGET 'http://localhost:9200/log-2012-12-27/hadoop/_mapping'

Delete Mapping API

<예제 18>은 정의한 매핑을 삭제하는 예다.

예제 18 매핑을 삭제하기 위한 쿼리

$ curl -XDELETE 'http://localhost:9200/log-2012-12-27/hadoop'

성능 최적화 팁

메모리와 오픈 파일 수

검색할 데이터가 많아질수록 많은 메모리가 필요하다. elasticsearch를 운영하다 보면 메모리 사용으로 인한 문제를 많이 겪게 된다. elasticsearch 커뮤니티에서 권장하는 운영 방법에 따르면, elasticsearch 전용 서버를 운영할 때는 메모리 용량의 절반만 elasticsearch에 할당하고, 나머지 메모리 용량은 운영체제가 시스템 캐시 목적으로 사용할 수 있도록 하는 것이 좋다. 메모리 크기는 ES_HEAP_SIZE 환경 변수를 설정하거나 JVM의 -Xms와 -Xmx 값을 사용해서 설정할 수 있다.

예제 19 힙 크기를 지정해 실행

bin/ElasticSearch -Xmx=2G -Xms=2G

elasticsearch를 사용할 때는 OOME(Out Of Memory Error)가 발생하는 경우가 많다. 필드 캐시가 최대 힙 크기를 넘어서면서 발생하는데, index.cache.field.type 설정을 기본값인 resident 대신 soft로 설정하면 soft 레퍼런스를 활용하므로 캐시 영역에 대해 우선 가비지 컬렉션(Garbage Collection)을 실행해 문제를 해결할 수 있다.

예제 20 필드 캐시 타입 설정

index.cache.field.type: soft

데이터가 많아지면 인덱스 파일 개수 또한 증가하게 된다. elasticsearch가 사용하고 있는 Lucene에서 인덱스를 세그먼트 단위로 관리하기 때문이다. 경우에 따라 MAX_OPEN 파일 개수를 넘어서는 일도 발생한다. ulimit 명령으로 최대 오픈 파일 제한을 변경해야 한다. 권장되는 값은 32000~64000이지만, 시스템 규모나 데이터의 양에 따라 더 큰 값으로 설정해야 할 수도 있다.

인덱스 최적화

날짜별로 인덱스를 관리하면 <예제 21>에서 보는 것처럼 관리가 필요 없는 오래된 로그를 쉽고 빠르게 삭제할 수 있어서, 문서별로 TTL 값을 설정해 삭제하는 것 보다 시스템에 주는 오버헤드가 적다.

예제 21 인덱스 삭제

$ curl -XDELETE 'http://localhost:9200/log-2012-10-01/'

인덱스 최적화(Index Optimization)를 수행하면 세그먼트를 병합시킨다. 이러한 방식으로 검색 성능을 향상시킬 수 있다. 다만 시스템에 부담을 주므로 시스템 사용이 적은 시간대에 작업하도록 해야 한다.

예제 22 인덱스 최적화

$ curl -XPOST 'http://localhost:9200/log-2012-10-01/_optimize'

샤드와 복제본

샤드 개수는 초기에 설정한 다음에는 변경이 불가능하므로 현재 시스템의 노드 수와 추후 발생할 수 있는 노드 증가를 고려해 정해야 한다. 예를 들어 현재 5개의 노드가 있고 향후 10개까지 노드를 증가시킬 계획이라면, 초기부터 샤드 수를 10개로 지정하는 것이 좋다. 초기에 5개로 지정하면 이후 노드를 10개로 증가시켜도 샤드는 5개이므로 5개의 노드는 활용할 수 없게 된다. 물론 복제본 수를 1로 지정했다면 추가한 5개 노드를 복제 전용 노드로 활용할 수 있다.

샤드 수를 늘리면 질의가 샤드 개수만큼 분산되므로 많은 데이터 처리에 유리하게 되지만, 너무 크게 설정하면 오히려 트래픽이 증가해 성능이 떨어질 수 있으니 적절하게 설정해야 한다.

클러스터 토폴로지 구성

elasticsearch의 설정 파일에는 <예제 23>과 같은 내용을 볼 수 있다. <예제 23>을 보면 세 가지 종류의 노드(데이터 노드, 마스터 노드, 검색 밸런서 노드)가 있음을 알 수 있다.

  • 데이터 노드: 마스터 역할을 수행하지 않고, 데이터만 저장한다. 클라이언트로부터의 요청이 왔을 때 샤드에서 데이터를 검색하거나 인덱스를 생성한다.
  • 마스터 노드: 클러스터를 유지하기 위한 역할을 하고 인덱싱이나 검색 요청을 데이터 노드들에 요청한다.
  • 검색 로드 밸런서 노드: 검색 요청이 오면 노드들에 데이터를 요청 후 취합해 결과를 전달한다.

하나의 노드가 마스터와 데이터 노드 역할을 다 하도록 운영할 수도 있으나, 세 가지 형태의 노드를 각각 사용하면 데이터 노드의 부담을 줄일 수 있다. 또한 마스터 노드를 별도로 구성하면 클러스터의 안정성을 높일 수 있다. 게다가 마스터 노드와 검색 노드는 저사양의 서버 장비를 활용할 수 있도록 해 운영 비용 또한 줄일 수 있다.

예제 23 토폴로지 관련 설정 내용

# You can exploit these settings to design advanced cluster topologies.
#
# 1. You want this node to never become a master node, only to hold data.
# This will be the "workhorse" of your cluster.
#
# node.master: false
# node.data: true
#
# 2. You want this node to only serve as a master: to not store any data and
# to have free resources. This will be the "coordinator" of your cluster.
#
# node.master: true
# node.data: false
#
# 3. You want this node to be neither master nor data node, but
# to act as a "search load balancer" (fetching data from nodes,
# aggregating results, etc.)
#
# node.master: false
# node.data: false

라우팅 설정

인덱싱할 데이터가 많으면 샤드의 수를 늘리는 것이 전체적인 성능을 증가시킬 수 있지만, 샤드의 개수를 증가시키는 만큼 노드 간의 트래픽이 증가한다는 문제점이 있다. 예를 들어 샤드가 100개면 하나의 검색 요청이 왔을 때 100개의 샤드에 모두 요청을 보내 데이터를 취합하는 형식이기 때문에 전체 클러스터에 부담이 된다. 라우팅을 사용하면 특정 샤드에만 데이터가 저장되어 샤드 수가 아무리 커져도 1개의 샤드에만 요청을 보내게 되므로 트래픽을 극적으로 줄일 수 있다. <그림 2>와 <그림 3>, <그림 4>는 Rafal Kuc이 Berlin Buzzwords 2012에서 발표한 자료에서 인용한 것이다. 라우팅을 사용하지 않으면 <그림 2>와 같이 전체 샤드에 모두 요청을 보내지만 라우팅을 사용하면 <그림 3>과 같이 특정 샤드에만 요청을 보내는 것을 볼 수 있다. <그림 4>에서 인용한 자료에 따르면 200개의 샤드에서 라우팅 사용 전과 후의 성능을 비교 했을 때 반응 시간이 10배 이상 차이 나는 것을 볼 수 있다. 라우팅을 적용하면 적용하지 않은 경우외 비교해 스레드 개수가 10~20배 증가하지만 CPU 사용률은 훨씬 적은 것을 볼 수 있다. 하지만 경우에 따라 라우팅을 적용하지 않은 것이 성능이 더 좋을 때도 있다. 여러 샤드로부터 결과가 취합되어야 하는 검색 질의에 대해서는 여러 샤드에 요청이 전달되는 것이 성능상 유리할 수 있다.

c0209f80b05fe14bd157cbace9270378.png

그림 2 라우팅 사용 전

b4a8e465ca9e0c609eff1677e8a0e690.png

그림 3 라우팅 사용 후

8aafb0f6569fda4b8c31e98cad9123f2.png

그림 4 라우팅 사용 전/후의 성능 비교

마무리

elasticsearch는 유용한 기능뿐만 아니라 간단한 설치와 높은 확장성때문에 사용자를 빠르게 늘려가고 있다. 버전 숫자로만 본다면 최근(2013년 1월 기준)에 0.20.4 버전이 나온 정도지만 커뮤니티가 활발하기 때문에 빠르게 기능이 개선되고 있다. 또한 점점 더 많은 회사에서 elasticsearch를 자사의 서비스에 사용하고 있다. 최근에는 개발자인 Shay Banon을 포함한 커미터들이 모여 Elasticsearch.com을 만들어 컨설팅과 교육을 제공하고 있다. 이번 글에서는 기본적인 설치와 사용 방법, 성능 튜닝을 위한 내용을 정리했다. 많은 개발자들에게 도움이 되길 바란다.

참고 자료

31a9898c16d64bb9fd3a2a0043aeb1d3.JPG
NBP 글로벌플래폼개발랩 이재익
글로벌플랫폼개발랩에서 중국개발자들과 로그시스템을 개발하고 있다. 최근 elasticsearch, node.js, iOS 개발에 관심을 가지고 업무에 활용하고 있으며, 여가시간에는 무지함에서 벗어나기위해 독서를 하거나 여행을 하려고 노력 중이다.



:

루씬 한국어형태소 분석기 lucene-core 3.2 에서 3.6 으로..

Elastic/Elasticsearch 2013. 1. 24. 16:03

lucene kr analyzer 사용 시 lucene core 3.2 에서 3.6 으로 올리시게 되면 아래 클래스에서 빨갱이가 나옵니다.
아래는 수정한 코드 인데 뭐 보시면 너무나 기본이라 이런건 작성할 필요가 있는지도 ^^;
암튼 머리 나쁜 저는 필요 해서.. 

[KoreanAnalyzer.java]

 /** Builds an analyzer with the stop words from the given file.

   * @see WordlistLoader#getWordSet(File)

   */

public KoreanAnalyzer(Version matchVersion, File stopwords) throws IOException {     

        this(matchVersion, WordlistLoader.getWordSet(new InputStreamReader(new FileInputStream(stopwords), DIC_ENCODING), matchVersion));        

}


  /** Builds an analyzer with the stop words from the given file.

   * @see WordlistLoader#getWordSet(File)

   */

public KoreanAnalyzer(Version matchVersion, File stopwords, String encoding) throws IOException {

        this(matchVersion, WordlistLoader.getWordSet(new InputStreamReader(new FileInputStream(stopwords), encoding), matchVersion));

}

/** Builds an analyzer with the stop words from the given reader.

* @see WordlistLoader#getWordSet(Reader)

*/

public KoreanAnalyzer(Version matchVersion, Reader stopwords) throws IOException {

  this(matchVersion, WordlistLoader.getWordSet(stopwords, matchVersion));    

}

기존 KoreanAnalyzer 에는 Version argument 가 없어서 추가만 했습니다. :)

:

루씬 2.4.3 Field options for term vectors

Elastic/Elasticsearch 2013. 1. 23. 19:02
퇴근 하면서 급하게 올리다 보니 아무런 내용도 없이 그냥 스크랩 내용만 등록을 했내요.

[요약하면]
Term vectors are a mix between an indexed field and a stored field. They’re similar to a stored field because you can quickly retrieve all term vector fields for a given document: term vectors are keyed first by document ID . But then, they’re keyed secondarily by term, meaning they store a miniature inverted index for that one document. Unlike a stored field, where the original

[어떤 경우에 사용하지]
Sometimes when you index a document you’d like to retrieve all its unique terms at search time. One common use is to speed up highlighting the matched tokens in stored fields. (Highlighting is covered more in sections 8.3 and 8.4.) Another use is to enable a link, “Find similar documents,” that when clicked runs a new search using the salient terms in an original document. Yet another example is automatic categorization of documents. Section 5.9 shows concrete examples of using term vectors once they’re in your index.


2.4.3 Field options for term vectors
Sometimes when you index a document you’d like to retrieve all its unique terms at search time. One common use is to speed up highlighting the matched tokens in stored fields. (Highlighting is covered more in sections 8.3 and 8.4.) Another use is to enable a link, “Find similar documents,” that when clicked runs a new search using the salient terms in an original document. Yet another example is automatic categorization of documents. Section 5.9 shows concrete examples of using term vectors once they’re in your index.
But what exactly are term vectors? Term vectors are a mix between an indexed field and a stored field. They’re similar to a stored field because you can quickly retrieve all term vector fields for a given document: term vectors are keyed first by document ID . But then, they’re keyed secondarily by term, meaning they store a miniature inverted index for that one document. Unlike a stored field, where the original
String content is stored verbatim, term vectors store the actual separate terms that were produced by the analyzer, allowing you to retrieve all terms for each field, and the frequency of their occurrence within the document, sorted in lexicographic order. Because the tokens coming out of an analyzer also have position and offset information (see section 4.2.1), you can choose separately whether these details are also stored in your term vectors by passing these constants as the fourth argument to the Field constructor:
TermVector.YES —Records the unique terms that occurred, and their counts, in each document, but doesn’t store any positions or offsets information
TermVector.WITH_POSITIONS —Records the unique terms and their counts, and also the positions of each occurrence of every term, but no offsets
TermVector.WITH_OFFSETS —Records the unique terms and their counts, with the offsets (start and end character position) of each occurrence of every term, but no positions
TermVector.WITH_POSITIONS_OFFSETS —Stores unique terms and their counts, along with positions and offsets
TermVector.NO —Doesn’t store any term vector information
Note that you can’t index term vectors unless you’ve also turned on indexing for the field. Stated more directly: if Index.NO is specified for a field, you must also specify
TermVector.NO .

We’re done with the detailed options to control indexing, storing, and term vec-tors. Now let’s see how you can create a field with values other than String .


:

루씬 한글형태소 분석기 로컬 테스트

Elastic/Elasticsearch 2013. 1. 23. 16:09

이런.. 아래 코드는 2.X 용이내요.. 
3.X 에서는 동작 하지 않습니다.
그냥 새로 짜야겠내요.. ^^;

--------------------------------------------------------------

Special Thanks to : 이창민

한글형태소 분석기 로컬 테스트.


http://cafe.naver.com/korlucene 카페에 보면 krmorph-20091117.war파일

한국어 형태소분석 파일을 테스트 해볼수 있는 파일을 개발자님이 직접 올려주셨네요. (공모전에 출품작이였던 것 같습니다.;)

첨부한 파일은 : 공모전에 출품하려고 개발자가 매뉴얼을 작성한 것 같습니다. 프로그램에 대해 자세하게 적혀있습니다.(카페에서 찾았습니다.)



krmorph-20091117.war

 

해당 파일을 실행시키는 방법

1. 이클립스에서 마우스 오른쪽 버튼 -> Import -> WAR file

2. 다운받은 krmorph-2091117.war파일 선택

3. 프로젝트 import 완료

4. 프로젝트 선택후 오른쪽 버튼 -> Run As -> Run On Server (기존에 톰캣이 셋팅 되어 있어야 함. & 일반 웹프로젝트 톰캣셋팅과 동일함)

5. 톰캣 재시작


※ 접속 URL : http://localhost:8080/krmorph-20091117/


형태소 분석기 소스를 받아서 고치거나 사전 업데이트 후 실제 어떻게 동작 하는지 테스트 할때 사용하면 유용할 것 같내요.
어제 stopwords 잘 안되던거 테스트 하기 위해서 필요 했는데. ㅎㅎ 창민군 고마워요.. :)


:

lucene kr analyzer flow

Elastic/Elasticsearch 2013. 1. 23. 10:43

stopwords 적용을 하다 보니 그냥 심심해서 어떤 workflow 인지 올려봅니다.
뭐 소스 보시면 다 아시는 내용이라 그냥 혼자 저장용으로 활용... ^^


[기본 flow]

KoreanAnalyzer.java        : 문장을 분석하기 위한 Analyzer 구성 (LUCENE.Version 과 stopwords, encoding)

KoreanTokenizer.java       : 지정한 token type 별로 token 분리

KoreanFilter.java              : 입력 받은 token 을 형태소 분석기를 이용해 AnalysisOutput 생성

MorphAnalyzer.java         : 여기서 한국어의 형태소를 분석 (동사, 명사, 조사, 어간, 어미 등등 ) 하여 keyword 추출


[개념적 flow]

KoreanAnalyzer -> KoreanTokenizer -> KoreanFilter -> MorphAnalyzer

:

lucene 튜토리얼

Elastic/Elasticsearch 2013. 1. 22. 18:56

lucene 튜토리얼(추천)
참조 사이트 : http://www.lucenetutorial.com/lucene-in-5-minutes.html

1. https://github.com/macluq/helloLucene에서 HelloLucene-mastsr.zip을 다운로드 받는다.
2. 압축을 해제 한다.
3. 마우스 오른쪽 버튼 -> import -> existing Maven Projects
4. Maven install
5. /src/main/java/HelloLucene/HelloLucene.java 마우스 오른쪽 버튼 Run As > Java Application을 실행

lucene라이브러리를 사용하여 아래의 과정을 보여줌으로써 기본적인 개념을 잡을 수 있도록 도와줌
1. create the index
2. query
3. search
4. display results

:

elasticsearch 한국어 형태소분석기 분석의 이해

Elastic/Elasticsearch 2013. 1. 22. 18:55

Spacial Thanks to : 이창민.

elasticsearch 한국어 형태소분석기 분석

  1. 소스 다운로드 (zip파일로 다운로드)
    1. 다운로드 : https://github.com/chanil1218/elasticsearch-analysis-korean
    2. 소스로 다운로드도 가능하지만 해당 위치를 elasticsearch plugin에서 플러그인명을 chanil1218/elasticsearch-analysis-korean로
      지정할 경우에도 사용된다. 이 때, 해당 elasticsearch 버전이 최신버전이면 해당 플러그인을 찾지 못한다. 서버와 플러그인의 버전이 같아야 설치 가능
  2. 이클립스에 프로젝트 import 방법
    1. eclipsesearch-analysis-korean-master.zip파일을 압축해제한다.
    2. 이클립스->마우스 오른쪽 버튼-> Import-> Maven -> Existing Maven Projects
    3. Browse...을 눌러 압축을 해제한 디렉토리를 선택하여 import 한다.
    4. 프로젝트 오른쪽 버튼 -> Run as -> Maven install을 하여 빌드 한다.
  3. 형태소 분석을 담당하는 주 클래스는 org.apache.lucene.analysis.kr.morph 패키지의 MorphAnalyzer 클래스이다.
    KoreaTokenizer가 한글과 영문을 토큰 단위로 분리를 하면, 이중 한글만 (한글, 숫자+한글, 영자+한글) MorphAnalyzer을 통해 형태소 분석.
  4. 형태소 분석한 결과는 KoreanFilter에 AnalysisOutput 클래스로 전달이 되며 명사인 경우만 색인어로 추출
  5. 형태소분석결과는 점수를 가진다. 30 or 100으로 표시되는 값
    1. 100인 경우는 형태소 분석에 성공한 경우이므로 분석결과를 그대로 색인어로 사용.
    2. 30인 경우는 문법형태소로는 분해를 하였지만 사전에는 없으므로 정확하지 않은 경우. 이런 경우는 검색이 않되는 경우를 방지하기 위해 bigram(바이어그램, 아래에 설명 추가)에
      의해 추가로 색인어를 추출합니다.
    3. 예를 들면, "블로그에" 라는 어절이 있을 때 "블로그"가 사전에 등록되어 있지 않으므로 형태소분석결과는 "블로그에(N)"와 블로그(N), 에(J)"가 되지만 색인어는 "블로그에", "블로그", "블로", "로그", "그에"가 됩니다.
  6. 형태소 분석결과 사전이 없을 경우 바이어그램으로 색인어를 추출하는데 false drop된 문서가 나온는 단점이 있다.
    1. http://blog.daum.net/maxmin93/10990156 에서 절단 검색부분에 bigram의 문제점과 trigram이 좀더 나은 검색결과를 제공가능 하지만 장단점이 있는 것 확인.
    2. 위의 한국어 형태소 분석기에는 현재 분석결과가 사전에 없을 경우 bigram만 적용 됨.
  7. 사전 데이터는 org.apache.lucene.analysis.kr.dic 패키지에 존재한다. (사전데이터 각 파일 설명)
    1. total. dic : 기본사전
      - 용언과 체언을 포함한 기본사전 입니다. 사전의 형식을 보면 다음과 같이 구성되어 있습니다.
      ==========================
      납부,10011X
      ==========================
      단어정보 - 단어정보는 6글자로 구성되어 있는데 각 글자는 단어의 사용규칙을 나타내며 아래와 같습니다.
          - 1 : 명사
          - 2 : 동사
          - 3 : 기타품사
          - 4 : 하여동사
          - 5 : 되어동사
          - 6 : 불규칙변형
          - 1~3은 품사에 대한 정보이며, 위에 기술한 각 품사 여부를 나타냅니다.
          - 4~5는 명사인 경우 "하다""되다"가 붙을 수 있는 경우를 나타냅니다. 주의) 동사는 반드시(0)이어야 합니다.
          - 6은 동사인 경우 불규칙변형의 종류를 나타내며 종류는 아래와 같습니다.
        
      B:  ㅂ 불규칙, H: ㅎ 불규칙, L: 르 불규칙, S: ㅅ 불규칙, R: 러 불규칙, X: 규칙
    2. extension.dic : 확장사전
      - 기본사전은 가능한 그대로 사용하는 것이 좋음. 사전을 조금 보완하여야 할 때 확장사전을 사용하면 됨. 사전을 구성하는 기본 규칙은 기본사전과 동일
    3. josa.dic : 조사사전
      - 조사들만 모아둔 사전. 각 조사는 한줄씩 구분이 됨
    4. eomi.dic : 어미사전
      - 어미들만 모아둔 사전. 각 어미는 한줄씩 구분이 됨
    5. prefix.dic : 접두어 사전
      - 복합명사를 분해시 2글자 이상의 단어로만 분해. 그러나 "과소비" 같은 경우 " 과"를 접두어로 분리해 내어 "과소비"와 "소비"를 색인어로 추출하기 위해 만든사전
    6. suffix.dic : 접미어 사전
      - 복합명사를 분해시 "현관문" 같은 경우 "문"을 접미어로 분해하여 "현관문"과 "현관"을 색인어로 추출하기 위해 만든 사전
    7. compounds.dic : 기분석 복합명사 사전
      - 복합명사는 명사 사전을 기반으로 최장일치법에 의해 분해를 합니다. 그러나 "근로자의날" 같은 경우 중간에 조사가 포함되어 있으므로 분해가 불가능합니다. 이런 경우 복합명사 사전에 등록을 합니다. 규칙은 다음과 같습니다.
      ==========================
      근로자의날:근로자,날
      ==========================

      - 콜론(\:)을 중심으로 좌측은 복합명사이고 우측은 함께 추출될 색인어입니다. 따라서 위의 경우는 색인어로 "근로자의날", "근로자","날" 이렇게 3개가 추출됩니다.

    8. syllable.dic : 음절정보
    9. 현재 파악 중 (cj.dic , occurrence.dic, uncompounds.dic 3개의 파일)

N-gram이란?
N-gram이란?
N-gram은 텍스트나 문서에서 추출한 문자 또는 단어의 시퀀스이며, 문자 기반 및 단어 기반이라는 두 그룹으로 분류할 수 있다. N-gram은 단어 또는 문자열(이 튜토리얼의 경우)에서 추출한 N개의 연속 문자 세트이다. 이 방법의 배후에는 비슷한 단어가 N-gram의 높은 비율을 차지할 것이라는 개념이 깔려있다. 가장 일반적으로 사용되는 N값은 2와 3이며, 각각의 경우를 bigram과 trigram이라고 한다. 예를 들어, TIKA라는 단어에서는 T, TI, IK, KA, A*라는 bigram과 **T, *TI, TIK, IKA, KA, A*라는 trigram이 생성된다. ""는 채우기 공간을 의미한다. 문자 기반 N-gram은 문자열으 유사성을 측정하는데 사용된다. 문자 기반 N-gram을 사용하는 애플리케이션으로는 맞춤법 검사기 스테밍(strmming), OCR등이 있다.
발췌 :  http://www.ibm.com/developerworks/kr/opensource/tutorials/os-apache-tika/section6.html

:

stopwords, thesaurus ... 등등

Elastic/Elasticsearch 2013. 1. 22. 18:49

아주 기초가 되는 내용인데.. 웹에서 돌아 다니다가 발견해서 그냥 스크랩해 봅니다.

원본출처는 사이트가 없어진것 같고, 아래 링크에서 퍼왔내요.
http://web.skhu.ac.kr/~mckim1/Lecture/IR/Note/hwork.html


Stopwords(불용어)


불용어란 검색엔진이 검색에서 무시해 버리는 문자열을 의미합니다. 전치사나 관사 a, an, the, that, this, in, on, by, if, is, are, as, be, but, of, for, to, from, with, you, he, there, may 등과 같이 의미없는 단어는 검색어로 취급되지 않는 것입니다.

검색식에 이러한 불용어나 특수기호(마침표,콤마,/,&,%,@,*,? ...)를 반드시 포함시키고자 한다면 대개는 구절검색 기능을 이용합니다. 어떤 검색도구에서는 불용어도 검색대상에 포함시킬 것인지에 대한 옵션을 제공하기도 합니다.



Any terms, Thesaurus
Extended Derivatives

집단검색어,유의어,시소러스, 확장검색


예를 들어 검색을 '대도시'라고 썼을 때 전국의 대도시 지명들을 OR조건으로 모두 나열한 것과 같은 효과를 내는 검색방식입니다. 이것은 집단검색어 파일을 따로 갖고 있는 데이터베이스에서만 사용할 수 있습니다.

비슷한 기능으로서 유의어사전을 지원하는 검색도구들이 있습니다. 대표적인 것이 심마니입니다. 심마니에서는 예를 들어 '장애인#'이라고 검색식을 입력하면 장애인 뿐만 아니라 장애자, 장해인, 장해자 등도 찾아 줍니다. 

이와 같이 사용자가 검색식에 입력한 문자열과 꼭 같지 않더라도 의미상 같거나 관련이 있는 용어들을 모아 검색가능하도록 구축한 데이터베이스를 시소러스(Thesaurus) 또는 유의어사전이라고 합니다.

약간 다르기는 하지만 주제어(Topic) 검색이라는 것이 있습니다. 영어성경검색이 좋은 예입니다. Poor라는 주제어를 입력하면, Beneficence; Giving; Liberality; Orphans; Poverty; Widow 등에 관하여도 볼 수 있습니다. 참고로 Lycos의 카탈로그나 야후의 디렉토리는 메뉴방식으로 원하는 정보를 선택하지만 사실은 내부적으로는 Topic별로 검색이 이루어지는 것입니다.

또 다른 하나의 예는 알파벳 순서에 의한 단어의 범위(Alphabetical Range of Words)를 지정하는 중괄호 { } (braces)입니다. Deja News에서 {monkey monkeying}라고 검색식을 입력하면 영어사전(엄밀히 말하면 Deja News의 색인집인 시소러스)의 monkey부터 monkeying까지 그 사이에 나오는 모든 단어가 검색대상이 됩니다.

Extended Derivatives 

영국의 웹검색기인 WWLib Extended Search Interface는 좀 특별한 확장검색을 합니다. 1.명사의 복수형도 검색하고 (Depluralisation) 2.동사의 분사형이나 진행형도 검색하며 (Degerundisation), 3.관련단어도 검색(Related words)해 주는 것이지요. 예를 들어 biology의 관련어에는 biologist, biologically 등이 있습니다.


Boolean Connectors

부울연산자 : 더하기, 빼기, 곱하기


1. AND

연산자 좌우의 검색어가 모두 나타나는 자료를 찾습니다. (예 welfare and rehabilitation) 

주로 and나 플러스 기호(+)로 표시하지만, 연산자 없이 그냥 공백만으로 and연산을 하거나 그외 엠퍼센드 기호(&)를 쓰는 경우도 있습니다. 심마니에서는 '그리고/와/과/및' 등의 한글 연산자도 사용할 수 있습니다.


2. OR

연산자 좌우의 검색어 중 어느 하나만이라도(any word) 들어 있는 자료를 찾습니다. (예 aged or alzheimer) 

주로 공백이나 or를 사용하지만, 가끔 플러스 기호(+)나 콤마(,)를 사용하기도 합니다. 검색도구에 따라서는 적합성(Relevancy) 점수를 부여할 때 or연산자 좌우의 단어가 모두 들어 있는 자료에 높은 점수를 주기도 합니다.


3. NOT 또는 AND NOT

연산자 앞쪽의 검색어를 포함하되, 뒤쪽의 검색어는 들어있지 않은 자료만 찾습니다. (예 retardation not illness) 

주로 마이너스 기호(-)나 not를 많이 사용하지만, 느낌표(!)나 &!를 사용하기도 합니다.



Phrase Searching

구절검색


두개 이상의 단어가 순서대로 연속해서 나오는 것을 찾습니다. 

예 "special education for the disabled children" 

보통 구절을 따옴표(" ")로 싸 주는데, 검색엔진은 이 구절을 하나의 긴 문자열로 취급하는 것이지요. 주로 두 단어 이상으로 되어 있는 전문용어 등을 찾을 때 사용하지만, 검색 문자열에 특수기호(마침표,콤마,/,&,%,@,*,? ...)나 불용어까지 포함시키려는 경우에도 사용합니다.


※ 구절검색을 할 경우 절단검색 기호(*)는 사용할 수 없고 불용어가 아닌 단어를 두개 이상 포함해야 합니다.


Grouping by Parentheses

검색식의 문법


인터넷의 검색도구들에서도 대체로 여러개의 검색어와 연산자들을 결합하여 복잡한 검색식을 사용할 수 있습니다. 그러나 대개는 상용 데이터베이스와는 달리 and연산자가 or연산자보다 우선되는 것도 아니고 그저 검색식의 왼쪽으로부터 오른쪽으로 차례대로 연산하는데, AltaVista처럼 괄호를 사용하여 검색 연산순서를 바꿀 수 있는 것도 있습니다.

예를 들어, 검색식을 vocational and training or placement (알타비스타라면 +vocational +training placement라고 쓰겠죠.)라고 입력하면 vocational과 training이 동시에 들어 있거나, placement가 들어 있는 자료를 찾습니다. 앞에서부터 차례대로 연산하기 때문입니다. 만약 장애인의 직업훈련이나 직업알선(배치)에 관한 자료를 원한다면 vocational AND (training OR placement) 와 같이 우선 연산하고자 하는 부분을 괄호로 그룹지어야 합니다. 이와 같이 괄호로써 연산자의 조합을 조정할 수 없는 검색도구에서라면 AND조건이 필요한 검색어를 뒤로 보내어 training OR placement AND vocational와 같이 입력하는 것이 좋습니다. AltaVista라면 training placement +vocational 이렇게 입력해야겠지요.



Proximity Searching, Concatenation

인접연산자


인접연산자는 앞뒤의 검색어가 동시에 나와야 한다는 점에서 and연산과 비슷하지만 두 검색어가 바로 옆에 또는 일정 거리내에 인접하여 있어야 합니다. Welfare-Net,Korea와 같은 구조의 문자열을 찾으려면 주로 따옴표로 전체를 묶어 하나의 구절로 검색하는 것이 보통이지만 구절검색이 지원되지 않을 때에는 하이픈(-)이나 콤마(,) 등 특수기호나 불용어 자리에 인접연산자를 쓰면 좋습니다.

※ 앞뒤 검색어가 얼마나 가까이 붙어 있어야 하는가, 두 검색어 사이에 몇개까지의 단어가 끼어드는 것을 허용하는가 하는 인접정도는 검색도구에 따라 조금씩 다릅니다. 100단어 이내, 5글자 이내, 또는 한 문단내에 인접해 있는 조건으로 해석되기도 합니다.

※ 인접연산자는 보통 하나의 검색식 내에서 하나만 사용할 수 있습니다. 여러개의 인접연산자로 구성된 검색식은 거의 허용되지 않을 뿐 아니라 그렇게 써야 할 경우도 거의 없습니다. 또한 구절검색식과 인접연산자를 함께 사용할 수 없습니다.


 검색어간의 순서까지 지정하는 ADJacent, 또는 Preceding

연산자 좌우의 검색어가 지정된 순서로 인접해 들어 있는 자료를 찾습니다. 다이얼로그의 Within 연산자와 같습니다.


예1 mental adj retardation Adj는 Adjacent(인접한)의 약자입니다.

예2 : attitude p3 disab* REHABDATA에서는 절단검색어는 인접연산자와 함께 사용할 수 있으나 구절검색어는 인접연산자와 함께 쓸 수 없습니다. 여기서 p는 preceding(앞에 오는)의 약자로 쓰였습니다.


검색어간의 인접관계만 지정하는 NEAR

이는 좌우 검색어가 앞뒤 순서에 관계없이 인접해 있는 경우를 말합니다. 다이얼로그의 Near 연산자와 같은 것이지요.


예1 : aged near/25 "day care" (WebCrawler)

예2 : welfare ^10 reform (Deja News) Deja News에서는 구절검색어나 절단검색어를 인접연산자와 함께 사용할 수 없습니다.

예3 : attitude w3 disab* (REHABDATA) REHABDATA에서는 절단검색어는 인접연산자와 함께 사용할 수 있으나 구절검색어는 인접연산자와 함께 쓸 수 없습니다. 여기서 w는 Within의 약자로 쓰였습니다. attitude for the disabled의 경우 w3을 써야 합니다. 즉, 인접연산기호와 함께 쓰이는 숫자에는 끝 단어도 계산되는 것입니다.



Truncation

절단검색


검색식에 입력된 문자열과 정확히 일치하는 단어를 찾아내는 것을 완전검색(Precise Searching)이라고 합니다. 검색도구에 따라 Whole words, Complete words, 똑같은거, Exact, Word based search 등으로 표현하는 옵션을 제공하기도 합니다. 예를 들어 입력된 용어가 'handicap'이면 정확히 handicap만 찾으므로, handicapped는 검색되지 않습니다.

검색식에 입력된 문자열로 시작하는 단어는 모두 검색해 준다든가 하는 기능을 절단검색이라고 합니다. 절단검색에는 검색어 뒷부분의 변화를 허용하는 우절단을 비롯하여 앞부분의 변형을 허용하는 후방일치 검색 등이 있습니다.


전방일치검색=어근검색=우절단검색 Right-Truncation

표현형식 : 단어* (또는 %단어) 

절단검색 옵션을 선택하거나 검색어 뒤에 절단기호를 덧붙입니다. 절단기호(가변글자기호)로는 대부분 별표(*)를 사용하지만, 임의의 글자 수만큼 물음표를 사용하는 경우도 있습니다. 한편, 검색식에서는 절단기호(*)를 쓰지 않고 우절단검색, Word-stem based search, Substrings, Start with, 전방일치검색 등으로 표시한 옵션을 선택하게 되어 있는 검색시스템들도 많습니다. 단순히 절단검색이라고 하면 이 우절단검색을 의미한다고 보셔도 됩니다.

예 : disab*

용도 : 검색용어의 끝부분을 임의의 문자로 지정하는 것으로서, 영어의 경우에는 주로 단수형과 복수형(disability, disabilities / child, children)을 한꺼번에 검색하거나, 품사의 차이로 어미변화를 일으키는 용어(volunteer, volunteering, voluntary)를 검색할 때 사용하고, 우리말과 일본어의 경우 앞이 같은 말로 시작되는 유사어나 복합어(장애, 장애인, 장애인복지, 장애자, 장애인시설, 장애연금)를 검색하고자 할때 이용합니다.


후방일치 : Left-Truncation

표현형식 : *단어 (또는 단어%) 

대부분 별표(*)를 사용하지만, 임의의 글자 수만큼 물음표를 사용하는 절단방식도 있습니다. 인터넷상의 거의 모든 검색도구들이 후방일치 절단검색을 지원하지 않습니다. 영국의 웹검색기인 WWLib Extended Search Interface에서는 이 기능을 지원합니다.

예 : 정보탐정에서 검색식을 '장애%'라고 쓰면 지체장애, 청각장애, 시각장애 등 '장애'로 끝나는 용어들을 찾아 줍니다.

용도 : 검색용어의 시작부분을 임의 문자열로 지정하는 것으로서, 영어단어의 경우 주로 화합물의 검색을 위해 사용한다고 하는데, 위의 예와 같이 이 검색식은 한글 복합어를 검색할 때 특히 유용합니다.


사이에 끼는 가변글자

표현형식 : 단어?단어

예 : wom?n

용도 : women, woman을 찾습니다. 다이얼로그와 같은 데이터베이스에서 주로 사용하는 것인데, 인터넷상의 정보검색엔진에서는 이런 검색방식을 지원하는 경우가 거의 없습니다. 다만 이와는 다르지만 영국의 웹검색기인 WWLib Extended Search Interface에서는 앞뒤로 절단검색하는 기능도 있습니다.


절단검색시 주의사항

절단검색어를 사용할 때, 어간이 짧은 경우에는 관계없는 용어들이 같이 검색되므로 어근을 너무 짧게 지정하지 않도록 주의하여야 합니다. 예를 들어, communication, communicate등 의사소통에 관한 자료를 찾기 위해 검색식을 com*이라고 쓰면 community, computer, compass, coma, commercial ...등 전혀 원하지 않는 용어들까지, 또는 너무 많은 용어들이 검색대상이 되어 버립니다.



Field (Context) Searching

필드 제한 검색


웹문서의 title, head, body, address 등이나 뉴스그룹 기사의 author, subject, newsgroup name 등 문서의 특정 부분(필드 또는 context라고 함)으로 제한하여 검색하면 보다 정확하고 빠르게 검색할 수 있습니다.


필드제한 검색의 유형

검색식에 직접 필드제한자를 붙이는 경우 

가장 유연한 검색방식입니다. 고급 서처들에게는 검색식내에 직접 여러 연산기법들을 사용할 수 있게 하는 엔진이 좋은 법이지요. 

예1 : AltaVista(예: title:"Department of Health and Human Services") 알타비스타의 필드제한 검색 특히, title, url, link필드에서의 검색은 정확한 자료를 찾아내는데 큰 도움이 됩니다. 그리고 이것은 과거에 책갈피를 만들어 둔 좋은 자료가 URL의 무단변경으로 인하여 더 이상 찾아내기 어려울 때 아주 유용한 검색기법입니다. 예를 들어 +url:sprc +title:"Social Policy Research Centre"의 검색은 지금의 정확한 주소는 모르지만 url과 타이틀중에 포함된 단어로써 찾아내는 것입니다. 

나의 홈페이지,웹문서를 다른 곳들에서 얼마나 많이 링크시켜놓고 있는지를 알고 싶을 때 +link:http://welfare.or.kr -host:welfare.or.kr 이와 같이 검색식을 입력하면 됩니다. 

예2 : Deja News(예: ~g alt.child*)

검색식을 입력한 다음 검색대상 필드를 옵션으로 선택하는 경우 

예1 : Galaxy 

예2 : OpenText Power Search

필드별 검색식 입력상자에 검색식을 작성하는 경우 

예1 : REHABDATA 

예2 : 유럽사회과학정보협의회 통합검색 CESSDA


필드내에서의 비교연산자 Comparison and Range Searches 

필드검색에 있어서, 특히 위의 세번째 유형처럼 각 필드별로 검색식 입력상자가 따로 있는 경우는 좀더 진보된 고급 연산자를 지원하는 것도 있습니다.(예:REHABDATA) 인터넷상의 일반 검색엔진에서는 좀처럼 보기 어려운 연산자이기는 하지만 고급 문헌검색엔진(Dialog, BRS ...)이나 일반 DBMS(dBASEIII+, Approach...)에서는 다 지원되는 것입니다.

연산자기호


의미


예제

=

Equal to (exact match)

=access


>

Greater than

>5500


>=

Greater than or equal to

>=5500


<

Less than

<1-Jan-1996


<=

Less than or equal to

<=TX


:

Within range

1993:1996


※ 주의사항

비교연산자는 수치의 대소뿐만 아니라, 문자열의 알파벳 순서(엄밀히 말하면 코드값), 날짜의 선후를 비교하는데에도 사용됩니다.

Equal to 연산자(=)는 해당 필드내에 정확히 그 문자열만 들어 있어야 한다는 것입니다. 다른 단어(들)이 더 있어서도 안되는 것입니다. 이는 해당 필드내에 들어 있는 여러 단어 중 하나에 대하여 좌우 첨가없이 정확히 일치하는 Whole word(절단검색의 반대)를 찾는 것과는 또 다른 것입니다.

범위(range)연산기호 :대신에 ..등을 사용하기도 합니다.

REHABDATA는 날짜필드에서 비교연산자와 함께 날짜값의 일부만 쓰는 경우, 즉 년월일을 다 적지 않고 년도나 월만 쓰는 경우에는 해당 년도 또는 월의 첫날부터 찾는 것으로 간주합니다. 그리고 날짜형식은 거의 모든 형식을 다 지원하지만 or연산자와 혼동될 수 있는 slash (/)는 쓰지 마십시오. 슬래시를 사용할 경우는 날짜 전체를 따옴표로 묶어야 합니다(예:"6/25/1996"). June 1995 또는 6-95와 같이 쓰시면 무난합니다.



Relevancy, Weight

적확도,정확성,우선순위


히트(hit) 

검색결과 추출된 자료 또는 그 건수를 히트(hit)라고 합니다. 예를들어, 사용자가 입력한 검색식의 조건에 맞는 자료가 1,000건이 나왔을 경우 "1,000건이 hit되었다"라고 표현합니다. 이 경우 히트수는 1,000건이 되는 것이지요.

적합성(relevancy) 또는 우선순위(weight) 

적합성이란 히트된 자료내에 우리가 요구한 검색어가 얼마나 중요한 곳에 들어 있는가? 또는 얼마나 많이 그리고 얼마나 여러번 나오는가? 등을 기준으로 계산하는 정확성의 척도입니다. 예를 들어 웹문서의 타이틀이나 헤드 영역에 해당 단어가 들어 있거나 자료 중에 우리가 입력한 검색식에 딱 맞는 문자열(들)이 들어 있거나 같은 검색어라도 문장 중에 여러번 나온다면 우리가 원하는 자료일 가능성이 높다는 뜻이 된다는 것입니다.

정확도를 평가하는 기준은 검색엔진에 따라 조금씩 다릅니다. 몇가지만 예를 들어 봅시다.


라이코스는 입력된 검색어들간의 인접정도와 출현빈도에 따라 적합성의 점수를 매깁니다. loose match는 적합성점수가 0.1이상인 자료를 찾아주고, 가장 높은 strong match는 0.9이상인 자료만 보여줍니다. 검색결과수(hit)나 적합성의 차이도 있지만 검색소요시간도 크게 차이나는데, strong match를 선택하면 아주 빨리 결과를 보실 수 있습니다.

마젤란은, 검색식에 입력된 검색어들 중에 몇개나 맞추는가와 출현횟수, 검색어가 웹문서의 Title(넷스케이프의 제목막대에 표시되는 문자열)이나 URL 또는 마젤란의 Review에 들어 있는가 를 기준으로 적합성의 점수를 부여합니다. 그리고 검색결과는 이 적합성이 높은 자료부터 표시됩니다.

기타 알타비스타나, 심마니, 미국 정부기록,간행물 데이터베이스 등의 경우도 비슷한 방법으로 정확성을 계산하고 결과에 그 값을 표시하되, 대개는 바로 이 적합성의 점수 순으로 정렬하여 보여줍니다.

적합성과 혼동되기 쉬운 것으로, 소위 사이트의 점수 (Rating)가 있습니다. 예를 들어, 마젤란 경우, 각 사이트를 평가하여 사용의 용이성, 갱신주기, 편집기술, 흥미유발정도 등을 기준으로 점수를 부여하고 그 결과를 별표(one to four stars)로 표시하는데, 별표가 많으면 점수가 높은 것입니다. 그러나 이 점수가 우리가 찾고자 하는 검색식에 얼마나 적합한가를 의미하지는 않습니다. 단지 그 사이트가 일반적으로 좋은 곳이냐 하는 것을 의미할 뿐입니다. 개별 자료의 정확도와는 전혀 다른 의미의 점수인 것입니다.


:

루씬 한국어 형태소 분석기 사전 구성 및 팁.

Elastic/Elasticsearch 2013. 1. 22. 14:25

원본출처 : http://cafe.naver.com/korlucene


형태소사전은 모두 8개로 구성되어 있습니다. 그 중 하나는 음절정보이므로 실제로는 7개로 봐야 하겠군요.

사전은 org/apache/lucene/analysis/kr/dic 아래에 있습니다.

이 사전은 모두 jar 에 함께 패키징되어 있는데, KoreanAnalyzer 는 우선 classpath 에 있는 파일에서 찾고

없으면 jar 에 패키징되어 있는 것을 읽어 옵니다. 따라서 커스터마이징된 사전을 사용하고자 한다면

%CLASSPATH%/org/apache/lucene/analysis/kr/dic 아래에 각자의 사전을 저장해서 사용하면 됩니다.

 

각 사전에 대한 자세한 설명은 다음과 같습니다.

 

1. total.dic : 기본사전

용언과 체언을 포함한 기본사전입니다. 사전의 형식을 보면 다음과 같이 구성되어 있습니다.

================

납부,10011X

================

콤마(,)를 중심으로 좌측은 단어이고 우측은 단어정보입니다.

단어정보는 6글자로 구성되어 있는데 각 글자는 단어의 사용규칙을 나타내며 아래와 같습니다.

=========================================================

  1      2         3            4             5             6

명사 동사  기타품사  하여동사  되어동사  불규칙변형

=========================================================

1~3은 품사에 대한 정보이며, 위에 기술한 각 품사 여부를 나타냅니다.

4~5는 명사인 경우 "하다"와 "되다"가 붙을 수 있는 경우를 나타납내다. 주의)동사는 반드시(0)이어야 합니다.

6은 동사인 경우 불규칙변형의 종류를 나타내며 종류는 아래와 같습니다.

    B:ㅂ 불규칙, H:ㅎ 불규칙, L:르 불규칙, U:ㄹ 불규칙, S:ㅅ 불규칙, D:ㄷ 불규칙, R:러 불규칙, X:규칙

 

2. extension.dic : 확장사전

기본사전은 가능한 그 대로 사용하는 것이 좋을 것입니다. 그런데 사전을 조금 보완하여야 할때 확장사전을

사용하면 됩니다. 사전을 구성하는 규칙은 기본사전과 동일합니다.

 

3. josa.dic : 조사사전

조사들만 모아둔 사전입니다. 각 조사는 한줄씩 구분되어 있습니다.

 

4. eomi.dic : 어미사전

어미들만 모아둔 사전입니다. 각 어미는 한줄씩 구분되어 있습니다.

 

5. prefix.dic : 접두어 사전

복합명사를 분해시 2글자 이상의 단어로만 분해합니다. 그러나 "과소비" 같은 경우 "과"를 접두어로 분리해 내어

"과소비"와 "소비"를 색인어로 추출하기 위해 만든 사전입니다.

 

6. suffix.dic : 접미어 사전

복합명사를 분해 시 "현관문" 같은 경우 "문"을 접미어로 분해하여 "현관문"과 "현관"을 색인어로 추출하기 위해

만든사전입니다.

 

7. compounds.dic : 기분석 복합명사 사전

복합명사는 명사 사전을 기반으로 최장일치법에 의해 분해를 합니다. 그런데 "근로자의날" 같은 경우 중간에 조사가

포함되어 있으므로 분해가 불가능합니다. 이런 경우 복합명사 사전에 등록을 합니다. 규칙은 아래와 같습니다.

=========================================

근로자의날:근로자,날

=========================================

콜론(:)을 중심으로 좌측은 복합명사이고 우측은 함께 추출될 색인어입니다. 따라서 위의 경우는 색인어로

"근로자의날","근로자","날" 이렇게 3개가 추출됩니다.

 

 

 

:

한글 stopwords

Elastic/Elasticsearch 2013. 1. 22. 11:27

정말 오랜만에 보내요.. 
제가 야후에 있을때 봤던 것 같은데.. 국민대 강승식 교수님의 한국어 형태소 분석기... 

[한글 Stopword]

https://github.com/wonderino/KeywordElection2012/blob/master/hdic/stopword.dic

;
;====================[ 불용어 및 특수색인어 사전 ]======================
;
; 불용어(stopword)는 자동색인시에 색인어로 추출되지 않도록 하고 싶은
; 명사들입니다. 즉, 이 파일에 등록된 stopword들은 색인어로
; 출력되지 않습니다.
;
; 특수색인어는 자동색인시에 1 음절 명사 혹은 숫자로 시작되는
; 용어가 누락되는 것을 방지하기 위한 것으로 특수색인어로 등록되면
; 항상 색인어로 추출해 줍니다.
;
;
; *. 이 파일은 반드시 KS 완성형(KS C 5601-1987) 한글코드로 작성되어야 합니다.
;
; 2. line의 첫문자가 ';'이면 comment로 간주하여 무시됩니다.
;
; 3. line의 첫문자가 '_'이면 불용어로서 색인어로 출력되지 않습니다.
;
; 4. line의 첫문자가 '*'이면 특수색인어로서 항상 색인어로 출력됩니다.
; 1 음절 명사(예: 꽃, 핵)나 숫자로 시작되는 용어(예: 3.1절) 등
; default로 불용어로 간주되는 용어가 누락되지 않게 할 때 사용합니다.
;
; 5. 색인어로 추출되지 않는 한글 명사를 특수색인어로 등록해도
; 여전히 누락되는 경우가 있습니다. 이러한 용어는 특수색인어로
; 등록하지 말고 사용자 정의사전(hangul.usr)에 등록하면 됩니다.
;
; 6. 한 line에 하나의 단어(명사)만 허용되며, line 중간에 blank 문자를
; 허용하지 않습니다.
;
; 7. Text editor로 삽입/삭제할 때 반드시 sorting 순서를 지켜야 합니다.
; sorting 순서가 틀리면 실행할 때 error message를 출력합니다.
;
; 8. 이 사전에 수록될 수 있는 최대 단어수는 10,000단어까지이며,
; 또한 총 60,000bytes를 넘지 않아야 합니다. comment는 제외함.
;
;
; 국민대학교 컴퓨터학부 강승식
;---------------------------------------------------------------------
;--.|_ / /| Seung-Shik Kang Tel: (+82-2) 910-4800
; / | /\ /\| Kookmin University Fax: (+82-2) 910-4868
; ---- -+ School of Computer Science sskang@cs.kookmin.ac.kr
; () () | Songbuk-gu, Seoul 136-702, KOREA http://nlp.kookmin.ac.kr
;---------------------------------------------------------------------
;
*112
*114
*119
*12-12
*12-12사태
*12.12
*12.12사태
*128메가
*16메가
*1기가
*2000
*2002
*256메가
*3-1절
*3.1절
*386
*386PC
*4-19
*4-19혁명
*4.19
*4.19혁명
*486
*486PC
*4메가
*5-16
*5-16혁명
*5.16
*5.16혁명
*5.17
*5.18
*586
*586PC
*6.25
*6.25사변
*64메가
*911
*D램
;1IBM연구소
*S램
_a
_about
_above
_across
_after
_against
_all
_almost
_alone
_along
_already
_also
_although
_always
_among
_an
_and
_another
_any
_anybody
_anyone
_anything
_anywhere
_are
_area
_areas
_around
_as
_ask
_asked
_asking
_asks
_at
_away
_b
_back
_backed
_backing
_backs
_be
_became
_because
_become
_becomes
_been
_before
_began
_behind
_being
_beings
_best
_better
_between
_big
_both
_but
_by
_c
_came
_can
_cannot
_case
_cases
_certain
_certainly
_clear
_clearly
_come
_could
_d
_did
_differ
_different
_differently
_do
_does
_done
_down
_downed
_downing
_downs
_during
_e
_each
_early
_either
_end
_ended
_ending
_ends
_enough
_even
_evenly
_ever
_every
_everybody
_everyone
_everything
_everywhere
_f
_face
_faces
_fact
_facts
_far
_felt
_few
_find
_finds
_first
_for
_four
_from
_full
_fully
_furhered
_further
_furthering
_furthers
_g
_gave
_general
_generally
_get
_gets
_give
_given
_gives
_go
_going
_good
_goods
_got
_great
_greater
_greatest
_group
_grouped
_grouping
_groups
_h
_had
_has
_have
_having
_he
_her
_here
_herself
_high
_higher
_highest
_him
_himself
_his
_how
_however
_i
_if
_important
_in
_interest
_interested
_interesting
_interests
_into
_is
_it
_its
_itself
_j
_just
_k
_keep
_keeps
_kind
_knew
_know
_known
_knows
_l
_large
_largely
_last
_lastest
_later
_leastless
_let
_lets
_like
_likely
_long
_longer
_longest
_m
_made
_make
_making
_man
_many
_may
_me
_member
_members
_men
_might
_more
_most
_mostly
_mr
_mrs
_much
_must
_my
_myself
_n
_necessary
_need
_needed
_needing
_needs
_never
_new
_newer
_newest
_next
_no
_nobody
_non
_noone
_not
_nothing
_now
_nowhere
_number
_numbered
_numbering
_numbers
_o
_of
_off
_often
_old
_older
_oldest
_on
_once
_one
_only
_open
_opened
_opening
_opens
_or
_order
_orderd
_ordering
_orders
_other
_others
_our
_out
_over
_p
_part
_parted
_parting
_parts
_per
_perhaps
_place
_places
_point
_pointed
_pointing
_points
_possible
_present
_presented
_presenting
_presents
_problem
_problems
_put
_puts
_q
_quite
_r
_rather
_really
_right
_room
_rooms
_s
_said
_same
_saw
_say
_says
_second
_seconds
_see
_seem
_seemed
_seeming
_seems
_sees
_several
_shall
_she
_should
_show
_showed
_showing
_shows
_side
_sides
_since
_small
_smaller
_smallest
_so
_some
_somebody
_someone
_something
_somewhere
_state
_states
_still
_such
_sure
_t
_take
_taken
_than
_that
_the
_their
_them
_then
_there
_therefore
_these
_they
_thing
_things
_think
_thinks
_this
_those
_though
_thought
_thoughts
_three
_through
_thus
_to
_today
_together
_too
_took
_toward
_turn
_turned
_turning
_turns
_two
_u
_under
_until
_up
_upon
_us
_use
_used
_uses
_v
_very
_w
_want
_wanted
_wanting
_wants
_was
_way
_ways
_we
_well
_wells
_went
_were
_what
_when
_where
_whether
_which
_while
_whole
_whose
_whoss
_why
_will
_with
_within
_without
_work
_worked
_working
_works
_would
_x
_y
_year
_years
_yet
_you
_young
_younger
_youngest
_your
_yours
_z
_가
_가운데
_갈
; _갑
_걔
_거
_건
; _걸
_것
_게
_겨
_겸
_겹
_경
_곁
_계
_고
_곱
_곳
_곳곳
_과
_곽
_굄
_구
_권
_그
_그간
_그것
_그곳
_그녀
_그달
_그당시
_그대
_그대신
_그동안
_그들
_그들대로
_그때
_그런고
_그런날
_그런데서
_그런줄
_그럴수록
_그로
_그무렵
_그외
_그이
_그전
_그전날
_그쪽
_근
*글
_급
_깁
_깡
*꽃
; _꽝
_끗
_낌
_나
_낙
_낟
_낱
_내게
_내년초
_내달
_내부
_냥
_너
_너나마
_너로
_너와
_너희
_너희대로
_너희들
_네
_네번
_네째
_네탓
_넷
_넷째
_년
_년간
_년도
_녘
_노
_놉
_누가
_누구
_누구누구
_누군가
_뉘
_닢
_다섯째
_다음달
_다음주
_닥
; _답
_당분간
_대다수
; _댁
; _덤
_덧
_데
; _돗
_되
_두
_둔
_둘
_둘째
_둥
_뒤
_뒷받침
_듯
_등
_따름
_따위
_딴
_때
_때문
; _땡
_떼
_뜀
; _런
; _룰
; _룸
_리
_릴
_마
_마련
_마리
; _마지막
_마찬가지
_막
_만
; _만원
; _만원씩
_만큼
_맏
; _맘
; _맴
_메
_멸
_몇
_무엇
_묶음
_물론
_뭇
_뭣
_밑
; _바
_밖
; _백
; _백만
; _백만원
_밸
_번
_번째
별안간
; _볏
; _본
; _봉
; _분
; *비타민A
; *비타민B
; *비타민C
; *비타민D
; *비타민E
_빈
; _빔
; _빽
; _뻥
; _뼘
_뿐
_사
; _삭
; _삵
_샅
_서
_서로
_석
_섟
; _섶
_세
_세째
; _셈
_셋
_셋째
; _송
_수
_수십
_수십개
; _숱
_쉬
_스스로
_승
; _쌈
; _쌍
_씀
; _씹
아홉째
_안
_앎
_압
_앵
_야
_얘
_어느편
_어디
_어디론지
_어떤때
; _억원
_여
_여러가지
_여럿
_여섯째
_열째
; _예
_예년때
_오
_온
_올
_올해
; _옴
; _옹
_왜
_요즘
_우
; _우리
_우리들
_우선
_운운
_움
_움직임
*웹
_위해서
; *윈도95
; *윈도95시스템
; *윈도NT
_유
_육
_율
_으뜸
; _을
_음
_이것
_이곳
_이기
_이날
_이달
_이달초
_이듬
_이듬달
_이때
_이런저런
_이런줄
_이번
_이번분
_일곱째
; _임
_잇
; _작
; _잔
_잘
; _잭
; _잽
; _쟁
_쟤
_저것
_저곳
_저기
_저기대
_저긴
_저도
_저런날
_저런줄
_저렴
_저마
_저쪽
_저하
_저희
_적극적
_전날
_전년
_전부
_전부문
_전일
_전체적
_절절
; _접
_제
_제나름
; _존
; _좆
; _좌
; _죄
_줄곳
; _줌
_중점적
; _쥔
_증
_지
_지난해
_직
_짓
_쪽
; _찬
; _채
; _챙
; _척
; _천만
; _천명
; _천원
_첫날
_첫째
; _촉
_최
_최근
; _충
_취
_층
_치
; _칭
; _칸
; _캡
_컷
; _켜
; _콕
_쾌
; _쿡
;_크기
; _큰폭
; _킥
_타
_탓
_태
; _토
_톡
; _톤
_톨
; _톳
; _퇴
_투
_퉁
; _판
; _패
; _팽
*페르시아만
_편
_평
;_평상시
; _폼
_푸르름
; _푼
; _필
_하
_하나
_하나둘
_한
_한가운데
_한가지
_한곳
; *한국HP
; *한국IBM
; *한국IBM연구소
_한마디
_한번
_한쪽
_한편
_할
; _합
; _항
*핵
; _행
;_향후
_허
_혁
; _현
; _호
; _홉
; _홍
; _홑
; _화
_확
_환
; _황
; _홰
; _획
; _횡
_후
; _훅
_휘
; _흑
_힐
*힘
;
;=======================[ 불용어, 특수색인어 사전 끝 ]====================
;


: