Elasticsearch 설정하기

드디어!! AWS 에 있는 Elasticsearch 서비스에 은전한닢 플러그인이 추가 됐습니다. 예전에는 이런 기능이 없어서 제가 따로 elasko 라고 은전한닢에 패치된 형태의 엘라스틱서치의 도커 형태를 만들었습니다. 이제 시간이 지나서 elasticsearch 6.0 이 나오고 (제가 만든 elasko 는 5.5 기반) 문법도 많이 바뀌고 해서 다시금 정리할 필요가 있습니다.

Elasticsearch 편하게 쓰는걸 원하신다면

  1. AWS 에 있는 서비스 추천입니다.
    • 기업 서비스용이라면 100% 추천입니다.
    • kibana 까지 이용하실려면 vpc 가 아닌 ip 기반으로 관리를 선택하세요

그러나 가난한 개인 개발자라면 한달에 EC2 가격만 해도 부담이 되겠지요. 이 글은 가난한 개발자들 위주로 진행하겠습니다. EC2 한대만 허용되어 있다면 docker 에 elasticsearch 를 이용해서 적용하는것이 가성비가 훌륭한 선택입니다.


  1. Elasticsearch 6.1.1 설치하기
    $ docker run -dit --name elastic -p 9200:9200 -p 9300:9300 \
        docker.elastic.co/elasticsearch/elasticsearch:6.1.1
    

    편하게 elasticsearch 가 설치됩니다.  


  2. elastic 컨테이너에 접속하기
    $ docker exec -it elastic /bin/bash
    

    접속해서 root console이 뜹니다.


  3. zip 설치하기

    필요한 것만 설치되어 있는 docker 컨테이너 특성상 zip 이 없습니다.

    # yum install zip
    

    마지막에 물어보는 대답에 'y' 하시면 됩니다.


  4. 은전한닢 패치하기
    $ bash <(curl -s \
       https://bitbucket.org/eunjeon/seunjeon/raw/master/elasticsearch/scripts/downloader.sh)\
         -e 6.1.1 -p 6.1.1.1
    

    엘라스틱서치 6.1.1 버젼에 플러그인 대상 6.1.1.1 버젼을 설치한다는 것입니다.

    $ ./bin/elasticsearch-plugin install \
      file://`pwd`/elasticsearch-analysis-seunjeon-6.1.1.0.zip
    

  5. Elasticsearch 재시작

    꼭 해야 하는지는 모르겠지만 한번쯤 해주는 것도 나쁘지 않아 보입니다.

    $ ps -ef | grep elasticsearch
    

    로 찾은 process 번호를

    $ kill -SIGTERM [process id]
    

    로 죽이면. 컨테이너 밖으로 튕겨 나가게 됩니다.

    $ docker start elastic
    

    밖에서 이 명령으로 다시 띄우시고


  6. 테스트 하기

    제대로 패치된게 맞는지 확인합니다. 기존 은전한닢 사이트에서 제공하는 확인 스크립트를 새버젼 (6.1.1)에 맞게 바꾸어 줍니다.

    #!/usr/bin/env bash
    
    ES='http://localhost:9200'
    ESIDX='seunjeon-idx'
    
    curl -XDELETE "${ES}/${ESIDX}?pretty"
    sleep 1
    curl -XPUT "${ES}/${ESIDX}/?pretty" \-H 'Content-Type: application/json' -d '{
      "settings" : {
        "index":{
          "analysis":{
            "analyzer":{
              "korean":{
                "type":"custom",
                "tokenizer":"seunjeon_default_tokenizer"
              }
            },
            "tokenizer": {
              "seunjeon_default_tokenizer": {
                "type": "seunjeon_tokenizer",
                "index_eojeol": false,
                "user_words": ["낄끼+빠빠,-100", "c\\+\\+", "어그로", "버카충", "abc마트"]
              }
            }
          }
        }
      }
    }'
    
    sleep 1
    
    echo "# 삼성/N 전자/N"
    curl -XGET "${ES}/${ESIDX}/_analyze?&pretty" -H 'Content-Type: application/json' -d '
    {
      "analyzer": "korean",
      "text":  "삼성전자"
    }
    '
    
    echo "# 빠르/V 지/V"
    curl -XGET "${ES}/${ESIDX}/_analyze?&pretty" -H 'Content-Type: application/json' -d '
    {
      "analyzer": "korean",
      "text":  "빨라짐"
    }
    '
    
    echo "# 슬프/V"
    curl -XGET "${ES}/${ESIDX}/_analyze?&pretty" -H 'Content-Type: application/json' -d '
    {
      "analyzer": "korean",
      "text":  "슬픈"
    }
    '
    
    echo "# 새롭/V 사전/N 생성/N"
    curl -XGET "${ES}/${ESIDX}/_analyze?&pretty" -H 'Content-Type: application/json' -d '
    {
      "analyzer": "korean",
      "text":  "새로운사전생성"
    }
    '
    
    echo "# 낄끼/N 빠빠/N c++/N"
    curl -XGET "${ES}/${ESIDX}/_analyze?&pretty" -H 'Content-Type: application/json' -d '
    {
      "analyzer": "korean",
      "text": "낄끼빠빠 c++"
    }
    '
    


요즘 바빠서 글을 잘 못 남기지만 정말 추천할 만한 포스트가 있어서 추천합니다. 간단한 파이썬 코드만 알면 요즘 유행하는 블록체인의 기본 원리를 알고 응용이 가능합니다. 쭈욱 따라하시면 됩니다. 


http://ecomunsing.com/build-your-own-blockchain



끝으로 요즘 여러 이야기가 있지만, 저는 블록체인을 흠잡을 이유가 없습니다. 분산 저장은 시대에 맞는 트렌드라고 봅니다. 다만 거래소가 안전하냐는 이야기는 절대 반대입니다. 돈이 오고 가는 서비스를 그리 허술하게 만들면 안된다고 봅니다. 



crontab 으로 스케쥴 잡 등록 시키기

python 과 crontab 을 잘 연결시키면 스케쥴 작업을 완벽하게 만들 수가 있습니다. 간단한 배치 작업들은 굳이 다른 시스템을 사용할 이유가 없습니다.

기본 editor 를 emacs 로 변경하기

$ export EDITOR=emacsclient

아무 설정을 하지 않으면 vi 로 설정되어 있습니다.

기본적인 기능

CRUD 에서 U 는 C 와 동일하니 기능을 살펴보기로 합니다.

입력 (Create)

$ crontab -e

보기 (Read)

$ crontab -l

지우기 (Delete)

$ crontab -d

주기 결정

*          *        *        *       *
분(0-59)  시간(0-23)  일(1-31)  월(1-12)   요일(0-7)

실제 예

* * * * * ls -la

인코딩 관련

crontab 으로 파이썬 스케쥴을 돌릴때 특히나 console 에 한글을 출력하는 경우에 에러가 자주 발생합니다. Unicode 에러 인데요. crontab 은 shell 환경을 가져오지 않기 때문에 발생합니다. 해결 방법은 의외로 간단합니다. crontab 에서 입력 할때 마치 쉘 환경 처럼 적어주면 끝입니다.

   PYTHONENCODING=utf-8
   LANG=ko_KR.UTF-8          
   0 * * * 1-5 source /Users/crazia/miniconda3/bin/activate /Users/crazia/miniconda3/envs/cr-mon/ && 
   /Users/crazia/miniconda3/envs/cr-mon/bin/python /Users/\
crazia/work/python-projects/cr_mon/manage.py stats >> /Users/crazia/work/stats.log 2>&1

miniconda 상에서 cr-mon 이라는 환경을 만들고 django style console 로 만들어서 실행시키고 로그를 남기는 예제 입니다.

Slide로 이동하기



Emacs 의 Org 모드를 이용해서 간단하게 제작한 Slide 이다. 추후에 KeyNote 버젼을 만들기 전 아이디어 정리 단계로 제작해 본 것이다.  



클라우드 서비스의 종류

클라우드 서비스를 이용해서 자체 서비스를 개발하는 것은 이제 흔한 일이 됐습니다. 저는 처음 클라우드가 만들어졌을 때 대체 이걸 어떻게 상용화 할까? 라고 생각했지만 무엇인가를 팔고 이윤을 남기기 위한 인간의 욕망을 무시하면 안된다는 것을 잘 알게 됐습니다.

그렇다면 클라우드의 종류인 IaaS (Infrastructure-as-a-Service) 와 PaaS (Platform-as-a-Service) 와 SaaS (Software-as-a-Service) 는 어떻게 차이가 있는가?


(출처: blog.msdn.microsoft.com)




위 그림에서 가장 쉽게 이야기 해주고 있습니다. IaaS 는 Host에 주안을 두는 것이고, PaaS 는 build 에 주안점, SaaS 는 consume 입니다. 이보다 더 자세하고 명확하게 알아보기 위해서는 다음 그림에서 확실히 소개하고 있습니다.


(출처: blog.msdn.microsoft.com)




위 그림이 가장 클라우드의 핵심입니다.

Packaged Software

이 경우는 보통 IDC (Internet Data Center) 에 직접 서버를 두고 관리를 하는 경우에 해당합니다. 관리해야 할 내용이 많습니다. 네트워크도 설정해야 하고, 저장소 크기도 상태 확인해 가면서 키워야 하고 서버도 직접 관리 등등 모든것을 직접 관리해야 합니다. 보통 이런 경우에 전문적으로 관리하는 SE (System Engineer) 가 필요한 경우가 많습니다. 조그만 회사에서는 서버 개발자가 전부 관리를 해야 합니다.

클라우드 서비스 전의 IT 회사는 대부분 이런 형태의 서버군을 배포환경으로 구성해야 했습니다.

IaaS

이 경우에는 IDC 에서 해야할 일이 전부 사라진 경우입니다. 그 일과 함께 SE 가 해야할 일도 하드웨어 사이드의 일이 전부 사라집니다. 나쁘게 말하자면 개발자가 어느정도 서버 (보통은 리눅스)의 관리를 할 줄 알게 된다면 SE 가 전혀 필요 없는 경우가 생깁니다.

서버의 인스턴스를 마우스 클릭질 몇번으로 생성하고 내가 필요한 어플리케이션을 서버에 올려서 바로 배포가 가능합니다. 배포를 염두에 뒀을 때 하드웨어 적으로 고려할 사항이 극도적으로 적어졌습니다.

PaaS

이 경우는 IaaS 보다 더 극단적으로 쉬워진 경우입니다. 배포 세팅에 대한 고려도 거의 안합니다. 쉽게 말하면 서버가 구동하기 위한 실행 로직 (흔히들 말하길 Business Logic)만 신경쓰면 됩니다. 이쯤 되면 SE 는 필요하지 않습니다. 개발자는 개발 로직만 만들어서 PaaS 에 올리면 나머지는 클라우드가 알아서 확장이나 상태를 관리하기 쉽게 해줍니다.

SaaS

개발도 필요없는 이미 만들어진 서비스를 이용하는 경우입니다. SE 뿐만 아니라 개발자도 필요없습니다.

어떤 플랫폼이 좋았는가?

사실 이야기 하고 싶은 것은 이 주제였습니다.

만들어야 하는 사이트는 웹 소설 플랫폼이였습니다. 개발 기간을 짧게 잡고 있었기 때문에 주요 개발 언어로는 Python 을 선택했고, 웹프레임워크로는 Django 를 선택했습니다. 대략 개발에만 집중해야 하는 기간이 4개월 정도 였기 때문에 Java 언어 기반으로 하기에는 시간적 부담이 느껴졌습니다.

기본이 OpenMarket 플랫폼이기 때문에 필요한 부분이


  • CP (Contents Provider) 사이트 영역
  • Customer 영역
  • 결제 부분
  • 정산 부분


이 필요합니다. 보통 플랫폼 개발은 개발자도 많이 투입하고 개발이 오래 걸리지만 사이트의 특성상 빠르게 개발하고 빨리 오픈하고 계속해서 고쳐 나가는 방법을 정했습니다.

개발 플랫폼을 정하는 것이 개발 초기의 가장 핵심적인 결정 사항이였기 때문에 여러모로 고심을 하다가 구글 앱 엔진 으로 선택했습니다. 이를 결정한 이유는 위에서도 언급이 있지만 배포나 시스템 설정등을 고려하지 않고 개발에 집중하고 싶었기 때문입니다. 왜 레진 코믹스는 구글 앱 엔진을 선택했나 라는 슬라이드도 보고, 아는 지인도 레진 코믹스에서 개발자로 있어서 자문도 구할 수 있었기에 흔쾌히 결정을 했습니다.


PaaS(Platform as a Service)인 구글 앱 엔진은 일단 신경 쓸게 별로 없습니다. 앱 엔진용 SDK 를 받아서 그걸 이용해서 코딩을 하고 베포와 운영은 아주 쉽습니다. 다만 앱 엔진용 SDK 를 공부하고 익숙해져야 하는 단점이 존재했습니다. 빠르게 프로토타입을 만들때는 정말 좋을꺼라고 생각을 하지만 뭔가 대용량의 시스템을 만들어 갈때는 앱 엔진에 맞춰서 개발해야 하는 점이 부담이 되고 잘못됐을 때 바로잡을 레퍼런스가 부족하다는 단점도 큽니다. 개발자들은 구글 앱엔진용 SDK 가 별로라고 원성이 자자했습니다. 그리고 무엇보다 한국에 IDC 가 없기 때문에 무지하게 느렸습니다. 처음부터 멤캐쉬를 고려하고 개발을 시작해야 한다는 문제입니다. (실제로 레진 코믹스도 느린 속도때문에 고생했었나 봅니다). 그러나 무엇보다 좋은 점은 검색 엔진을 구글것을 쓸 수 있다는 점이 장점이였습니다.


초기의 개발은 문제 없이 진행됐습니다. Google App Engine - Django Skeleton 을 이용해서 장고(Django)를 이용한 서비스를 쉽게 '구글 앱 엔진'에 올릴 수가 있었습니다. 하지만 파일 업로드 기능부터 문제가 발생하기 시작했습니다. 일반적으로는 전혀 문제가 안되는 기능인데 구글 앱 엔진을 이용하면 문제가 되는 현상입니다.


결국 최종적으로 사이트가 완성이 되고 최초 공개가 됐을 때 사이트가 너무 느리다는게 문제로 작용했습니다. 웹이나 앱 서버등이 데이타를 가져오는 데 걸리는 시간이 너무 걸리는 것입니다. 너무 느려서 슬쩍 레진 코믹스 개발자에게 너무 느린게 아닌가. 자문을 했더니 뭐 보통 그정도 속도인데? 이런 반응을 보이는 것입니다. 아니 이 느린 환경에서 개발을 이뤄내고 회사를 그 정도 크기 까지 키운 레진 코믹스의 개발자들이 너무 대단스러워 보이는 것입니다. 그래서 마구 칭찬을 했더니 '니네는 투자도 받았다면서? 그냥 AWS 로 개발하는게 낫지 않겠어?' 라고 하더군요. 그래서 바로 IaaS (Infrastructure as a Service) 인 AWS 로 개발 플랫폼을 바로 바꿨습니다.


변경하는데 1주일 정도 걸리더군요. 아직 실제로 서비스 하는 중이 아니였지만 실제로 운영중이였다고 하더라도 그리 오래걸리진 않았을 것이라고 생각됩니다. 사실 편하게 바꿀 수 있었던 이유중의 한가지는 팀원중의 한명이 리눅스(Linux)를 설치하고 그 안에서 서비스 배포의 경험이 많았던 사람이라서. 마우스 클릭질 몇 번으로 서버가 생기고 그 안에서 배포하는 걸 쉽게 할 수 있었기 때문입니다. 구글 검색이 문제 였는데 이것은 엘라스틱서치 에 한글 자소분석기를 붙인것을 Docker 로 만들어서 배포한 걸 이용해서 2분도 안되서 설치해서 적용했습니다. 물론 검색 API 같은것은 따로 만들어 줘야 했지만 말입니다.


결론적으로 우리 회사는 AWS 를 이용한 IaaS 를 이용하는 것이 여러모로 편했습니다. 서버 이해도가 높은 개발자들이 있어서 더욱 그러했던것 같습니다. 만약 구글 앱 엔진이 그리 속도가 느리지만 않았다면 (구조적인 문제입니다. IDC 가 미국 중부나 심지어 동부에 있으니..) 계속 썼을 수도 있으나 만약 쓴다고 해도 아예 처음부터 멤캐쉬(memcache)를 이용한 방식의 아키텍쳐를 구성해야 했을 것입니다. (이 부분은 다시 잘 정리해야 할듯)


어떤 플랫폼을 쓰느냐에 대해서 정답이 없을 듯 합니다. 다만 조금이라도 복잡한 기능을 구현하려고 한다면 자유도가 높은 IaaS 를 추천합니다.





예전에 Emacs for OSX 관련 설치글에서 File Dired Mode 에서 한글이 깨지는 문제는

(require 'ucs-normalize)
(set-file-name-coding-system 'utf-8-hfs)

위 내용을 .emacs 에 써주면 된다고 했습니다. 그런데 shell-mode 에서 한글이 제대로 출력이 안되는 이슈가 존재합니다.

역시 .emacs 에

(setq default-process-coding-system '(utf-8-hfs . utf-8-hfs))

와 같은 내용을 써주면 해결됩니다.

프로그래밍 언어는 python을 이용하고 웹 프레임워크는 Django 를 사용하고, 데이타베이스로는 MySQL 을 사용중인데 admin 사이트 구현중에

date_hierarchy = 'created_at'

이 구문 때문에

Database returned an invalid value in QuerySet.dates(). Are time zone definitions and pytz installed?

이런 에러가 발생한다.

해결을 위해서는 일단 pytz 를 설치해줘야 한다.

$ pip install pytz

그리고 우분투에 설치된 mysql 에 한하여 (docker 로 설치한 mysql 도 괜찮다, 테스트 해보니 osx 도 된다)

$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p  mysql

하고 데이타베이스를 재시작 하면 된다. docker 데이타베이스는 설정을 바꾸면 재시작이 안되니 조심해야 한다. 원격 데이타베이스에 관해서는 (Google App Engine 의 Cloud SQL 도 가능하다)

$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p  -h $REMOTE_SERVER mysql



각각의 request_log 에 application_log 가 딸려있다. 그리고 각각의 어플리케이션 로그는 형식에 맞춰서 로그를 남길 수가 있으며 위 사진을 보면 알 수 있듯이 각각의 아이콘 그림까지 다르다!! 



A 라는 브랜치에서 B 의 브랜치를 merge 하는 경우라고 치면

$ git checkout A 
$ git merge B

로 A 에다가 B 내용을 merge 하는 명령입니다.

<<<<<<< HEAD
머지 (merge) 가 될 대상 브랜치 이다. 대부분의 경우에는 내가 작업하기 위해서 체크 아웃한 브랜치다. (즉 내꺼, HEAD) 

|||||||

=======
합쳐질 브랜치이다. 

>>>>>>>

즉 위쪽에 있는 것이 (보통 git 에서는 HEAD 라고 붙어 있습니다.) 현재 내가 작업하던 브랜치 , 아래쪽이 다른 브랜치 (pull 명령중이면 리모트 브랜치)의 내용이니 비교해서 적용하면 됨

클로져(Closure)에 대한 말들은 많다. 최근 핫하다고는 하지만 전산의 태동기부터 존재하던 문법이다. 1급 객체(First class Object)를 지원하는 언어는 자연스럽게 지원하지만 개념 자체를 이해 못하는 경우가 많다.

파이선과 연계해서 클로져(Closure)를 설명하는 좋은 설명이 있어서 소개하고자 한다.

Objects are data with methods attached, closures are functions with data attached.

객체는 메서드가 달라붙어 있는 데이타라면, 클로져는 데이타가 달라붙은 함수이다.

예제는

def make_counter():
  i = 0
  def counter(): # counter() is a closure
    nonlocal i
    i += 1
    return i
  return counter

c1 = make_counter()
c2 = make_counter()

print (c1(), c1(), c2(), c2())
# -> 1 2 1 2

위에서 보면 counter 라는 함수가 i 라는 데이타를 포함하고 있는 클로져(closure)다.

http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python

+ Recent posts