일단

http://crazia.org

입니다. 별거 아니지만 누르고 들어가면 https://crazia.org 로 바뀝니다. 정말 너무 일반적인 형태의 웹사이트로 보이지만 나름 최신 기술들로 잘 버무려져 있습니다. http2 도 지원함 ㅋㅋ

1 AWS 의 Certificate Manager 를 이용해서 SSL 인증서를 발급 받았습니다.

  • 혁신적이죠. 기존에는 항상 싼 SSL 인증서를 사서 사용했는데, 여기는 클릭 몇번으로 공짜로 인증서를 받을 수 있습니다.

2 AWS 의 ELB (Elastic LoadBalancer) 를 사용하고 ELB 에 인증서를 포함시켰습니다.

  • 기존에는 NginX 에 인증서를 포함시키는 방법을 썼는데 이제는 이렇게 하는게 편하더군요. 알아서 갱신까지 해줘서 설정만 해주면 문제 없습니다.

3 Nginx 를 사용했습니다.

  • 웹서버는 Nginx 죠!! 아파치는 이제 설정하는 법도 까먹었네요 ㅎㅎ
  • SSL 인증서가 ELB 에 있기 때문에 기존에 SSL 인증서 가진 웹서버 세팅으로는 TOO_MANY_REDIRECT 가 발생할 수가 있습니다.
    server{
       listen 80;
    
       server_name crazia.org;
    
       access_log /var/log/portfolio_access.log;
       error_log /var/log/portfolio_error.log;
    
       if ($http_x_forwarded_proto != 'https') {
         rewrite ^ https://$host$request_uri? permanent;
       }
    
       server_tokens off;
       location / {
             proxy_pass http://localhost:3000/;
             proxy_set_header Host $http_host;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header X-Forwarded-Proto $scheme;
             proxy_redirect  off;
     }
    
      gzip on;
      gzip_disable "msie6";
    
      gzip_vary on;
      gzip_proxied any;
      gzip_comp_level 6;
      gzip_buffers 16 8k;
      gzip_http_version 1.1;
      gzip_types text/plain text/css application/json \
        application/x-javascript text/xml application/xml \ 
        application/xml+rss text/javascript
    }
    

    이렇게 80 포트만 신경 써주면 됩니다.

4 clojure 를 사용했습니다.

  • 무지하게 마이너 언어지만 제가 사랑하는 언어입니다.
  • 리습의 방언(dialect) 이고 JVM 기반의 프로그래밍 언어입니다.

5 Luminus 를 사용했습니다.

  • clojure 의 웹프레임워크중의 하나입니다. 그나마 자동화가 많이 되어 있고, 프레임워크 구조 설계가 좋아서 종종 애용하고는 합니다.

6 Jetty 임베디드 방식입니다.

  • WAR 를 만들고 앱엔진에 배포하는 방식이 아니라 Jetty 를 임베디드 시켜서 jar 파일 한개로 앱엔진 + WAS 의 기능을 하게 만들어 주는 것입니다.
  • 일반 스크립트 형 WAS 랑 차이가 뭔가? 바로 그 방식과 유사한 것입니다.

7 Bootstrap 을 이용해서 간단한 화면을 구성했습니다.

  • 말이 필요 없는 그 부트스트랩 입니다.
  • HTML, CSS, JS 를 한꺼번에 알맞게 제공해주죠. 저 같은 디자인 고자(?) 도 대충 이쁜 사이트를 구성하는게 가능해집니다.

8 Systemd 를 이용해서 관리합니다.

  • Ubuntu 16.04 부터 자주 이용해야 하는 관리 스크립트입니다.
  • /lib/systemd/system/myapp.service 위치에 스크립트를 만들고
    [Unit]
    Description=My Application
    After=network.target
    
    [Service]
    WorkingDirectory=/var/myapp
    EnvironmentFile=-/var/myapp/env
    Environment="DATABASE_URL=jdbc:postgresql://localhost/app?user=app_user&password=secret"
    ExecStart=/usr/bin/java -jar /var/myapp/myapp.jar
    User=deploy
    
    [Install]
    WantedBy=multi-user.target
    

    이와 같이 만들어주고 저장하고

    sudo systemctl daemon-reload
    sudo systemctl start myapp.service
    

    스크립트를 인식시키고 시작하면 됩니다. start|stop|restart 가 될 것이고요.

    sudo systemctl enable myapp.service
    

    인스턴스가 재부팅시에 자동으로 시작되게 세팅도 가능합니다. (멋진 기능!!)

클로져는 정말 멋지게도 언어레벨에서 Concurrency 를 지원합니다. 물론 그래서 어렵다는 평을 받긴 하지만 이미 개념을 알고 있는 사람들은 이보다 더 편할 수가 없습니다. 게다가 자바와의 연계성이 뛰어난 점 때문에 클로져는 정말 멋진 언어입니다. 


최근 무어의 법칙이 더이상 통하지 않고 CPU 의 코어수만 늘어나는 상황하에서 멀티쓰레드 프로그래밍을 모른다면 진정한 컴퓨팅 파와를 쓸 수가 없습니다. 그렇기 때문에 저는 예전부터 클로져를 눈여겨 왔었는데요. 그 클로져의 Concurrent Programming 에 관한 괜찮은 글을 찾아서 여기에 소개합니다. 


http://blakesmith.me/2012/05/15/understanding-clojure-concurrency-part-1.html


위는 간단하 개요 소개의 글입니다. 정말 쉽게 설명했습니다. 아쉽지만 영어입니다 ㅎㅎ 


http://blakesmith.me/2012/05/25/understanding-clojure-concurrency-part-2.html


각각의 프로그램 언어에서 지원하는 개념들과 예제입니다. 차분히 읽어 가시면 어려울게 별로 없으니 클로져에 관심이 있다면 꼭 한번 보실만 합니다. 



저번 포스트 에서 Emacs 버젼을 24 로 업그레이드 한 후에 가장 큰 문제가 생겼습니다. ClojureCommon Lisp 개발환경이 동시에 안되는 문제가 발생했습니다. 

몇번의 노력끝에 결국 Emacs 에서도 편하게 설치하는 쪽을 받아들이게 됐습니다. 기존에는 "이맥스 유저는 이래야 해!!" 라는 말도 안되는 자존심으로 수동으로 이거 저거 설치하는 쪽이였으나 이제 대세를 받아들이기로 했습니다. 

클로져 (Clojure) 개발 환경 설정 


예전 포스트 에서 쉽게 설치하는 방법을 소개한 적이 있었습니다.  그러나 swank-js 를 만들었던 당사자가 더 훌륭한 솔루션이 나왔다고 GG 를 쳐버렸습니다. -0- (당신을 믿고 포스팅을 했었다고!!! ㅜ.ㅜ ) 

nRepl 을 설치해줍니다.  

nrepl.el is an Emacs client for nREPL, the Clojure networked REPL server. It's a great alternative to the now deprecated combination of SLIME + swank-clojure.


설치법은 간단합니다. Emacs 24 버젼부터는 Package 관리가 기본으로 포함되어 버렸습니다. 대세는 게을러지기 아니겠습니까? 
.emacs 파일에 다음과 같은 내용을 추가합니다. 


(require 'package)
(add-to-list 'package-archives
    '("marmalade" . "http://marmalade-repo.org/packages/"))
(package-initialize)


그리고 재 시작후 , M-x list-packages 로 출력해서 nrepl 을 찾아서 설치해 주거나 , 설명 페이지에서 추천하는 대로 

M-x package-install [RET] nrepl [RET]



로 설치해주시면 됩니다. 추가로 편리하게 사용하기 위해서 세팅 몇가지만 해주시면 됩니다. 

(add-hook 'nrepl-mode-hook
     (defun clojure-mode-slime-font-lock ()
         (let (font-lock-mode)
             (clojure-mode-font-lock-setup))))


이제 클로져 관련 파일을 열고나서 M-x nrepl-jack-in  를 입력하시면 익숙한 REPL 버퍼가 보일 것입니다. (속도도 Swank-js 보다 빨라졌습니다)


Common Lisp 개발 환경 설정 (SLIME 설정)
 
이제 이것 설치도 쉽게 하는 방법이 있습니다. SBCL 은 이미 설치되어 있다고 가정합니다. (참조사이트 : http://www.mohiji.org/2011/01/modern-common-lisp-on-linux/

일단 quicklisp 파일을 다운 받아야 합니다. http://beta.quicklisp.org/quicklisp.lisp 에서 받아줍니다. 적당한 곳에 옮겨주시고요. 

$ sbcl


sbcl 을 실행시켜줍니다.

user> (load "/path/to/quicklisp.lisp")


sbcl 상에서 위와 같이 quicklisp 파일이 받아진 것을 읽어들입니다.  

user> (quicklisp-quickstart:install)
user> (ql:add-to-init-file)
user> (ql:quickload "quicklisp-slime-helper") 


그리고 위와 같이 연속으로 실행시켜줍니다.  이러면 자연스럽게 SLIME 까지 설치가 됩니다. 이제 Emacs 에게 위치를 알려주는 일만 해주면 됩니다. 

(setq inferior-lisp-program "sbcl")
(load (expand-file-name "~/quicklisp/slime-helper.el"))

이제 M-x slime 을 입력하면 자연스럽게 SLIME REPL 이 뜨게 됩니다.  

May The Source Be With You !!!
 
ClojureScript 라고 들어 보셨는가요? 자바 스크립트 (Javascript) 는 대단히 편리한 언어이고 렉시칼 스코프 (Lexical Scope)를 지원해서 Anonymous Function 이나 Closure 를 지원하는 등, 고급 추상적인 언어가 지녀야할 몇가지 장점을 지니고 있습니다. 또한 문법도 쉽고 그래서 빠르게 전파되고 있습니다. 게다가 V8 엔진을 쓰는 Node.js 등 이제는 속도면에서도 자바(Java)에 필적하고 있습니다. (예전 제 포스트 참조) 

그러나 자바스크립트는 또한 약점이 존재합니다. 자바스크립트 지지자들도 여러번 지적하는 사항이라고 하는데요 (사실 저는 잘 모르겠습니다 -ㅅ- ). 지나치게 단순하고 어딘가 허술하며, 확장시키기 좋지 않으며 어떤 기능을 구현하기 위해서 불편하게 추가해야 하는 사항이 많다는 것입니다. 그런 이유로 커피스크립트 (CoffeeScript) 같은 것이 나와서 자바스크립트의 그러한 문제점들을 보완하고 있다는 것입니다. 

그래서 숨어있던 리습(Lisp)의 추종자들이 구글이 제공하는 Google Closure Compiler 의 힘을 바탕으로 해서 강력한 어둠의 Lispy Magic 을 이용해서 커피 스크립트 같은 것을 만들어 냈습니다. 그것이 바로 ClojureScript 입니다. 

예전에 폴 그레이엄이 말하길 '자신이 개발해야 하는 언어로 가장 생산성 있게 개발하고 싶다면, 그 언어를 이용해서 Lisp 해석기를 만들고 그 리습으로 코딩을 하고 나중에 원래 언어로 컴파일 하라.' 라는 이야기를 한 적이 있습니다. 바로 그렇게 만들어 버린 것입니다. 개발자들은 ClojureScript 로 개발을 하고 Google Closure Compiler 로 컴파일을 하면 자바스크립트 파일이 튀어 나옵니다. 이 파일을 이용해서 Client Side 의 작업과 심지어는 Server Side (Node.jsJavascript 로도 바꾸어 줍니다) 작업까지도 일원화 할 수가 있습니다. 

이름에서도 유추할 수 있듯이 사용하고 있는 Lisp 의 방언 (dialect) 은 바로 Clojure 입니다. 

개요만 찾아서 보시고 바로 튜토리얼로 넘어가면 좋을 것 같습니다. 

무엇이든 지 간에 실제로 짜보기 전에는 공부가 됐다고 말할 수가 없을 것입니다. 그런 의미로 조금 복잡한 프로그램을 만들어 본다면, 거의 할 수 있는 최고의 공부가 될 것입니다. 거기다가 처음부터 차근 차근 만들어 볼 수 있다면? 

그런 의미에서 Nethack 이라는 게임을 클로져로 만들어 보는 것이 정말 괜찮은 공부가 될 수 있을 것입니다.  
저도 우연히 발견한 사이트 인데 정말 많은 공부가 되고 있습니다. 실전 Clojure 공부라고 볼 수 있습니다.

http://stevelosh.com/blog/  

1 부터 차례로 따라하시면 됩니다. 
요즘 Protocol 을 사용해서 (defprotocol) 무엇인가 만들어 보는 중인데, 알 수 없는 이상한 버그가 종종 발생합니다. 분명히 돌아가는 코드인데, 코드를 살짝 변경했는데, method 를 찾을 수 없다는 에러. 답답해서 별 짓을 다 해봤지만 원인을 알 수가 없었는데, 우연히 발견한 방법으로 에러를 추정할 수가 있었습니다. 

target/ 디렉토리 안에 들어있는 class 파일들을 캐싱하다가 definition 을 못 찾는 것으로 추정됩니다. 뻔하게 돌아가야 하는데 안 돌아간다면 project 디렉토리에서

$ lein clean



한 번 실행해 주고 다시 컴파일을 해 준다면 정상적으로 돌아 갈 것입니다. (이 걸 몰라서 몇 주째 고생했음 ㅜ.ㅜ)

ps.
 명령을 실행하기 전에 clojure  연결은 다 끊어 주셔야 합니다. 
 
요즘 Node.js 로 프로젝트를 진행중입니다.  엄청나게 빠르고 편하게 개발할 수가 있는 좋은 개발 환경인데 단 하나의 장점이 너무 빠르게 개발해서 기획이나 클라이언트 개발과 페이스를 맞출 수 없는 단점 아닌 단점이 있습니다. 게다가 페어 프로그래밍 방식으로 일하는 친구마저 있으니 속도가 상상을 할 수 없을 만큼 빠릅니다. (최근에는 진짜 어려운 일이 아니면 페어도 그만두었습니다. 여유를 좀 가지고 일하자고 해서 ㅎㅎ )

그러다 보니 딴 짓을 하게 되더군요. 지금 열심히 만들고 있는 게, DB 에 테스트 데이터를 랜덤으로 만들어서 집어넣는 프로그램을 만들었습니다. 아주 쓸만하더군요. (생각보다 괜찮음 ㅋㅋ) 

그중에서 현재 날짜를 가지고 와서 주어진 포맷팅 형식으로 변환하여 String 타입으로 리턴하는 함수를 만들어 봤습니다. (갑자기 친구놈이 디비 스킴을 바꿔서 ..)



CLisp 이나 C++ 에서는 쉽게 설정하는 함수 인자 기본 값 (Default) 설정하는 방법에 관한 예제입니다. 일단 쉽게 설정하는 방법이 없는 듯 합니다. 

1 user=> (defn bar
2          ([a b]   (bar a b 100))
3          ([a b c] (* a b c)))
4 #'user/bar
5 user=> (bar 5 6)
6 3000
7 user=> (bar 5 6 2)
8 60

이 와 같은 식으로 가장 인자 수가 많은 함수를 내부에서 호출하는 형식으로 꾸며줍니다. 그 외에 다른 방식으로는 :keyword 형식으로 호출하는 등등이 있으나 위에 쓰여지는 방법이 그나마 다른 언어(Language)에 익숙한 방법이라 사료됩니다. 

defn 설명 페이지 


Parallelism Versus Concurrency

Lest our discussion of concurrency and parallelism lead you to think they are the same thing, let’s disentangle the two notions.

Concurrency is the coordination of multiple, usually interleaved threads of execution that are accessing or modifying some shared state.

Parallelism involves state as well, but usually in the inverse. Being an optimization technique used to efficiently utilize all of the available resources (usually computational, but sometimes other resources, like bandwidth) to improve the performance of an operation, approaches to parallelization generally aim to maximize the window of exclusive access to state (or, often, chunks of state) so as to minimize coordination overhead. Rather than involving interleaved threads of execution, the multiple evaluations of a parallelized operation run simultaneously—sometimes on different CPU cores, other times on different physical machines entirely.

-- Clojure Programming 책 중에서 .. 


쉽게 설명하자면 

'동시성' 은 공유되는 자원에 대한 접근이나 변경을 주도하는 쓰레드들을 배치하는 작업에 관한 용어이고 

'병렬성' 은 공유될 수 있는 자원에 대한 최적화된 사용에 관한 용어입니다. 보통 쓰레드 배치나 이런 것은 당연히 적용하지만 잡-스케쥴링 (Job - scheduling) 을 통해서 다중 CPU 일 경우 각각의 CPU 나 코어 에서 작업을 분배시켜서 돌리게 하거나 또는 아예 다른 기계에서 작업을 돌리게 한다던지 와 같은 오히려 작업 분배에 관한 용어로 쓰일 때가 많습니다. 



 

재미로 만들어(만들었 다기 보다는 포팅- Porting) 본 스팸 필터 입니다. 

https://github.com/crazia/spam-filter

여기에 올려두었습니다. (''

 Practical Common Lisp 이라는 책에 보면 폴 그레이엄이 구상한 스팸 필터에 관한 간단한 예제가 있습니다.  그 알고리즘을 바탕으로 책에서는  CLisp 으로 구현한 예제가 있습니다. (Chapter 23 - Practical: A Spam Filter)

위 내용을 바탕으로 해서  Programming Clojure 라는 책을 쓴 Stuart Halloway 가 간단하게  PCL (Practical Common Lisp) 에 있는 예제들을 Clojure 로 옮긴 것들이 있습니다. (practical-cl-clojure)

그런데 몇몇의 내용을 살펴보면 Clojure 예전 버젼에 맞춰서 소스가 만들어져 있고 무엇보다도 클로져의 가장 중요한 기능인 병렬성에 맞게 코딩이 되어 있지 않더군요. 따라서 그 부분을 보강하고 Halloway 가 구현 하지 않고 끝을 낸 부분을 추가하는 중에 있습니다. (train 이나 score 같은 함수들) 

클로져를 따로 공부하시는 분들에게 도움이 될까 해서 github 에 공개를 해둡니다. 

+ Recent posts