2014년 12월 21일 일요일

OS X 에서 Postgresql 설치하는 두가지 방법

오전 7:49 Posted by jonnung No comments

개발할때는 내 로컬환경에 데이터베이스를 사용하고 싶어서 Postgresql을 설치해 보았다.
방법은 찾아보면 여러가지가 있겠지만 맥 사용자라면 대부분 Homebrew로 패키지들을 설치하니까 일단은 Homebrew로 Postgresql을 설치했다.
그런데 지금은? 지웠다. ㅋㅋㅋ (이유가 뭘까?)

일단 내가 진행한 Homebrew 설치 과정을 간단하게 정리하자면 아래와 같다.
# Homebrew 업데이트
$ brew update

# Postgresql 설치
$ brew install postgresql

# 데이터베이스 생성(솔직히 이거 왜 하는지 모르겠다.)
$ initdb /usr/local/var/postgres -E utf8

# 서버 띄우기
$ pg_ctl -D /usr/local/var/postgres start

# postgresql 서버 내리기
pg_ctl -D /usr/local/var/postgres stop -s -m fast

특별히 중간에 잘 안되던 부분도 없었고 순조로웠다. 문제(?)는 아래 구문을 적용 하면서부터 였는데 사실 모르고 일단 했다가 본격적으로 삽질을 시작하게 되었다.
$ cp /usr/local/Cellar/postgresql/9.4.0/homebrew.mxcl.postgresql.plist ~/Library/LaunchAgents/
$ launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist

저 뒤로부터 계속 postgresql이 종료되지 않는 것이다.(stop) 직접 pid를 kill 해봐도 새로운 프로세스가 계속 생성 되었다. '_')a
그뒤로 계속 조사를 해보니 launchctl이 리눅스 crontab처럼 스케줄 작업 프로그램이고 이녀석이 자꾸 postgresql을 실행하는 것 같았다. 
그리고나서 가만히 생각해보니 launchctl에 등록된 상태로 항상 postgresql이 실행되고 있는 것도 낭비고, 그렇다고 빼자니 매번 pg_ctl로 시작했다가 종료하는 과정도 불편한 것 같았다.

그런데 또 한가지 방법인 Postgresql.app을 설치 해보니 고민거리가 말끔히 해결 되었다.
Postgresql.app을 다운 받아서 그대로 Application에 넣고 실행하면 앱 자체에 포함되어 있는 postgresql이 실행되고, 터미널에서 psql을 입력하면 바로 접속할 수도 있었다.
할일을 모두 마치면 그저 앱을 종료하면 되는 것이다.

2014년 12월 18일 목요일

Python으로 좀비 프로세스 만들어보기

오후 4:40 Posted by jonnung No comments
원래는 좀비/고아 프로세스만 찾아서 kill 하는 것만 하려고 했으나, 조사를 좀 해보니까 좀비프로세스가 시스템 자원을 그렇게 대놓고 차지하는 것은 아니더라..
프로세스 제어블록을 차지하는 것이기 때문에 엄청나게 폭발적으로 생기는 좀비가 아니고서야 큰 영향은 없다고 싶었다. 

좀비 프로세스가 생기는 원인은 부모 프로세스가 자식 프로세스의 종료 코드를 받지 않고, 무한히 대기하는 상태이다. 한마디로 자식이 좀비가 되도 부모는 종료된 상황이 아닌 것이라는 말이지!
(고아 프로세스는 자식이 끝나지도 않았는데 부모가 끝나버려서 자식이 고아가 된 경우를 말함)

아무튼 확인을 해보기 위해서 좀비프로세스 발생시키는 스크립트를 하나 만들어 보았다.

subprocess 모듈의 Popen() 함수로 자식 프로세스를 하나 띄우고, 자식 프로세스가 끝나는걸 기다리지 않고 부모가 계속 무한루프를 돌도록 했다.

이 상태에서 "ps aux | grep ' Z' | grep -v grep" 를 실행해보면  상태값이 'Z'인 프로세스를 하나 발견할 수 있는데 이게 좀비 프로세스이다. 

부모를 죽이면 이 좀비프로세스도 사라진다. 

2014년 12월 5일 금요일

코딩 호러가 들려주는 진짜 소프트웨어 개발 이야기 - 도서 리뷰

오후 10:51 Posted by jonnung No comments
<코딩 호러가 들려주는 진짜 소프트웨어 개발 이야기, 제프 앳 우드 지음, 2012.11, 위키북스>


 코딩 호러의 두번째 시리즈이다. 지난 번에 '코딩 호러의 이펙티브 프로그래밍'을 너무 재밌게 읽어서 바로 이어서 읽어보았다.
 이 책도 코딩 호러에 실린 재밌는 글들을 모아 놓은 것인데 1편보다 훨씬 흥미로운 이야기들이 많다.  개인적인 생각이지만 현업에서 겪게 되는 상황들과 느끼는 고민거리들과도 더 잘 맞아 떨어지는 내용들이 많다.
 그러다보니 책을 읽다보면 제프 형(이제 형이다.ㅋㅋ)이 나를 위해 좋은 말씀을 해준다는 느낌을 받게 되는듯 했다.

아래에는 두고 두고 보면서 마음속에 새겨두면 좋을 만한 내용을 옮겨 보았다.


p.38
 실패는 놀라운 선생님이다. 그렇지만 일부러 실패를 찾아다닐 필요는 없다. 그것이 당신을 찾아올 것이다. 어떤 프로젝트에 참여하든 그것을 당신의 기술을 연마하고 새로운 것을 배우는 기회로 삼아라. 그렇게 하는데는 그럴만한 가치가 있기 때문이다. 프로젝트라는 여행은 그 여행의 끝에 어떤 결과가 기다리고 있는가에 상관없이 그 자체로 보상이 될 것이다.

p.39
전문가가 된다는 것은 다른 사람에게 자기가 아는 것을 말하는 것이 아니다. 그것은 바로 어떤 질문을 할지 아는 것, 자신의 지식을 주어진 특정한 상황에서 어떻게 적용할지 아는 것을 의미한다. 전문가가 된다는 것은 합리적이고 상황에 매우 적절한 방향을 제시할 수 있음을 의미하다. 
  • 연습하라, 연습하라, 연습하라!
  • 경험과 전문성을 혼동하지 말라.
  • 민간풍습을 믿지 말라. 하지만 그것을 배우기는 해라.
  • 아무것도 절대적으로 믿지 말라. 자신만의 방법론을 세워야 한다.
  • 자가 학습을 주도하라. 아무도 대신 해주지 않는다.
  • 명성 = 돈. 스스로의 명성을 구축하고 보호하라.
  • 자원, 자료, 도구를 끊임없이 확보하라.
  • 자신만의 기준과 도덕률을 확립하라.
  • 장인적 기술을 사소한 것으로 만드는 자격증을 피하라.
  • 항상 노력하는 동료를 곁에 둬라.
  • 쓰고, 말하고, 항상 자신이 보기에 진실인 것만을 발언하라.
p.59
반복의 속도가 반복의 질보다 우선한다. (보이드의 반복 법칙)
이와 동일한 의미의 법칙이 현대 소프트웨어 공학의 원리에도 적용된다는 사실을 알 수 있다.
  • 단위 테스트는 작고 빨라서 모든 빌드 과정에서 실행될 수 있어야 한다.
  • 사용성 테스트는 2주마다 작은 변화를 줘서 제대로 작동하지 않을 것을 바로바로 없앨 수 있을때 가장 효과적이다.
  • 대부분의 애자일 방법론에서는 4주보다 길지 않은 반복주기를 권장한다.
  • 소프트웨어 테스트는 빨리 그리고 자주 실패하는 것이 핵심이다.
  • 기능에 대한 명세는 간결하고 차츰 진호하는 방식으로 작성하는 것이 가장 좋다.
p.70
 코딩에 대한 열정은 경이로운 일이다. 하지만 이미 자기가 충분한 능력을 가지고 있다는 사실을 여러 차례에 걸쳐 증명한 기술에 대해 계속 아무 생각 없이 반사적으로 파고드는 경우가 너무나도 많다. 진정으로 더 나은 프로그래머가 되고 싶다면 프로그래밍 주변에 있는 다른 모든 것들에 열정을 쏟아야 한다.

p.105
 혼자서 일하는 방식으로는 얼마 가지 못한다. 다른 영리한 프로그래머를 곁에 두도록 노력하라. 그들과 함께 일하라. 사무실 안에서 가장 멍청한 존재가 되려고 노력하라. 그렇게 하면 소프트웨어 개발이라는 것이 대부분의 사람들이 생각하는 것보다 훨씬 더 사회적인 활동이라는 사실을 깨닫게 될 것이다. 내성적인 동료들에게서 배울 수 있는 것이 너무나도 많다.

p.129
 먼저 단순한 것들을 디자인한 다음, 필요하면 더 큰 공간으로 옮겨가라. 복잡한 것을 먼저 만들고 작은 곳으로 옮겨가는 것은 잘못된 접근법이다.

p.133
 프로그래머로서 우리들이 도를 넘어서 영리해지는 것을 경계해야 한다는 점이다. 우리는 가능하면 최대한 다른 사람들이 하는 것과 똑같은 방식을 고수하려고 노력해야 한다. 왜냐고? 당신이 작성한 코드라고 해서 영원히 당신만 작업하리라는 보장은 없기 때문이다. 

p.145
코딩을 하는가? 그건 쉬운 일이다. 당신이 만드는 애플리케이션을 사용자의 손에 쥐어주고 그들이 사용하고 싶게 만드는 것. 그게 진짜 어려운 부분이다.

"스티브크룩의 사용성 평가, 이렇게 하라!"

p.169
  • 이걸 어떻게 테스트하지?
  • 어떤 종류의 테스트를 수행해야 하지?
  • 공통적이고, 기대되는 결과는 무엇이지?
  • 흔하지 않지만 발생 가능한 결과는 무엇이지?
  • 이 코드에는 외부 의존성(extnal dependency)이 얼마나 있지?
  • 어떤 종류의 시스템 오류를 야기할 수 있지?
단위 테스트는 프로그램이 올바르게 동작하는 것을 보장해주지 않는다. 그런 기대를 하는 것은 합리적이지 않다. 하지만 단위 테스트를 작성하는 것은 개발자가, 아무리 간단하게라도 앞에 나열한 것 같이 테스트와 관련된 어려운 질문을 스스로 고민하도록 만드는 것은 보장한다. 이것은 확실히 옮은 방향으로 나가는 일보 전진이다.

p.179
 책임감 있게 실행되는 소프트웨어를 만드는 프로젝트라면 맨 먼저 해야 하는 일이 예외와 에러를 보고하는 장치를 만드는 것이다.

p.203
 프로그래밍은 재미있다. 그것은 발견하는 기쁨으로 가득하다. 창조의 기쁨과 성취감으로 그득하다. 배우는 즐거움도 있다. 자신의 손으로 만든 무엇이 화면 위에서 동작하는 것을 지켜보는 즐거움도 있다.
옆에서 일하는 동료가 자기가 작성한 코드를 보고 감탄하는 것을 바라보는 기쁨도 있다. 자신이 만든 것을 사람들이 이용하는 것을 바라보드는 즐거움도 있다. 자신 작품을 대중이 사용하고, 이웃이 사용하고, 언론에서 다루는 것을 보는 쾌감도 있다. 
프로그래밍은 반드시 즐거운 것이어야 한다며, 만약 그렇지 않다면 그것을 즐겁지 않게 만드는 것이 무엇인지 알아내서 고쳐야 한다. 
나는 종종 제품을 출시하는 것이 마치 누군가 당신을 때리는 것을 멈추는 것처럼 좋은 기분을 전달해 준다고 말했왔다. 당신의 업무는 이 제품을 완성하고, 보그를 수정하고, 출시하는 것이다. 버그를 수정해야 한다면, 수정하라. 문서를 작성해야 한다면, 작성하라. 코드를 테스트할 필요가 있다면, 테스트하라. 이런 모든 것들은 출시를 구성하는 요소이다. 당신은 프로그래밍 자체를 위해 고용된 것이 아니라, 출시를 위해 고용된 것이다. 자기 업무에 충실하라. 

p.218
 나는 이미 존재하는 것을 되풀이해서 개발하는 것을 지지한다. 학습을 위한 최선의 방법이기 때문이다. 하지만 이미 존재하는 대상의 모든 측면을 철저하게 연구한 다음 그것을 다시 개발해야 하는 이유를 입증하기 전까지는 그렇게 하지 말아야 한다. 즉 철저한 연구라는 숙제를 먼저 해야 하는 것이다.








2014년 11월 30일 일요일

프로그래머 철학을 만나다 - 도서 리뷰

오전 7:10 Posted by jonnung No comments
<프로그래머 철학을 만나다, 유석문 지음, 2014.08, 로드북>

 올해 여름이 끝나갈 무렵에 '유석문'님의 '라이엇 게임즈' 입사 후기를 읽어보고 참 멋지다라고 생각했었다. 그리고 때마침 기회가 되서 '유석문'님이 발표하는 세미나에 참석할 기회가 있었는데 미련하게도 날짜를 착각하는 바람에 다른 약속을 잡아버려서 결국 취소했다. 얼마나 아쉬웠던지...

 얼마전에 회사에서 운영하는 도서관에 신간 몇권이 들어왔는데 대여를 한 책이 '유석문'님이 쓰신 책이였다. 왠지모를 반가움! 
실제로 뵙지 못한 분을 책으로 뵙게 되니 예전에 아쉬움이 좀 달래지는 기분이였다.

 이 책에 대해 말하기 전에 잠시 내가 회사 생활을 하면서 마주쳤던 걱정과 고민에 대한 이야기를 해볼까 한다. 

 업무가 잘 안풀릴때나 사람 관계에서 발생하는 여러가지 문제들을 해결하기 위해 내 스스로 묻고 답을 구하려고 했던 노력들. 나름대로 수없이 많은 생각들로 해결책을 찾으려고 했지만, 결국 만족스러운 답을 찾지 못했을때 느끼는 스트레스로 자존감, 자신감에 흠집이 나기도 했었다.
 혼자하는 고민으로 해결하고자 하는게 과연 가능했던 걸까? 내안에 지배적인 생각은 세상 어디에도 나의 걱정을 해결하거나 도와줄 사람은 없다는 것이다.
하지만 그렇다고 계속 이렇게 살 수는 없지 않은가? 내가 찾은 대안은 책이였다. 책을 전혀 읽지 않는 편은 아니지만 내 입으로 자랑(?)스럽게 말할 정도로 많이 읽지는 않는다.

 난 자기 계발 서적을 좋아하는데 개발자라는 직군에 초점을 맞춰서 자기 성찰을 다루는 책은 그다지 많지 않은 것 같다. '나는 프로그래머다' 라는 책도 읽어 본 적이 있는데 선배 개발자분들의 개발 인생에서 겪은 노하우와 생각을 책을 통해 만나볼 수 있는 기회 였지만, 나에게 어떤 길을 제시하기 보다는 '난 이렇게 살았다' 정도의 인상만 남아있는 것 같다.

 이 책은 개발자들이 살아가면서 겪게 되는 비슷한 상황들에 대해 느끼게 되는 감정들에 대해 더 좋은 방향으로 나아갈 수 있는 해결책을 철학적인 관점에서 이야기 해준다.
이런 컨셉이 좋았다고 느낀 이유는 저자의 개인적인 경험을 통해서 '난 이런식으로 생각하고 행동했다'라는 것보다 철학자들이 평생에 걸쳐서 연구하고 도달하게 된 지혜를 바탕으로 방향을 제시하기 때문에 더 설득력 있게 느껴졌다. 

 책을 읽어가면서 중요하다고 생각했던 부분을 표시해 두었는데 아래 그 내용들을 정리해 보았다. 

 '자존감'을 높이기 위해서는 외부 환경에 영향을 받지 말고, 자신이 통제할 수 있는 영역에만 집중해야한다고 말한다. 회사내에서 겪을 수 있는 상사의 권위에 대한 실체와 올바른 권위란 무엇인가를 제안한다. 
외부 요인을 바꾸기 힘든 것은 누구나 알고 있다. 그렇다고 외부 요인에 맞춰 자신을 바꿔서는 안된다. 자신의 내면에 집중하고, 자신의 존재가치를 확고히 해야하며 외부의 통제 시도에 단호하게 저항할 수 있어야 한다.
 나 자신의 영향력을 확장하는 것은 외부를 지배하거나 통제하고자 얻는 것이 아니다. 올바른 영향력의 확장은 자신의 내면이 확고하고 올바르게 발전하여 외부에서 이를 인지하고 인정하는 것이다.
 실패를 두려워 할 필요가 없다. 실패라는 것은 끝이 아니며 삶의 과정이다. 받아들이고 직시하면서 그것을 통해 더 배우면 되는 것이다. 실패한 순간을 떠올리며 몸서리 치듯 자책하는 대신 잘했던 부분과 개선할 점을 찾아 실천해야 한다.

 '지속적인 발전'을 위해서는 좋은 습관을 만들고, '나쁜 습관'을 제거해야 한다. 그렇게 하기 위해서는 첫째 '목표 설정', 둘째 '동기 부여' 셋째는 '꾸준한 실천'이다. 내안에 철학을 정착시켜 자신이 개선되고 있다는 좋은 피드백을 받아 작은 성공을 만드는 것이 훌륭한 동기 부여가 될 것이다.

 가장 기억에 많이 남는 부분은 '화에 대하여'이다. 사실 나의 고민과 스트레스들은  '화'에서부터 시작된 것이라고 생각한다. '화'가 나를 지배하게 했기 때문에 어떠한 긍정적인 생각과 다짐들도 무력화되기 마련이다. 
 내 안에서 시작된 '화'는 내가 받은 질책과 항의가 그대로 흡수되어 진화한 것이다. 상대가 내비친 화의 원인을 파악하지 못하고 그대로 나 자신의 '화'가 되는 것이다. 
나의 '화'를 다룰수 있다면 상대방의 화를 조절할 방도가 없는 상태라고 하더라도 완화 시킬 수 있는 여유와 기회가 있을 것이다.

 그리고 미래를 예측하는 것에 대한 주의를 요구한다. 인간이 예측하는 미래는 현재를 기준으로 삼기 때문이다. 현재의 행복이 미래를 반영한다고 볼 수 없다. 행복한 현재를 살아가는 개발자가 되기 위해서는 함께 하는 사람들과의 조화로운 삶을 위한 노력이 필요하다. 두리뭉실하게 노력하자가 아니라 증명된 효과적인 방법론들을 접목해보자. ATDD(Acceptance Test Driven Development), TDD(Test Driven Development)는 저자가 가장 추천하는 방법중에 하나이다.

 마지막으로 '실천적인 지혜'를 쌓기를 바란다. 나 자신을 믿고 내 잠재력 위에 지적인 미덕을 쌓고, 이를 실천하며 도덕적인 미덕을 쌓아야 한다. 

 나는 내 주위에 함께 일하는 개발자분들이 이 책을 꼭 한번 읽어보기를 강력하게 추천한다. 내 자신이 좋은 영향을 받은 이유도 있고, 이 지혜를 함께 이해하고 느끼면서 살아가면 더 즐겁고 행복한 (개발) 인생을 살아갈 수 있지 않을까 생각한다.



2014년 10월 14일 화요일

코딩호러의 이펙티브 프로그래밍 - 도서 리뷰

오전 9:12 Posted by jonnung No comments
<코딩 호러의 이펙티브 프로그래밍, 제프 앳 우드 지음, 2013.03, 위키북스>

 작년(2013년)쯤에 이 책이 도서관에 비치된 것을 봤을 때만해도 제목 때문인지 뭔가 어려울 것 같은 느낌을 받았다. 지금 생각하면 조금 웃긴게 "코딩 호러"라고 하니 무시무시한 느낌도 나고, "이펙티브(Effective)"라고 하니 '그래..이펙티브 하게 해야겠지.. 그런데 지금 난 잘 못할 것 같아'라고 생각 했던 것 같다. (겁먹은 거겠지..)
아무튼 지금은 그게 중요한건 아닌 결국에 시간이 흘러서 내가 이 책을 펼치는 순간이 찾아왔다는 것이다.

 간략하게 책에 대한 소개를 하자면, 개발자라면 누구나(그치?) 알고 있고, 많은 도움을 얻고 있는 http://stackoverflow.com 을 만든 제프 앳우드 가 지은 에세이 형식의 개발담 + 인생 조언에 대한 내용이다.

 개발자라는 직군에 종사하는 사람들(= 우리 모두)에게 힐링과 자극을 줄 수 있는 내용들로 시작하는데 아래는 '1부_들어가며: 결국은 프로그래머가 되고 싶은 거로군'에 나오는 내용중 일부를 옮겨봤다.

"솔찍히 말해서 나는 사람들이 너무 많은 일을 벌이는 것보다는 자기가 진심으로 좋아하는 것이 무엇인지 발견하고, 그 대상을 집중적으로 파는 것이 좋다고 생각한다. 
인생에서 정말 어려운 일은 이론적으로만 유용한 무엇을 실제로 배우는 과정이 아니라 자기가 진짜로 좋아하는 것이 무엇인지 깨닫는 과정에 놓여 있기 때문이다. 
자기가 정말 좋아하는 것을 찾아가는 연구와 탐색의 과정이 자신을 마침내 코딩으로 이끌었다면, 나의 축복을 받으며 코딩을 하기 바란다."

 프로그래머로써 살아가면서 한번쯤은 해봤을 법한 갈등과 고뇌들. 저자도 똑같이 느꼈기 때문에 이렇게 말해 줄 수 있지 않을까 싶다. 나는 개인적으로 저 말에 많은 용기와 힘을 얻었다.
이렇게 초반부터 감동을 받으니 평소 같으면 꾸벅꾸벅 졸기 바쁜 왕복 3시간의 출퇴근 시간에도 계속 책을 찾게 되었나 보다.

 그런데 300페이지 정도 이후 부터는 솔찍히 좀 지루했다. 처음에는 내 집중력을 탓하기도 하고, 그것이 지속되니 번역하신 분(임백준님..ㅎㄷㄷ)을 의심하기도 했지만 결론적으로는 내 관심사의 문제였던거 같다.
초중반의 stackoverflow의 개발담들이 사실 더 재밌던거지모..

 한줄 서평으로 마무리 하자면..

"재밌다. 그리고 출퇴근 지하철에서 읽으면 표지 덕분에 눈길을 끌 수 있다"


2014년 10월 12일 일요일

파이썬 소켓(socket) 모듈을 사용한 네트워크 프로그래밍 - Python 도서 리뷰

오전 1:49 Posted by jonnung , 8 comments


네트워크 프로그래밍(2/2)

 이전 포스트에서 '클라이언트/서버 아키텍처와 소켓 (socket)' 부분에 대해 정리했다. 이번에는 이 개념을 파이썬에 도입해서 프로그램을 작성 해보자.

일단 책에 나오는 TCP 서버/클라이언트, UDP 서버/클라이언트를 예제를 통해서 주로 사용하는 socket 모듈에 대한 구조를 파악해봤고, 이번에는 연습문제 중에 하나인 '전이중(full-duplex) 채팅 프로그램'을 만들어 보겠다.

책에는 나오지 않지만 검색을 해보던 중에 소켓 프로그램의 주요 이슈중 하나인 블럭킹(Blocking)에 대해 알게 되었는데 블럭킹을 해결하기 위한 방법중에 하나인 select 모듈을 채팅 프로그램에 적용해 보았다.

소스코드를 살펴 보기 전에 당연히 이 블럭킹(Blocking) 이라는 녀석이 무엇인지 살펴 보는 것이 순서겠다.


블럭킹(Blocking)

 어떤 일이 일어나기를 기다리면서 멍하니 있는 상태를 말한다. 예를 들어 소켓 서버에서 recv() 를 호출해 놓고, 클라이언트가 보내는 데이터를 기다리는 경우, 소켓 서버는 읽기 상태에서 블럭킹 되어 있다고 말한다고 한다.
 서버나 클라이언트나 차례대로 서로 데이터를 주고 받으면 이것은 크게 문제가 되지 않는다. 하지만 만약 서로가 데이터를 주기를 기다리는 상태가 된다면 어떻게 될까?

 이런 블럭킹 상태를 피하는것이 가장 좋겠지만, 그렇지 못할 수도 있기 때문에 일정 시간 이후 타임아웃이 걸려서 이 상태를 벗어나는 것도 좋은 방법이 될 수 있다.

그래서 채팅 프로그램 예제에서는 이 블럭킹 문제를 해결하기 위해 select 모듈을 사용한 것이다.
현재 수준에서 select 모듈을 더 파보는 것은 조금 무리가 있기 때문에 간단한 사용법만 익혀서 바로 적용했다. 하하;;


TCP 서버/클라이언트 채팅 프로그램

일단 전체 소스코드는 아래와 같다. 

상대적으로 클라이언트(tcpChatClient.py)가 쉽다(?)고 느껴지기 때문에 공을 더 들인 부분은 서버측 스크립트(tcpChatServer.py) 이다.

select 모 듈의 select 메소드는 양쪽 모두에서 사용되었다. 네번째 인자로 전달된 값이 '블럭킹' 단락에서 언급한 그 타임아웃 시간이다. 
10초라는 의미의 값을 전달 했기 때문에 읽어 들일 객체(첫번째 인자에 리스트 형태로 전달한 소켓들)가 없으면 비어있는 리스트를 반환한다.

38 ~39번 라인의 # 새로운 접속 부분에서 select() 가 반환한 read_socket 리스트의 값중에 서버소켓(serverSocket)과  같은 객체를 체크해서 새로운 접속인지를 판단한다.
하지만 아직 서버는 클라이언트의 연결이 받아들여진 상태는 아니다. listen() 메소드에서 일단 클라이언트의 접속이 되면, accept() 를 호출해서 별도의 소켓에 넘겨주고 통신을 진행하는 방식이 TCP 통신의 특징이고 UDP 와의 큰 차이인 것이다.

프로그램을 종료 하려면 강제로 종료시키는 방법 밖에 없는데 이때 KeyboardInterrupt 예외가 발생한다.
연습 삼아 만든 프로그램이지만 보기 안좋은 부분을 보완하기 위해서 try ~ except로 예외를 잡아 소켓을 닫고, 프로그램을 종료 시켰다. (책에서는 이 부분에 대한 코드는 없지만 '부드럽게 종료하기' 라는 참고사항으로 권장하고 있다.)


참 고

클라이언트/서버 아키텍처와 소켓(Socket) - Python 도서 리뷰

오전 12:46 Posted by jonnung , No comments




네트워크 프로그래밍(1/2)



'코어 파이썬 애플리케이션 프로그래밍' 의 두번째 챕터 '네트워크 프로그래밍'에 대한 리뷰 형식의 포스트 이다.
이번 챕터에서는 네트워크 프로그래밍의 배경 지식과 파이썬에서의 소켓(Socket)을 사용하는 방법을 설명하고 있다.


클라이언트/서버 아키텍처

  • 클라이언트/서버 아키텍처의 전제는 하드웨어일 수도, 소프트웨어일 수도 있는 서버가 하나 이상의 클라이언트(사용자)에게 '서비스'를 제공한다는 점
  • 서버의 존재 목적은 (클라이언트의) 요청을 기다리다가 클라이언트의 요청에 응답 후 다시 다른 요청을 기다리는 것
  • 2가지 형태의 클라이언트/서버 아키텍처를 소개하고 있다.
    1. 하드웨어 클라이언트/서버 아키텍처
    2. 소프트웨어 클라이언트/서버 아키텍처
  • 네트워크 프로그래밍은 서버가 클라이언트의 요청에 응답하려면 설정 과정이 필요하고, 통신 종단점(communication endpoint)은 서버가 요청을 리슨(listen)하기 위해 만들어지고 무한 루프에 들어가서 연결해 오는 클라이언트를 기다린다.
    그리고 클라이언트는 자신의 통신 종단점을 만든 후 서버에 연결해야 한다.

소켓

소켓은 '통신 종단점'이라는 개념을 구체화한 컴퓨터 네트워크 데이터 구조이다.
네트워크를 사용하는 애플리케이션은 통신을 시작하기 전에 항상 소켓을 만들어야 한다.
소켓 없이는 통신을 시작할 수 없기 때문이다.
원래 소켓은 실행중인 프로그램(프로세스)이 같은 호스트안에 실행 중인 다른 프로그램과 통신하기 위해 깨발 되었다고 한다.

소켓의 유형

  1. 유닉스 소켓
    • AF_UNIX 라는 '패밀리 이름' 을 가진다. AF는 주소 패밀리(Address family)를 의미.
    • 쉽게 클라이언트와 서버가 유닉스 환경의 동일한 컴퓨터에 존재해야 한다는 뜻.
    • 이 소켓은 파일 기반이다. 소켓의 기반 구조가 파일 시스템을 통해 지원된다는 것이다.
    • 파일 시스템은 같은 호스트에서 실행 중인 프로세스 사이에 지속적으로 공유되므로, 합리적인 방법이라고 할 수 있다.
  2. 네트워크 기반
    • 패밀리 이름은 AF_INET 이다.
    • 클라이언트와 서버가 인터넷 어디서든 존재할 수 있다는 의미를 갖는다.
파이썬은 AF_UNIX, AF_NETLINK, AF_TIPC, AF_INET{,6} 패밀리를 지원한다.

연결 방식에 따른 소켓의 종류

  1. 연결 지향 소켓(connection oriented)
    • 통신을 하기 전에 반드시 연결 돼 있어야 한다(전화를 거는 것과 유사)
    • 레코드 경계 없이 데이터를 순서대로 신뢰성 있게 중복없이 전달. 각 메세지는 여러 조각으로 나뉘어서 반대편에 확실히 전달된 다음에 다시 순서대로 한데 묶인 후 기다리는 애플리케이션에 전달
    • 연결 지향 소켓을 구현한 프로토콜(protocol)로는 전송 제어 프로토콜(TCP, Trasmission Control Protocol) 이 있으며, 이 소켓을 만드려면 소켓 유형으로 SOCK_STREAM(스트림 소켓)을 지정
    • 이 소켓은 네트워크상에서 IP를 호스트를 찾기 위해 사용하기 때문에 두 프로토콜의 이름을 붙여 TCP/IP 라고 함.
  2. 비연결형 소켓(connectionless)
    • 스트림 소켓과 대비되는 데이터그램(Datagram) 유형의 비연결 소켓
    • 통신 시 최초 연결하는 과정이 필요 없음
    • 데이터 전달 과정에서 순서나 신뢰성 이나 중복 방지를 보장할 수 없음. 이는 메세지가 연결 지향 소켓처럼 조각으로 나뉘지 않고 통째로 송신된다는 것을 의미(우편 서비스에 비유)
    • 연결 지향 소켓은 가상 회선을 맨 처음 만들고 유지하기 위해 상당한 부가 비용이 드는데 비연결 지향 소켓은 이런 부담이 덜하고 성능면에서 더 좋다.
    • 데이터그램 소켓을 구현한 프로토콜로는 데이터그램 프로토콜(UDP, User Datagram Protocol)이 있고, UPD 소켓을 만들려면 SOCK_DGRAM을 소켓 유형으로 지정.
    • 이 소켓도 IP를 네트워크상에서 호스트를 찾기 위해 사용하므로, UPD/IP라고도 부름





2014년 9월 21일 일요일

파이썬의 정규식(re) - Python 도서 리뷰

오전 9:02 Posted by jonnung , 1 comment

추석전에 연휴기간에 볼 책을 빌리러 도서관에 갔다가 신간으로 들어온 책을 1빠로 득했다. 
최초 번역판일 것 같아서 빌리지말까 하다가 읽어보니까 번역이 상당히 잘 되어 있는 것 같은 느낌이다. 아 그리고 이미 예전에 '코어 파이썬 프로그래밍' 이라는 책에서 '응용' 부분만 좀 더 확장했다는 것 같다.

그런데 반납일까지 1주일 남았는데 1챕터밖에 못봤다. ㅠ_ㅠ  어짜피 사려고 했으니까 뭐;;;
(페이지랑 가격이 좀 후덜덜;;; 하긴 함)

아무래도 파이썬에 대한 책이고, 실습(실행 > 확인) 위주로 공부를 하다보니까 IPython notebook 이 딱 일것 같다.

첫번째 정규식 챕터, 리뷰 보러가기


Python - 클로저(Closure) 쉽게 생각하기

오전 8:28 Posted by jonnung 1 comment


함수 안에 다른 함수가 정의된 함수를 중첩 함수(Nested Function) 이라고 한다.
중첩 함수는 자신을 감싸고 있는 함수가 가진 변수에 접근 할 수 있다. 이건 자바스크립트(Javascript)도 동일한 특성이다. 

일단 간단한 예제 코드를 살펴보자.
#-*- coding: utf-8 -*-
 
def print_hello(msg):
    def inner_print():
         # nonlocal msg  # python3.x에만 있는 키워드
        print('Hello %s' % msg)
    return inner_print
 
printer = print_hello('jonnung')

printer()  # Hello jonnung

print_hello() 함수는 'jonnung'을 전달 받아 호출 되었고, 반환된 inner_print함수는 printer 변수에 할당 되었다.
printer() 함수의 실행 결과로 출력되는 값으로 알 수 있는 사실은 print_hello()의 실행이 종료 되었더라도 전달된 값(msg)이 기억되고 있는 것을 알 수 있다.

이러한 코드를 파이썬에서는 클로저(Closure)라고 한다.
그리고 감싸는 함수 안에 변수는 현재 네임스페이스상에서 함수가 삭제되더라도 사라지지 않는다.
del print_hello
 
printer()  # Hello jonnung

결국 중첩 함수가 감싸진 영역안에 변수를 참조할때 클로저를 갖는다고 할 수 있다.

그럼 이제 파이썬에서 클로저를 만들기 위한 조건을 정리해보자.
  • 중첩 함수(Nested Function)를 갖는다.
  • 중첩 함수는 자신을 감싸고 있는 함수 영역(부모함수)의 변수를 참조하고 있다.
  • 부모함수는 중첩 함수(자식 함수)를 반환한다.
여기서 한가지 물음이 생길 수 있겠다. 그렇다면 클로저는 언제 사용해야 할까?
클로저는 전역 변수를 사용하지 않기 위함과 내부 데이터에 대한 은닉을 위해서 활용할 수 있겠다.
그리고 객체지향에 대한 문제점의 해결책이 될 수 있다. 적은 메소드(대부분 1개?)를 갖는 클래스에 대한 대체로 클로저를 활용한 코드는 좀 더 우아한 방법이 될 수도 있다고 한다. 

위 샘플 코드의 실행 결과와 추가적인 예제는 아래 IPython Notebook에서 자세히 확인 할 수 있다.



2014년 9월 16일 화요일

gae-init (약간) 사용 후기, 구글 앱 엔진(Google App Engine) 웹 어플리케이션 빠르게 시작하기

오전 6:53 Posted by jonnung , , , , , No comments

gae-init 은 Google App Engine에 웹 어플리케이션을 좀 더 쉽게 시작하기 위한 프로젝트 이다. 
일반적인 웹 어플리케이션 개발에서 수행하는 공통적인 작업들(파일 구조를 잡고, 최신 라이브러리를 다운로드 받고, 이전 프로젝트에서 개발한 코드 조각들을 모으는 등)을 자동으로 세팅 할 수 있도록 도와준다.
개발자는 더이상 시간 낭비 하지 않고, 좀 더 어렵고 중요한 작업에 집중할 수 있는 것이다.

공식 문서에서 제공하는 튜토리얼(Tutorial) 에서는 gae-init을 사용해서 개발, 빌드, 실행 그리고 배포까지 다루는 phonebook 예제(데모 보기)를 다루고 있다.

gae-init을 사용하기 위해서는 당연히 python이 있어야 한다.(GAE는 아직 python2.7만 지원함)
그리고 Node.js / Git / pip, virtualenv가 필수적으로 있어야 한다.
설치는 gae-init git 저장소를 clone 받으면 간단하게 시작 할 수 있다. 그리고  run.py -s  를 실행하면 venv(python 가상 환경)과 bower_components, node_modules을 자동으로 세팅하고, Flask로 만든 간단한 구조의 어플리케이션이 GAE SDK에서 제공하는 개발 서버를 통해 실행된다.

튜토리얼의 대부분의 내용은 기본적인 gae-init 세팅 구조에 phonebook 앱의 연락처 기능을 만드는 방법을 자세하게 다루고 있다. 

일단 난 튜토리얼을 다 따라해보지는 않았다. (이미 해 본 내용이기도 하고..)
사실 gae-init 이 세팅하는 구조가 내 입맛에 딱 맞지는 않았다.
그리고 난 거의 pycharm으로 개발을 하니까 개발 서버 실행을 위해 run.py 을 실행 할 일은 없겠지만, 그래도 run.py 파일을 보니까 나중에 참고해 볼만한 코드가 상당히 많았다.
Flask 어플리케이션 코드가 위치한 main 디렉토리도 커스터마이징해서 사용하면 될 것 같다.


(와아~ 어디서 run.py를 실행했는지도 수집하네ㅋㅋㅋ)

2014년 8월 11일 월요일

프론트엔드 웹 개발을 위한 자동화 관리 툴: Yeoman, Grunt, Bower

오전 6:54 Posted by jonnung , , , No comments
이미지 출처: http://yeoman.io/learning

최근에 개인적인 스터디 그룹 프로젝트에 Grunt와 Bower를 적용 해봤는데 정말 재밌었고, 나름대로 상당히 만족을 하고 있다.

잘 배워두고 자주 사용하면 기본적인 구조를 잡는 것부터 각종 라이브러리 설치와 의존성 관리, 그리고 각종 빈번한 작업들(소스 코드 합치기, 압축 등등)을 편리하게 수행하고 관리 할 수 있을 것 같다.

이번 포스팅은 Grunt, Bower와 더불어 Yeoman에 대한 간단한 소개와 참고 링크 정도를 남겨 본다.

Grunt

  • 자바스크립트 프로젝트를 위한 테스크 기반의 커맨드 라인 빌드 툴
  • 테스크(task)란 무엇인가?
    작업의 단위라고 생각하면 되겠다.
    js, css, html 같은 static 파일들을 하나로 합치고(concat) 압축을 해서 파일 사이즈를 줄이는(minification) 작업들, 테스트, 배포 등등을 각각 하나의 테스크라고 생각하면 쉽다.
    Grunt는 이런 빈번한 작업들을 사용자가 미리 정의해 놓은대로(Gruntfile.js) 자동으로 빌드해주는 툴이다.
  • Node.js로 만들어져 있다. 따라서 Node.js가 설치 되어 있어야 하고, npm에 등록 되어 있으며 global로 설치 한다.

Bower

  • 프론트엔드 컴포넌트 의존성 관리 툴 이다. 쉽게 말해 위에서 Grunt를 설치하기 위해 사용한 npm과 비슷한 것이다.
  • 예를 들어, 새로운 프로젝트를 시작하거나 진행하던 프로젝트에 bootstrap3을 설치한다고 했을때 bootstrap 웹사이트에 가서 소스코드를 다운 받고, 프로젝트의 적당한 디렉토리에 복사할 것이다.
    하지만 이미 설치 되어 있는 jquery 버전과 bootstrap에 포함된 jquery 버전과 차이에 의한 의존성 관계가 문제 될 수도 있다.
  • bower는 이런 상황에서 각종 컴포넌트들의 설치도 간편하게 해주겠지만, 의존성 부분도 말끔하게 관리해준다.

Yeoman

  • 일단은 스캐폴딩 기능만 사용해 봤기 때문에 웹 어플리케이션의 기본 구조를 쉽고, 편하게 잡아줄 수 있는 도구로 생각하고 있다.
  • Generator 라는 것을 이용해서 개발하려는 프로젝트 종류(webapp, bootstrap, angularjs 등등)에 따라 기본적인 구조를 알아서 잡아준다.
  • 내부적으로 Grunt, Bower를 사용하고 있다.

설치와 사용법 참고 사이트


스터디 그룹 프로젝트에 적용해 보면서 생각 한건데 Python Flask 웹앱을 스캐폴딩 해주는 Yeoman Generator가 있었으면 좋겠다는 생각이 들었다.

그랬는데 역시나 있었다. github에서 2개 정도 찾았는데 한개는 angularjs와 flask 조합 제너레이터(generator-angular-flask) 이고, 나머지 하나(flask-app-generator)는 package.json 도 없고, 기타 등등 없는게 많은지 제대로 동작을 안한다.

바로 python virtual 환경 세팅(virtualenv)랑 flask 설치, 그리고 테스트 웹서버 실행까지 Grunt랑 조합해서 가능할 것 같은 생각이 드는데...

간단하게 하나 만들어 봐야겠다.

2014년 7월 10일 목요일

Python - 파이썬2.x Unicode와 UTF-8 인코딩 감잡기

오후 8:47 Posted by jonnung 3 comments
 파이썬2.x의 기본 인코딩은 ascii 이다. 파이썬 스크립트에서 한글을 사용하게 될 때 파이썬은 ascii 인코딩일 것으로 예상하고 해석하려고 하지만 한글을 ascii로 해석이 불가능 하기 때문에 SyntaxError가 발생 한다.

 이 문제를 해결하기 위해 파이썬 파일의 최상단에는 아래와 같은 주석을 추가하면 조금 도움이 된다.

#-*- coding: utf-8 -*-

 이 주석이 있으면 해당 파이썬 스크립트는 utf-8로 인코딩 되어 있다는 것을 미리 알려주는 역할을 한다.

 여기서 잠깐 유니코드(unicode)와 utf-8에 대한 설명을 간단하게 하자면 utf-8은 유니코드를 위한 문자 인코딩 방식 중에 하나이다. utf-8 인코딩은 유니코드 한 문자를 나타내기 위해 1바이트에서 4바이트까지 사용한다고 한다.

 다시 파이썬의 인코딩에 대한 부분으로 돌아가서 간단한 예제를 하나 보도록 하자.

# -*- coding: utf8 -*-

print(type('한글').__name__)  # str
print(type(u'한글').__name__)  # unicode
print(type('한글').__name__)
print(type(u'한글').__name__)

SyntaxError: Non-ASCII character '\xed' in file…블라블라~

 위 예제 코드의 결과를 보면 쉽게 감을 잡을 수 있다.

 첫번째 에제코드에서 상단에 내부 문자에 대한 인코딩을 utf-8로 하겠다는 미리 알려줬기 때문에(누구에게?? print에게!!) ‘한글’이라는 문자열의 타입은 확인해보면 string 이다. 그리고 u’한글’으로 하게 되면 유니코드로 잘 변환해서 출력 시켜주는 것을 알 수 있다.

 두번째 예제에서는 상단에 선언한 부분을 제거하고 스크립트를 실행 시켜봤는데 역시나 문법에러(SyntaxError)가 발생 하는 것을 확인 할 수 있었다. ‘한글’을 기본적으로 ascii로 해석하려 하기 때문에 type을 알 수도 없고, 유니코드로 변환도 할 수 없는 것이다.

# -*- coding: utf8 -*-

print str(unicode('한글'))
print str(unicode(‘한글', ‘utf-8'))

 ‘한글’을 유니코드로 변환하고, 그 유니코드를 다시 문자열로 바꿔서 출력하려고 한다.
이 코드는 결과는 무엇일까?
unicode() 기본적으로 전달된 인자값을 ascii로 해석하려고 하기 때문에 위 예제는 아래와 같은 에러가 발생한다.

UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 0: ordinal not in range(128)

 결국 상단에 utf-8을 사용할 것이라고 선언했어도 unicode() 함수를 사용할때는 소용없다는 것을 알게 되었다.

이 코드를 정상적으로 동작하도록 해보자.

# -*- coding: utf8 -*-

# 유니코드로 다루기 예제1
hoo = unicode('한글', 'utf-8')
print str(hoo.encode('utf-8'))

# 유니코드로 다루기 예제2
bar = '한글'.decode('utf-8')
print bar.encode('utf-8')

# 유니코드로 다루기 예제3
foo = u'한글'
print str(foo.encode('utf-8'))

정신 건강을 위해서라도 파이썬 스크립트 내부에서 사용하는 모든 문자열은 유니코드로 다루는 것이 좋겠다.
그리고 파일이나 DB에 저장하거나 네트워크로 전송하기 직전에는 string으로 변환해서 넘겨주는 방식으로 개발하는 것이 좋다…

아! 그리고  ‘유니코드가 아닌 상태로 CJK(Chinese. Japanese, Korean) 비교할 때 주의할 점’(https://gist.github.com/kimdwkimdw/a2ea13848167984adc8f)도 참고하고 숙지해서 개발시에 엉뚱한 삽질은 안하도록 하자!


참고 자료



2014년 6월 30일 월요일

javascript 상속(Inheritance) - 의사 클래스 방식과 Object.create 메소드 의 연관성

오전 6:08 Posted by jonnung 1 comment
객체지향 프로그래밍에서 상속은 너무나 자연스럽게 다뤄지는 프로그래밍 기법이다.
상속은 코드 재사용의 한 형태이고, 부모 객체의 데이터 타입 체계를 그대로 전달 받기 때문에 개발 비용을 감소 시켜주는 장점이 있다

하지만 일반적인 객체지향 프로그래밍 언어와 다르게 자바스크립트는 클래스(class)가 없다. 상속(Inheritance) 메커니즘을 구현하기 위해서는 자바스크립트의 특징이라고 할 수 있는 프로토타입(prototype)을 기반으로해서 부모 객체를 자식에게 상속 할 수 있다.
이것은 다시 말해 객체가 다른 객체로 바로 상속 된다는 것을 의미 한다.

이번 포스트에서 정리할 내용은 자바스크립트의 상속 패턴중에서 함수의 프로토타입 프로퍼티를 활용한 방식이다.

지난번 javascript 함수 - 함수 객체의 프로토타입 프로퍼티 이해하기 에서 정리한 함수의 프로토타입 프로퍼티(prototype property)을 먼저 살펴보면 좋을 것 같다.

의사 클래스 방식 Pseudoclassical


의사 클래스(Pseudo class, 슈도 클래스라고 읽음)는 가짜 클래스 정도로 이해하자. 사실 이번에 처음 알게된 표현인데 너무 어렵게 생각했던 것 같다.
자바스크립트에서의 의사 클래스 방식은 클래스가 없는 자바스크립트가 클래스를 흉내내기 위해 작성하는 패턴이라고 생각하면 된다.

자바스크립트는 프로토타입적 특성에 맞게 객체에서 다른 객체로 직접 상속하는 방법을 갖기는 하지만 생성자 함수를 통해서 객체를 생성해야하는 조금 혼란스러운 단계가 있다.

좀 더 자세히 설명하자면, 객체의 프로토타입은 해당 객체가 생성 될때 사용한 객체의 원형에 대한 연결을 담고 있기 때문에 이미 생성된 객체의 프로토타입에 다른 객체를 바로 상속할 수는 없다.
다른 객체를 새로운 객체에 상속하기 위해서는 객체가 생성되기 전에 생성자 함수에서 함수객체의 프로토타입 프로퍼티에 객체를 직접 할당하는 식으로 상속을 구현하는 것이다.
(함수 객체의 프로토타입 프로퍼티에는 자신을 통해 생성될 객체가 참조할 객체의 원형을 갖고 있다.)

자, 그럼 이제 자바스크립트의 상속을 구현하기 위해 의사 클래스 방식으로 예제를 작성해보겠다.

다음 코드는 '여자친구가 당분간 연락하지 말자'고 했을때 당분간의 정확한 기간을 계산해주는 객체를 생성한다.

var Love_anger_formula = function () {
    this.__swear_word_constant = 18;  // 욕주율
    this.get_swear_word_constant = function () {
        return this.__swear_word_constant;
    };
};

var do_not_contact = function (contact_stop_time, lie_count) {
    this.contact_stop_time = contact_stop_time;  // 연락 두절 시간
    this.lie_count = lie_count;  // 거짓말 횟수
};

// do_not_contact 함수의 prototype property 객체를 Love_anger_formula 의 인스턴스로 대체한다.
do_not_contact.prototype = new Love_anger_formula();

var how_long = new do_not_contact(24, 2);

// how_long 객체에 새로운 메소드를 추가한다.
// '당분간'의 기간을 계산한 결과를 돌려준다.
how_long.get_remain_period = function () {
    var  swear_word_constant = this.get_swear_word_constant();
    return this.contact_stop_time * this.lie_count * swear_word_constant;
};

console.log(how_long.get_remain_period());
Do_not_contact 라는 생성자 함수를 정의 하고, 이 함수의 prototype을 Love_anger_formula 의 인스턴스로 대체하는 방식으로 의사 클래스 만들어서 객체를 상속했다.

더글라스 크락포드는 이런 의사 클래스 패턴을 객체지향처럼 보이게 고안 됐지만 마치 어디 외계에서 온 패턴과 같다고 말했다.
자바스크립트에 익숙하지 않는 개발자에게 친숙한 방식이 될 수도 있겠지만, 자바스크립트의 장점을 가리게 되는 방법이라는 말도 덧붙였다.

아무튼 이렇게 생성된 객체의 최대의 문제점은 바로 모든 속성들이 public 이라는 것이다. private은 없다.
how_long.__swear_word_constant로 부모 객체의 속성에 바로 접근해서 읽거나 값을 변경할 수 있다.

또한 생성자 함수를 new 연산자로 실행하지 않으면 this는 새로운 객체에 바인딩 되지 않고, 전역 객체(window)에 연결된다. new 연산자를 빼먹어도 어떠한 에러도 발생하지 않기 때문에 매우 심각한 문제가 발생할 수 있다.

이 문제에 대한 해결책(?)으로 더글라스 크락포드가 추천하는 방법은 2가지가 있는데 new 연산자로 실행해서 객체를 생성하는 생성자 함수의 이름은 첫글자를 대문자로 표기하는 것이다.
그리고 나머지 한가지는 new 연산자 사용을 피하는 것이다.

언어의 특징을 비교하는 차원에서 위 예제 코드와 동일한 기능을 하는 파이썬(python) 코드를 작성해 보았다.
LoveAngerFormula 클래스의 __swear_word_constant 변수는 완전 안전한 private 이다.

# -*- coding: utf8 -*-


class LoveAngerFormula():
    __swear_word_constant = 18  # 욕주율

    def get_swear_word_constant(self):
        return self.__swear_word_constant


class DoNotContact(LoveAngerFormula):
    def __init__(self, contact_stop_time, lie_count):
        self.contact_stop_time = contact_stop_time  # 연락 두절 시간
        self.lie_count = lie_count  # 거짓말 횟수
        self.swear_word_constant = self.get_swear_word_constant()

    def get_remain_period(self):
        """
        '당분간 연락하지 말자' 했을때 당분간의 정확한 기간을 계산
        :return: 기간(일)
        :rtype: integer
        """
        return self.contact_stop_time * self.lie_count * self.swear_word_constant


how_long = DoNotContact(24, 2)
print(how_long.get_remain_period())

Object.create() 전달한 객체를 프로토타입으로 새로운 객체를 생성하는 메소드


Object.create() 메소드로 만들어지는 객체는 프로토타입을 직접 지정해서 생성할 수 있는 편리한 기능을 제공한다.
이런게 있는지도 몰랐었는데 이미 표준에 포함되어 있는 메소드 이다!
크롬(Chrome)과 파이어폭스(Firefox)에서는 당연히 제공하고 있었고, IE는 뒤늦게 9부터 지원한다.

Object.create() 메소드가 생기게 된 배경은 new 연산자 사용이 '자바스크립트 스럽지 못하다'는 의견이 나오게 되면서 new 연산자 사용을 자제하기 위해 만들어졌다고 한다.

그런데 이 메소드를 지원하지 않는 브라우저를 위해서 작성하는 코드를 보면 조금 웃긴 사실을 알 수 있다.

if (typeof Object.create !== 'function' ) {
    Object.create = function (obj) {
        function F();
        F.prototype = obj;
        return new F();
    }
}
결국 Object.create()메소드도 내부적으로 F()라는 빈 함수를 만들고, 위에서 살펴본 의사 클래스 방식으로 F 함수의 프로토타입 프로퍼티에 전달받은 객체를 대체한다.
그리고 new 연산자로 생성한 객체를 돌려준다.

new 연산자 사용을 자제하기 위해서 만들어진 메소드는 결국 손바닥으로 하늘을 가리는 꼴이다.

마무으리


자바스크립트의 프로토타입 특징을 활용한 상속에 대해 정리 해봤는데 조금 찝찝한 느낌을 지울 수 없는 것은 사실이다.
하지만 함수의 프로토타입 프로퍼티로 클래스를 흉내내는 의사클래스방식과 Object.create()메소드의 연관성에 대한 부분은 확실히 알고 간다는 것에 매우 만족한다.




2014년 6월 23일 월요일

javascript 함수 - 함수 객체의 프로토타입 프로퍼티 이해하기

오전 8:17 Posted by jonnung No comments
앞으로 몇번에 걸쳐서 자세히 알아볼 부분은 모든 개발 언어에서 굉장히 많이 사용하고, 자바스크립트에서도 핵심이라고 할 수 있는 함수에 대한 부분이다.
그리고 이번 정리에서는 함수 객체와 프로토타입 연결 특성과의 관계에 대해서 중점적으로 알아볼 것이다.

객체의 프로토타입(prototype)


자바스크립트에서 숫자, 문자열, 불리언(true/false), null, undefied를 제외한 모든 값은 객체이다. 생소한 표현이지만 숫자나 문자열, 불리언은 메소드를 갖기 때문에 유사객체라고도 한다. 이 유사객체에 대한 부분은 다음 기회에 좀 더 조사해 볼 것이다.

더글라스 크락포드의 'Javascript The Good Parts'에서는 함수 객체에 대해 설명한 부분에서 프로토타입과 관련해서 설명한 부분을 요약해서 정리하자면 아래와 같다.
프로토타입에 대해 어느정도 알고 있더라도 이것을 보게 되면 상당히 혼란을 일으킬 가능성이 높다.

함수는 객체이다. 객체는 프로토타입 객체(Prototype Obeject)로 숨겨진 연결을 갖는 이름/값 쌍들의 집합이다. 객체 중에서 객체 리터럴로 생성되는 객체는 Object.prototype에 연결 된다.  반면 함수 객체는 Functon.prototype에 연결 된다. Function은 다시 Object.prototype에 연결 된다.  모든 함수 객체는 prototype이라는 속성이 있다. 이 속성의 값은 함수 자신 자체를 값으로 갖는 constructor라는 속성이 있는 객체이다. 이는 Function.prototype으로의 숨겨진 연결과는 다른 의미 이다.
자바스크립트 개발을 해본 경험이 있다면 대부분 프로토타입(Prototype)에 대해서 들어봤을 것이다. 프로토타입은 클래스가 없는 자바스크립트에서 객체지향적인 프로그래밍을 하기 위해서 사용하는 특징이라고 할 수 있다.
좀 더 쉽게 말하자면 상속(Inheritance)을 구현하여 객체가 다른 객체에 속성들을 물려줄 수 있도록 하기 위해 프로토타입을 사용할 수 있는 것이다.

위 인용문의 내용을 살펴보면 크게 객체와 프로토타입과의 관계함수와 프로토타입과의 관계 부분으로 구분되는 것을 알 수 있다.

간단하게 객체를 만들어서 차이점을 확인해 보면 좋을 것 같다.
var func = function () {
    this.one = 'Hello';
    return {
        one: one,
        two: 'world'
    };
};
var obj1 = func();

var obj2 = {
    one: 'Hello',
    tho: 'world'
};

console.dir(obj1);
console.dir(obj2);
위 예제를 실행 결과로 나오는 obj1과 obj2는 완전히 똑같다. 객체 생성 방법에 대한 다른 표현 방식이 있다는 것을 보여주기 위해 똑같은 객체를 생성했을 뿐이지 사실 여기서 중요하게 봐야하는 부분은 console.dir()의 결과로 콘솔에 출력되는 내용이다.


인용문에서 언급된 '객체 리터럴로 생성된 객체는 Object.prototype에 연결된다'는 부분은 위 그림에 나타나있는 __proto__를 말한다.
어렵다. 이렇게 하면 이해하기가 쉽지 않다. 이해를 해야 사용할 수 있고, 누구에게나 설명할 수 있기 때문에 이 개념을 좀 더 명확한 예제로 확인해 볼 필요가 있다.

var Func = function () {
    this.prp = 'Jonnung';
}

var ins = new Func();

console.dir(ins);
이 예제 코드는 new 키워드를 사용해서 객체를 생성할 수 있는 생성자 패턴으로 작성된 함수이다.
생성된 ins라는 객체 내부를 살펴본 모습은 아래와 같다.

ins 객체의 __proto__.constructor를 확인 해보면 Func() 생성자 함수가 들어 있는 것을 알 수 있다. 한마디로 ins 객체는 Func() 라는 생성자 함수를 원형(프로토타입)으로 생성된 객체라고 할 수 있다.
이제 그림이 조금 명확히 보이기 시작하는 느낌이다.
위에서 객체 리터럴로 생성된 객체는 __proto__.constructor 속성에 Object()가 있던 것은 리터럴 표기법으로 생성 된 객체는 리터럴의 특성상 즉시 객체화가 되기 때문에 직접적인 객체의 원형이라고 할 수 있는 대상이 없고, 바로 최상위 원형인 Object이 원형이 되는 것이다.

함수는 객체이다.


객체의 프로토타입에 대해 정리가 끝났다고 프로토타입에 대한 이해가 끝난것은 아니다.
이전 단락의 인용문에서 말하듯 함수도 역시나 객체이다. 이제부터 혼란을 방지하기 위해 함수를 함수 객체로 표현하도록 하겠다.
이번에 살펴볼 내용은 함수객체만이 갖고 있는 프로토타입 프로퍼티(prototype property) 라는 것이다.

위 단락의 두번째 예제의 console.dir()을 객체가 아닌 생성자 함수에 대해 실행해 보도록 하겠다.

var Func = function () {
    this.prp = 'Jonnung';
}

var ins = new Func();

console.dir(Func);

위에서 객체의 내부에 __proto__가 객체의 원형인 프로토타입이라고 했는데 이 함수 객체에는 __proto__도 있고, prototype 이라는 속성도 있는 것을 확인 할 수 있다.

이 prototype property는 함수 객체만이 갖고 있는 속성이다. 그리고 위에서 설명한 객체의 프로토타입과는 의미가 전혀 다르기 때문에 절대로 착각해서는 안된다. 우리가 흔히 상속의 개념으로 생각하는 객체의 원형인 프로토타입은 전 단락에서 설명한 객체가 생성되기 위해 사용한 원형이라는 의미의 프로토타입이 맞다.

그럼 함수 객체만이 갖고 있는 이 prototype property는 무엇인가!
바로 자신을 통해 만들어질 객체들이 원형(프로토타입)으로 사용할 객체 이다.

일단 정의 자체가 다르기 때문에 혼란스러워할 이유는 없다. 그리고 이런 흐름을 증명할 수 있는 증거는 이미 위 코드의 결과에서 확인한 것이나 다름없다. (갑자기 반전스러운 말투)

마무으리


  1. Func() 생성자 함수는 자신을 원형으로 해서 생성될 객체가 참조할 객체를 프로토타입 프로퍼티(prototype property)에 갖고 있다.
  2. Func() 생성자 함수로부터 탄생한 객체 ins는 흔히 프로토타입이라고 하는 자신이 만들어질 때 원형으로 사용한 객체에 대한 연결 정보를 갖고 있다.

참고






2014년 4월 4일 금요일

Python 기초 팁과 트릭

오전 3:38 Posted by jonnung No comments

객체 진위

  • 객체의 길이가 0인지, 값이 비어 있는지 체크할 필요가 없다. 파이썬의 객체는 비어있으면 거짓(False)이다. 숫자 0도 거짓이다.

삼중 따옴표를 사용한 문자열 선언

  • 삼중 홑따옴표든 쌍따옴표든 내부에 인용구 표현처럼 또 다른 삼중따옴표를 쓸 수 있다. 이스케이프가 필요 없어진다.

문자열안에 부분 문자열 찾기

  • 부분 문자열을 찾기위해 find 메소드를 사용할 필요가 없다. 리스트, 튜플, 사전을 다루듯이 in을 사용하면 같은 효과를 볼 수 있다.

람다함수

  • 람다함수는 단 하나의 표현식의 결과를 돌려주는 미니 함수 이다.
  • 람다함수는 그 자체가 표현식이다. 다른 서술문 안에 사용 될 수 있다.
  • 함수를 인자로 넘겨여 할때나, 복잡한 연산을 여러번 하고 싶을때 람다함수를 활용할 수 있다.

2014년 1월 27일 월요일

Concept git rebase and example

오전 6:47 Posted by jonnung 1 comment
git으로 코드의 버전관리를 하면서 브랜치 작업을 많이 하게 되는데 사실 난 브랜치 생성을 좀 즉흥적으로 하는 감이 없지 않아 있다.

무언가 작은 것이라도 개발을 할 때는 브랜치 계획을 어느정도 수립해 놓게 되면 느닷없는 브랜칭으로 커밋 로그가 복잡해지는 일은 없을 것 같는 생각이 든다.

브랜치를 사용하면서 개발을 하다 보면 어느 순간에는 머지(merge)를 하기 마련이다.
그런데 예전에 Git 브랜치 배우기을 해보면서 git에 merge와 결과는 같지만 동작 방식이 다른 리베이스(rebase)라는 기능이 있다는 사실을 알게 되었다.
그때 rebase 예제를 풀어보면서 개념 부족으로 상당히 오랜 삽질을 했던 기억이 난다. 윽..

아무튼 일단 rebase와 merge의 차이에 대한 결론부터 정리하자면 아래와 같다.


Merge는 결과를 합치고

Rebase는 과정을 비교하여 결과와 같이 합친다.

rebase와 merge의 차이를 간략하게 알았다면, 언제 rebase를 써야하는 지가 가장 중요하다.

위에서 말 했듯이 브랜치를 merge 하게 되다보면 히스토리가 복잡해지기 마련이다.
rebase를 사용하면 이런 히스토리를 깔끔하게 정리할 수 있는 효과가 있다고 보면 된다.

간단한 예제를 직접 해보면서 rebasemerge의 차이와 명령어를 좀 더 자세히 알아보겠다.


Base History


일단 merge와 rebase를 비교하기 위해 적당한 히스토리를 만들어 보겠다.
number.txt 라는 새로운 파일을 하나 만든다.
적당히 내용을 입력하고, master 브랜치의 stage영역에 추가(add) 후 커밋(commit)을 했다.
그리고 또 한번 number.txt 파일의 2번 줄의 문장을 변경 하고, 다시 한번 commit을 한다.

123456789
Number content.

이제 2명의 개발자가 각각 브랜치를 만들어 내용을 수정하는 과정을 진행 하겠다.
첫번째 개발자의 브랜치명은 dev-1, 두번째 개발자의 브랜치명은 dev-2로 정했다.

일단 dev-1 개발자가 먼저 파일을 2번 수정하고 각각 2번 commit 했다.

0123456789
Number content!!!

아직까지 dev-2 개발자는 파일을 수정하지 않았다. 그런데 이번에는 master 브랜치에서 파일의 수정이 한번 더 발생 했다. (파일 내용은 생략)

그리고 이제 dev-2 개발자가 자신의 브랜치에서 파일을 수정한다

0123456789
9876543210
10 Numbers contents.

그리고 마지막으로 다시 master 브랜치로 돌아와 새로운 내용을 한번만 더 추가 했다.

123456789
987654321
192837465
Number content.

자 이제 모든 수정이 완료 되었다. 횟수는 적지만 약간 복잡하게 파일 수정이 발생했고, 중간 중간에 master 브랜치의 내용도 수정이 되면서 상황은 점점 악화 되고 있다.

벌써부터 conflict의 그림자가 발밑까지 와있는 느낌이다.

제가 이렇게 히스토리를 만든 이유는 히스토리 그래프를 이해하기 쉽게 만들기 위함과 conflict 발생시 해결하는 과정 그리고 merge와 rebase의 차이점 모두를 담기 위함이 였습니다. 돌 던지지는 마세요. ㅠ_ㅠ)a

현재 상태에서 merge와 rebase를 각각 진행 해보겠다.


Merge


일단 현재 브랜치가 master 인지 확인하고, dev-1 브랜치를 merge 한다.

$ git branch
  dev-1
  dev-2
* master


Cap 2014-01-25 13-27-29-679



$ git merge dev-1

위와 같이 master와 dev-1브랜치 사이에 conflict가 발생했다고 알려준다. 그렇다면 에디터를 열고 number.txt 파일을 원하는 형태로 직접 수정을 해주고 계속 진행을 해야 한다.

<<<<<<<< HEAD
123456789
987654321
192837465
Number content.
=======
0123456789
Number content!!!
>>>>>>> dev-1

'======='을 중심으로 위쪽은 master 브랜치쪽 내용, 아래쪽은 dev-1 브랜치쪽 내용 이다.
123456789
987654321
192837465
Number content!!!

위 결과처럼 dev-1 브랜치의 내용 중 마지막 'Number content!!!'만 병합 하도록 수정 했다.
conflict를 해결하고 머지를 마무리하는 머지 커밋(Merge commit)을 한다.

$ git add number.txt
$ git commit
[master bc64d16] Merge branch 'dev-1'

Cap 2014-01-25 13-58-35-547

그리고 dev-2 브랜치도 위와 동일한 방법으로 master브랜치에 merge 한다.

$ git merge dev-2 
# 에디터에서 Conflict를 해결하고 다시 커밋!

$ git add number.txt
$ git commit
[master 2195143] Merge branch 'dev-2'

Cap 2014-01-25 14-09-07-136


Rebase


이제 rebase를 해보겠다.

이번에는 merge때와 위치하는 브랜치가 다르다는 것을 주의 해야 한다. 아래와 같이 rebase가 되는 토픽 브랜치(Topic)로 checkout 하고 master 브랜치로 rebase를 하도록 명령어를 실행 시킨다.

$ git branch
  dev-1
  dev-2
* master

$ git checkout dev-1
$ git rebase master

Cap 2014-01-25 14-21-04-841



여기서 rebase의 특징이 나오게 된다. Git은 변경 이력을 모두 비교하면서 병합을 시도 하기 때문에 위와 같이 conflict가 발생하는 것을 알려주고 처리 방법을 제안 한다.

123456789
<<<<<<< HEAD
987654321
192837465
Number content.
=======
Number content!!!
>>>>>>> 마침표를 느낌표 3개로 변경

저는 아래와 같이 수정하여 conflict를 해결하고 stage 영역에 올려놓고(add) 다음 rebase를 진행 한다.

123456789
987654321
192837465
Number content!!!


$ git add number.txt
$ git rebase --continue

다음 리비전에서의 conflict도 위와 동일한 방법으로 해결하고 계속 rebase를 진행 한다.

$ git add number.txt
$ git rebase --continue


$ git rebase --skip

Cap 2014-01-25 14-32-27-288
$ git checkout master
$ git merge dev-1

Cap 2014-01-25 14-32-56-525



dev-2 브랜치에 대해서도 위와 동일한 방법으로 master 브랜치에 rebase 한다.

$ git checkout dev-2
Switched to branch 'dev-2'

$ git rebase master


$ git add number.txt

$ git rebase --continue


$ git add number.txt
$ git rebase --continue
Applying: 더 자세한 내용 정의 문장으로 수정


$ git checkout master
Switched to branch 'master'


$ git merge dev-2
Updating bad6d94..258c855
Fast-forward
number.txt | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

Cap 2014-01-25 14-39-35-832

이제 필요 없어진 dev-1과 dev-2 브랜치는 삭제 한다.

$ git branch -d dev-1 dev-2
Deleted branch dev-1 (was bad6d94).
Deleted branch dev-2 (was 258c855).

Cap 2014-01-25 14-40-00-703

위에서 각각 해 본 rebase와 merge는 결과는 같지만 보여지는 커밋 트리들의 차이가 있는 것을 알 수 있다.

2014년 1월 12일 일요일

Git 기본 명령어 정리와 참고하면 좋은 링크 정보

오후 5:01 Posted by jonnung No comments
 작년에 처음 Github를 알게 되면서 Git을 배워볼 기회가 있었다.
개인적으로 진행하는 스터디에 활용을 해보기는 했으나, 당시 회사에서 사용하는 버전관리 프로그램으로 SVN에서 머큐리얼(Mercurial)로 전환하는 시기였다.
그러다 보니 머큐리얼도 학습하게 되었고, 사용하게 되면서 당연히 Git보다는 머큐리얼을 사용하는 비중이 높아졌다.

 하지만 시간이 흐르면서 Github에서 소스 코드를 검색하고, 참고하는 빈도가 증가하는 것을 느끼게 되었다.
 그러면서 드는 생각이 올해는 내가 만든 소스 코드들을 Github에 올려서 전세계 개발자들과 공유하고, 평가 받으며(관심을 끌 수만 있다면..) 핵심적으로는 내가 열정을 갖고 진행하는 것들에 대한 증거를 남기고 싶다는 목표가 생기게 되었다.
 그래서 올 한해 계획을 세우면서 가장 먼저 배우고 능숙하게 다뤄야 하는 기술로 Git을 선정했고, 이번 포스트에서는 Git을 사용하기 위한 기본적인 명령어를 정리해 보았다.

 기본적인 명령어에 대한 구성은 웹 상에서 Git의 기본적인 명령어를 직접 실행해보고, 사용 방법을 배울 수 있는 Code School의 Try Git의 각 단계를 참고 하였다.

 각 명령어에 대한 설명은 Try Git에서 나오는 설명들을 기초로 하였고, 나름 번역을 해보았다.
 Git을 처음 접하는 사람들은 이 포스트를 보는 것 만으로 Git을 사용하기에는 많이 부족할 것이지만 Try Git을 단계별로 학습하면서 참고하면 좋을 것 같다.

Git의 고급 테크닉을 조금 더 능숙하게 다루기 위한 정보를 하나 더 추가 하자면 Git 브랜치 배우기를 추천한다.
Try Git에서 다루지 않지만 Git에서 좋다고 소문난 Rebase와 Cherry pick에 대한 학습에 많은 도움이 되었다.




tryGit

Initializing


Initialize a Git repository

Git 저장소를 생성 한다.

git init


Checking the status


To see what the current state of our project

현재 상태를 확인 한다.

git status


Adding Changes


Notice how Git says 'untracked?' That means Git sees that this is a new file.
추적 되지 않은 새로운 파일이 있다는 의미 한다.

To tell Git to start tracking chang
es made to this file. we first need to add it to the staging area by using git add
파일의 변경 내역을 추적하기 위해 Git의 준비 영역으로 파일을 추가 할 필요가 있다.

git add octocat.txt
git add '*.txt'

Committing All Changes

Notice how Git says 'changes to be committed?' The file listed here are in the Staging Area, and they are not in our repository yet. We could add or remove files from the stage before we store them in the repository.
 git status 명령어로 현재 상태를 확인하면 'changes to be committed'라는 부분을 볼 수 있다.

 여기에 해당하는 파일 리스트는 아직 Git 저장소의 준비 영역에 있는 파일들의 목록이고, 저장소로 보내기 전에 준비 영역에서 추가 하거나 삭제 할 수 있다.

To store our staged changes we run the commit command with a message describing what we've chaged.
준비 영역에서 변경 내역을 저장소로 저장하기 위해서는 남길 메세지와 함께 commit 명령어를 사용한다.

git commit -m "Add cute octocat story"

History

Git's log as a journal that remembers all the changes we've committed so far, in the order we commited them.
Git 로그는 커밋 된 모든 변경 사항에 대한 기록 이다.

git log

Remote Repositories

To push our local repo to the GitHub server we'll need to add a remote repository.
로컬 저장소의 변경 내역을 Github 서버에 push 하기 위해서는 원격 저장소(중앙 저장소)를 추가 해야 한다.

git remote add origin https://github.com/try-git/try_git.git

Pushing Remotely

The push command our local changes to our origin repo (on Github)
push 명령어는 로컬 변경 내역을 origin 이라고 지정한 중앙 저장소로 보낸다.

The name of our remote is origin and the default local branch name is master.
origin은 원격(중앙) 저장소의 이름(닉네임 정도)이고, 기본 로컬 브랜치의 이름은 master 이다.

The '-u' thel Git to remember the parameters, so that next time we can simply run git push and Git will know what to do.
'-u' 파라미터를 추가하면 다음 push 명령어 실행부터는 중앙 저장소와 로컬 브랜치의 이름을 입력하지 않고도 push 할 수 있다.

git push -u origin master

Pulling Remotely

We can check for changes on our Github repository and pull down any new changes.
Github 서버의 변경 내역이 있는지 확인하기 위해서 pull 명령어를 사용해 새로운 변경 사항을 가져온다.

git pull origin master

Differences

Let's take a look at what is different from our last commit by using the git diff command.
로컬 저장소의 최종 커밋 로그와 차이점을 살펴보기 위해서 diff 명령어를 사용 한다.

In this case we want the diff of our most recent commit, which we can refer to using the HEAD pointer
가장 최근의 변경 내역을 비교하려면 HEAD 포인터를 사용해서 조회 할 수 있다.
git diff HEAD

Staged Differences

Another great use for diff is looking at changes within files that have already been staged.
diff는 이미 준비 영역에 있는 변경 내역과의 비교하기에도 좋다.

Staged files are files we have told git that are ready to committed.
준비 영역의 파일은 커밋 되기를 전의 파일을 말한다.

git diff --staged

Resetting the Stage

Unstage files by using the git reset command.
준비 영역의 파일을 삭제하려면 reset 명령어를 사용한다.

git reset octofamily/octodog.txt


브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌린다. 이러한 관점에서 '히스토리를 고쳐쓴다.'라고 할 수 있다. 이것은 마치 애초에 커밋을 하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것과 같다.

git reset HEAD~1

Undo

Files can be changed back to how they were at the last commit by using the command: git checkout -- <target>
마지막 커밋 된 파일로 교체하기 위해서 checkout 명령어를 사용한다.

git checkout -- octocat.txt


위 명령은 로컬의 변경 내용을 변경 전 상태(HEAD)로 돌려놓는다. 하지만 이미 준비 영역에 추가된 변경 내용과 새로 생성한 파일은 그대로 남는다.

Branching out

Code make separate commits to. Then when they're done they can merge this branch back into their main master branch.
새로운 코드는 새로운 브랜치에 커밋을 할 수 있다. 브랜치는 특정 커밋에 대한 참조(Reference)이며, 그 코드가 완료가 되면 다시 master 브랜치와 병합 할 수 있다.

Create a branch call.
branch는 새로운 브랜치를 만들기 위한 명령어 이다.

git branch clean_up

Delete a branch

branch를 삭제하려면 -d 파라미터를 추가하고 브랜치명을 입력 한다.

git branch -d clean_up

Switching Branches

다른 브랜치로 변경 하려면 checkout 명령어와 브랜치명을 같이 입력한다.

git checkout clean_up
git checkout -b clean_up

Removing all the things

Not only remove the actual files from disk, but will also stage the removal of the files for us.
rm은 준비 영역의 파일을 삭제 할 뿐만 아니라 실제 개발자 컴퓨터에 있는 파일도 삭제 된다.

removed all files you'll need to commit your changes.
파일을 삭제한 변경 내역도 커밋해야 한다.

git rm octodog.txt
git rm '*.txt'

Preparing to Merge

The moment has come when you have to merge your changes from the clean_up branch into the master branch.
별도 브랜치의 변경 내역으로부터 master 브랜치로 병합할 때가 오면 merge 명령어를 사용한다.

git merge clean_up

Rebase

브랜치끼리 작업을 접목하는 방법으로 rebase가 있다. 리베이는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳으로 떨궈 놓는 것이다.

리베이스를 하면 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점이 있다.

git rebase master

Revert

각자의 컴퓨터에서 작업하는 로컬 브랜치의 경우 reset을 잘 쓸 수 있지만, '히스토리를 고쳐쓴다'는 점 때문에 다른 사람이 작업하는 원격 브랜치에는 쓸 수 없다.

변경 내역을 되돌리고, 되돌린 내용을 다른 사람들과 공유하기 위해서는 revert를 사용해야 한다.

git revert HEAD

Push

All that's left to do is to push everything you've been working on to your remote repository.
모든 것이 완료 되면 원격(중앙) 저장소로 push 한다.

git push




참고하면 좋은 정보

http://rogerdudler.github.io/git-guide/index.ko.html
http://git-scm.com/book/ko
http://marklodato.github.io/visual-git-guide/index-ko.html