Hadoop, Pig, Hive 설치 가이드!

이번 학교 수업에서 hadoop, pig, hive를 이용하게 되었습니다. 설치가 쉬울 줄 알았지만, 생각보다 까다롭고 기존의 guide에서 제시하지 못했던 예외들이 많이 발생하였기에, 또 기억하기 위해, 직접 포스팅하고자 합니다.

아주 만약에 혹시나 정말 혹시라도 이 포스팅이 마음에 드신다면, 널리널리 공유해주시면 정말 감사하겠습니다!

  • 시작하기에 앞서, 이 포스팅은 순전히 hadoop, pig, hive를 맛보고자 하시는, 혹은 설치에 어려움을 겪고 계시는 초보자분들을 위한 포스팅입니다. 따라서 숙련자 분들께서 보시기에는 답답하거나 틀린 부분이 있을 수 있으니, 혹여나 잘못된 부분에 대해서는 nohyg90@gmail.com 으로 메일을 주시면 참고하여 수정하도록 하겠습니다.

  • 이 포스팅은 제가 직접 작성함과 동시에 테스팅하며 바로바로 한 줄씩 확인하였음을 밝히고, 따라서, 혹여나 에러가 발생하신다면 먼저 작성하였던 코드 중, 오타가 없는지 확인바랍니다.

  • 이 포스팅은 AWS를 이용하였습니다. (하지만 OS 환경만 ubuntu로 일치한다면, 이 가이드를 똑같이 따라하셔도 무방하다고 판단됩니다!)

  • 이 포스팅은 hadoop의 여러 Operation 중, Fully-Distributed Operation에 대해서 다뤘습니다.

  • 이 포스팅은 이론적인 내용이 거의 담겨있지 않습니다. 이론적인 부분은 포스팅 중간중간에 삽입된 공식사이트를 통해 확인부탁드립니다.

  • 이 포스팅은 2016년 6월 1일에 작성되었습니다. 시간이 흐름에 따라 버전 등이 맞지 않을 수 있으니 확인바랍니다.

1. AWS EC2 인스턴스 만들기

1.5 EC2 접속하기

2. hadoop 설치하기

3. pig 설치하기

4. hive 설치하기



1. AWS EC2 인스턴스 만들기



먼저 AWS에 접속하여 EC2 인스턴스를 만들도록 합시다. EC2를 만드는 방법은 구글링을 조금만 해봐도 아주 많이 나오니 여기서는 간단한, 꼭 설정해야할, 설정들에 대해서만 언급을 하고 지나가겠습니다.

  • Step 1: AWS EC2에 접속하여 Launch Instance 버튼을 누릅니다.

  • Step 2: AMI(Amazon Machine Image)로 Ubuntu를 선택합니다.

  • Step 3: Review and Launch를 눌러 가뿐히 skip 합니다.

  • Step 4: Launch를 눌러 skip 합니다.

    • 여기까지 진행하였으면, key pair를 선택하거나, 새로 create하라는 창이 뜹니다.

    • case 1 혹시 keypair가 있으시고, 그것을 사용하실 분은 해당하는 keypair 를 선택하여 주시면 됩니다.

    • case 2 만약, key pair 가 없으신 분은 Create a new key pair를 선택 후, 이름을 지어 download key pair 버튼을 누르시기 바랍니다. (여기서 저는 통일성을 위하여 keypair 이름을 sample이라고 하겠습니다.) 저는 chrome 사용을 권장합니다. keypair 다운로드 시, safari에서는 .txt파일로 다운되어 서버에 접속이 안되는 것을 확인하였습니다.

    • 다운로드를 완료하였으면 그 경로를 잘 기억해두시고, Launch Instance 버튼을 누릅니다.

  • 여기까지 하였으면 Launch Status라는 헤더가 보이실텐데, 그럼 잘 따라오셨다고 보시면 됩니다.

위의 과정을 3번 더 반복하여 instance를 총 4개 만듭시다. (주의: 첫 인스턴스를 제외한 두번째 인스턴스부터는 접속할 때의 편의를 위하여 keypair를 방금 생성하신 keypair를 선택하시기 바랍니다.)


자 이제 4개의 instance 를 모두 만드셨으면 Elastic IP와 Security group을 설정하실 차례입니다.

일단 먼저 Elastic Ip 설정하겠습니다.

  • Step 1: AWS 메인에서 EC2를 선택하시고 들어오시면 좌측 탭에 Instances 라는 것을 클릭합니다.

  • Step 2: 아까 만든 Instance 4개가 보이실텐데, 이 4개의 instance에 적절한 이름을 지어줍니다.(예: hadoop1, hadoop2, hadoop3, hadoop4)

  • Step 3: 좌측 탭의 Elastic IP를 클릭합니다.

  • Step 4: Allocate New address를 클릭하여, 새로 Elastic IP를 생성해줍니다. 이 과정을 4번 반복하여 Elastic IP가 총 4개 생성되도록 합니다.

  • Step 5: 모두 생성되었으면, 각 Elastic IP 마다 우클릭하여 Associate Address를 클릭합니다.

  • Step 6: 그럼 창이 하나 뜰텐데요. 여기서 다른 것은 건드리지 않고, Instance 칸만을 클릭하여 아까 이름 정했던 instance 중 하나를 선택하고, Associate 버튼을 누릅니다. 이 과정을 4번 반복하여 각각의 instance가 서로 다른 Elastic IP를 가질 수 있도록 합니다. (사실 이 과정은 하나의 instance에 대해서만 해도 될 듯 합니다만, 일단은 4개에 대해 모두 하도록 합니다.)

좌측 Instances 를 클릭하고, 임의로 아까 설정한 instance들을 보았을 때, 하단 정보에 Elastic IP가 할당되어 있으면 제대로 설정하신 겁니다.


다음으로 Security group을 설정하겠습니다.

생각보다 포스팅이 길어질 것 같네요..

  • Step 1: 먼저 지난 과정에서 만든 Instance 를 차례대로 클릭하여 하단 정보에 나오는 Security groups의 이름들을 기억하도록 합니다. 아마 뒤의 숫자가 연속된 숫자일 것입니다.(제 경우는 launch-wizard-10, launch-wizard-11, launch-wizard-12, launch-wizard-13 이네요.)

  • Step 2: 좌측 탭의 Security Groups를 클릭합니다.

  • Step 3: 그럼 방금전에 보았던 launch-wizard-xx 들이 보이실겁니다. 먼저 이들 중 맘에 드는 하나를 선택합니다.

  • Step 4: 하단에 정보가 나올텐데요. Inbound 탭을 클릭하고, Edit 버튼을 클릭하도록 합니다.

  • Step 5: Add Rule 버튼을 클릭하고, 새로 생긴 것에서 All TCP를 선택합니다. 또한, 새로 생긴 것에 Custom IP라고 되어있는 것을 클릭하여 Anywhere로 바꿉니다.

  • Step 6: 다시 한번 Add Rule 버튼을 클릭하고, All ICMP를 클릭, 마찬가지로 Anywhere로 바꿔줍니다. 그 후 Save버튼을 눌러 빠져나옵시다.

  • Step 7: 다시 Instances 탭을 클릭하여 돌아갑니다.

  • Step 8: 전 단계에서 생성하였던 4개의 Instances에 대해, Step 9를 반복합니다.

  • Step 9: 각 instance를 클릭하고, 우클릭하여 Networking -> Change Security Groups를 클릭합니다. 그 후 체크된 것을 해제하고, 방금 전에 설정한 Security group을 체크해줍니다. 그리고 Assign Security Groups를 클릭하여 빠져나옵니다.

  • Step 10: 모두 다 변경하였으면, 4개의 instance들을 하나씩 클릭하여 하단 정보에 Security groups가 아까 설정한 security group으로 일치하는지 확인합니다.

여기까지가 AWS 설정 단계였습니다. 이제 Hadoop. Pig, Hive를 설치할 장소를 마련하였습니다!



1.5 EC2 접속하기



EC2 Instance를 만들었으니, 접속해보도록 합시다.

이 것은 Mac OS 기준으로 작성되었으니, windows분들은 이곳을 참고하여 접속하시기 바랍니다.

  • Step 1: keypair가 있는 곳으로 이동합니다.

  • Step 2: chmod 400 [keypair이름.pem] 명령어를 입력하여 keypair의 권한을 변경합니다.

  • Step 3: AWS에 접속하여 맘에 드는 하나의 EC2 instances의 Elastic IP를 확인합니다. (instance를 클릭하면 나오는 하단 정보에서 Elastic IP를 확인할 수 있습니다.) 그리고, 이 EC2 instance의 이름을 반드시 기억하도록 합시다. 앞으로 nameNode로 사용될 instance입니다.

  • Step 4: ssh -i [keypair이름.pem] ubuntu@[ElasticIP]를 입력합니다. 연결을 계속할 것이냐는 문구가 나오면 yes를 입력합니다.

이제 EC2에 접속하는 방법을 배웠습니다! 현재는 하나의 EC2 instance에 접속하였지만, 추후에는 4개의 instance에 접속하게 될 것입니다.



2. Hadoop 설치하기



아 드디어 본론인 2. Hadoop 설치하기 입니다. 이 부분이 조금 지루하실 수도 있고, 에러가 많이 발생하실 수도 있지만, 꼼꼼히 오타없이 따라오시면 분명히 잘 해내실 수 있을거라 믿습니다! 참고로 저는 이 포스팅을 하기 전에 며칠간 하둡을 한 5 ~ 7번은 재설치하며 오류를 찾아내느라 고생을 하였습니다….

아, hadoop의 공식사이트는 이곳이므로, 제가 담지 못한, 혹은 궁금하신 내용은 사이트를 통해 확인바랍니다.

  • Step 1: EC2 instance 에 접속합니다. (위의 1.5 AWS 접속하기를 참고하길 바랍니다.)

  • Step 2: 아래의 명령어를 입력하여 하둡을 다운받습니다(시간이 조금 소요될 수 있습니다. 참고로 저는 홈 디렉토리(~)에 작업하니, 저와 디렉토리를 일치시켜주시길 권장합니다.):

wget http://apache.mirror.cdnetworks.com/hadoop/common/hadoop-2.7.1/hadoop-2.7.1.tar.gz
  • Step 3: 다운로드가 완료 되었으면, tar -xvf hadoop-2.7.1.tar.gz 명령어를 입력하여 압축을 해제합니다.

  • Step 4-1: 잠시 압축을 해제한 것은 뒤로 미뤄두고, .bashrc 파일을 설정해봅시다. sudo vi ~/.bashrc 명령어를 입력하여 .bashrc를 엽니다.

  • Step 4-2: Shift + g를 눌러 가장 마지막 줄로 이동합니다. 그리고 o 키를 눌러서 입력모드로 전환하고, 마지막 줄에 아래의 내용을 입력합니다.

export HADOOP_HOME=~/hadoop-2.7.1
export PATH=$PATH:$HADOOP_HOME/bin
  • Step 4-3: 입력을 모두 하셨으면 esc키를 누르시고 Shift + ;키를 누른 후, wq라고 입력하고 엔터를 쳐서 빠져나옵니다.

  • Step 4-4: source ~/.bashrc라고 커맨드 창에 입력하여 현재 변경한 내용이 바로 적용될 수 있도록 합니다.

  • Step 5-1: 자 이제 hadoop에 필수적인 java를 설치할 차례입니다. 아래의 명령어를 순서대로 하나씩 커맨드창에 입력하여 진행합니다: (마지막 명령어 설치시, 보라색 화면이 나오면 YES를 선택합니다.)

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer
  • Step 5-2: 자바를 설치하였으니, 환경변수를 설정해줍니다. ( 이곳을 따라서 환경변수 설정을 할 수도 있습니다만, 제가 이곳에 입력하는 것을 따라하셔도 완전히 무방합니다. ) sudo vi /etc/profile를 커맨드에 입력합니다. 마찬가지로, Shift + g를 눌러 마지막줄로 이동, o를 눌러 입력모드로 변환하고, 마지막 줄에 다음을 입력합니다:
export JAVA_HOME=/usr/lib/jvm/java-8-oracle
  • Step 5-3: source /etc/profile을 커맨드에 입력하여 변경사항이 바로 적용되도록 하고, 완전성을 위해 exit를 입력하여 서버에서 로그아웃하고, 재접속 하도록 합시다.

  • Step 5-4: 재접속하셨으면 echo $JAVA_HOME을 커맨드에 입력하여 출력을 확인합니다. (출력되는 것이 없다면 설정이 제대로 이루어지지 않은 것입니다.) 정상적인 경우, 아까 설정한 /usr/lib/jvm/java-8-oracle이라는 메시지가 나옵니다.

  • Step 6: 이제 다시 hadoop으로 돌아옵시다. hadoop-2.7.1 폴더로 이동합니다.vi etc/hadoop/hadoop-env.sh명령어를 통해 hadoop-env.sh 파일을 엽니다.

  • Step 7: 마찬가지로 Shift + g, o를 차례대로 눌러서 마지막줄로 이동, 입력모드로 변경합니다. 다음의 내용을 입력하도록 합니다:

export JAVA_HOME=/usr/lib/jvm/java-8-oracle
export PATH=${JAVA_HOME}/bin:${PATH}
export HADOOP_CLASSPATH=${JAVA_HOME}/lib/tools.jar:${HADOOP_CLASSPATH}
  • Step 8: 마찬가지로, esc, shift + ;, wq를 차례로 입력하고 엔터를 눌러, 빠져나온 뒤, source etc/hadoop/hadoop-env.sh 명령어를 통해 변경내용을 바로 적용시켜줍니다.

  • Step 9-1: 자 이제 host 이름을 설정하도록 할텐데요, 먼저 AWS 홈페이지로 이동하여 4개의 EC2 인스턴스들에 대해 각각의 Private IP를 확인하도록 합니다. Private IP는 각 instance를 클릭하면 하단의 정보에서 확인하실 수 있습니다.

  • Step 9-2: 확인한 private ip들을 sudo vi /etc/hosts를 통하여, (앞에서 배운 내용들을 토대로 마지막 줄에) 입력하도록 합시다: (참고로 [privateIP1] 등이 자신들의 private ip로 변경되어야합니다. 그리고 여태까지 작업했던 instance의 private ip를 첫번째에 위치시켜 nameNode라는 이름을 갖도록 합시다.)

[privateIP1] nameNode
[privateIP2] resourceManager
[privateIP3] dataNode01
[privateIP4] dataNode02

모두 입력하였으면 빠져나오도록 합니다.(esc, shift + ;, wq)

  • Step 10-1: 자 이제 가장(?) 중요한 configuration을 할 차례입니다. 더욱 주의해서 따라오시기 바랍니다. 먼저 cd etc/hadoop을 통해 etc/hadoop 폴더로 이동합시다.

  • Step 10-2-1: vi core-site.xml 명령어를 입력하여 엽니다.

  • Step 10-2-2: <configuration> 태그 사이에 다음을 입력하도록 합니다:

<configuration>
	<property>
		<name>fs.defaultFS</name>
		<value>hdfs://nameNode</value>
	</property>
</configuration>
  • Step 10-3-1: vi hdfs-site.xml 명령어를 입력하여 엽니다.

  • Step 10-3-2: <configuration> 태그 사이에 다음을 입력하도록 합니다:

<configuration>
	<property>
		<name>dfs.replication</name>
		<value>2</value>
	</property>
	<property>
		<name>dfs.hosts</name>
		<value>/home/ubuntu/hadoop-2.7.1/etc/hadoop/slaves</value>
	</property>
	<property>
		<name>dfs.namenode.name.dir</name>
		<value>/home/ubuntu/hadoop-2.7.1/data/namenode</value>
	</property>
	<property>
		<name>dfs.datanode.data.dir</name>
		<value>/home/ubuntu/hadoop-2.7.1/data/datanode</value>
	</property>
</configuration>
  • Step 10-4-1: 먼저, cp mapred-site.xml.template mapred-site.xml을 입력하여 복사하고, vi mapred-site.xml 을 입력하여 엽니다.

  • Step 10-4-2: <configuration> 태그 사이에 다음을 입력하도록 합니다:

<configuration>
	<property>
		<name>mapreduce.framework.name</name>
		<value>yarn</value>
	</property>
</configuration>
  • Step 10-5-1: vi slaves 명령어를 입력하여 엽니다.

  • Step 10-5-2: 다음의 내용이 되도록 내용을 변경합니다:

nameNode
resourceManager
dataNode01
dataNode02
  • Step 10-6-1: vi yarn-site.xml 명령어를 입력하여 엽니다.

  • Step 10-6-2: <configuration> 태그 사이에 다음을 입력하도록 합니다:

<configuration>
	<property>
		<name>yarn.nodemanager.aux-services</name>
		<value>mapreduce_shuffle</value>
	</property>
	<property>
		<name>yarn.resourcemanager.hostname</name>
		<value>resourceManager</value>
	</property>
</configuration>

여기까지 오타 없이 잘 오셨으면, hadoop + pig + hive 설치의 60%는 끝낸 셈입니다. 조금만 더 참고 따라오시면 됩니다!

  • Step 11-1: 자 이제 처음으로 드디어 4개의 instance에 접속할 때가 왔습니다! 먼저 terminal을 추가로 3개 더 켜고, 마찬가지로 각각의 terminal이 각각의 instance에 접속할 수 있도록 해주세요.(nameNode, resoureManager, dataNode01, dataNode02가 될 것 입니다.) 아래의 step(step 11-5까지)은 각각의 instance에 모두 실행해주세요!

  • Step 11-2: SSH 암호화 키를 설정하여, 다른 node들에 접근할 때 암호 없이 바로 접근가능하도록 설정하겠습니다. 참고로 저는 이곳을 토대로 설명을 하겠습니다.

  • Step 11-3: cd ~ 명령어를 통해 ~ 디렉토리로 이동합니다.

  • Step 11-4: ssh-keygen -t rsa를 입력하고 나오는 내용들은 모두 enter를 눌러 skip합시다. 그럼 이상한 직사각형에 무늬들이 찍혀있는 액자를 보실 수 있을 것입니다.

  • Step 11-5: 다음의 명령어들을 차례대로 터미널에 입력하여 권한을 변경합니다:(다음의 파일들은 ls -al ~/.ssh/ 명령어를 통해 존재를 확인할 수 있습니다.)

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 644 ~/.ssh/authorized_keys
  • Step 12: 먼저, 4개의 instance를 모두 연결한 김에 Step 9-2을 모든 instance에 적용시켜 줍시다.

  • Step 13-1: 또, 4개의 instance를 켠 김에 .pem 없이 암호로 접속가능하도록 설정을 합니다. 아래의 Step 13-x를 각각의 instance에서 실행합니다.

  • Step 13-2: sudo passwd ubuntu 라고 입력하여 암호를 설정합니다. (암호가 입력되는 것은 보이지 않습니다. 암호 입력 후 엔터를 눌러서 암호 확인까지 입력해주세요.)

  • Step 13-3: sudo vi /etc/ssh/sshd_config를 입력하여 엽니다.

  • Step 13-4: 위의 파일을 연 상태로, 아무것도 안 누른 채로 /PasswordAuthentication을 입력 후 엔터를 칩니다. 그 후 i를 눌러 입력모드로 전환, no라고 되어있는 부분을 yes로 변경하고 저장하고 나옵니다.(esc, shift + ;, wq)

  • Step 13-5: 변경사항이 저장될 수 있도록 restart합니다. sudo service ssh restart

  • Step 14: 자 그럼 모든 id_rsa.pub 파일을 nameNode로 복사할 건데요. 다음의 명령어를 4개의 모든 인스턴스에서 실행하도록 합니다: (*단, id_rsa_1.pub 이 부분의 숫자는 파일이 중복되지 않도록 각 instance에서 모두 다르게 입력하도록 합니다. 즉, id_rsa_1.pub, id_rsa_2.pub id_rsa_3.pub, id_rsa_4.pub *)

scp ~/.ssh/id_rsa.pub ubuntu@nameNode:id_rsa_1.pub
  • Step 15: nameNode~에서 ls를 쳐보면 다른 node들이 전송한 id_rsa파일들이 왔음을 알 수 있습니다.

  • Step 16: 그럼, 이 파일들을 하나로 묶도록 하겠습니다. 먼저 touch idrsa라고 입력하여 파일을 하나 생성해줍니다.

  • Step 17: cat id_rsa_1.pub >> idrsa 명령어를 id_rsa_1.pub 번호만 바꿔가며 실행해줍니다. (전송 받은 id_rsa.pub 파일들을 idrsa라는 파일안에 모두 옮겨 담는 작업입니다.)

  • Step 18: idrsa를 각각의 instance에 배포해줘야겠지요. 다음의 명령어를 통하여 nameNode에서 각각의 instance에 뿌려줍시다:

scp idrsa ubuntu@resourceManager:idrsa
scp idrsa ubuntu@dataNode01:idrsa
scp idrsa ubuntu@dataNode02:idrsa
  • Step 19: 이제 각각의 instance에서 idrsa 파일을 실제로 암호를 관리하는 authorized_keys에 붙여넣읍시다. 다음의 명령어를 모든 instance에서 입력합니다:
cat idrsa >> ~/.ssh/authorized_keys
  • Step 20: 자, 거의 막바지입니다. 이제는 저희의 여태까지 계속 작업했던 첫번째 instance를 제외한 나머지 instance에도 java를 설치할 차례입니다. 거의 끝났으니 조금만 더 힘내서 따라옵시다. Step 4에서 Step 5를 나머지 3개의 instance에 적용시켜줍시다. (하나의 step씩 동시에 3개의 instance에서 복사해가며 하는 것이 편합니다.)

  • Step 21: 여태까지 저희가 hadoop을 어디에 설치했었는지 기억하시죠. 바로 nameNode입니다. 다른 instance(node)들에는 제가 hadoop을 깔지 않았는데, 그 이유가 바로 하나의 instance에만 깔고 나머지 instance는 복사하여 사용하여도 전혀 무관하기 때문입니다! nameNode~에서 다음의 명령어를 통해 hadoop을 복사합니다(마찬가지로 [nodename]은 resourceManager, dataNode01, dataNode02 로 대체돼서 실행하셔야 합니다.):

scp -r hadoop-2.7.1 ubuntu@[nodename]:hadoop-2.7.1
  • Step 22: nameNode에서 다음의 명령어를 통해 format을 합니다!
hadoop namenode -format
  • Step 23-1: 그럼 이제 nameNode에서 cd hadoop-2.7.1/ 명령어를 통해 hadoop-2.7.1 폴더로 이동하고, ./sbin/start-all.sh 명령어를 통해 hadoop을 실행합니다.

  • Step 23-2: 각각의 instance(node)에서 jps 명령어를 통해 다음이 출력되면 아주 잘 설정된 것입니다:

namenode의 경우:
???? NameNode
???? SecondaryNameNode
???? NodeManager
???? Jps
???? DataNode

그 외의 node의 경우:
???? Jps
???? NodeManager
???? DataNode
  • Step 24-1: 그럼 이제 resourceManager로 설정된 instance를 켜고 있는 terminal에서 마찬가지로 hadoop-2.7.1 폴더로 이동하고 ./sbin/yarn-daemon.sh start resourcemanager 명령어를 통해 resourcemanager를 실행합니다.

  • Step 24-2: resourceManager에서 jps를 입력하였을 때 다음과 같이 나오면 정상입니다:

???? Jps
???? ResourceManager
???? DataNode
???? NodeManager
  • Step 25: hadoop이 제대로 설치 되었나 확인해봅시다. nameNode의 Elastic IP를 AWS에서 확인하고 [elasticIP]:50070을 인터넷 주소창에 입력합니다. Hadoop 정보페이지가 나오고, 아래로 내려보면 표가 있는데, 그 표에서 Live Nodes4라고 설정되어 있다면 완료된 것입니다. hadoop 설치 완료.

  • Step 26: hadoop을 종료할 때는 마찬가지로 nameNode에서 ./sbin/stop-all.sh 명령어를 입력하고, resourceManager에서 ./sbin/yarn-daemon.sh stop resourcemanager를 입력합니다. jps 명령어를 통해 모든 instance에서 hadoop이 종료된 것을 확인하길 바랍니다. (???? Jps는 항상 존재하는 것입니다.)

  • Step 27: 중요한 단계입니다! AWS를 사용을 마치셨으면 ec2 instance를 우클릭하여 Instance State -> Stop 을 클릭하여 항상 stop해두시길 바랍니다. EC2 Instance 는 무료가 아닙니다. 일정량(free tier, 1대 기준 1달 750시간)을 초과하게 되면 과금이 됩니다! 자세한 AWS EC2 요금은 이곳을 참고하시기 바랍니다.

성공적으로 하둡 설치를 마치셨습니다. 어떻게 보면 간단하지만 어떻게 보면 길고도 실수할 것이 아주 많은 하둡 설치였습니다. 하나의 오타만 발생하여도 에러가 발생하고, 하나의 line이 빠지게 되면 node가 제대로 생성되지 않는 등 주의가 필요한 설치였습니다.



3. pig 설치하기



이제 앞으로는 간단한 일만 남았습니다. pig와 hive의 설치는 hadoop에 비하면 아주 간단한 수준입니다.

참고로, pig의 공식사이트이곳이니 제가 담지 못한 자세한 내용은 사이트를 방문하여 확인바랍니다.

그럼 pig를 설치해보도록 하겠습니다.

  • Step 1: nameNode ~에서 다음 명령어를 입력하여 pig 파일을 다운받습니다:
wget http://apache.tt.co.kr/pig/latest/pig-0.15.0.tar.gz
  • Step 2: 다음 명령어를 입력하여 다운받은 파일을 압축해제합니다:
tar -xvf pig-0.15.0.tar.gz
  • Step 3: 압축해제하여 얻은 pig-0.15.0 폴더를 하둡 폴더 안으로 이동시킵니다:
mv pig-0.15.0 hadoop-2.7.1/
  • Step 4: pig 폴더로 이동하여 pig를 실행하여 봅시다(grunt>가 나온다면 정상실행된 것입니다.):
mv pig-0.15.0
./bin/pig

pig 설치를 완료하였습니다. PATH를 설정하게되면 pig명령어를 통해 pig를 쉽게 실행할 수 있습니다.



4. hive 설치하기



이 포스팅의 마지막인 드디어, 4. hive 설치하기 입니다.

마찬가지로 공식사이트이곳이니 자세한 사항은 사이트에서 확인바랍니다.

  • Step 1: 다음 명령어를 통해 nameNode~에 hive를 다운받습니다:
wget http://apache.tt.co.kr/hive/hive-2.0.1/apache-hive-2.0.1-bin.tar.gz
  • Step 2: 다음 명령어를 통해 압축을 해제합니다:
tar -xvf apache-hive-2.0.1-bin.tar.gz
  • Step 3: pig와 마찬가지로 hadoop 폴더 안으로 압축해제한 폴더를 옮깁니다:
mv apache-hive-2.0.1-bin hadoop-2.7.1/
  • Step 4: hive를 다루기 전에, hadoop-2.7.1 폴더로 이동하여 hadoop을 실행시켜줍니다:
./sbin/start-all.sh
  • Step 5: 마찬가지로, resourceManager로 이동하여 resourcemanager도 실행시킵니다:
ssh ubuntu@resourceManager
./hadoop-2.7.1/sbin/yarn-daemon.sh start resourcemanager
  • Step 6: jps 명령어를 통해 node들이 제대로 생성되었음을 확인한 후, exit를 입력하여 다시 nameNode로 돌아옵니다.

  • Step 7: 이제 hive 폴더로 이동합니다:

cd apache-hive-2.0.1-bin/
  • Step 8: hive을 실행하기 전에 초기화 작업을 해줍니다:
./bin/schematool -initSchema -dbType derby

혹시나 이 단계에서 error가 발생하시는 분은, 이곳을 참고하시기 바랍니다.

  • Step 9: 초기화를 완료하였으면, hive를 실행시킵니다(hive>가 나온다면 정상실행된 것입니다.):
./bin/hive

hive 설치를 완료하였습니다. pig와 마찬가지로 PATH를 설정하게 되면 hive명령어를 통해 hive를 쉽게 실행할 수 있습니다.



끝까지 봐주셔서 감사합니다!

C coding convention(style guide)

C에 관한 coding convention을 찾다가 만족스러운 guide를 발견하여 영어 공부도 할겸 변역하고자 합니다. 이 글의 원본은 이곳 임을 밝힙니다. 번역을 허락해주신 Eno Thereska께 감사드립니다.

아직 영어를 배워나가는 단계이므로 혹여나 이해가 안가는 부분에 대해서는 메일을 주시면 제가 이해한 수준에서 최대한 도움을 드리도록 하겠습니다.

혹여나 오역 등에 대한 문의는 nohyg90@gmail.com 으로 주시면 검토 후 수정하겠습니다. 감사합니다.

혹시 이 글이 도움이 되었다면, 많은 분들이 볼 수 있게 이 글의 링크를 널리널리 공유해주시길 바랍니다!



history

160511 번역시작.



목차

1. 이름

이름에 단위를 포함하라
구조체의 이름
C 파일 확장자
올바른 이름 짓기
스택에 오르는 변수 이름
포인터 변수
전역 상수
Enum 이름
#define과 매크로 이름

2.포맷팅(formatting)

{} 규칙
키워드와 함수에 관한 () 규칙
한 줄은 78 캐릭터를 넘어서는 안된다.
if then else 포맷팅
switch 포맷팅
goto, continue, break, ? :의 사용
한 줄에는 하나의 실행문만

3. 문서화

코멘트는 이야기여야 한다.
문서 결정
헤더들을 사용하라
Gotchas(@)를 명확히하라
함수 선언 코멘트하라
실행문 문서화를 포함하라

4. 복잡함 관리

레이어링(Layering)

5. 기타 여러가지

헤더 파일 가드를 사용하라
C와 C++ 혼합
모든 변수를 초기화하라
Const를 올바르게 하라
짧은 함수들
매직 넘버들을 사용하지 마라(No magic numbers)
Error Return Check Policy
Enum을 사용 혹은 사용하지 않기 위하여
매크로들
Do Not Default If Test to Non-Zero
일반적으로, 함축된 할당을 피하라
큰 코드 블럭 바깥에 코멘팅하기
#ifdef 대신 #if를 사용하라
여러가지들
헤더파일 안에 데이터를 정의하지마라


1. 이름



적합한 이름 짓기

이름은 프로그래밍의 심장이다. 과거에 사람들은 어떤 사람의 진짜 이름을 아는 것은 자신에게 그 사람을 뛰어넘는 신비로운 힘을 준다고 믿었다. 만약 당신이 무언가의 진짜 이름을 생각해낼 수 있다면, 당신은 당신 자신, 그리고 후에 오는 사람들에게 그 코드를 뛰어넘는 힘을 줄 것이다. 우스갯소리가 아니다!

이름은 그것이 살고 있는 환경에 대한 깊은 생각 후에 나오는 과정의 결과물이다. 그 시스템을 전체로서 이해하는 프로그래머만이 그 시스템에 가장 “적합한” 이름을 만들 수 있다. 만약 그 이름이 자연스럽게 모든 것과 적절히 맞아떨어진다면, 관계가 명확해지고, 의미가 추론될 수 있고, 그리고 인간의 직관으로부터 오는 추리들이 기대했던 것처럼 잘 맞아떨어질 것이다.

만약 당신의 모든 이름이 Thing and Dolt가 될 수 있다는 것을 발견한다면, 당신은 아마 당신의 설계를 다시 보아야만 할 것이다.


함수 이름

  • 보통 모든 함수는 하나의 액션을 수행한다. 그래서 그 이름은 그것이 하는 일을 명확하게 보여주어야 한다:

    • error_check() 대신에 check_for_errors()를 data_file() 대신에 dump_data_to_file() 등을 사용하라. 이것은 함수와 데이터 객체(object)를 더욱 쉽게 구별 가능하도록 할 것이다.

    • Struct들은 보통 명사다. 함수 이름을 동사로 만들거나, 다른 naming convention을 따름으로써, 더욱 자연스럽게 읽혀지도록 할 수 있다.

  • 접미사는 때때로 유용하다:

    • max - 무언가가 가질 수 있는 최대값
    • cnt - 현재 진행 중인 count 변수의 현재의 값
    • key - 키 값

    • 예를 들어, retry_max 는 retries의 최대값을 의미하고, retry_cnt는 현재 retry count를 의미한다.
  • 접두사는 때때로 유용하다:

    • is - 무언가에 대한 질문 요청. 누군가가 is를 볼 때마다 그들은 그것이 질문이라는 것을 알 게 된다.
    • get - 값을 얻음
    • set - 값을 정함

    • 예를 들어, is_hit_retry_limit

이름에 단위를 포함하라

만약 변수가 시간, 무게, 혹은 다른 단위들을 나타낸다면, 단위를 이름안에 포함하라. 그러면 개발자들이 더욱 쉽게 문제들을 발견할 수 있을 것이다. 예를 들어:

uint32 time_outmsecs;
uint32 my_weight_lbs;

구조체의 이름

  • 이름 구성요소들을 분리하기 위해 언더바(_)를 사용하라
  • 구조체 내에서 변수들을 선언할 때, 메모리 낭비를 최소화를 시도하는 방식을 사용함으로써(because of compiler alignment issues), 혹은 사이즈, 알파벳 순으로써 선언하라. 예를 들어 “int a; char *b; int c; char *d;” 등은 사용하지 마라. “int a; int b; char *c; char *d;” 등을 사용하라. 비록 비트(bit) 영역에서 (그것이 하나의 bit 영역의 부분임을 분명히 하기위해) 예외가 발생할 수는 있지만, 각각의 변수들은 그들 소유의 타입과 라인을 가진다. 일반적인 bit 영역의 사용은 discouraged 됨을 주목하라. 만약 (구조체가) 여러 소스파일들에서 사용된다면, 주요 구조체들은 그들이 사용되는 파일, 혹은 분리된 헤더 파일의 최상단에 선언되어야 한다. 만약 그들(구조체)이 헤더 파일에 선언되었다면 구조체의 사용은 분리된 선언들에 의해야만, 그리고 “외부에” 있어야만 한다. 각각 멤버들 이름에 대해 의미 있는 접두사를 사용하는 것은 유용하다. 예를 들어, “struct softc”에 대해, 접두사는 “sc_“여야 한다.

예시

struct foo {
	struct foo *next; /* List of active foo */
	struct mumble amumble; /* Comment for mumble */
	int bar;
	unsigned int baz:1, /* BitField; line up entries if desired */
			fuz:5,
			zap:2;
	uint8_t flag;
};
struct foo *foohead; /* Head of global foo list */

스택에 있는 변수의 이름

  • 모두 소문자들로 사용하라
  • 단어 구분을 위해 ‘_‘를 사용하라

정당화

  • 코드 내의 변수 범위에 대한 접근이 명확하다.
  • 코드 내에서 모든 변수들이 다르게 보이고 인식할 수 있다.

예시

int handle_error (int error_number) {
	int error= OsErr();
	Time time_of_error;
	ErrorProcessor error_processor;
}

포인터 변수

  • *를 포인터 타입이 아닌, 변수 이름에 가까이 붙여라.

예시

char *name= NULL;
char *name, address;

전역 변수

  • 전역변수는 이름 앞에 ‘g_‘가 붙어야 한다.

  • 전역변수는 가능한 사용을 피해야 한다.

정당화

  • 변수의 범위를 아는 것은 중요하다.

예시

Logger g_log;
Logger* g_plog;

전역 상수

  • 전역 상수는 모두 대문자여야하고, ‘_‘를 구분자로 사용하여야 한다.

정당화

이렇게 사용하는 것이 전통적인 방식이다. 다른 #defineenum 라벨들과 충돌하지 않기 위해 주의해야한다.

예시

const int A_GLOBAL_CONSTANT= 5;

#define과 매크로들의 이름

  • #define과 매크로들을 ‘_‘를 구분자로 사용하여 모두 대문자로 만들라. 매크로들은 대문자화되어야 하고, 괄호로 싸여야하고, 부작용을 피해야만 한다. 매크로 이름의 앞과 뒤에 공간을 주는 것은 어떠한 공간이어도 된다. (즉 탭이나 띄어쓰기 등 아무거나 해도 된다는 말인듯 합니다.) 그러나 파일 내에서 TAB의 사용은 일관성을 가져야한다. 만약 그들이 한 줄로 늘어선 함수의 확장이라면, 그 함수는 모두 소문자로 정의되어야하고, 매크로는 모두 대문자로 된 같은 이름을 가져야한다. 만약 매크로가 하나의 표현이라면, 괄호로 그 표현을 감싸라. 만약 매크로가 하나 이상의 명령문이라면, 뒤따라오는 세미콜론이 동작하기 위해 “do {…} while(0)”을 사용하라. 백슬래쉬들을 우측으로 당겨라; 그것은 더 쉽게 읽을수 있도록 해줄 것이다.

정당화

이는 변경될 수 없는 값이나, 매크로 내에 있는 값을 명확히 해주고, 케어를 요하는 당신이 사용중인 construct를 명확히 해준다.

매크로 이름이나 enum 라벨이 같은 이름으로 사용된다면, 몇몇 눈에 잘 안띄는 흐릿한 에러들이 발생할 수 있다.

예시

#define MAX(a,b) blah
#define IS_ERR(err) blah
#define MACRO(v, w, x, y)
do {																\
	v = (x) + (y);										\
	w = (y) + 2;											\
} while (0)													\

Enum 이름

라벨들은 구분자로 ‘_‘를 사용하고, 모두 대문자로 쓰여야한다.

이것은 enum 라벨들의 표준 규칙이다. 마지막 원소에는 콤마가 없다.

예시

enum PinStateType {
	PIN_OFF,
	PIN_ON
};

에러 상태에 대한 라벨을 만들어라

어떠한 가능한 상태에도 enum이 없다는 것을 말할 수 있는 것은 자주 유용하다. 초기화 되지 않은, 혹은 에러 상태에 관한 라벨을 만들어라. 그리고 가능하다면 그것을 첫 라벨로 하라.

예시

enum { STATE_ERR, STATE_OPEN, STATE_RUNNING, STATE_DYING};


2. 포멧팅(formatting)



괄호의 위치

세 개의 주요 괄호들의 위치에 관한 전략들 중 권장되는 것은 다음이다:

	if (condition) {
		...
	}
	while (condition) {
		...
	}

언제 괄호가 필요한가

모든 if, while 그리고 do 문은 반드시 괄호를 가지거나, 혹은 하나의 라인으로 구성되어야 한다.

항상 괄호를 사용하는 형식

모든 if, while 그리고 do 문은 괄호 안에 하나의 실행문만이 있더라도 괄호를 요구한다. 예를 들어:

if (1 == somevalue) {
	somevalue = 2;
}

정당화

이것은 누군가가 후에 코드에 라인을 추가할 때, 그곳에 이미 괄호가 있다면, 그들이 괄호를 까먹지 않을 것임을 보장해준다. 이것은 더욱 일관된 모습을 제공한다. 이것은 실행 속도에 영향을 미치지 않는다. 괄호는 어렵지 않은 일이다.

한 라인의 형식

if (1 == somevalue) somevalue = 2;

정당화

이것은 밀집된 읽을 수 있는 폼을 유지하며 새로운 라인이 추가될 때 안전성을 제공한다.


닫히는 괄호에 코멘트를 달아라

닫히는 괄호에 코멘트를 다는 것은 당신이 코드를 읽을 때 도와준다. 왜냐하면 당신은 그것이 어떻게 흘러가는지 알기 위해 시작 괄호를 찾을 필요가 없기 때문이다.

while(1) {
	if (valid) {

	} /* if valid */
	else {
	} /* not valid */
} /* end forever */

화면 크기 제한을 생각하라

어떤 사람들은 코드를 일반적인 화면 크기내로 맞추기 위한 블럭들을 좋아한다. 그러면 코드를 읽을 때 스크롤을 할 필요가 없다.


키워드와 함수에 쓰이는 괄호 () 규칙

  • 키워드 바로 옆에 괄호를 쓰지마라. 사이에 공간을 둬라.

  • 함수 이름 바로 옆에 괄호를 써라.

  • 꼭 필요한 경우가 아니면 return 문에 괄호를 쓰지마라.

정당화

  • 키워드는 함수가 아니다. 키워드 바로 옆에 괄호를 두는 것은 함수와 키워드의 이름을 비슷해 보이게 만든다.

예시

if (condition) {
}

while (condition) {

strcpy(s, s1);

return 1;

한 라인은 78 character를 넘어서는 안된다.

  • 라인들은 78 character를 넘어서는 안된다.

정당화

  • 큰 모니터에 우리가 창을 넓게 펼지라도, 우리의 프린터는 프린트 가능한 너비만 프린트한다. 그러면 우리는 여전히 프린트할 코드가 필요하다.

  • 창이 더 커질 수록 우리는 더 적은 창을 가지게 된다. 더 많은 창을 켜는 것이 큰 창을 켜는 것보다 낫다.

  • 우리는 모든 터미널과 프린터에서 다른 결과물을 훨씬 올바르게 볼 수 있다.


if then else 포멧팅

레이아웃(Layout)

프로그래머에게 달려있다. 다른 괄호 스타일은 약간 다른 모습을 가져올 것이다. 하나의 흔한 접근은 이것이다:

if (condition) {
} else if (condition) {
} else {
}

만약 당신이 else if문을 사용한다면, 다루지 않는 경우들을 발견하기 위한 else블록을 항상 만드는 것은 좋은 생각이다. 그곳에서 적절한 액션을 취하지 않더라도, else문 안에 log 메시지를 넣는 것이 좋다.

조건 포멧

항상 비교문 안의 왼쪽에 상수를 넣어라. 예를 들어:

if (6 == errorNum) ...

이에 대한 첫 번째 이유로 만약 당신이 = 들 중 하나를 빠트린다면, 컴파일러는 당신에게 에러를 찾아줄 것이다. 두 번째 이유로, 이것은 당신이 찾고 있는 값을 표현식의 가장 끝에 두는 것 대신에, 당신이 바로 찾을 수 있도록 바로 오른쪽 앞에 둔다. 이 포멧에 익숙해지는 것은 약간의 시간이 걸리지만, 이것은 정말 유용하다.


switch 포멧팅

  • case 문을 통해 다음 case문으로 떨어지는 것은 코멘트가 포함되어 있는 경우에 한해서 허용된다.

  • default case는 항상 존재해야하고, 만약 그것에 다다라서는 안되는 경우인데 도달한다면 에러를 발생시켜야한다.

  • 만약 변수를 만들어야한다면, 모든 코드를 블록 안에 둬라.

예시

switch (...)
{
	case 1:
		...
	/* comments */

	case 2:
	{
		int v;
		...
	}
	break;

	default:
}

goto, continue, break 그리고 ?:문의 사용

Goto

Goto문은 구조를 잘 갖춰진 코드 내에서 아껴서 사용해야한다. goto에 대한 논의는 지루하므로 우리는 여기서 그것들에 대해 언급하지 않을 것이다. 그들이 유용하게 사용될 수 있는 주요 장소는 여러 레벨의 switch, for 그리고 중첩 while문을 중단할 경우이다. 비록 그런 일들을 하기 위한 요구는 내부 생성자들이 성공, 실패의 return 코드와 함께 반드시 분리된 함수들로 부서져야한다는 것을 가리킬 수 있을 지라도 말이다.

	for (...) {
		while (...) {
			...
			if (disaster) {
				goto error;
			}
		}
	}
	...
error:
	clean up the mess

goto문이 필수적일 때, 수행되는 라벨은 한 라인에 홀로 있어야만 하고, 잇따르는 코드의 좌측에 있어야한다. goto는 (가능하면 블록 헤더에) 그것의 유용성과 목적에 대해 코멘트 되어야 한다.

continue와 break

실제로 continue와 break는 goto를 가장한 것이므로 이곳에서 다루기로 한다.

goto 같은 continue와 break는 코드 안에서 magic이므로, 아껴서 사용되어야 한다. 간단한 마법을 가진 신내림을 받은 독자는 기록되지 않은 이유들이 어디에 있는지 안다.

주된 continue의 두가지 문제들:

  • 테스트 조건을 그냥 통과할 지도 모른다.

  • 증가, 증감 표현식을 그냥 통과할 지도 모른다.

두 가지 문제가 발생하는 다음의 예를 생각해보자:

while (TRUE) {
	...
	/* A lot of code */
	...

	if (/* some condition */) {
		continue;
	}
	...
	/* A lot of code */
	...
	if ( i++ > STOP_VALUE ) break;
}

주목하라: “A lot of code”는 프로그래머가 쉽사리 그 문제를 잡아내지 못하게 하기 위해 필요하다.

위의 예로부터, 한층 더 규칙들이 주어질 수 있다: continue와 break를 같은 loop안에서 섞는 것은 재앙으로 가는 명백한 길이다.

?:

보통 사람들이 ?: 사이에 너무 많은 코드를 시도하려 하고 또, 채워넣는 것이 문제이다. 여기에는 몇 개의 명백한 규칙들이 있다:

  • 다른 코드로부터 그것을 실행하도록 괄호 안에 condition을 두어라.

  • 가능하다면 테스트를 위한 액션은 간단한 함수여야한다.

  • 한 라인에 둘 정도로 명백하지 않다면, then과 else 문을 위한 액션은 분리된 라인에 두어라.

예시

(condition) ? funct1() : funct2();

or

(condition)
	? long statement
	: another long statement;

한 라인에 하나의 실행문

실행문들이 매우 밀접하게 연관이 있지 않는 한, 한 라인에는 하나의 실행문 만이 있어야 한다.

이유는 이렇다:

  1. 읽기가 쉽다. 약간의 여백 역시 사용하라. 한 라인의 코드를 읽는 것보다 더 좋은 것은 없다.

한 줄에 하나의 변수

이것과 연관되는 것은 항상 한 줄에 하나의 변수를 정의하라는 것이다:

Not:

char **a, *x;

Do:

char **a = 0; /* add doc */
char *x = 0; /* add doc */

이유는 이렇다:

  1. 문서화는 한 줄에 있는 변수에 대해서 추가될 수 있다.

  2. 변수들이 초기화되는 것은 명백하다.

  3. 변수 선언이 clear하다. 그것은 당신이 char형 선언만을 의도했을 때, 포인터를 선언해버리는 가능성을 줄여준다.


Enums를 사용하기 위한, 혹은 사용하지 않기 위한

C는 상수 변수를 허락한다. 상수로서 enums의 사용하는 것을 비난하여야만 한다. 불행히도 대부분의 컴파일러들에서 상수는 공간을 차지한다. 몇몇 컴파일러는 상수를 제거할 것이지만 모두 그렇지는 않다. 공간을 차지하는 상수들은 임베디드 시스템 같은 빡빡한 메모리 환경에서 그들이 사용되는 것을 방해한다. workstation 유저들은 상수를 사용해야만 하므로, 이 남은 토론을 무시해야한다.

enums로서 #define이 선호되는 일반적인 enums들은 디버거에 의해 이해된다.

enums는 보증하는 크기가 아니라는 것을 알아라. 그러니 당신이 알려진 변수 범위를 사용할 수 있는 타입을 가진다면 그리고 그것을 메시지로 옮긴다면, 당신은 enum을 타입으로서 사용할 수 없다. 올바른 정수 크기를 사용하고 상수나 #define을 사용하라. 그 enum안에 없는 값을 형변환 함으로서, 정수와 enum 사이에서의 형변환은 에러를 발생할 경향이 매우 크다.


헤더 파일 가드를 사용하라

포함하는 파일들은 그 파일들을 가드하는 매크로의 사용을 통한 여러 포함에 대해 보호되어야 한다. c++의 적합성, 상호 연산성의 이유에 대해 주목하고, 헤더 가드의 첫번째나 마지막 문자로서 언더스코어 ‘_‘를 사용하지마라. (아래를 보아라)

#ifndef sys_socket_h
	#define sys_socket_h /* NOT _sys_socket_h_ */
	#endif

매크로들

C를 Pascal로 바꾸지마라

매크로 치환을 통해 문법을 변경하지마라. 그것은 프로그램을 지능적이지 못하게 만들 것이다.

매크로들을 인라인 함수(inline function)으로 대체하라

C에서 매크로들은 코드 효율성에 대해서 필요하지 않다. 인라인(inline)을 사용하라. 하지만 짧은 함수들에 대해서는 매크로도 괜찮다.

예시

#define MAX(x, y)	((x) > (y) ? (x) : (y)) // Get the maximum

위의 매크로는 정수들에 대해 효율성을 잃지 않고 아래의 인라인 함수(inline function)으로 대체될 수 있다:

inline int
max(int x, int y) {
	return (x > y ? x : y);
}

부작용에 주의하라

매크로들은 주의를 기울여 사용되어야한다. 왜냐하면 부작용을 가지고 있는 표현식과 함께 호출될 때 에러에 대한 가능성이 있기 때문이다.

예시

Max(f(x), z++);

항상 표현식을 괄호로 감싸라

표현식을 매크로에 넣을 때, 연산 교환법칙의 모호성을 피하기 위해 항상 그 표현식을 괄호로 감싸라.

예시

#define ADD(x, y)	x + y

같은 것은 반드시

#define ADD(x, y)	((x) + (y))

처럼 쓰여야 한다.

유일한 매크로 이름을 만들어라

전역 변수들처럼 매크로도 다른 패키지의 매크로들과 충돌을 일으킬 수 있다.

  1. 매크로 이름 앞에 패키지 이름을 붙여라.
  2. MAX, MIN 등과 같은 흔하고 단순한 이름을 피하라.

모든 변수들을 초기화하라

  • 항상 모든 변수를 초기화하라. 항상. gcc에 flag -W를 함께 사용하는 것은 초기화 되지 않은 변수들에 대한 연산을 잡을 수 있다. 그러나 그것은 또한 아닐 수도 있다.

정당화

  • 포인터나 초기화 되지 않고 남아있는 변수들에 대해 당신이 믿을 수 있는 것보다 더 많은 문제들이 언젠가는 발견될 것이다.

짧은 함수들

  • 함수들은 한 페이지 내로 그들 자신을 제한해야한다.

정당화

  • 각각의 메소드는 하나의 목표만을 달성하기 위한 기술을 나타낸다는 것이 그 아이디어이다.

  • 오랫동안 돌릴 때(in the long run) 많은 비효율성의 인자들은 틀렸다는 것이 밝혀졌다.

  • True 함수 콜은 하지 않는 것보다 느리다. 하지만 충분히 생각한 결정이 필요하다 (너무 이른 최적화를 보라).


Null 실행문들을 기록하라

항상 for 또는 while 실행문에 관한 null body를 기록하라. 그 null body가 의도적이고, 결여된 코드가 아님을 명확히 하기 위해서 말이다.

while (*dest++ = *src++)
{
	;
}

non-zero에 대한 테스트라면 default 하지마라

non-zero에 대한 테스트를 default 하지 마라., 즉

if (FAIL != f())

가 아무리 FAIL이 C에서는 false로 고려되는 0의 값을 가질 지라도,

if (f())

보다 낫다. 명백한 테스트는 나중에 누군가가 실패 리턴이 0 대신에 -1이어야만 하는 것을 정할 때 당신을 도와줄 것이다. 명백한 비교는 비교값이 절대 바뀌지 않는 경우에만 사용되어야 한다; 예를 들어, if (!(bufsize % sizeof(int)))는 그 테스트의 (boolean이 아닌) 숫자의 본질을 반영하기 위해 if ((bufsize % sizeof(int)) == 0)로 대신 쓰여야만 한다. 문제를 일으키는 잦은 지점은 그 결과가 절대 한번도 default가 되지 않는 곳에서 문자열이 같은 지 테스트하기 위해 strcmp를 사용하는 중이다. 선호되는 접근은 STREQ라는 매크로를 정의하는 것이다.

#define STREQ(a, b)	(strcmp((a), (b)) == 0)

더 적절하게 표현하면, 인라인 메소드(inline method)를 사용하는 것이다:

inline bool
string_equal(char* a, char* b)
{
	(strcmp(a, b) == 0) ? return true : return false;
		Or more compactly:
	return (strcmp(a, b) == 0);
}

이것은 단지 하나의 예라는 것을 주목하라, 이 비교를 하기 위해서 당신은 사실 표준 라이브러리 문자열 형식을 사용해야만 한다.

아래의 제한들에 만족하는 술부나 다른 함수들 또는 표현식들에 대해서 그 non-zero 테스트는 자주 default된다:

  • 다른 어떤 것도 아닌, false를 위해 0을 return하는 경우

  • true return의 의미를 절대적으로 명백하게 하기 위해서 이름이 지어진 경우라면 check_valid()가 아닌, is_valid() 술부를 호출하라.


습관적으로 함축된 할당(Embedded assignments)을 피하라

함축된 할당을 위한 시간과 공간이 있다. 몇몇 구조들에서, 그 코드를 더 크고, 읽기 힘들게 만드는 것 없이, 그 결과를 달성하기 위한 더 나은 방법은 없다.

while (EOF != (c = getchar())) {
	process the character
}

++와 --연산자는 할당 실행문으로서 계산한다. 따라서 많은 목적들을 위해, 부작용을 가진 함수들을 사용하라. 런타임 성능을 향상시키기 위한 함축된 할당 실행문을 사용하는 것 또한 가능하다. 하지만, 함축된 할당문이 인공적인 공간에서 사용될 때 일어나는 증가되는 속도와 감소되는 유지가능성 사이의 거래(tradeoff)를 고려해야만 한다. 예를 들어,

a = b + c;
d = a + r;

d = (a = b + c) + r;

로 대체되어서는 안된다. 심지어 후자가 한 사이클을 더 절약할 수 있을지라도 말이다. 오랜 시간의 동작에서(In the long run) 이 둘 간의 시간 차이는 옵티마이저가 숙성(maturity) 되는 동안에 감소될 것이다. 반면에 유지의 용이함의 차이는 후자의 코드 조각들이 어떻게 흘러가는지에 대한 사람의 기억이 흐릿해지기 시작함으로서 증가할 것이다.


New Model Could Show That Stephen Hawking Is Right About Black Holes

New model could show that stephen hawking is right about black holes. - Alfredo Carpineti

새로운 모델이 블랙홀에 관해 Stephen Hawking이 옳다는 것을 보여줄 수도 있다. - Alfredo Carpineti

One of the longest standing mysteries of black holes is what happens to stuff when it falls inside. Information can’t move faster than light, so it can’t escape a black hole, but we know that black holes shrink and evaporate over time, emitting Hawking radiation. This has troubled scientists for 40 years. Information can’t simply vanish.

블랙홀에 관해 가장 오래 제기된(stading) 것들 중 하나는 ‘물체가 안쪽으로 떨어질 때 무슨 일이 발생하는가’이다. 정보는 빛보다 빠를 수 없다. 따라서 그것은 블랙홀을 탈출할 수 없다. 그러나 우리는 시간이 지남에 따라, 블랙홀이 호킹 복사(Hwaking radiation)를 내뿜으며 차츰 줄어들고 증발한다는 것을 안다. 이것은 40년동안 과학자들을 괴롭혀왔다(trouble). 정보는 단순히 사라질 수 없다.

Now, physicists Kamil Brádler and Chris Adami, from the University of Ottawa and Michigan State University respectively, have been able to show that the information is not at all lost, but is transferred from the black holes into the aforementioned Hawking radiation, potentially solving a long-standing mystery of cosmology.

요즘, 각각 Ottawa, Michigan 대학교 에서 온, Kamil Badler와 Chrise Adami 물리학자는 정보는 모두 소멸(lost)되지 않는다는 것을 보여줄 수 있었다. 그러나 정보는 블랙홀로부터 앞에서 말했던 호킹 복사로 옮겨진다. 어쩌면(potentially) 우주의 오래 제기된(long-standing) 문제를 풀면서.

Over 40 years ago, Stephen Hawking put forward the idea that although nothing can escape a black hole, there should be a certain amount of particles emitted from the outer edge of the black hole’s event horizon. This emission would over time steal energy from a black hole, causing it to evaporate and shrink.

40년도 전에, 스티븐 호킹은 그 아이디어 -비록 무엇도 블랙홀을 탈출할 수 없지만, 그곳에는 틀림없이 블랙홀의 사건의 지평선(the black hole’s event horizon)의 바깥 고리로부터 방출된 많은 양의 입자들이 있다는- 를 앞당겼었다(put forward). 이 방출은 블랙홀로부터 오랫동안 에너지를 뺴앗았다. 블랙홀이 증발하고, 줄어듦을 야기하며.

The emission was not from the black hole itself, so physicists began to wonder what happens to the information within black holes when they disappear. If the information is irretrievably lost there would be a violation of the laws of quantum mechanics, and this led to the Black Hole Information Paradox.

그 방출은 블랙홀 자신으로부터 온 것이 아니었다. 따라서 물리학자들은 궁금해하기 시작했다. 그들이 사라질 때, 블랙홀 안에서 정보에게 무슨 일이 발생하는지. 만약 그 정보가 돌이킬 수 없게(irretrievably) 사라진다면, 그곳에는 양자 법칙(the laws of quantum mechanics)의 위배가 존재하게 되고, 그리고 이것은 블랙홀 정보 역설(the Black Hole Information Paradox)를 야기한다. (양자 역학에서는 어떤 사건의 결과로 발생할 수 있는 모든 결과의 확률의 합은 언제나 1로 보존되어야 한다는 단일성이라는 필수적 성질이 있는데, 정보의 소실은 곧 단일성의 위반을 의미한다.)

“The issue was never laid to rest because Hawking’s calculation was not able to capture the effect that the radiation, called Hawking radiation, has on the black hole itself,” Adami said in a statement.

“이 이슈는 절대 묻힐 수 없었다(was never laid to rest). 왜냐하면 호킹의 계산은 그 효과-호킹복사라고 불리는 복사(radiation)가 블랙홀에서 스스로(itself) 가지고 있는-를 잡아내지(capture) 못했었기 때문이다.”라고 연설에서 Adami가 말했다.

“Physicists assumed that the black hole would shrink in time as the Hawking radiation carries away the black hole’s mass, but no one could verify this through mathematical calculations.”

“물리학자들은 호킹 복사(Hawking radiation)가 블랙홀의 질량을 줄이는 그때에 그 블랙홀이 줄어들 것이라고 가정했다. 그러나 누구도 이것을 수학적 계산을 통해 입증하지 못했다.”

Is Hawking radiation transferring information out of black holes? NASA/JPL-Caltech

호킹 복사(Hawking radiation)가 블랙홀에서부터 정보를 빼았는 것인가? NASA/JPL-Caltech

Several solutions have been put forward to resolve the paradox, but many physicists just assumed that it would be solved once we had a complete theory of quantum gravity. Although general relativity and quantum mechanics are two of humanity’s greatest achievements they don’t work well together. Black holes are one of those cases in which both theories are needed.

몇몇 해결책들은 그 역설을 풀기 위해 앞당겨져왔다. 그러나 많은 물리학자들은 그것은 단지 우리가 양자 중력 이론의 완전함을 가졌을때 풀려진다고 가정한다. 비록 일반적인 연관성, 그리고 양자 매커니즘은 인류의 가장 큰 업적들 중 두가지이지만, 그들은 함께 잘 동작하지 않는다. 블랙홀은 그 두가지의 이론이 필요한 경우들 중에 하나이다.

The model put forward by Brádler and Adami looks at the quantum effect that produced Hawking radiation. They used computer simulations to evolve the the black holes, and they noticed that the Hawking radiation was taking energy and information out of the black hole.

Bradler와 Adami에 의해 앞당겨진 그 모델은 호킹 복사(Hawking radiation)을 생성하는 그 양자 효과에 주목한다. 그들은 그 블랙홀을 이끌어내기 위해 컴퓨터 시뮬레이션을 사용하였고, 그리고 호킹 복사(Hawking radiation)는 에너지와 정보를 블랙홀의 바깥으로 내보낸다는 것을 알아내었다.

“To perform this calculation, we had to guess how a black hole interacts with the Hawking radiation field that surrounds it,” Adami said.

이 계산을 해내기 위해, 우리는 어떻게 블랙홀이 그것을 둘러싸고 있는 호킹 복사 영역(Hawking radiation field)과 상호 작용하는지 추축해야만 했다.”라고 Adami가 말했다.

“This is because there currently is no theory of quantum gravity that could suggest such an interaction. However, it appears we made a well-educated guess because our model is equivalent to Hawking’s theory in the limit of fixed, unchanging black holes.”

“왜냐하면 현재 그러한 상호작용을 지지하는(suggest) 양자 중력(quantum gravity) 이론이 없었기 때문이다. 그러나 그것은 우리가 잘 교육된(well-educated) 추측을 만들었을때 나타났다. 왜냐하면 우리의 모델은 고정되고 변하지 않는 블랙홀들의 한계에 관한 호킹의 이론과 동등하였기 때문이다.”

Their work, published in Physical Review Letters, is an interesting step forward in understanding black holes. Other teams are also trying to solve the information paradox. But while it doesn’t tell us much about the future theory of quantum gravity, it hints that this theory is there for us to discover.

물리 서평 편지(Physical Review Letters)에 기고된 그들의 업적은 블랙홀을 이해해 나아가는 하나의 흥미로운 단계(step)이다. 다른 팀들 역시 정보 역설(information paradox)을 풀기 위해 노력하고 있다. 그러나 그것이 양자 중력(quantum gravity)의 미래 이론에 관해 우리에게 많은 것을 알려주지 않으면, 그것은 이 이론이 우리에게 발견하기 위해 그곳에 있다는 것을 암시한다.

“While our model is just that – a model – we were able to show that any quantum interaction between black holes and Hawking radiation is very likely to have the same properties as our model,” Brádler said.

“우리의 모델이 단지 ‘모델(a model)’ 일지라도, 우리는 보일 수 있었다. 블랙홀과 호킹 복사(Hawking radiation) 사이의 어떠한 양자 작용은 우리의 모델의 경우처럼 똑같은 성질들을 가질 가능성이 매우 높다는 것을.”라고 Bradler가 말했다.