Emacs 를 mac 에서 사용하다 보면 몇가지 불편한게 있습니다. 대표적으로 ClipBoard 와 연동문제가 있습니다. 그러다가 Emacs for OSX 라는 것이 있더군요.

https://github.com/railwaycat/emacs-mac-port

위 사이트에서 자세한 설명은 되어 있지만 언제 끝날지 모르는 프로젝트더군요. 설명은 저기서 참조하고 소스는 실제로 작업하는 일본 프로그래머의 사설 git 레파지토리에서 받아서 컴파일을 하면 됩니다.

http://www.math.s.chiba-u.ac.jp/~mituharu/emacs-mac.git

이게 그 사설 git 레파지토리 입니다. 이걸 받으셔서 제가 예전에 올렸던 OSX 에서 컴파일해서 사용하기 를 참조해서 컴파일 하시면 됩니다.

$ ./configure --with-mac

옵션을 줘야 mac용으로 컴파일 됩니다. 그리고 결과는 ./build 안에 있더군요. 아이콘이 멋지게 바껴있는 것을 확인하실 수가 있습니다. 다만 사용하시다 보면 한글 디렉토리명이 깨지는 경우가 있습니다. 이건 예전에 제가 Subversion 에서 한글 파일을 인식못하는 문제 에서 썼듯이 UTF8이 종류가 달라서 그러한 문제가 발생합니다. 이걸 해결 하기 위해서 원작자에게 메일로 문의했더니 답변을 주더군요. (감사 감사)


이렇게 파일 이름들이 깨지는 현상입니다.


.emacs 파일안에다가

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

와 같은 식으로 적어주면 문제가 해결이 됩니다.


게임을 만들어 보는 것은 컴퓨터 과학쪽에 공부하는 몇몇분들에게는 꼭 해보고 싶은 일일것입니다. 물론 저도 예외는 아니여서 학창시절에 이리 저리 궁리를 해가면서 게임을 만들어 본적이 있었습니다. 아 그리고 어떤 게임회사에서는 실제로 MMORPG 게임 서버를 실제로 만든적이 있습니다. 나중에 그 게임이 런칭 됐을 때 무척 기뻤습니다. 비록 그 회사를 나왔지만 말이죠.

최근에 다시 한번 게임을 만들고 싶어서 - 이런 욕망이 왜 정말 지옥같이 바쁠때 솟아 나는지 모르겠습니다만 - 여러가지 게임 엔진을 건드려 보았습니다.

1 Unity3D

유니티3D 는 아주 유명한 게임 엔진입니다. 실제로 2일에서 3일만 노력해도 게임을 만들 수 있는 툴로 아주 유명합니다. 그래서 저도 과연 그러한가? 싶어서 한번 설치를 해봤습니다. 공짜로 설치도 되지만 지인의 말을 빌자면 공짜 버젼으로 할 수 있는게 별로 없다는 것을 빠르게 알게 될 것이라고 하더군요. 그럼에도 불구하고 여기 저기 둘러보았는데 소싯적에 만졌던 3D 렌더링 툴들 (마야, 3D studio 등) 과 많이 비슷하더군요. 즉 개발자 측면보다는 기획이나 디자인쪽에 가까운 툴이라고 여겨지더군요.

2 Cocos2D

코코스2D 는 2D 기반의 게임을 가볍게 빠르게 만들 수 있는 엔진으로 유명합니다. 그런데 최근 업데이트 (그래봐야 1년도 넘었습니다) 되면서 3D 도 같이 지원하게 바뀌며, 3D 기반의 게임을 만들 수가 있습니다. 그 유명한 '세븐나이츠' 가 코코스2D 를 이용해서 구현 한것으로 유명합니다. 게다가 상당히 개발툴이 개발자스럽게 구현되어 있습니다. 즉 나중에 이미지 배치등은 편하게 해줄려면 결국 Cocos Sutdio 등을 이용해야 하지만 일단 가변운 게임은 코딩만으로도 개발할 수가 있습니다. 즉 개발자 친화적이라는 것입니다. 예전에 게임을 만들던 가락이 있는 분들은 이 엔진을 이용하시는 편이 훨씬 편하게 게임쪽에 접근이 가능합니다.

그래서 다시 한번 게임을 만들려고 Cocos2D 를 설치하고 나니 이게 참 마땅한 따라하기용 샘플이 없더군요. 열심히 찾다가 발견한 것이

http://horns.tistory.com/category/cocos2d-x

위 블로그 였습니다. 충격을 받았습니다. 정말 차분하게 처음부터 잘 정리하셨더군요. 열심히 따라하면서 공부를 잘 할 수 있었으며 어떻게 개발이 되는지 전부 알 수가 있었습니다. 다만 아쉬운 것이 예전 버젼의 cocos2d 로 만들어졌기 때문에 현행 API 와는 안맞는 부분이 많이 있었습니다. 따라서 제가 현행화를 했습니다. 블로그를 보니 자신의 블로그에 연재하신다는 분도 관대하게 허락해 주시는 분이니, 단지 현행화만 한 저는 굳이 허락을 받지 않아도 되겠다 싶어서 이렇게 현행화만 하고 저분의 블로그를 링크해서 공부를 할 수 있게 하는 것이 좋겠다 생각합니다.

 모든 자료와 모든 그림, 그리고 모든 소스는 저 위의 블로그에서 작성된 것을 기반으로 만들었기 때문에 소유권은 저 블로그 소유자가 가지는 것을 여기에 명시해 둡니다.

제 현행화된 자료는 (Cocos2D 3.4 버젼에 맞춘)

https://github.com/crazia/pyocopang

에 올라가 있으며 혹시나 외국 친구들이 볼까봐 안되는 영어로 간단하게 영문 소개를 달아두었습니다. (설치법 또한)

안드로이드 어플리케이션 개발 시 YoutubeStandAlonePlayer 를 쓸 일이 있었서 사용했는데 예상치 못한 버그가 발생하더군요. 그 현상과 해결방법을 정리합니다.

1 현상

안드로이드 앱 개살시 메인 어플리케이션을 Portrait 전용으로 개발중이였습니다.

Intent intent = YouTubeStandalonePlayer.createVideoIntent(context,
                    DEVELOP_KEY, youtubeCode);
                context.startActivity(intent);

와 같은 식으로 유튜브 플레이어를 띄우니 띄운 액티비티(Activity) 와 그 스택에 쌓여있던 액티비티 들의 onResume 이 호출되는 현상이 있습니다. 그래서 플레이중에 멋대로 호출된 Activity 로 튕깁니다. 게다가 어찌 어찌 플레이되더라도 플레이중에 백키를 누르면 호출된 액티비티로 가는게 아니라 앱이 종료됩니다.

2 원인

아마도 Landscape 전용인 YouTubeStandalonePlayer 와 Portrait 로 만들어진 메인 앱과의 차이점 때문인 것 같다고 판단하여 해결법을 찾았습니다.

3 해결

YouTubeStandalonePlayer 를 호출하는 Activity 와 그 스택에 쌓여 있는 Activity 들의 AndroidManifest 안에 android:configChanges="orientation|screenSize|keyboardHidden" 와 같은 내용을 추가해주면 해결됩니다.

<activity
    android:name=".scene.IntroActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:screenOrientation="sensorPortrait" />
<activity

와 같은 식입니다.

매번 버젼이 바뀔때 마다 쓰는 것이 지겨워서 한동안 안쓰고 있었는데 예전에 설치하던 시절하고 너무 많이 바껴서 정리를 할 필요가 있겠더군요.

http://rocksea.tistory.com/282

위의 링크는 제자가 열심히 정리한 버젼입니다. 이번 포스트는 저 포스트에서 부족한 부분을 채우는 식으로 정리할려고 합니다.

1 준비 사항

  • HOST OS: OSX Yosemite
  • 가상 컴퓨터 소프트웨어: VMWare 7.0 (아니면 Virtual Box)
  • Linux Ubuntu 14.04 LTS (Server Version)

1.1 버추얼 박스(Virtual Box)

굳이 버추얼 박스가 아니라도 괜찮습니다. VMWare 나 Parallel 도 괜찮습니다. 버추얼 박스는 공짜기 때문에 제목으로 달아논 것이고 저는 실제로 VMWare Fusion 을 썼습니다.

  • Guest OS 를 우분투로 세개 설치해줍니다. 저는 14.04 LTS 를 이용했습니다. 그리고 세개를 다 깔아주면 불편하기 때문에 한개를 깔고 기본적인 설정을 해주고 그 Guest OS 파일을 복사해주고 Mac Address 를 바꿔주는 식으로 설치해줬습니다.

1.2 네트워크를 고정 아이피로 설정해주기

고정 아이피로 만들면 이후에 세팅에서 엄청나게 편해집니다.

m/s hostname id
master cloud0 cloud
slave cloud1 cloud
slave cloud2 cloud


위와 같은 형태로 서버들을 구성할 예정입니다. 따라서 다음 부분은 각각의 Guest OS 에 전부 적용해 주어야 합니다.

1.2.1 DHCP 로 받아오는 부분을 static 으로 변경해서 파일을 변경해준다. /etc/network/inteface 를 열어서 다음 부분을 바꾸어 준다.

auto etho0
iface eth0 inet dhcp

이 부분을 커멘트 처리해주고 ('#' 을 맨 앞 라인에 써준다)

auto eth0
iface eth0 inet static 
address 172.16.242.100
netmask 255.255.255.0
gateway 172.16.242.2

와 같은 식으로 적어준다. dhcp 가 static 으로 바뀌고 address , netmask , gateway 를 상황에 맞게 써주는 것을 잊지 않는다. 위의 것은 어디까지 나의 경우에 예에 해당하는 것입니다.

1.2.2 /etc/resolvconf/resolv.conf.d/base 의 수정

예전에는 /etc/resolv.conf 를 수정했으나 이 파일이 이제 서버가 리스타트 될 때마다 리셋이 된다. /etc/resolvconf/resolv.conf.d/base 를 열어서

nameserver 8.8.8.8

를 추가해주고

$ sudo resolvconf -u

로 새로 만들어 주면 된다. 이 작업은 cloud0 , cloud1, cloud2 각각의 상황에 맞게 작성해줘야 합니다.

그리고 /etc/hosts 파일에

172.16.242.100 cloud0
172.16.242.101 cloud1
172.16.242.102 cloud2

와 같이 추가해 줍니다. 역시나 각각의 cloud0, cloud1, cloud2 에서 작업해줘야 합니다. 주어진 ip 는 제 경우입니다.

1.3 password 없이 각각의 서버에 접속할 수 있게 만들기

master 에서 slave 들에만 접속할 수 있게 만들면 됩니다. 즉 cloud0 -> cloud1 , cloud2 로 연결되어야 하니 cloud0 에서 다음과 같은 작업을 해 줍니다.

$ ssh-kegen -t rsa 

$ ssh cloud@cloud1 mkdir -p .ssh
$ ssh cloud@cloud2 mkdir -p .ssh

$ cat ~/.ssh/id_rsa.pub | ssh cloud@cloud1 'cat >> ~/.ssh/authorized_keys'
$ cat ~/.ssh/id_rsa.pub | ssh cloud@cloud2 'cat >> ~/.ssh/authorized_keys'

1.4 add-apt-repository 을 사용할 수 있게 만들어 주기

우분투(Ubuntu) 를 쓰면서 한번도 add-apt-repository 가 동작 안하는 것을 상상해 본적이 없어서 당황스러웠습니다. 우분투 server 로 설치하면 add-apt-repository 를 사용하기 위해서 필요한 패키지가 있습니다.

$ sudo apt-get install software-properties-common

이것을 설치해 줘야 합니다.

1.5 Java 설치

Java 의 버젼은 상관 없다고들 합니다. 그런데 계속해서 테스트 했던 버젼이 oracle java 이기 때문에 그것을 설치하기로 합니다. 이래저래 귀찮으니까 apt-get 을 이용해서 설치해 주기로 합니다. 뭐니 뭐니 해도 쉬운게 최고입지요.

$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java7-installer

질문 나오는 것에 모두 YES 해서 설치해주면 됩니다. 참고로 이건 cloud0, cloud1, cloud2 에서 다 설치해줘야 합니다.

2 하둡 (Hadoop) 설치

Guest OS 세대에 전부 Ubuntu Server 를 설치해주고 네트워크 까지 설치했다면 본격적으로 설치를 시작할 시간입니다. master 로 설정할 cloud0 에서 작업을 시작합니다.

2.1 하둡 다운로드

http://ftp.daum.net/apache/hadoop/core/stable2/hadoop-2.6.0.tar.gz

위의 파일을 다운 로드 받아서 게스트 (Guest) 에 밀어 넣던지 아니면 게스트에서 (인터넷이 된다는 가정하에)

$ cd ~/
$ wget http://ftp.daum.net/apache/hadoop/core/stable2/hadoop-2.6.0.tar.gz

같은 방식으로 다운 받으시면 됩니다. 그리고 rsync 를 이용할 것이기 때문에 master 인 cloud0 에서 작업을 진행하면 됩니다. 최근의 spark 는 2.4.1 대의 하둡을 지원합니다. 그러나 어느날 갑자기 옛날 버젼의 하둡이 사라졌습니다. 현재의 stable2 는 바로 hadoop 2.6.0 버젼입니다. 나중에 spark 는 따로 컴파일을 해줘야 할 것입니다. 아니면 2.6.0 대로 맞춘 버젼이 나오길 기다립시다.

적당한 곳에 풀어줍니다.

$ cd ~/
$ tar xvzf hadoop-2.6.0.tar.gz

$HADOOP_HOME = ~/hadoop-2.6.0 이라고 가정합니다.

2.1.1 실제 데이타 저장 디렉토리 생성

실제로 데이타가 저장될 디렉토리를 만들어 줍니다. cloud0, cloud1, cloud2 에서 모두 만들어줘야 합니다.

$ sudo mkdir -p /data/hadoop/tmp $ sudo mkdir -p /data/hadoop/dfs/name $ sudo mkdir -p /data/hadoop/dfs/data $ sudo chown -R cloud:cloud /data/hadoop

/data/hadoop 의 owner 를 cloud 로 바꿔주는 것을 잊으면 안됩니다. 이 작업을 안해주면 나중에 hadoop 이 포맷하고 실제로 네임노드 , 데이터노드가 실행시 에러가 발생합니다.

2.1.2 $HADOOP_HOME/etc/hadoop/core-site.xml 수정

다음과 같이 수정해줍니다.

<configuration>
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://cloud0:9000</value>
  </property>
  <property>
   <name>hadoop.tmp.dir</name>
   <value>/data/hadoop/tmp</value>
  </property>
</configuration>

fs.defaultFS 는 하둡 파일시스템의 진입점을 보통 지정합니다. master 를 가르키는게 일반적입니다.

2.1.3 $HADOOP_HOME/etc/hadoop/hdfs-site.xml 수정

다음과 같이 수정합니다.

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>2</value>
    </property>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/data/hadoop/dfs/name</value>
        <final>true</final>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/data/hadoop/dfs/data</value>
        <final>true</final>
    </property>

    <property>
        <name>dfs.permissions</name>
        <value>false</value>
    </property>
</configuration>

dfs.replication 은 HDFS 내에서 몇개의 블록을 복사해서 유지할 것인가 하는 것입니다. 숫자가 커질수록 안정도는 올라가지만 속도는 저하됩니다. 우리는 그냥 2로 정합니다. dfs.namenode.name.dirdfs.datanode.data.dir 은 위에서 지정해 준 디렉토리를 지정해줍니다.

2.1.4 $HADOOP_HOME/etc/hadoop/mapred-site.xml 수정

아마 파일이 없으면 만들어 주시면 됩니다.

<configuration>
  <property>
      <name>mapreduce.framework.name</name>
      <value>yarn</value>
  </property>
  <property>
    <name>mapred.local.dir</name>
    <value>/data/hadoop/hdfs/mapred</value>
  </property>
  <property>
    <name>mapred.system.dir</name>
    <value>/data/hadoop/hdfs/mapred</value>
  </property>
</configuration>

mapreduce.framework.name 이 중요합니다. 최근 하둡은 맵리듀스 관리를 얀(YARN) 으로 합니다. 꼭 지정해 줘야 합니다.

2.1.5 $HADOOP_HOME/etc/hadoop/yarn-site.xml 수정

<configuration>
<!-- Site specific YARN configuration properties -->
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>
  <property>
    <name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
    <value>org.apache.hadoop.mapred.ShuffleHandler</value>
  </property>
  <property>
    <name>yarn.resourcemanager.resource-tracker.address</name>
    <value>cloud0:8025</value>
  </property>
  <property>
    <name>yarn.resourcemanager.scheduler.address</name>
    <value>cloud0:8030</value>
  </property>
  <property>
    <name>yarn.resourcemanager.address</name>
    <value>cloud0:8035</value>
  </property>
</configuration>

cloud0 로 쓰여진 부분은 각자 자신의 환경에 맞춰주면 됩니다.

2.1.6 $HADOOP_HOME/etc/hadoop/masters

마스터 (master) 서버가 어떤건지 지정해주는 파일입니다.

cloud0

cloud0 로 지정해주면 됩니다.

2.1.7 $HADOOP_HOME/etc/hadoop/slaves

datanode 로 사용할 서버들을 적어주면 됩니다.

cloud1
cloud2

전체 3대를 사용할 꺼기 때문에 master 를 제외한 나머지를 적어주면 됩니다.

2.1.8 $HADOOP_HOME/etc/hadoop/hadoop-env.sh 수정

export JAVA_HOME=/usr/lib/jvm/java-7-oracle

와 같은 식으로 자바 위치만 정해주면 됩니다.

2.1.9 rsync 를 이용한 복사

cloud0 에서 다음과 같이 실행해 줍니다.

$ rsync -avz ~/hadoop-2.6.0 cloud@cloud1:/home/cloud/
$ rsync -avz ~/hadoop-2.6.0 cloud@cloud2:/home/cloud/

이러면 모든 노드(Node) 의 설정이 동일해집니다. 나중에 따로 생각해 내서 하기 힘들기 때문에 이 부분을 스크립트(script)로 만들어서 노드가 추가되면 스크립트에 추가된 노드분만 추가해 주는 식으로 관리해 주는것이 편할것 같습니다.

2.2 하둡(Hadoop) 실행

사용하기 전에 HDFS 를 포맷해줄 필요가 있습니다.

$ hadoop namenode -format

그리고 분산파일 시스템과 맵리듀스 시스템을 구동시켜주면 됩니다. $HADOOP_HOME 에서

$ sbin/start-dfs.sh
$ sbin/start-yarh.sh

를 실행시켜주면 됩니다. 제대로 동작하고 있는지 확인을 위해서는 cloud0 (즉 마스터) 에서

$ jps

를 입력해서 namenode (dfs 관련 서버) 와 resourcemanager (yarn 관련) 가 구동되어 있는지 확인하면 되고 cloud1 와 cloud2 에서도 마찬가지로

$ jps

를 입력해서 datanode(dfs 관련 서버) 와 nodemanager (yarn 관련)이 구동되어 있는지 확인하면 됩니다.


조금 광오한 제목을 썼지만 제자들과 같이 일하는 동료들에게 설명하기 위해서 만든 자료라 조금 거창하게 만들었습니다. 사진이나 그림들도 돌아다니는 것을 그냥 썼기에 저작권 이슈가 있을 수도 있습니다. 고발이 들어오면 바로 내리겠으니 양해해 주세요. 자료는 지금까지 제가 만들어 온 것과 마찬가지로 KeyNote 로 작성됐습니다. 원본이 필요하시면 메일 남겨주시면 보내드립니다. 



IT 쪽과 산업군과 심지어 경영쪽에서도 말이 많은 BigData 입니다. 최근의 핫한 이슈라서 어디서나 BigData를 말하고 있습니다. 저는 실제로 이 기술을 접한지는 오래됐습니다. 선배 (저에게 기술을 알려주신 사부님 되십니다.)의 회사에 놀러가서 최근에 나온 기술중에 BigData 란 것에 관심 있다고 하니 말  없이 책을 한권 주시더군요. 그러면서 하시는 말씀이 '벌써 적용해서 사용하고 있다' 라는 말이였습니다. 괴물 같으니라고.. 

그래서 어느정도 공부하고 실전에 적용해보면서 느낀 소감은 아직 멀었다는 것이였습니다. 이 기술을 준비한다는 업체는 절대 데이타가  Big 하게 많지가 않더군요. 그래서 잠시 다른일을 하느라 1년정도 손을 놨더니만 세상이 바꼈더군요. 제가 알던 시절하고 인프라도 많이 바뀌고 그 당시는 준비 단계의 프로젝트가 상위 프로젝트로 많이 올라왔더군요. 이번에 다른곳에 적용하기 위해서 POC 를 준비하면서 느끼게 된 것을 교육차원 으로 정리하는 것입니다. 

빅 데이타 입니다. 워드 클라우드 형태로 표현되고 있는데 사실은 저 표현되고 있는 말들의 대부분이 연관되는 것입니다. 일단은 Storage 라는 말과 Analytics 라는 글이 눈에 들어오는 군요. 뗄레야 뗄 수 없는 관계라고 볼 수 있습니다. 쉽게 생각해도 빅데이타라는 말은 일반적으로 많은 데이타를 처리하는 것이지.. 라고 막연하게들 생각하고 있습니다. 그러면 어떤 일을 하는 것일까요? 빅데이타란? 


이게 과연 완전히 새로운 기술이냐? 하는 것입니다. 인프라적으로 봐도 적용 형태로도 봐도 완전히 새로운 기술이라고 볼 수가 없습니다. 아니 세상에 완전히 새로운 기술이 있기는 한가? 라고 묻고 싶기도 합니다. 그렇다면 이 기술은 어떤 기술과 유사한 것인지? 


넵 바로 Business Intelligence 입니다. 바로 빅데이타 기술은 본인이 생각하기에 이 분야와 아주 유사합니다. 그렇다면 어떤점이 유사한 것인가? 라고 묻기 전에 과연 이 Business Intelligence 가 무엇인지 아주 아주 간단하게 살펴볼 필요가 있겠습니다. 


보통 Business Intelligenc 는 BI 라고 줄여서들 많이 이야기 합니다. BI 는 무엇을 지칭하는 것일까요?


한 BI 업체의 BI 가 할수 있는 일들 입니다. 여러가지를 할 수 있다고 자랑스럽게 이야기 하고 있습니다. 물론 저러한 일들을 할 수가 있겠죠. 나가는 돈은 별도로 하고 말이죠. 그렇다면 BI 가 하는 가장 본질적인 일이 무엇이냐? 이것만 이해하면 저런 것들은 그런 일의 연장이라고 볼 수가 있습니다. 


이게 바로 핵심이라고 볼 수가 있겠습니다. 뭐 속된말로 데이터 분석입니다. 이게 돈이 되느냐고 묻는 분들은 BI 업체의 존립 이유를 부정하시는 거라고 볼 수가 있습니다 ㅋㅋ. 게다가 생각보다 쉽지도 않습니다. 머리만 가지고 되는 일도 아닙니다. 저런 유의미한 데이터를 이끌어 내기 위해서 무지 많은 준비 작업을 거쳐야 하며 왜 그게 유의미한 데이타가 되는지 설명도 해야 합니다. 비싼 돈을 주기에 충분한 행위입니다. 


그러면 BigData 는 BI 네? 라고 이야기 할수도 있겠지만, 거기에 나아가서 만약 그렇다면 현존하는 BI 업체는 거의 다 BigData 로 진화를 했겠네? 라고 생각도 할 수 있습니다. 그러나 모든 업체가 그렇지는 않습니다. (진화하는 업체도 있습니다) 그러면 무엇이 다른 것인가? 


바로 이 3V에서 차이점이 존재합니다. 이것에 관한 자세한 내용은 예전에 제가 쓴 HBR 관련 포스트 (Big Data Management Revolution ) 에서 언급한 적이 있습니다. 


기존 데이타베이스로는 감당이 안되는 수준으로 용량들이 큽니다. 기가단위를 넘어선 페타단위의 데이타도 다룰 수 있습니다. 데이타가 커지면 지금의 기법으로는 당연히 호환이 안됩니다. 큰 데이타 단위에 맞춰서 동작하는 방식을 배워야 합니다. 


속도 입니다. 제 예전 글에서는 실시간에 근접해야 한다고 썼지만, 절대 실시간에 근접할 수가 없습니다. 많은 사람들의 예상과는 다르게 하둡베이스는 절대 시간이 실시간에 가깝지는 않습니다. 맵 리듀스에 올리고 잡(Job)을 분배하는 시간까지 포함한다면 실시간은 되지 않습니다. 그렇다면 무엇이 속도냐? 라고 질문을 던질 수가 있을 것입니다. 3박4일 걸리는 것이 8시간으로 줄수가 있고 , 8주 걸리는 것이 1주로 줄 수가 있습니다. 즉 단위가 큰 시간대를 줄이는 것이지 실시간에 근접하는 것은 아니라고 할 수가 있겠습니다. 


정말 다양한 데이터를 처리할 수가 있습니다. 예전과는 다르게 최근에 추가된 데이터 타입이라면 gps 를 들 수가있습니다. 다양한 자료들 다양한 데이타베이스들 다양한 D/W 들과 전부 연관되서 다루는 분야기 때문에 정말 다양성이 핵심입니다. 그리고 이미지, 동영상.. 등등 여러가지 데이터 타입들이 있습니다. 


그렇다면 왜 이리 BigData 는 화두가 되는 것인가? 하는 것입니다. 경영인들이 즐겨보는 HBR 이라는 잡지가 있습니다. 여기에는 경영잡지 답게 최신 IT 기술중 경영에 도움이 되는 기술은 종종 소개하고는 합니다. 대표적인 예로 지금 주제인 BigData 와 클라우드(Cloud) 가 있습니다. 


클라우드는 HBR 에 실리기까지 5년이 걸렸습니다. 사실 비용절감 과 서비스의 인구 밀도가 급격하게 변하는 경우 말고는 딱히 경영자들한테 매력적인 포인트는 아니였다고 저는 개인적으로 생각합니다. 그러나 빅데이터(BigData)는 마케팅에 활용이 될수도 있고 기업에서 새로운 방향의 통찰력(insight) 를 얻을 수가 있습니다. 그래서인지 이례적으로 3년이라는 시간안에 실릴 수 있었을 것이라고 봅니다. 


그래서 HBR 에서 나왔던 사례를 소개합니다.  시어스 홀딩스(Sears Holdings) 에서 했던 프로젝트입니다. 보시다 시피 자회사가 많은 시어스 홀딩스는 마트계열의 회사들을 여러개 소유한 회사입니다. 개별 개별 데이타가 얼마나 쌓이는지 상상하기도 힘들 정도입니다. 


그래서 시어스 홀딩스는 자사의 데이타들을 이용해서 고객 맞춤 프로모션을 진행하고 싶어합니다. 그런데 현행 시스템으로는 아무리 빨라도 8주가 걸린다고 보고가 올라왔다고 합니다. 그래서 왜 그리 오래 걸리나 조사를 하니 각각의 자회사들이 소유한 정말 방대한 데이타와 그 데이타가 저장되어 있는 데이타베이스 그리고 구성되어 있는 D/W 가 형태들이 다른게 문제였습니다. 그런데 이러한 맞춤 프로모션이 8주가 걸린다면 그것은 이미 현행화에 뒤진다는 것이 경영진의 생각이였고 이것을 적어도 1주정도로 줄여야 겠다고 결심했습니다. 


그래서 오라클에게 자문을 구했습니다. 이러 이러한 시스템을 구축해서 빠르게 고객 맞춤 프로모션을 진행하고 싶다. 오라클의 대답은 '가능하다' 였습니다. 다만 이 정도의 돈이 든다고 말을 했다고 합니다. 그 금액의 규모가 얼마인지는 전해지지 않지만 '천문학적인 돈이였다' 라던지 '그 돈이면 목적에 맞는 새로운 데이타베이스 시스템을 만들겠다' 라는 말로 보아 장난이 아닌 수준이였다는 것만 짐작할 수가 있습니다. 


그래서 시어스 홀딩스의 CTO 였던 필 쉘리(Phill Shelley) 는 2010년에 그 당시 거의 초창기 수준이던 하둡(Hadoop)을 이용해서 이 문제를 해결했습니다. 처음에는 이 일을 할 수 있는 사람을 찾을 수가 없어서 외주를 줬지만 그 다음에는 자사의 인력들이 배워서 충분히 해결할 수 있는 수준이 됐으며, 점점 더 분석 시간이 짧아지고 있다고 합니다. 게다가 오픈소스이기 때문에 시스템 구축비용은 거의 들지 않았으며 , 하둡은 로그(Log) 기반이기 때문에 데이타베이스의 포맷이 맞지 않는 것은 의미가 없었습니다. 모든 데이타를 로그로 변환해서 분석하면 그만이기 때문입니다. 


시어스 홀딩스 사례에서 잠깐 언급됐던 하둡(Hadoop)! 요즘 빅데이타 하면 빠지지 않고 등장하는 이름입니다. 그 이름에 대해서 언급하기 전에 구글이 빅데이타에 끼친 영향에 대해서 이야기를 하고 넘어가야 할 것입니다. 


바로 이 논문입니다. 구글에서 자신들이 쓰고 있는 검색 엔진의 인덱스를 저장하고 있는 시스템에 관한 논문을 발표했습니다. 2006년으로 알고 있는데요. 여기에는 정말 방대한 인덱스를 저장하기 위해서 어떻게 분산을 써서 내용을 나누고 그것을 어떻게 관리하는지 어떤 방식으로 구조화 시켜서 저장하는지에 관한 설명이 되어 있는 논문입니다. 여기에서 바로 모든 빅데이타(BigData) 플랫폼들이 시작됐습니다. 


구글의 논문을 보고 야후의 개발자가 생각해낸 개념이 바로 하둡입니다. 분산 저장방식에 관심을 가졌을 거라고 추측합니다. 그래서 야후에서 오픈소스 프로젝트로 시작하고 바로 아파치 재단으로 이동했습니다. 그리고 하둡은 2010년부터 꾸준히 빅데이타(BigData)를 논할 때 빠지지 않는 구성요소가 됐습니다. 그렇다면 대체 하둡의 핵심은 무엇일까? 


저는 그 핵심요소를 '분산'이라고 봅니다. 하둡은 핵심에 분산을 깔아놓구 있습니다. 데이타를 저장하는 방식에 분산을 적용한 것이 HDFS 고, 계산을 하는 방식에 분산을 적용한 것이 맵리듀스(Map Reduce) 입니다. 즉 다시 말하지만 '분산' 입니다. 핵심은 '분산' 


HDFS 는 하둡에서 데이타가 저장되는 핵심입니다. 자세한 부분에 관한 설명은 나중에 따로 할 예정이니 전체적인 레이아웃만 살펴보시면 됩니다. 한개의 네임노드(NameNode)와 그 네임노드가 다운됐을 때를 대비한 세컨드리 네임노드(Secondary Namenode) 가 존재하고 실제로 파일들이 일정 크기(Chunk)로 나뉘어서 저장되는 데이타노드(Datanode)가 다수개가 존재합니다. 이 데이타노드가 작게는 3개에서 많게는 수천개까지 늘어날 수가 있습니다. 어딘가에서 봤는데 (정확한 정보는 아닙니다) 페북은 4000여개의 노드를 사용하고 있다고 합니다. 


일반적인 파일시스템(FS:File Systems)에서 파일을 저장하는 방식과 너무 유사합니다. 파일이 저장되면 그 파일의 존재하는 OS 상의 위치와 실제로 하드디스크에 저장되는 물리적 위치로 나뉩니다. 그림에서 보이는 네임노드(Namenode) 가 OS 상의 위치에 해당한다고 보시면 편하고, 데이타노드(Datanode)에 쪼개서 저장되는 방식이 마치 하드디스크에서 물리적으로 데이타가 저장되는 모습에 해당한다고 보시면 됩니다. 안정성을 위해서 레플리케이션(Replication)을 둬서 물리적으로 2개 이상의 사본이 저장되서 비상상황 발생시 대응을 쉽게 할 수 있게 하지만 그 부분은 자세한 설명은 안하기로 하겠습니다. 


맵리듀스 입니다. 맵 리듀스는 분산 계산 플랫폼이라고 보시는게 가장 유력할 것입니다. HDFS 내에 존재하는 데이터를 맵-리듀스 어플리케이션을 만들어서 빠르게 계산하는 것이 그 목적입니다. 원래는 잡트래커(Job tracker) 와 태스크 트래커(Task Tracker) 였으나 YARN 에 들어오면서 그림과 같이 리소스 매니져 (Resource Manager)와 노드메니져(Nodemanager) 로 바꼈습니다.  


맵리듀스 프레임워크에 맞춰서 작성한 어플리케이션을 올리면 리소스 매니져가 몇개 노드에서 작업을 수행할지 나눠서 배포하고 노드매니져가 작업을 해서 그 결과가 출력되는 형식을 취합니다. 사실 더 자세하게 보자면 복잡하지만 핵심만을 설명한 것입니다. 결국 여기서도 알아야 할 것은 어플리케이션 = 잡 (Job) 을 '분산' 시켜서 처리한다는 것입니다.


그러면 빅데이타 계의 다른 이슈거리인 노에스큐엘(NoSQL) 입니다. SQL 과는 다르다는 정도로 받아들이면 될 것입니다. 일반적인 Row 기준적인 RDBMS 와는 다르게 대부분의 NoSQL 은 key-value 나 Column 베이스 입니다. 이런것의 차이는 추후에 설명하기로 하고요. 일반적인 RDBMS 와의 가장 큰 차이를 보이는 부분이 Relation 이 없기 때문에 NoRel (No Relation)으로 바꿔야 한다는 소리도 있습니다. 


대표적인 컨셉이자 제일 유명한 것인 하베(HBASE) 가 있습니다. 하둡의 서브 프로젝트에서 시작해서 지금은 당당하게 대표 프로젝트로 자리 잡았습니다. 


NoSQL 은 설명할때 제일 힘든 것이 그게 뭐냐라는 질문에 딱히 대답하기가 어렵다는 점입니다. 그래서 제가 제일 쉽게 설명하는 방법은 바로 거대한 구조화된 데이타 저장소 라는 개념입니다. HDFS 는 파일 시스템 개념이라서 밑바닥에 깔려있는 것이고 이것은 그 위에서 구조화된 데이타를 저장하는 저장소 개념입니다. 따라서 구글의 논문이자 구글에서 사용하고 있는 BigTable 에 가장 유사한 형태를 취하고 있습니다. 이 하베는 페이스북(FaceBook)의 메시징 서버를 구현하는데 사용되서 유명합니다. 페이스북이 투자하고 키워오던 카산드라(cassandra)를 대신해서 이용되었기 때문입니다. 

하베의 구조도 입니다. 역시 어디선가 가져왔습니다. 이 한장의 그림으로 정말 하베의 모든것이 설명되고 있다고 보시면 됩니다. 

하베는 분산의 마스터 노드에 해당하는 HMaster 와 분산의 슬레이브 노드에 해당하는 HRegionServer 로 나뉩니다. 이 마스터와 슬레이브 방식을 관리하는 것이 바로 주키퍼(ZooKeeper) 입니다. 그래서 사용자의 클라이언트는 주키퍼를 통해서 마스터(HMaster)에 접근해서 데이터를 추가(insert)하고 읽어오는 작업을 하면 그 작업의 내용을 마스터는 리젼서버(HRegionServer) 에 명령을 내려서 수행하는 방식입니다. 그리고 저장되는 내용은 실제로 Distributed File System 을 통해서 하둡(Hadoop) 에 저장됩니다. 하둡은 전통적으로 파일을 저장하는 방식대로 데이타노드(Datanode) 에 개별 개별의 조각으로 나누어서 저장합니다. 


하베에서 데이타를 저장하는 방식에 대한 설명입니다. 한개의 테이블이 있다면 그 안에 컬럼 패밀리가 다수가 존재하고 그 컬럼패밀리 '군'에 속하는 개별적인 컬럼들이 존재하는 형태 입니다. 상식적으로 RDBMS 방식에 익숙하다면 익숙하지 않은 방식이라고 보일 텐데요. 실제로 컬럼(Column) 방식이 어떤식으로 데이타가 저장되는지 보겠습니다. 


Row 방식과 Column 방식의 차이입니다. 여러값이 들어가지는 않고 각각의 값하고 Column 방식으로 정렬되어 있다는 느낌을 주지요? 거기다가 각각의 Column 과 매칭되는 id 값이 전부다 존재합니다. 이래서 NoSQL 은 보통 Key-Value 방식이라는 이야기를 합니다. 그림에 보다 시피 Key(id 값) 과 그것에 해당하는 각각의 값들이 존재합니다. 


여기까지가 대략적으로 빅데이타라고 말해지는 것들의 개략적인 설명입니다. 개략적인 설명만 듣고 잘난척은 가능하지만 실제 적용하고는 오만년 광년쯤 떨어진 이야기라는 것을 알 수가 있을 것입니다. 그러면 실제로 준비하는 것에 관한 이야기를 들어보기로 합니다. 정말 필요한 순서상으로 따라하기식 설치는 따로 매뉴얼로 작성할 예정입니다.


그럼 일단 하드웨어 준비사항입니다. 첫 항목은 최근에 유명한 라즈베리 파이로 설치해서 하둡을 해볼까 라는 소리를 들어서 입니다. 물론 설치는 가능합니다. 대신 제가 항상 주장하는 '설치를 해서 뭘 해볼껀데?' 라는 질문에 대한 대답하기가 힘듭니다. 물론 각각의 노드매니져나 데이타노드 구동 메모리를 256 메가나 128 메가로 낮추면 돌릴 수 있지 않을까 하는 분들도 계실지 모릅니다. (라즈베리 파이는 256메가나 512메가 메모리를 가지고 있습니다) CDH5 의 기본 설정을 데이타노드에 1기가 노드매니져에 1기가 입니다. 그래서 최소 2기가 이상의 메인메모리가 필요합니다. 2 코어가 필요하다는 이유도 어찌보면 당연합니다. 물리적 노드 한대에 데이타노드와 노드매니져가 함께 있으니 효율성을 극대화 하기 위해서 필요합니다. 

주키퍼(Zookeeper) 권장 사항은 홀수대입니다. 홀수인 이유는 노드중에 한대가 죽었을 때의 대처가 좋기 위해서라는데 (사실 그 이유는 자세히 살펴보지는 않았습니다) 시키는대로 하는 것이 좋겠죠? 

그리고 실제로 클러스터(Cluster)를 구현하기 위해서는 최소 복수개의 노드가 필요하니 (거기에 주키퍼 권장사항) 3대 정도가 필요합니다. 


리눅스가 하둡을 돌리는 최고의 OS 라는것은 이미 다 알려져 있는 내용입니다. CentOS 나 우분투(Ubuntu) 어떠한 것도 가능합니다. 그런데 저는 우분투를 추천합니다. 단 CDH5 를 설치할려고 하면 우분투 14.04 버젼은 주키퍼 설치에 실패하기 때문에 13.04 나 12.04를 추천합니다. 참고로 저는 14.04를 설치했기 때문에 주키퍼를 직접 설치해줬습니다. 자바는 1.7 버젼을 추천하더군요. 저는 혹시나 몰라서 Oracle 용 자바 (Java)를 설치해줬습니다. 찾아보면 우분투에서 apt-get 으로 자바를 설치하는 방법이 있으니 참고하셔서 설치하면 됩니다. 


하드웨어와 기본적인 OS가 준비가 됐다면 어떤 하둡 구현체를 쓸것인가? 하는 문제가 남아 있습니다. 


최근 빅데이타 컨설팅 업계의 삼대장이라고 하면 클라우데라 (Cloudera), 맵알(MapR), 호톤웍스(Hortonworks) 마지막 업체는 잘 모르니 차치하고라서도 , 각각은 많이 발전했으면서도 확연히 차이점이 존재합니다. 


클라우데라는 자신들이 생각하는 방식으로 하둡과 그에 딸려오는 제반 인프라를 설치하기 쉽게 만들어 뒀습니다. 각각을 전용 계정들도 만들게 하며 서비스 방식으로 띄울 수 있게 모든 것을 체계화 했습니다. 게다가 환상적으로 쉬운 (그렇지만 영어입니다) 매뉴얼을 제공해서 열심히 따라하면 손쉽게 (그나마) 거의 모든 빅데이타 인프라를 설치해 볼수가 있습니다. 게다가 아파치 라이센스기 때문에 상업용으로도 이용할 수가 있습니다. 다만 자신들의 입맛에 바꿔놓은 부분이 많기 때문에 클라우데라가 지원하지 않는 솔루션을 설치해 볼려고 하면 한방에 안 깔리는 경우가있습니다. (예를 들면 타조- Tajo ) 

우리나라에서 로그가 많이 나오기로 유명한 카카오에서 분석용 기반 플랫폼으로 사용한다고 합니다. 


제가 사용해본것은 클라우데라지만 MapR 에 관한 이야기는 많이 들었습니다. 하둡에서 시간이 걸리는 부분을  C/C++ 로 변경을 해서 속도 향상을 가지고 왔다고 합니다. JVM 의 한계를 넘어섰는지는 잘 모르겠습니다. 다만 인터페이스가 여전히 자바 기반이기 때문에 기존의 다른 하둡 기반 인프라와 궁합이 잘 맞는다고 합니다. 

그러나 이러한 최적화는 가장 시간이 걸리는 부분은 결국 잡을 나눠서 어떻게 할 것인지에 영향을 미칠 가능성이 매우 크기 때문에 속도향상은 어느정도 있겠지만 그 부분이 절대적이라고 볼 수는 없을 것 같습니다. 게다가 하둡이 어느정도 버젼이 안정화 된 이후에 C/C++ 작업이 들어가는지 (어떻게 보면 당연한 것이라 볼 수가 있을 것입니다) 버젼업이 생각보다 빠르지가 않다고 합니다. 

게다가 유료!! 라고 합니다. 자세한 스펙은 조사하지 않았으나 영업자료에 그리 써 있었다고 합니다. 머신 노드 1기당 800만원이라는 소리가 있으니 보통 작은 은행권에서는 보통 15-20대 가량을 쓰니 소프트웨어 가격만으로도 돈이 적당히 들어갈 것으로 보입니다. 


왜 호톤웍스가 없는지는 묻지 말기로 하고.. 어떤 방식을 추천할 것인가? 에 관해서는 지금 나와 있는 빅데이타 플랫폼을 다 이해하가면서 설치해보고 싶다면 당연히 각각의 컴포넌트를 아파치 재단에서 받아서 설치하는 것을 추천합니다. 지금 속도가 괜찮다고 평가되는 타조(Tajo)는 CDH 와 뭔가 안맞는지 설치가 안됩니다. - 가장 손쉽게 생각하자면 하이브(Hive)의 개량방식이라고 평가받는 솔루션이 타조 (Tajo)와 임팔라(Impala)가 있습니다. 둘다 빠른 동물을 형상화 했지요? 그런데 타조는 국내의 오픈소스 개발이 주력으로 개발됐습니다. 임팔라는 CDH 가 밀고 있습니다. SKT 빅데이터 팀에서 여러 오차를 겪고 나서 타조를 선택했다는 글을 본적이 있는데 그 논리대로라면 타조가 좋을꺼 같아서 설치할려고 했더니 CDH 는 임팔라를 민단 말이죠.. 그러니 타조를 지원할 일이 없는 것입니다 ㅎㅎ. 

그렇다고 CDH 가 나쁘다는 것은 절대 아닙니다. 귀찮은 설치과정을 쉽게 만든 것만으로도 CDH 는 쓸만합니다. 일일이 설치하는 것을 공부라고 여길 필요가 없는 분들! 설치하고 난 뒤에 데이타를 만지작 거리는 것이 진정한 빅 데이타다!! 라고 생각하시는 분들 (열렬하게 공감합니다) 은 CDH5 를 강력추천합니다. 


그렇다면 빅데이타라는 것을 써봤다고 말할려면 무엇을 설치해야 하는 것인가? 이것이 궁금할 수가 있습니다. 항상 남에게 해봤다고 말해볼 수 있을만큼만 하면 됩니다. 


이 세가지가 기본입니다. 사실 가장 왼쪽의 주키퍼(ZooKeeper)는 설치가 안되면 하둡도 설치가 안되는 것이니 필수요소이기도 합니다. <-- 이건 클라우데라 매뉴얼에 있는 내용이고, 실제로 소스를 직접 받아다 설치할 경우에는 주키퍼와 하둡은 상관 관계가 없다고 판명되었습니다. 그리고 하둡이 설치가 되지 않으면 처음이자 끝도 없는 것이지요. 그리고 하이브 입니다. 하이브는 사실 초창기때에는 알기도 쉽지 않았습니다. 그 당시는 피그(Pig)라는 것만 있었습니다. 게다가 왠만하면 전부 맵리듀스 프로그램을 직접 짜서 분석을 하는 것이 일반적이였습니다. 그러다가 일일이 할 때마다 프로그램을 짜는 것이 너무 불편하다는 이야기가 나와서 등장한 것이 하이브(Hive) 입니다. 하이브는 쉽게 말하면 sql 로 분석 구문을 만들면 자동으로 그 내용을 맵-리듀스로 변경해서 하둡의 맵-리듀스 프레임워크에 태워서 분석을 가능하게 해주는 괜찮은 솔루션입니다. 귀찮은 프로그램을 일일이 짤 필요 없이 탑재된 로그 데이타를 분석할 때 강력함을 발휘합니다. 


자 그러면 실제 사례를 보기로 합니다. 


그러면 왜 하이브(Hive)를 쓰는 것인지는 저번에 설명했지만 다시 설명하자면 매번 반복되는 불편함을 제거하기 위해서 시작한 것으로 알고 있습니다. MySQL 의 문법과 기본적인 것은 호환이 되지만 100% 는 아닙니다. 예를 들면 자료형 자체가 많지 않습니다. 자주쓰는것은 INT 와 STRING 입니다. 한가지 여러가지 쿼리를 돌리다가 알아낸 사실입니다. 하둡 관련 플랫폼의 특징은 결국 자바 환경이라는 것인데, 자바의 약점을 그대로 가지고 있습니다. 바로 정해진 힙의 크기를 넘어가면 속된말로 '터진다'는 점입니다. 예를 들면 Group by 키워드를 사용하면 Map 의 영역입니다. 그래서 Map 을 돌리다가 멈추면서 힙(heap)이 터집니다. (자주 보던 그 키워드가 나옵니다. 터졌다고 ㅎㅎ) 그리고 Join 은 reduce 의 영역이라  reduce 에서 힙(heap)이 터집니다. (무식하게 10억건 이상되는 데이타를selfJoin 걸었기 때문이죠 ㅎㅎ) 게다가 이게 가능해야 분석가가 한발을 거칠 수가 있습니다. 분석할때마다 코딩하셔야 합니다. 라고 하면 분석 전문으로 하시는 분중에서 가능한 분이 몇명이나 있겠습니까? 


실제로 POC 를 준비했던 사례를 설명하겠습니다. 어떤 회사인지 말을 못합니다. (뭐 당연하겠죠? ㅎㅎ) 준비 과정에서 CDH5 버젼으로 각각 설치했습니다. 우분투( Ubuntu 14.04 ) 버젼으로 설치했기 때문에 주키퍼 (ZooKeeper)설치에 문제가 있었지만 직접 설치하는 것으로 해결하고 나머지 부분은 CDH 부분이 무난하게 설치 됐습니다. (하둡, 하이브, 하베 세개 다 설치했지만 하베는 사용안해서 지웠습니다) 물론 하드웨어는 제각각의 스펙을 가지고 있었고 그중 제일 괜찮은 서버에 네임노드(Namenode)를 설치해줬습니다. 증권사에서 준 데이타는 10개월치 13억건의 데이타 총 용량 300기가에 해당했습니다. (진짜 BigData 였습니다 ㅋㅋㅋ) 내준 숙제는 과거 데이타 중에 부정한 거래가 일어난 것을 잡는 케이스 였습니다. 샘플 600건을 POC 전날 제공받고 , 당일에는 300기가의 데이타를 제공해서 주어진 5시간 안에 전 데이타를 올리고 그중에서 분석해서 부정사례를 발견하는 것이 숙제였습니다. 이것을 제대로 했는지의 여부는 비밀입니다 ㅋㅋ 


데이타가 담겨 있는 USB 하드는 exFat 형태로 제공됩니다. 이걸 착각해서 ext 타입(ext3, ext4)으로 착각해서 드라이버 설치하는데만 한시간 걸렸습니다. 인터넷이 되면 한줄로 받는 명령을 인터넷이 안되는 환경이라 노트북에 프락시를 설치하고 핸드폰으로 테더링 걸고.. 난리도 아니였습니다. ㅜ.ㅜ 이게 첫번째 실수였습니다. 

그리고 데이터 전송을 한달별로 그리고 일자별로 정리가 되어 있는 자료여서 이것을 멀티프로세싱을 이용해서 한꺼번에 올렸습니다. 무지하게 걸리더군요.. 한달에 40분가량씩? 답이 도저히 안나오는 시간대라 이거 정말 업로드 가능한건가? 고민하다가 개별 개별로 올리기 시작했습니다. 1일치 올라가는 시간이 3-4초 늦어봐야 10초가 걸리더군요.. 이건 정말 무식해서 발생한 일이였습니다. 어차피 하드에 쓰는 속도 차이가 있는 것인데 멀티 프로세싱으로 동작을 시키면 물리적 하드에 쓰기 위해서 헤드가 왔다리 갔다리 하면서 시간이 오히려 더 걸리는 것이였습니다. 그래서 멀티프로세싱이 만능이 아니라는 옛말을 이제야 실감하게 되더군요. 전부 다 올려서 마트를 구성하는 건 10분정도 걸리고 , 전체 카운트 계산은 20초가 안 걸리더군요. 


준비과정에서 있었던 일을 포함해서 설명을 드리자면, 네트워크의 속도가 아주 중요합니다. 일반적인 100M bps 스위치를 기가 스위치로 바꾸고 네트워크 카드가 2개 있는 것을 전부 1개로 본딩(Bonding: 물리적인 2개의 네트워크 카드를 마치 1개 인양 묶어주면 HDD 레이드하는 것처럼 속도가 빨라짐)으로 묶어주니 업로드 속도가 거의 9배 가까이 상승하고 , 쿼리 속도가 거의 4배 상승했습니다. 

그리고 자바환경이기 때문에 역시 튜닝포인트는 존재합니다. 데이타 건수가 너무 많아서 올라가지 않는 문제는 없었기 때문에 거의 쿼리를 던지면 힙이 터지는 문제가 대부분입니다. 그래서 그런 쿼리를 처리하는 것이 노드매니져(nodemanager)의 힙 메모리 사용량을 변경하는 것으로 튜닝이 가능합니다. 기본은 1기가로 되어 있기 때문에 4기가로 올린 것만으로 안돌아가던 쿼리들이 돌아가기 시작하더군요. 만약 8기가 단위의 서버들을 이용해서 클러스터(Cluster)를 구성한다면 노드매니져의 메모리 튜닝만으로도 150만개의 데이터의 셀프조인(self join) 계산인 대략 2조개의 데이터까지 처리가 가능할 것으로 보입니다. 


제가 지금 까지 빅데이타가 우리나라에 소개되기 시작한 초창기부터 스터디하고 실제로 적용해보면서 느꼈던 단상을 말하자면 빅데이타가 만능이 절대 아니라는 것입니다. 사람들은 절대 만능이 아니지라는 말에 격한 공감을 하지만 실제로 이야기 하는 것을 보면 만능인것처럼 기대한다는 것입니다. 그러나 힙도 터지기도 하고 아무리 분산이라고 하지만 처리할 수 있는 용량의 한계는 분명히 존재합니다. 그래서 확장도 해야하고 머신 노드 자체를 늘려야 할 필요도 존재합니다. 

그리고 기본적으로 데이타에서 통찰력을 이끌어 내야 하는 부류이기 때문에 BI 와 같이 컨설팅의 영역에 가깝습니다. 개별 개별 정리할려고 하는 로그가 일정하지 않기 때문입니다. 비정형 데이터를 정리할 필요가 있는 것이지요. 그렇기 때문에 분석가가 달려들려고 해도 이러한 부분이 장벽으로 존재합니다. 즉 인프라 (Infrastructure)에 대한 이해도 필요합니다. 그렇기 때문에 원론적으로 말하는 데이타 해커(Data Hacker: 데이터를 수집하고 분석에 알맞게 정리하고 편하게 분석할 수 있게 구성할 수 있는 사람)와 데이타 과학자(Data Scientist: 데이터를 분석하고 분석된 데이타로부터 통찰력을 가져올 수 있는 사람)이 같이 필요합니다. 그래서 적어도 빅데이타 업체라는 소리를 할려면 이 두가지 종류의 사람이 다 필요합니다. 

그렇기 때문에 빅데이타쪽은 인프라가 필수적입니다. 일단 인프라를 설치하고부터가 시작입니다. 설치하고 데이타를 올리고 분석을 시작하면 갖가지 문제점들이 마구 마구 튀어나올 것입니다. 하지만 그러한 것들이 터져준다면 또한 행복한(?) 일일것입니다. 그러한 것들을 잡아나가는 것이 바로 발전의 시작이기 때문입니다. 




안드로이드 개발을 위해서 구글이 내놓은 새로운 개발툴 입니다. 최근에 이클립스가 maven 지원이 더딘것 때문에 사용자를 늘려가던 (유료인데도 불구하고!!) IntelliJ 기반입니다. 물론 구글이 내놓아서 공짜랍니다. 크기는 무려 700메가 정도군요, 기가단위가 아니라서 가벼운게냐..


조금 더 만져보니 이게 프로젝트가 비쥬얼 스튜디오 마냥 한번에 하나의 프로젝트만 열게 되어 있군요. 그래서 여러개를 한꺼번에 오픈하는 방식인 ADT 보다 가볍다는 소리를 듣는군요. 


자세한 설명과 다운로드는 바로 http://developer.android.com/sdk/installing/studio.html 에서 다운받을 수가 있습니다. 


지금까지 ADT 를 잘 사용했는데 왜 이걸 또 배워야 하느냐고 물으실 수가 있습니다. 저는 구글의 대변인은 아니지만 ㅎㅎ 이게 비록 베타인데도 웨어러블 (Wearable) 앱 만드는데 최적화가 되어 있습니다. (추천한다고 여기 저기 쓰여져 있습니다) 그리고 메이븐도 사용할 수가 있습니다. 자세한 것은 위의 주소에 가면 설명이 되어 있지만 따로 가져와 본다면 




제가 하는 영역과 관련되서 딱 하나의 불만은 NDK 가 지원 안된다는 점이지만 뭐 급할 것은 없겠지요. 받아서 설치하시고 나면 


바로 테마를 Default 에서 취향에 맞춰서 Darcula (드라큘라가 아니다? -ㅅ- ) 바꿔주셔도 좋습니다. 테마가 두개 밖에 없으니 알아서 골라주세용 


아 그리고 에디터를 이용할때 사용하는데 전혀 거부감이 없었습니다. 그 말인즉슨 에디터가 기본으로 이맥스(Emacs) 키 바인딩을 지원한다는 것이겠지요. 이것 또한 아주 마음에 드는 부분이였습니다. 


 Programming is not about typing... it's about thinking. -Rich Hickey



아 리치 히키가 한 말이니 전적으로 동감을 하지만 서도.. 생각만 한다고 잘 되는 것도 아니고, 일단은 키보드를 가지고 뭔가 쓰기 시작해야지 뭔가 되기도 하는데, 리치 히키가 한 말은 단순히 치기보다는 생각을 좀 하라는 뜻으로 받아들이는 게 나을 것 같습니다.
 
정말 예전 포스트 에서 민트 리눅스 (Mint Linux) 를 추천한 적이 있었습니다. 간만에 그 노트북이 생각나서 꺼내서 사용하니 OS 설치한지 오래되서 지원이 끊겼습니다. 민트 리눅스도 기반이 우분투(Ubuntu) 인지라 우분투의 지원주기랑 같습니다. 즉 우분투가 LTS (Long Term Support) 버젼이면 민트도 LTS 가 되는 것이지요. 따라서 우분투 LTS 버젼의 최근 것이 12.04 니까 민트도 거기에 해당하는 버젼이 민트 13 마야 (Mint Linux 13 Maya) 가 되는 것이지요. 

http://www.linuxmint.com/release.php?id=18

위 링크를 클릭하시면 민트 리눅스를 받을 수 있습니다.  저사양 노트북에는 씨나몬 (Cinnamon) 보다는 메이트 (Mate) 가 낫다고 하더군요. 기능성은 조금 떨어지지만 더 가볍다고 합니다. 그리고 제 빌어먹을 소니 노트북은 32비트 CPU 기 때문에 32 비트 버젼 Mate 를 설치해줍니다. 

다운로드 받은 iso 파일이 있다면 이제 이것을 USB 스틱에다 넣어서 부팅이 가능하도록 만들어 줘야 하는데 몇가지 방법이 있습니다. 그러나 제 경험으로는 몇가지 방법이 있다고는 하지만 되는 방법은 별로 없었습니다.

제 추천은 Universal-USB-Installer 를 이용하는 것을 추천드립니다.  


만약 윈도우에서 Linux 계열의 부팅이 가능한 USB 스틱을 만드는 경우라면 위의 프로그램을 이용하는 것이 가장 편했습니다.

그후에 시키는대로 대충 누르시면 설치가 됩니다. (민트 리눅스를 설치하는 방법은 여러군데서 찾을 수 있을 뿐더라 설치 자체도 쉽습니다)

설치후에 해야 할 일

사실은 이 부분이 더 중요합니다.  먼저 민트 리눅스 마야 (Maya) 는 LTS 인 12.04를 기반으로 하긴 하지만 이 버젼 자체가 옛날에 나온 것이기 때문에 소프트웨어 업데이트를 해줘야 합니다. 하지만 소프트웨어를 가져오는 소스 기반이 해외로 되어 있기 때문에 안그래도 시간이 걸리는 업데이트가 하루종일이 걸릴 수가 있습니다. 

1. 소스 레파지토리 (Source Repository) 한국으로 변경해주기 

$ sudo vi /etc/apt/sources.list


커맨드 라인에 위처럼 입력하시고 비밀번호를 입력하시면 나오는 상태에서

:1,$s/archive.ubuntu.com/ftp.daum.net/g


 로 입력하시면 병경이 됩니다. 그리고 

deb http://packages.medibuntu.org/ precise free non-free 



이 주소는 더 이상 사용되지 않는 것 같더군요. 원활한 진행을 위해서 맨 앞에 # 를 추가해서 막아줍니다. 

$ sudo apt-get update 



를 커맨드 라인에 입력하셔서 업데이트 해 줍니다.

그리고 왼쪽 하단의 'Menu' 버튼을 클릭하시고 '패키지 관리자'를 실행해 줍니다. (아마 한글이 안 깔린 상태라면 'Package Manager' 란 이름일 것입니다) 

 
이런게 뜨면  '설정' - '저장소' 를 눌러서 화면을 띄웁니다. 그러면 나오는 화면에서 



 위처럼 클릭하시고 나온 화면에서 



이렇게 선택하시고 '서버 선택' 버튼을 클릭하시면 됩니다. 그리고 다시 '소프트웨어 소스' 화면에서 두번째 '기타 소프트웨어'탭을 클릭하셔서 http://packages.medibuntu.org 항목을 체크 해제 하거나 지워주세요. 


위 그림처럼 해주면 되지만 실은 이 부분은 커맨드 라인에서 해주는 작업하고 동일합니다. 만약 커맨드 라인 작업을 먼저 하셨다면 이 부분은 필요 없을  수도 있습니다. 

여기까지 마치셨으면 오른쪽 하단의 방패 마크를 클릭하셔서 나오는 화면에서 


 '새로 고침'을 눌러서 저장소 업데이트 해주고 위 그림처럼 '업데이트 설치' 를 눌러서 긴 시간동안 설치해주시면 최신 소프트웨어로 업데이트 됩니다. 

2. 한글 설정

아직 한글이 제대로 설정이 안되는 경향이 있습니다. 이것은 1번 작업을 했다면 손 쉽게 해결할 수가 있습니다.  왼쪽 하단의 'Menu' 버튼을 클릭하시고 '제어판'을 클릭하시면 (한글 디스플레이 표기 전이라면 Control Pannel 일 것입니다. 아마도..) 


에서 위 그림과 같이 'Language Support' 를 클릭하셔서 나오는 화면에서 무엇인가를 설치하겠냐고 물어보면 설치한다고 대답하시고 나오는 화면에서 

 


위 그림 처럼  저 버튼 (다시 말씀드리지만 한글 디스플레이가 안되는 상황이면 영어 일 수가 있습니다) 을 클릭하셔서 나온 화면에서 

 
위 그림처럼 선택해서 (제 경우에는 영어 표시였고 Korean 을 선택해 줬습니다) '바뀐 내용 적용' 을 클릭해서 적용하면 됩니다.

여기까지면 한글 언어 팩이 설정된 것이고 이제 한글 입력기를 설치할 차례 입니다. 한글 입력기는 우분투에서 쓰이는 기본인 iBus 가 민트에서는 제대로 동작 안됐던 기억이 있습니다. 아마 소소한 버그였는데 고쳐졌을 지도 모르지만 한번 디인 상태라 모험하긴 싫더군요. 따라서 나비 (nabi) 를 설치해 주기로 합니다.

$ sudo apt-get install nabi



라는 마법의 키워드 한번만 입력해 주면 설치 완료 입니다.  한글이 적용되는 것을 확인하기 위해서 'Log out' 했다가 다시 'Log in' 하면 적용 된 모습을 확인 하실 수 있습니다. 

참고로 이 포스트는 그 설치된 민트 리눅스 마야 버젼에서 작성되었습니다. (화면 캡쳐도 물론 입니다. 이 버젼에 포함된 화면 캡쳐  프로그램 정말 쓸만하군요. @.@ )  


 위 그림은 '죠죠의 기묘한 모험'에 나오는 악역인 디오 브란도 입니다. 이 디오는 죠죠라는 만화에서 특이한 위치를 차지하는 악역입니다. 심지어 죠죠가문 3대째에 이르는 악역이기도 합니다. (혈통으로는 4대째이지만) 잔혹하고 무자비하지만 부하들에게는 공포로 또는 위엄으로 군림하고 상당한 힘을 가지고 있는데도 불구하고 힘으로만 밀어 붙이는 타입도 아니고 상당히 간교합니다. 뭐 자세한 건 직접 보시면 되고 '죠죠 3부'에 나오는 디오는 특이한 능력을 가지고 있습니다. 시간을 멈추는 능력을 가지고 있는 스탠드 (더 월드 라고 합니다)를 활용해서 기술을 쓰는데, 주인공 파티가 그 능력을 파악하지 못하고 속수무책으로 당합니다. 그러다 한 파티원이 혹시 시간을 멈추는 것이 아닐까 라는 내용을 주인공한테 전달하고 주인공(쿠죠 죠타로)은 시간을 멈춘다는 능력을 '인식'하는 순간 '더 월드'의 능력은 더 이상 속수 무책의 능력이 아니게 됩니다. (사실 그 연유는 길고도 긴 사연이지만..) 

  길게 사설을 늘어 놓은 이유는 바로 '인식'에 관한 이야기를 하고 싶어서 입니다. 길고 긴 세월동안 프로젝트를 진행하며 수 많은 프로그램을 만들어오면서 만들어야 하는 것이 어떤 것인지 인식하지도 못하고 만들었던 적도 많습니다. 재밌는 것은 그러한 인식없이 만들기 시작하다 보면 만들면서도 뭐를 어떻게 해야 하는지 전혀 감이 안온다는 것입니다. 그렇지만 그런 상태에서 조금 더 이해하기 위해서 노력을 기울이다 보면 어느덧 만들어야 하는 것이 어떠한 원리로 돌아가는 것이고 왜 그런 방식으로 만들어야 하는지 명확하고 '단순'하게 인식될 때가 있습니다. 그런 그 순간이 복잡했던 프로젝트가 단순해지며 오픈소스를 쓰고 있더라도 어떤식으로 응용해야 할지 명확하게 드러나는 순간입니다. 안타깝게도 이러한 '인식'의 순간을 빨리 맞이하는 것은 연차가 짧을 때는 잘 되지 않았습니다. 이런 저런 전산적인 경험을 쌓고 나서야 (그럼에도 불구하고 순식간에 인식을 맛보는 것은 아직까지 가능하지가 않더군요..) 가능해 지더군요. 이러한 인식의 순간이 경험과 상관없이 빠르게 맞이하는 존재들을 세상에서는 천재라고 부르는 것이겠지요. 

  어렵고도 잘 이해가 안되는 프로젝트를 진행하고 있거나, 역시 비슷한 정도로 어려운 오픈소스를 파고 있다면, 아직 인식의 순간이 오지 않았기 때문에 어렵다고 생각하시면 될 것입니다. 그래도 조금씩 힘내서 이거 저거 '단순화' 시키려고 노력하시다 보면 갑자기 전체적인 형태가 파악되고 결국 간단한 구동 원리를 구현하기 위해서 여러가지 살을 붙이다 보니 지금 처럼 복잡하게 됐다는 것을 깨달으시게 될 것입니다. 


-- 오늘도 밤늦게 까지 개발하시는 개발자 여러분 파이팅 -- 
Android NDK (Native Development Kit) 을 이용해서 개발하고 있습니다. NativeActivity 를 이용하고 있습니다. 그런데 작지만 해결하기 어려운 버그가 있습니다. 

NativeActivity 는 Java 의 Activity 의 일종인데 JNI 를 이용한 Native C/C++ Entry Point 를 쓰레드 (Thread)를 이용해서 호출하는 부분을 잘 감싸서 NDK 를 이용해서 개발하고자 하는 사람들에게 편의를 제공할려는 목적으로 만들어 진것으로 보입니다. 특히나 게임 , 전화, 멀티미디어 용 어플리케이션을 개발하는 사람들은 필히 관심을 가져볼 만합니다. 

발생한 이슈는  제가 추천한 책에서 언급된 소스에 다른 모듈을 붙일려고 하는 순간에 발생했습니다. 참고로 만들어본 Android.mk 파일입니다. 



LOCAL_PATH := $(call my-dir)
TOP_ROOT_PATH := $(LOCAL_PATH)

include $(call all-subdir-makefiles) 
# 이 하위 Android.mk 에서 Shared Library 를 만들어 줍니다. 
# 그 라이브러리 이름을  codec 이라고 (예를 들어서) 해줍니다. 

include $(CLEAR_VARS)

LOCAL_PATH = $(TOP_ROOT_PATH)

LS_CPPP=$(subst $(1)/, ,$(wildcard $(1)/*.cpp ))

LOCAL_MODULE := game 
LOCAL_SRC_FILES := $(call LS_CPPP,$(LOCAL_PATH))

LOCAL_CFLAGS += -D GL_GLEXT_PROTOTYPES

LOCAL_LDLIBS := -landroid -llog -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue png
LOCAL_SHARED_LIBRARIES := codec                          
# 이 부분이 문제의 그 부분입니다. 

include $(BUILD_SHARED_LIBRARY)

$(call import-module, android/native_app_glue)
$(call import-module, libpng)


이게 대체 뭐지? 라고 생각하시는 분들은 제가 곧 'NDK 프로그래밍 따라하기' 포스트 한 두개를 올릴테니 그 때까지 이 부분을 보실 필요는 없습니다. 

위의 Android.mk 를 이용해서 컴파일을 하면 libgame.so 가 만들어 집니다. 책에서 나와 있는 그대로 만들어 집니다. 그러나 codec 이라는 (libcodec.so)를 이용해야 하는 필요가 생겨서 따로 만들어 줘서 프로젝트에 포함시켜 주면 실행이 안되고 에러가 발생합니다. 

잘 된 캡슐화의 문제점 중의 한가지가 난감한 에러가 발생하면 해결하기 어렵다는 점입니다. 구글링도 해보고 여러가지 독립적인 테스트를 해 본 결과 전혀 엉뚱한 작업을 진행중에 해결이 됐습니다. 100% 확신을 한 바는 아니지만 NativeActivity 가 결국 Java 클래스 이고 내부적으로는 결국 JNI 를 이용해서 Library 를 불러오는데, 정해진 방법으로만 호출하기 때문에 (위의 예제의 경우에는 libgame.so ) 다른 라이브러리를 호출을 못하기 때문에 발생하는 것 같습니다. 따라서 해결해 주기 위해서는 몇가지 수동으로 처리해 줘야 합니다. 

$ cd $PROJECT_ROOT
$ cd src/com/comjuck/game     (없으면 만들어 주셔야 합니다)
$ emacs NativeActivity

package com.comjuck.game;

import android.app.NativeActivity;
import android.os.Bundle;

public class GameActivity extends NativeActivity {

	static {
		System.loadLibrary("codec");
	}


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
  }
  
}


GameActivity 를 만들어주고 NativeActivity 에서 상속을 받습니다. (물론 package 경로에 맞춰주는 것을 잊어주시면 안됩니다) , 그리고 위에서 표기한 대로 추가해 준 라이브러리를 직접 불러줍니다. 
그리고 AndroidManifest.xml 을 열어서 추가해 준 Activity 를 android.app.NativeActivity 대신 지정해 줍니다. 

$ cd $PROJECT_ROOT
$ emacs AndroidManifest.xml 
 

    <activity android:name="PhoneActivity"
                  android:label="@string/app_name">


이제는 문제 없이 앱이 실행되는군요. 

ps. 이걸 알아내기 위해서 4시간을 소모했습니다. ㅜ.ㅜ 

+ Recent posts