Elasictsearch With 은전한닢 for Windows



옛날 버전의 게시글입니다.
최신 버전의 elasticsearch 에서는 nori 라는 한국어 형태소 분석기를 자체적으로 내장하고 있어 아래와 같이 복잡하게 설치하지 않아도 됩니다.

docker 기반으로 설치하는 게시글은 제가 추가로 정리했습니다.

아래 게시글에서 확인 가능합니다.
https://sooyeol86.blogspot.com/2019/12/elasticsearch-with-nori-feat-docker.html

docker를 사용하고 싶지 않은 분은 최신버전의 elasticsearch 를 받아서 직접 설치하시고
nori 플러그인만 인스톨 하면 간단하게 설치가 끝납니다. (엄청 쉽습니다!)

bin/elasticsearch-plugin install analysis-nori 
요고 한줄이면 설치가 됩니다.


아래 공식사이트 참고)
https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-nori.html


추가로 nori + 사용자사전 + 유의어사전 + 품사에 대한 간략한 설명한 게시글도 작성했습니다.
품사에 대해서 참고하시면 검색엔진 구축 시 조금이나마 도움이 될 수 있을 것 같습니다.
https://sooyeol86.blogspot.com/2019/12/elasticsearch-nori.html


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



ElasticSearch를 처음 접한 건 2013년 경에 회사 프로젝트를 진행하며 형태소분석기를 사용해야 할 일이 있어서 접하게 되었다.
당시는 Elasticsearch를 검색엔진으로 사용하지 않고, 은전한닢 만 형태소 분석하는 목적으로 사용을 해봤다.

그리고 해당 경험을 바탕으로 2016년에 Elastichsearch를 사용하여 검색엔진을 구축했다.
하지만 당시에는 윈도우에서 최신버전의 은전한닢을 사용할 수 없어 상당히 낮은 버전의 Elastichsearch (0.9버전) 으로 구축을 했다.

, 시간이 흘러 2017년에 Elasitchsearch를 사용하여 새로 검색엔진을 구축할 일이 있었고,
검색을 해보니 친절하신 분께서 윈도우에서도 손쉽게 은전한닢을 쓸 수 있도록 빌드를 해주셨다.

나는 추 후 참고를 위해 해당 내용을 간략하게 정리를 해볼 생각으로 글을 작성해 둔다.


# 준비물
           Elastichsearch (검색엔진) : x64 v5.5.0
           은전한닢 플러그인 (형태소분석기) : v5.5.0
           Mecab-ko / mecab-ko-dic / mecab-java
           JDK : x64 1.8 144


# 설치 및 테스트
01.   JDK 설치
A.     JDK 1.8 x64 144 버전으로 구축 진행.
02.   JAVA_HOME 설정
A.     시스템 > 고급시스템 설정 > 환경변수 에 JAVA_HOME 생성
03.   환경변수에 PATH 설정
A.     Java 경로 설정
04.   Mecab 다운로드
B.      mecab-ko-msvc 다운로드
C.      mecab-ko-dic-msvc 다운로드
D.     mecab-java-msvc 다운로드
05.   mecab 설치 및 테스트
A.     다운로드 받은 파일을 c:\mecab 폴더에 압축 해제
* 해당 폴더에 압축 해제 하지 않을 경우 Elastchsearch 와 제대로 연동이 안될 수 있음. (github 참고)
B.      Mecab 폴더 path 설정
                         i.         환경변수에서 path 설정
C.      CMD 창을 열어서 test.java 파일 빌드 (반드시 encoding UTF-8로 해야함)
Javac encoding UTF-8 test.java
D.     빌드한 파일 실행
Java test
06.   Elasticsearch 다운로드
A.     Elasticsearch 5.5.0 버전 사용
07.   Elasticsearch 설치
A.     C:\Elastichsearch 폴더에 받은 파일 압축 해제
B.      C:\Elastichsearch\config\ elasticsearch.yml 에 설정
                         i.         쿼리 조건 길이를 확장하고 싶은 경우 아래 코드 추가
                        ii.         indices.query.bool.max_clause_count : 10240
08.   은전한닢 플러그인 설치
A.     CMD 창 열어서 아래 명령어 실행
정상적으로 설치 되면 아래와 같이 폴더가 생김.
09.   Elastichsearch 서비스 등록
A.     elasticsearch-service install
10.   Elastichsearch 서비스 환경설정
A.     시작 옵션 설정
B.      자바 가상 메모리 조절 (필요한 경우)
11.   Elastichsearch 서비스 시작
초기 서비스 등록 후 자동시작이 되어 있지 않기 때문에, 수동으로 시작을 해줘야 함.
위의 옵션으로 자동 시작하게 하면 재부팅 후 부터는 자동으로 시작하게 됨.
12.   Elastichsearch 실행 및 은전한닢 형태소 분석기 정상 동작 확인
A.     Elasticsearch 동작 확인
GET 으로 http://localhost:9200 페이지 호출
B.      Index 생성
PUT 으로 http://localhost:9200/test/ 호출
##호출하는 JSON 본문##

{
 "settings":
 {
  "index": {
   "max_result_window" : 500000,
   "analysis": {
    "analyzer": {
     "korean_index": {
      "type": "custom",
      "tokenizer": "mecab_ko_standard_tokenizer"
     },
     "korean_query":
     {
      "type": "custom",
      "tokenizer": "korean_query_tokenizer"
     }
    },
    "tokenizer": {
     "mecab_ko_standard_tokenizer": {
      "type": "mecab_ko_standard_tokenizer",
      "mecab_args": "-d C:/mecab/mecab-ko-dic"
     },
     "korean_query_tokenizer": {
      "type": "mecab_ko_standard_tokenizer",
      "compound_noun_min_length": 100,
      "mecab_args": "-d C:/mecab/mecab-ko-dic"
     }
    }
   }
  }
 }


}

C.      형태소 분석 요청
POST http://localhost:9200/test/_analyze?analyzer=korean_query 페이지 호출
##결과 JSON##

{

 "tokens": [
  {
   "token": "은전",
   "start_offset": 0,
   "end_offset": 2,
   "type": "NNG",
   "position": 0
  },
  {
   "token": "한",
   "start_offset": 2,
   "end_offset": 3,
   "type": "NR",
   "position": 1
  },
  {
   "token": "닢",
   "start_offset": 3,
   "end_offset": 4,
   "type": "NNG",
   "position": 2
  },
  {
   "token": "프로젝트",
   "start_offset": 4,
   "end_offset": 8,
   "type": "NNG",
   "position": 3
  }
 ],
}


HTTP/2 프로토콜에 대한 간략한 정리


1-2년 정도 전부터 HTTP/2 프로토콜에 대한 얘기가 자주 나왔었던 것 같다.
나도 우연하게 HTTP/2 프로토콜 에 대해서 접하게 되 해당 내용을 간단하게 정리를 한다.
처음 접했을 때는 서버와 소스코드를 둘 다 적용을 해야 http/2 사용이 가능한지 궁금해서 내용을 찾아봤다.

HTTP/2 프로토콜에 대해선 자세하게 정리 되 있는 글들이 있어서 해당 글을 링크 걸고 간략하게만 정리한다.

# HTTP/2 목적
           지연 시간을 줄이는 것.
- 전체적 요청 응답 다중화 지원
- HTTP 헤더 필드 효율 적 압축을 통한 오버헤드 최소화
- 요청 우선 순위 지정 및 서버 푸시 지원

# HTTP/2 역사
           Google에서 2009년에 SPDY(스피디) 라는 실험 프로토콜을 발표함.
           HTTP Working Group(HTTP-WG)에서 SPDY에 자극 받아 새로운 HTTP/2 프로토컬을 만들고 표준이 되기 위해 움직임. (초기 출발점으로 SPDY 사양이 채택됨)
           SPDY HTTP/2 가 양존하며 같이 발전해오다가, Google에서 공식적으로 SPDY 지원 중단 일정을 발표함.

# HTTP/2 속도개선
           HTTP/1.1 프로토콜의 경우 브라우저에서 Connection 회수를 도메인 당 6-8건 정도로 제한을 둠. (참고 : https://code.i-harness.com/ko/q/2321284)
           HTTP/2 프로토콜의 경우 도메인 당 1개의 Connection 만 연결하기 때문에 브라우저에서 제한을 걸지 않음.
           새로운 형태의 바이너리 프레이밍 계층을 만들어서 헤더 사이즈를 효율적으로 압축하고 줄였음. (오버헤드가 적어지기 때문에 비용이 적게 발생)
           리소스간의 우선순위를 설정할 수 있게 함.
           서버 푸시를 통해 클라이언트가 HTML 을 분석 후 요청을 하지 않아도 리소스를 서버가 판단하여 전달할 수 있음.

# HTTP/2 속도 데모 사이트
           http://www.http2demo.io/
          

# HTTP/2 적용 확인 방법
           1. 크롬 확장 플러그인을 통한 확인
해당 플러그인을 설치하면 우측에 번개모양 표시가 있고 해당 번개모양의 색상으로 적용여부를 알 수 있음.
파란색 : HTTP/2 , 초록색 : SPDY , 회색 : 미적용
2. 개발자 도구를 통한 확인
F12 개발자도구에서 프로토콜을 통해서 확인 가능.


여기서부터는 테스트 서버 구축에 대한 설명

작성자는 보통 ASP.NET 개발을 진행하여 IIS 서버가 익숙해서 IIS에서 테스트 서버 구축이 가능한지 검색을 해보았으나, IIS 10 부터 지원한다고 되 있다.
실제 적용한다고 봤을 때 대부분의 서버는 IIS 8.5 가 설치 되 있기 때문에 현실적이지 못하다고 판단하고 IIS로 테스트 진행을 빠르게 포기했다.
대신 Node JS 를 통해 간단하게 서버구축 후 테스트 가능할 것 같아 Node JS를 통해 구축한 내용 정리한다.
참고1) 지원 브라우저 목록 : https://caniuse.com/#feat=http2

참고한 사이트http://blog.hellworld.me/12

# Node JS 설치
           NodeJS 사이트 : https://nodejs.org/en/
           NodeJS 사이트에 접속하여 설치 파일 받아서 설치 진행. (그냥 다음 다음 다음 누름 설치 됨)
           이미 검색을 통해 많은 설치방법을 찾을 수 있음.

# Node JS 서버 작업할 폴더를 생성
           D:\node2 폴더를 만들고 해당 폴더로 지정할 예정
          

# Plugin 설치
           플러그인 설치는 cmd 명령어로 설치
           1. express 플러그인 설치 (npm install express)
          

           2. fs 플러그인 설치 (npm install fs)
          
          
           3. spdy 플러그인 설치 (npm install spdy)
          

# 사설 인증서 생성 (Feat. OpenSSL)
           빌드를 해서 쓸 수 있지만 귀찮으니까 Binary 파일을 직접 다운 받음
           다운 받은 파일을 C:\OpenSSL 에 압축을 품.
           명령어 실행 (openssl req -x509 -newkey rsa:4096 -keyout self.key -out self.crt –nodes)
          
           Self.crt (인증서) 파일과 self.key (Key) 파일) 이 생성 됨.
           해당 파일을 아까 생성한 폴더(d:\node2)로 복사

# html 파일 생성 – index.html
           위에서 언급한 demo 사이트의 일부 소스를 발췌하여 테스트

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="utf-8" />
</head>
<body>
<DIV id="IMGLoad">
 <DIV class="imgGroup">
  <DIV class="imgInner">
   <DIV class="imgRow">
    <IMG width="32" height="48" src="static/tile_0.png"> <IMG width="32" height="48" src="static/tile_1.png"> <IMG width="32" height="48" src="static/tile_2.png"> <IMG width="32" height="48" src="static/tile_3.png"> <IMG width="32" height="48" src="static/tile_4.png"> <IMG width="32" height="48" src="static/tile_5.png"> <IMG width="32" height="48" src="static/tile_6.png"> <IMG width="32" height="48" src="static/tile_7.png"> <IMG width="32" height="48" src="static/tile_8.png"> <IMG width="32" height="48" src="static/tile_9.png"> <IMG width="32" height="48" src="static/tile_10.png"> <IMG width="32" height="48" src="static/tile_11.png"> <IMG width="32" height="48" src="static/tile_12.png"> <IMG width="32" height="48" src="static/tile_13.png"> <IMG width="32" height="48" src="static/tile_14.png"> <IMG width="32" height="48" src="static/tile_15.png"> <IMG width="32" height="48" src="static/tile_16.png"> <IMG width="32" height="48" src="static/tile_17.png"> <IMG width="32" height="48" src="static/tile_18.png">
   </DIV>
   <DIV class="imgRow">
    <IMG width="32" height="48" src="static/tile_19.png"> <IMG width="32" height="48" src="static/tile_20.png"> <IMG width="32" height="48" src="static/tile_21.png"> <IMG width="32" height="48" src="static/tile_22.png"> <IMG width="32" height="48" src="static/tile_23.png"> <IMG width="32" height="48" src="static/tile_24.png"> <IMG width="32" height="48" src="static/tile_25.png"> <IMG width="32" height="48" src="static/tile_26.png"> <IMG width="32" height="48" src="static/tile_27.png"> <IMG width="32" height="48" src="static/tile_28.png"> <IMG width="32" height="48" src="static/tile_29.png"> <IMG width="32" height="48" src="static/tile_30.png"> <IMG width="32" height="48" src="static/tile_31.png"> <IMG width="32" height="48" src="static/tile_32.png"> <IMG width="32" height="48" src="static/tile_33.png"> <IMG width="32" height="48" src="static/tile_34.png"> <IMG width="32" height="48" src="static/tile_35.png"> <IMG width="32" height="48" src="static/tile_36.png"> <IMG width="32" height="48" src="static/tile_37.png">
   </DIV>
   <DIV class="imgRow">
    <IMG width="32" height="48" src="static/tile_38.png"> <IMG width="32" height="48" src="static/tile_39.png"> <IMG width="32" height="48" src="static/tile_40.png"> <IMG width="32" height="48" src="static/tile_41.png"> <IMG width="32" height="48" src="static/tile_42.png"> <IMG width="32" height="48" src="static/tile_43.png"> <IMG width="32" height="48" src="static/tile_44.png"> <IMG width="32" height="48" src="static/tile_45.png"> <IMG width="32" height="48" src="static/tile_46.png"> <IMG width="32" height="48" src="static/tile_47.png"> <IMG width="32" height="48" src="static/tile_48.png"> <IMG width="32" height="48" src="static/tile_49.png"> <IMG width="32" height="48" src="static/tile_50.png"> <IMG width="32" height="48" src="static/tile_51.png"> <IMG width="32" height="48" src="static/tile_52.png"> <IMG width="32" height="48" src="static/tile_53.png"> <IMG width="32" height="48" src="static/tile_54.png"> <IMG width="32" height="48" src="static/tile_55.png"> <IMG width="32" height="48" src="static/tile_56.png">
   </DIV>
  </DIV>
 </DIV>
</DIV>
</body>
</html>



서버 js 파일 생성 #1 (view 코드) – app.js

var express = require('express');

var fs = require('fs');
var app = express();
app.use('/static', express.static('public'));

app.get('/', function (req, res) {
 console.log("Index Page Call");
 fs.readFile('index.html', function(error, data) {
  res.writeHead (200, { 'Content-Type' : 'text/html' });
  res.end(data);
 });
});



module.exports = app;


서버 js 파일 생성 #2 (http/2 설정 및 서버 open 코드) – app2

var fs = require('fs');

var spdy = require('spdy');
var app = require('./app');

var options = {
 key: fs.readFileSync('self.key'),
 cert: fs.readFileSync('self.crt')
 //protocols: [ 'h2', 'spdy/3.1', ..., 'http/1.1' ] //HTTP2부터 HTTP1.1 까지 다양합니다.
};



spdy.createServer(options, app).listen(8080);

서버 js 파일 생성 #2 (http 설정 및 서버 open 코드) – app3

var express = require('express');
var fs = require('fs');
var app = express();

app.use('/static', express.static('public'));

app.get('/', function (req, res) {
 console.log("Index Page Call");
 fs.readFile('index.html', function(error, data) {
  res.writeHead (200, { 'Content-Type' : 'text/html' });
  res.end(data);
 });
});

app.listen(3000, function() {
 console.log('server start.');
});

# http2 테스트 서버 호출 (node app2)

Blogger 에디터 변경에 대한 연구..


이것저것 저장 목적으로 글을 작성을 하려고 블로그를 신설했다.
근데, Blogger 에디터를 써보니 오래된 에디터라 아래와 같이 불편함이 있었다.
           - 캡쳐 붙여넣기가 되지 않는 문제.
           - Code Highlight 코드 삽입이 불편한 문제.
           - 뭔가 깨끗하게 생성되지 않는 듯한 html 코드

위의 문제점들을 어떻게 하면 개선할 수 있을지에 대해서 고민을 시작했다.

#1 Windows Live Editor
많은 사용자들이 Blogger 에디터의 불만을 갖고 사용하는 툴이라고 한다.
하지만, Windows 10 에서는 지원하지 않는 것 같다. (설치가 되지 않는다)
           별도의 툴을 설치해야 하는 불편함 때문에 고민 되기도 했다
ð Pass

#2 Blogger Api 를 통한 직접 개발
           내가 원하는 에디터를 쓸 수 있기 때문에 좋을 것 같았고,
           Code Highlight 삽입하는 것도 별도 플러그인을 추가를 통해 쉽게 입력할 수 있을 것 같았다.
           하지만, 난 개인 서버를 갖고 있지 않다. Summernote를 붙여서 Api를 연동하기 위해서는 개인 서버가 필요할 듯 하다.
ð  Pass

#3 Email 을 통한 글 작성
           회사에서 글을 쓸 경우 회사 메일 클라이언트 (outlook) 외부에서 글을 쓸 경우 개인 메일을 통해 작성이 용이할 것 같았다.
           보통 이메일의 경우 직접 html 입력을 제공해주지 않기 때문에 Code Highlight 를 입력은 여전히 불편할 것 같다.
           하지만, 임시로 저장을 하고 Blogger에서 2차 수정을 하는 방식으로 사용하면 나름 유의미할 것 같다.
ð 일단은 이거로 GO..


# 결론
           일단은 Email 을 통한 글 게시를 통해 글을 작성해보기로 한다.
           현재 이 글도 그렇게 작성해보고 있다.


# 이메일 글 게시 설정 및 게시하는 방법
1. 설정 작업
설정 > 이메일 > 이메일을 사용하여 글 게시 > 이메일을 통해 즉시 게시 or 이메일을 임시 글로 저장 (나의 경우 이메일을 임시 글로 저장)
ID+스트@blogger.com 으로 메일 주소를 만들어주고 설정 저장
2. ID+스트@blogger.com 으로 메일 전송
           메일 제목 : 글 제목
           메일 내용 : 글 내용

Blogger에 Code Highlight 적용하기


이것 저것 테스트를 해보면서 정리를 해야할 공간이 필요해서 블로그를 신설해봤다.

정리된 코드를 이쁘게 보기 위해서는 code highlight 가 지원이 될 필요성이 있어 혹시 몰라 해당 방법을 정리해둔다.


블로그 [설정]에서 [테마]를 선택하여 페이지 이동 후 [HTML 편집]을 진행한다.


</head> 코드 위에 아래 코드를 삽입하고 사용한다.


<link href='//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/obsidian.min.css' rel='stylesheet'/>
<script src='//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js'/>
<script>hljs.initHighlightingOnLoad();</script>

사용하는 방법은 별거 아래 코드와 같이 html 모드로 삽입을 하면 된다.

<pre><code class="language-html">
&lt;link href='//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/obsidian.min.css' rel='stylesheet'/&gt;
&lt;script src='//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js'/&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;
</code></pre>

근데 이거 블로그 글쓰기 및 사용방법이 너무 불편하다....

간단한 AWS 웹 서버 구축 with mongodb (feat. Github and Docker)

오랫만에 블로그에 게시글을 업데이트 해봅니다. 최근에 AWS 로 서버 구축하는 것을 테스트 해본 것이 있어서, 이번 게시글에서는 AWS 를 사용하여 간단하게 웹 서버 구축하는 것을 진행하려고 합니다. AWS EC2 서버 프리티어 버전으로 1대 발급 받...