In console 'Terminal'

$ sudo apt-get install clojure
$ sudo apt-get install leiningen
$ sudo apt-get install slime

install clojure-mode

$ cd ~/.emacs.d
$ git clone git://github.com/technomancy/clojure-mode.git

append to dot-emacs

$ emacs ~/.emacs

add followings below

    (add-to-list 'load-path "~/.emacs.d/clojure-mode/")
    (require 'clojure-mode)

install swank-clojure

$ lein plugin install swank-clojure 1.3.3

make clojure test project
   
$ mkdir ~/tmp
$ cd ~/tmp
$ lein new test-project
$ cd test-project
$ lein deps

invoking slime for clojure
   
$ emacs project.clj

in Emacs

M-x clojure-jack-in

enjoy yourself!!

for Korean

클로져를 Emacs 랑 연동하는 방식이 여러가지가 존재합니다. 이거 저거 다 해봤는데 잘 안되더군요. 개인적으로 apt-get 을 이용해서 개발환경 관리하는 것을 즐겨하는 편인데 잘 뒤져봐도 이것에 관한 내용들이 없더군요. 그래서 정리해 봤습니다.

터미널 창에서 다음 과 같이 입력해 줍니다. emacs 는 이미 설치가 되어 있다고 가정합니다.

$ sudo apt-get install clojure
$ sudo apt-get install leiningen
$ sudo apt-get install slime

클로져 모드 (Clojure-mode) 를 설치해줍니다. git 는 이미 설치가 되어 있다고 가정합니다.

$ cd ~/.emacs.d
$ git clone git://github.com/technomancy/clojure-mode.git

.emacs 를 열어서

$ emacs ~/.emacs

다음과 같은 내용을 추가해 줍니다. 이는 클로져 모드를 쓸 수 있게 해주는 것입니다.

    (add-to-list 'load-path "~/.emacs.d/clojure-mode/")
    (require 'clojure-mode)

 스웽크 클로져(swank-clojure)를 설치해줍니다. slime 이 연결하는 대상이 될 것입니다.

$ lein plugin install swank-clojure 1.3.3

테스트용으로 clojure 프로젝트를 만들어 봅니다.
   
$ mkdir ~/tmp
$ cd ~/tmp
$ lein new test-project
$ cd test-project
$ lein deps

실제로 slime 하고 연동해 보기로 합니다.
   
$ emacs project.clj


clj 파일을 열어서 Emacs 상에서 다음과 같이 명령을 입력해 주면

M-x clojure-jack-in

바로 Slime 하고 연동되서 뜨는 것을 확인하실 수 있습니다.
 


Closure 라고 들어 보셨는지요. 최근에 차기 Java 버젼에 포함되기를 많은 사람이 희망하였다가 무산 되서 실망의 글로 자바 관련 게시판들이 도배가 됐다고 합니다. 자 그러면 대체 클로져 (Closure) 란 무엇인지 위키피디아의 내용을 보기로 하겠습니다.


http://en.wikipedia.org/wiki/Closure_%28computer_science%29


어려운 내용들로 도배가 되어 있습니다. 쭈욱 살펴보자면 함수를 리턴하는 언어들에게서 흔히 찾아 볼 수 있는 개념이고요. Anonymous Function 하고 착각하면 안된다고 쓰여져 있습니다. 즉 'function value' 개념이라는 식으로 언급이 되어 있습니다.


가장 쉽게 설명하자면 '지역 변수' 가 코드가 쓰여질 때의 값으로 지정되는 것이 아니라 '클로져'가 생성될 때 그 '값'에 접근이 가능하다? 라는 식으로 쓰여질 수가 있겠습니다. 


이러니 저러니 해도 여러가지 형태가 결부되어 있지만 , 


1. 함수가 리턴 되어야 하고

2. variable 이 관련 있어야 한다. (이것이 관련 없으면 클로져가 아니다)



아무래도 정말 쉽게 설명 하자면 예제 케이스를 가지고 설명하는 것이 가장 쉬울 것 같습니다.

EDITED. 2012 - 09 - 04

아무래도 Lisp 의 방언인 Clojure 로 설명을 하니 못 알아먹겠다는 원성이 자자해서 위키 페이지에 나와 있는 자바스크립트를 예로 설명드리겠습니다. 

function derivative(f, dx) {
  return function (x) {
    return (f(x + dx) - f(x)) / dx;
  };
}

함수 derivative 는 f 라는 함수와 dx 라는 변수를 입력받아서 , x 라는 인자를 받아서 처리하는 함수를 리턴하는 함수 입니다. 

리턴되는 function(x) 는 derivative 에서 넘겨받은 f 와 dx 에 영향을 받을 수밖에 없겠지요? 즉 리턴되는 function (x) 는 어찌 되었든 간에 derivative 에서 넘겨 받는  f 와 dx 에 의존해서 구현이 달라집니다. 이때 function(x) 가 derivative 의 인자인 f 와 dx 와 클로져 (Closure) 다 라고 합니다. 



클로져 (Clojure) 로 만든 Closure 의 예입니다. (발음이 같은 이유는 바로 관련이 있기 때문입니다)  함수를 세분해서 설명하겠습니다.


user> (defn make-greeter [greeting-prefix]
        (fn [username] (str greeting-prefix ", " username)))
#'user/make-greeter


make-greeter 라는 함수를 리턴하는 함수입니다. greeting-prefix 값을 받아서 그 값을 이용하는 함수를 리턴합니다.
defn 은 함수 선언을 지정하는 함수이고요. fn 은 내부 함수 선언용입니다. (str greeting-prefix ", " username) 이 부분 greeting-prefix 랑 " , " username 을 합쳐서 리턴하는 명령 입니다.

user> (def hello-greeting (make-greeter "Hello"))
#'user/hello-greeting

make-greeter 에 "Hello" (greeting-prefix 값이 "Hello" 가 됩니다) 를 인자로 넘겨서 반환되는 함수를 hello-greeting 으로 지정해 줍니다.

user> (hello-greeting "crazia")
"Hello, crazia"
user>

완성된 함수를 테스트 해봅니다.  greeting-prefix 값이 변함에 따라서 전혀 다른 함수가 만들어 집니다. "Hello" 대신 "Hi " 를 넣어서 리턴되는 함수는 또 다른 함수가 되겠지요? 자 이때!!!

make-greeter 에 의해서 리턴되는 함수가 greeting-prefix 값 에 대한  closure 다

이라고 합니다.


"실제로 고수인 것도 중요하지만, 고수처럼 보이는 것 또한 중요하다"

제가 늘상 하고 다니는 이야기 입니다. 사람은 인식의 동물입니다. 아무리 고수라고 하더라도 평범하게 보이면 사람들은 깔보는 법입니다. 사실 그런 태도를 불식시키기 위한 행동의 일환입니다. Ubuntu, Console , Terminal, Emacs, Conkeror 등을 남들이 보면 '엇 저게 뭐지?' 라고 볼 수 있는 것을 잘 쓰면 사람들은 놀랍니다. 게다가 자신의 이해범주를 벗어난 것을 보면 사람들은 쉽게 포기합니다. 그리고 합리적으로 빠르게 결정짓습니다. "고수인가 보다.." - 혹은 '오타쿠 인가 보다..'

자 서론이 길었습니다. 컨커러 (conkeror) 는 Emacs 와 같이 단축키로 브라우징을 하는 Emacs 형 브라우져 입니다. 즉 마우스를 거의 쓸일이 없는 (사실은 약간 써야 합니다. 아직은 불완전 해서리..) 브라우져 입니다. Emacs 를 사용하는 사람이라면 한번쯤은 써볼만 합니다. (설치는 http://conkeror.org/#InstallationandStartup 에서) 게다가 이런걸로 브라우징을 하고 있으면 남들이 특이하게 고수로 봅니다. (누누이 말하지만 겉보기 포스가 중요합니다.)

회사에서 일하다 보면 정말 귀찮은 보안정책이 저를 귀찮게 합니다. 사실 보안정책이라는 것은 70%의 사람을 통제하기 위함이지요. (저는 그 70% 안에 안들어간다고 생각합니다) 가장 쉽게 'ssh 터널링'이라는 것을 쓰면 대부분의 방화벽을 뚫을 수가 있습니다. 이 이야기는 'ssh 터널링'을 이미 쓰고 있다고 가정하고 글을 쓰는 것입니다.

그래서 컨커러를 쓰다 보면 proxy 설정을 할 필요가 있습니다. 그런데 컨커러는 아직 개발중이라 설정 창이라는 개념이 없는 듯합니다. 그래서 Mozilla 의 설정하는 방법을 몇개 차용했습니다.

이제부터 방법입니다.

1. 컨커러 (conkeror) 의 주소창에서 about:config 를 입력합니다.

2. 다음 그림과 같이 입력합니다. 굵은 부분만 써주시면 됩니다. 10008 은 자신의 터널링 포트를 적어주시면 됩니다.



이제부터 회사가 막아논 사이트를 즐겁게 돌아다니면 됩니다.


몽고 DB 에서 간단한 맵 리듀스 (MapReduce)를 돌려보겠습니다.

예제의 원문은

http://cookbook.mongodb.org/patterns/pivot/

에서 찾을 수 있습니다.


db.actors.insert( { actor: "Richard Gere", movies: ['Pretty Woman', 'Runaway Bride', 'Chicago'] });
db.actors.insert( { actor: "Julia Roberts", movies: ['Pretty Woman', 'Runaway Bride', 'Erin Brockovich'] });

기본이 되는 데이터를 집어 넣습니다.

map = function() {
  for(var i in this.movies){
    key = { movie: this.movies[i] };
    value = { actors: [ this.actor ] };
    emit(key, value);
  }
}


map 함수입니다. mapreduce 를 돌리는 대상이 아래에도 나오지만 actors 이기 때문에 this 는 actors 컬렉션을 지칭한다고 보면 됩니다.

  for(var i in this.movies){

map 은 대체적으로 모든 데이터 한 row 당 매핑 (mapping) 된다고 보면 되기 때문에 actors 의 한 row 는 actor 한개와 movies 여러개가 들어 있습니다. 첫 줄은 movies 갯수만큼 for 문을 돌리라는 이야기 입니다.

    key = { movie: this.movies[i] };

key 값은 영화명으로 지정해 주는 것입니다. 해쉬 값으로 설정되는 것이겠지요? {movie: **** } 형태입니다.

    value = { actors: [ this.actor ] };

value 값은 배우명으로 지정해 주는 것입니다. 역시 해쉬 값으로 설정되는 것입니다. {actors: ***}

    emit(key, value);

map 함수들이 보통 하는 것이 reduce 에게 전달하기 위한 값들을 추출하는 것이 목적이기 때문에 (key, value) 쌍으로 값을 송출합니다.


reduce = function(key, values) {
  actor_list = { actors: [] };
  for(var i in values) {
    actor_list.actors = values[i].actors.concat(actor_list.actors);
  }
  return actor_list;
}

리듀스 (reduce) 함수는 프레임워크가 맵 (map) 함수에서 송출된 데이터를 key 값으로 정렬 시킨 값을 넘겨 받습니다. 넘겨 받는 인자가 (key, values) 로 바뀐것을 주목하시면 됩니다. 즉 map 에서 송출한 데이타들을 key 값으로 정렬한 것입니다. 즉 { movie : aaa } 라는 key 값으로 { actors : [bbb , ccc]} 라는 값으로 넘어옵니다.

  actor_list = { actors: [] };

reduce 함수는 일정한 형태로 값을 넘겨 받아야 합니다. 그 형식을 만들어 주는 것이라고 보면 됩니다. (단  key, value 가 한개씩 붙어 있는 형태는 reduce 를 거치지 않고 바로 db 에 쓰여집니다)

  for(var i in values) {
    actor_list.actors = values[i].actors.concat(actor_list.actors);
  }

values 에 있는 값들을 한개씩 리턴할 값에 붙여 주는 행동입니다.


printjson(db.actors.mapReduce(map, reduce, "pivot"));


실제로 mapReduce 를 구동시키고 그 결과값을 Pivot 에 써주는 작업입니다.

db.pivot.find().forEach(printjson);


잘 쓰여졌는지 확인하는 작업입니다.

위 파일을 내려 받으시고 command line 상에서

$ mongo movie-star.js --shell


라고 입력하시면 구동하시는 모습을 확인할 수 있습니다.


저번 포스트 에서 Clojure 와 Slime 을 연결해봤습니다. 그런데 REPL 에서 색이 안 이쁘더군요. 간단하게 색을 집어넣는 방법을 설명하겠습니다.

.emacs 파일을 열어서 맨 아래쪽에 다음 과 같은 내용을 추가해 줍니다.

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

끝!!


한동안 Subversion 을 돌아보지 않았더니 (사실 게을러서 예전에 설치한 버젼을 그냥 쓰는 주의라서..) 많은 변화가 있더군요. 먼저 서브버젼이 아파치쪽으로 이동한 듯 보이더군요.

바뀐사이트 : http://subversion.apache.org/

아마도 1.7.x 대부터 변경된 듯 합니다. 따라서 예전에 제가 작성한 패치는 전혀 동작하지를 않게 바꼈더군요. 그래도 혹시나 예전 버젼 (1.6.x) 을 사용하신다면 예전 포스트 를 보시고 따라하시면 되실것입니다.

설치환경

OSX  Lion 이 설치되어 있고 Mac Port 가 설치되어 있다고 가정합니다. 따라서 Mac Port 가 설치되어 있다고 하면 Command Line Tool 이 설치 되어 있다고 봐야 합니다. 또한 Command Line Tool 이 설치되어 있다는 것은 XCode 가 설치되어 있다는 것입니다.


Mac Port 가 설치되기 위한 준비를 하는 방법은 제 예전 포스트 에서 다루고 있습니다. 참조하세요.

1. Subversion 1.7.4 을 컴파일하기 위한 모든 환경을 만들어 줍니다.

$ sudo port install subversion


어느정도 긴 시간이 흐른 뒤에 설치가 되어 있을 것입니다.
 
2. Subversion 1.7.4 버젼의 소스를 받아옵니다.

http://subversion.apache.org/download/
위 사이트에서 1.7.4 버젼의 subversion-1.7.4.tar.gz 를 받아옵니다. 적당한 곳에 옮겨줍니다. (저는 보통 ~/work 에 복사해 둡니다)

3. 압축을 풀어줍니다.

$ cd ~/work
$ tar xvzf subversion-1.7.4.tar.gz


4. 여기서 두가지 방향이 있습니다.
  - 포스트 하단의 path.c 를 받아서 정해진 위치 (제 경우를 예를 들어서 설명하자면)
   
  $ cp path.c ~/work/subversion-1.7.4/subversion/libsvn_subr


  - 포스트 하단의 utf8_mac_1.7.4.diff 를 다운 받아서
   
    $ cp utf8_mac.1.7.4.diff ~/work
    $ cd ~/work
    $ patch -p0 < utf8_mac_1.7.4.diff

5. 파일 패치가 이루어 졌으므로 이제 소스를 컴파일 해줍니다.

$ cd ~/work/subversion-1.7.4
$ ./configure --with-ssl
$ make
$ sudo make install


6. 설치가 끝났습니다. 이제 PATH 만 손봐주면 될 듯합니다.

 
$ emacs ~/.profile (또는 mate , vi , vim 등 자신이 좋아하는 에디터)


에 아래처럼 "/usr/local/bin" 을 추가해줍니다.
 
export PATH=/usr/local/bin:/opt/local/bin:/opt/local/sbin:$PATH



이 문제는 제가 2년전부터 수정하고 있는데 계속해서 커밋을 신청하는 데 (제가 귀찮아 하는 관계로..) 채택이 되질 않는 군요. - 혹시 제 영어가 황이라서..? -




 HBase  구동시에 만약 다음과 같은 에러가 발생한다면

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/crazia/work/hbase-0.92.0/lib/slf4j-log4j12-1.5.8.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/crazia/work/hadoop-1.0.1/lib/slf4j-log4j12-1.4.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]

 클래스패스에  slf4j-log4j12  관련  jar  가 여러개 있어서 이런 현상이 발생하는 것입니다. 제 경우에는 hbase 에는 1.5.8  버젼과 하둡 (hadoop) 에는 1.4.3 버젼이 중첩해서 있어서 발생하는 문제였습니다.

한 버젼으로 통일하고 단 한개만 클래스패스에 존재하게 바꾸어 줍니다. 제 경우에는 hbase 안에 있는 jar 를 hadoop 쪽에 옮겨주고 지워버렸습니다.

아래 사이트 참조해서 해결했습니다.

http://www.slf4j.org/codes.html#multiple_bindings


맥북에서 부트캠프를 깔고 윈도 7을 사용하고 있습니다. 보통 때 한글 변환은 Shift + Space 로 하고 있는 지라 사용하는 데 별 불편함이 없었는데 한자를 쓸 일이 생기니 불편한 일이 발생하더군요.


위 압축 파일을 받아서 압축을 해제해 보면 , 그 안에 여러가지 파일이 존재하는 데요.

mackeybind.exe

이 파일을 실행시키면 맥북의 오른쪽에 위치한 "Command" 와 "option" 키를 "한영 변환 / 한자 변환" 으로 손 쉽게 세팅할 수 있습니다. 그 후로 리붓하면 바로 사용 가능합니다.

好學 -> 知 , 力行 -> 仁 , 知恥 -> 勇
테스트 입니다. 중용에서 언급된 내용으로

배우는 것을 좋아하는 것이 '지' 요 , 힘써서 행하는 것을 '인' , 부끄러움을 아는 것이 '용' 이라고 한답니다.




가지고 있던 맥북 프로를 지금 일하는 곳에 묶이게 되버려서 새로 노트북을 장만했습니다. 맥북 에어를 장만 했는데  Lion 이 기본으로 설치되어 있습니다. 아무 생각 없이 Mac port 를 설치해 줬는데 동작을 안하는 것입니다. 그래서 예전 기억을 더듬어 봤더니 XCode 를 설치해 줘야지만 동작했던 게 기억이 났습니다.

그래서 App Store 에서 XCode 4.3 을 설치하고 돌려봤지만 여전히 동작을 안합니다. 이유를 알아봤더니만 예전에 추가로 설치해 줬던 'System Tools' 가 없기 때문에 발생하는 문제였습니다.

XCode 4.3 가 설치되어 있다고 가정합니다.

1. XCode 를 실행시키고 메뉴중에서 "XCode" -> "Preferences..." 을 선택합니다.

2. "Downloads" 탭 (Tab) 으로 이동합니다.


3. 위 그림에서 보는 바 와 같이 "Command Line Tools" 를 클릭해서  설치해 줍니다.

이상입니다
먼저 하둡(Hadoop) 이 필히 설치가 되어 있어야 합니다. 이번에 HBase 를 가-분산 방식 (Pseudo Distributed )으로 설치해 볼 예정이기 때문에 하둡 (Hadoop) 또한 가-분산 방식으로 설치가 되어 있는 것이 좋을 것입니다.

하둡이 먼저 설치되어야 하는 이유는 HBase 가 하둡 기반위에서 돌아가기 때문입니다. $HBASE_HOME/lib 밑의 추가되어 있는 hadoop-core-x.x.x.jar 는 스탠드얼론(Stand Alone) 버젼에서 쓰이는 것으로 나중에 분산적용할 때는 클러스터(Cluster)에 설치되어 있는 하둡과 버젼을 일치시켜줘야 한다. 따라서 HBase 0.92.0 버젼을 설치하기 위해서는 Hadoop-1.0.0 버젼이 설치되어야 합니다.

하둡 설치하는 방법은 저의 지난 아티클 을 참조합니다.


하둡이 설치되고 구동되는 것까지 확인해 보셨다면 설정 파일들을 몇개 수정해 줘야 합니다. 일단 디렉토리를 계속 왔다리 갔다리 하는게 귀찮으니 하둡쪽의 conf/hdfs-site.xml 을 HBase 쪽의 conf/hdfs-site.xml 로 링크를 걸어주는 작업부터 하기로 합니다.

$ cd ~/work/hbase-0.92.0/conf
$ ln -s ~/work/hadoop-1.0.0/conf/hdfs-site.xml hdfs-site.xml

링크가 걸렸다면 다음 파일을 열어서

conf/hbase-site.xml, conf/hdfs-site.xml

 
<property>
    <name>dfs.support.append</name>
    <value>true</value>
 </property>

위의 내용을 추가해 줍니다.

그리고

conf/hdfs-site.xml 파일 아래쪽에 동시에 제공될 수 있는 파일들 갯수의 상한선을 지정해줘야 합니다.

      <property>
        <name>dfs.datanode.max.xcievers</name>
        <value>4096</value>
      </property>


에 추가 , 이것을 지정 안해 줄시에는 이상한 에러가 발생한다고 하니 유념하시기 바랍니다.

그리고 다음 파일을 열어서

conf/hbase-env.sh

export HADOOP_HOME = /home/crazia/work/hadoop-1.0.0
export HBASE_CLASSPATH=${HBASE_CLASSPATH}:$HADOOP_HOME/conf


이 내용을 추가해 주고

export JAVA_HOME=/usr/java/jdk1.6.0_31/


위의 내용을 추가해서 어떤 자바를 쓸 것인지 지정해줘야 합니다.

여기까지는 공통된 부분이고 이제부터 분산방식을 지정해야 합니다.  분산 방식은 보통 가-분산 (Pseudo-Distributed) 방식이랑 완전-분산(Fully-Distributed) 방식으로 나뉩니다. 컴퓨터 한대에 설치해서 테스트 해 볼것이기 때문에 가-분산 방식으로 설치해보기로 합니다.

하둡은 이미 설치되서 가-분산 방식으로 설정이 되어 있다고 했었기 때문에

hbase-site.xml 의 최종 모습입니다.

<configuration>

  <property>
    <name>hbase.rootdir</name>
    <value>hdfs://localhost:9000/hbase</value>
  </property>

  <property>
    <name>dfs.support.append</name>
    <value>true</value>
  </property>

  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>

</configuration>


hbase.rootdir 은 $HADOOP_HOME/conf/core-site.xml 에 있는 fs.default.name 을 참조합니다. 제 것은 포트 번호가 9000으로 되어 있군요. 그래서 9000 으로 지정해주고 /hbase 라고 추가해 줬습니다.

hdfs-site.xml 의 최종모습입니다.

<configuration>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>

  <property>
    <name>dfs.name.dir</name>
    <value>/home/crazia/work/hadoop-1.0.0/name</value>
  </property>

  <property>
    <name>dfs.data.dir</name>
    <value>/home/crazia/work/hadoop-1.0.0/data</value>
  </property>

  <property>
    <name>dfs.support.append</name>
    <value>true</value>
  </property>

  <property>
    <name>dfs.datanode.max.xcievers</name>
    <value>4096</value>
  </property>

</configuration>


설정이 다 되었습니다. 이제 하둡부터 구동시킵니다.

$ cd $HADOOP_HOME


  하둡이 설치된 곳으로 이동하라는 명령입니다. 참고로 저는 /home/crazia/work/hadoop-1.0.0 에 설치가 되어 있습니다.

$ ./bin/start-all.sh


하둡을 구동시킵니다. 사실 하둡 파일 시스템만 구동시키면 되지만 그냥 전부 다 구동시켜줍니다. (파일 시스템만 구동시킬 경우에는 start-dfs.sh 를 사용합니다) 하둡이 완벽하게 구동 되었으면 이제 HBase 를 구동시킬 차례입니다.

$ cd $HBASE_HOME


  HBASE 가 설치된 곳으로 이동하라는 명령입니다. 참고로 저는 /home/crazia/work/hbase-0.92.0 에 설치가 되어 있습니다.

$ ./bin/start-hbase.sh


구동이 완료 되었습니다. 저번 아티클 에서 언급됐던 shell 을 띄워서 제대로 구동이 됐는지 테스트를 해봅니다.

이상입니다.


+ Recent posts