Wednesday, November 14, 2012

git 을 이용한 branching & merging



마스터 브랜치에서 개별 작업(iss53)을 하기 위해 새로운 브랜치를 생성하고 커밋.


git checkout -b iss53
git commit


중간에 다른 hotfix 요청이 들어오면 또다른 브랜치를 생성하고 커밋.


git checkout -b hotfix
git commit


이제 hotfix 를 마스터에 머지하고, 해당 브랜치를 삭제


git checkout master
git merge hotfix
git checkout -d hotfix


iss53을 다시 불러와 작업

git checkout iss53
git commit


iss53을 마스터에 머지하고, 브랜치 삭제

git checkout master
git merge iss53
git checkout -d iss53

Tuesday, September 20, 2011

Closure의 namespace 관리 : provide() , require()

JavaScript 에서 namespace를 만드는 방법

1) API 에 prefix 를 다는 방법
간단하지만 라이브러리가 복잡해지면 골치아픈 방법.

GM_log(), GM_getValue(), ..

2) 하나의 global object 를 정의하고 여기에 함수를 붙여가는 방법
체계적이고 충돌의 여지가 적다는 장점이 있지만, 매번 오브젝트를 뒤지므로 오버헤드가 있고, 타이핑이 길어지는 단점이 있음.

var goog={};
goog.array = {};
goog.array.binarySearch = function( ... );

Closure는 두번째 방식을 이용. closure compiler는 최적화를 하므로 오버헤드의 문제는 해결된다.

goog.provide(namespace) : namespace 정의

com.dopanysoft.Object 라는 오브젝트를 정의한다고 할때. goog.provide() 를 호출하면 여기서 정의된 오브젝트가 필요시 생성됨. 즉 Java에서의 패키지와 같은 개념으로 활용 가능. (자바처럼 디렉토리 구조가 일치해야 할 필요는 없음)

goog.provide("com.dopanysoft");
com.dopanysoft.Object = function() {...};

goog.require(namespace) : namespace 호출

myobject.js 라는 파일에서 goog.provide("com.dopanysoft")를 정의했다고 하면.
나중에 "com.dopanysoft" 를 어떻게 찾아야 할까? javascript 는 java와 달리 패키지 개념도 없고 말이지.
여기서 goog.addDependency()가 등장한다. (http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html 참고)

goog.addDependency() 는 goog.require() 에서 지정된 namespace를 담고 있는 javascript 파일의 경로를 지정해주고, 이렇게 지정된 javascript 파일들은 해당 goog.require() 가 호출된 script 의 뒷부분에서 <script>로 추가된다.
말이 좀 어려운데..
http://code.google.com/closure/library/docs/gettingstarted.html 에서 나온 예제를 예로 들자면, 다음과 같이 정의된 스크립트를

<script src="closure-library/closure/goog/base.js"></script>
<script>
  goog.require('goog.dom');
</script>
<script>
  var newHeader = goog.dom.createDom('h1');
</script>

이렇게 대치한다고 생각하면 될듯.

<script src="closure-library/closure/goog/base.js"></script>
<script src="closure-library/closure/goog/dom/dom.js"></script>
<script>
  var newHeader = goog.dom.createDom('h1');
</script>


closure api의 addDependency() 는 closure library에 포함되어 있는데,
"com.dopansoft" 와 같이 사용자가 만든 패키지의 namespace를 분석해서 addDependency()를 호출해주는 deps.js 코드 생성 툴이 바로 DepsWriter.

Tuesday, September 13, 2011

Closure 설치 및 설정

closure library , templates, compiler, inspector 다운로드 및 설치 방법 정리

mkdir ~/closure
cd ~/closure
svn co http://closure-library.googlecode.com/svn/trunk/ closure-library

cd ~/closure
svn co http://closuretemplates.googlecode.com/svn/trunk/ closure-templates
cd ~/closure/closure-templates
ant SoyToJsSrcCompiler
( result :  ~/closure/closure-templates/build/SoyToJsSrcCompiler.jar)

cd ~/closure
svn co http://closure-compiler.googlecode.com/svn/trunc/ closure-compiler
cd ~/closure/closure-compiler/
ant jar
( result : ~/closure/closure-compiler/build/compiler.jar )

http://code.google.com/closure/compiler/docs/inspector.html

Friday, May 6, 2011

PER, PBR 조회 서비스 오픈

작년 12월경에 증권거래소의 투자지표를 스크래핑하는 방법에 대한 글을 포스팅한 적이 있는데요.

이를 서비스화해서 만들어 봤습니다 :

http://bit.ly/pbrper

google appengine 기반으로 서비스를 만들었고요, jquery와 jqueryui를 이용해서 UI를 만들었습니다. 개인적으로 자바스크립트나 UI 쪽은 그닥 재능이 없는 데다가 만들다 말기를 여러번 반복해서.. 코드가 상당히 스파게티 스럽습니다.


어쨌건 오픈했으니 이용자나 요구사항이 폭주하지 않는 한.. 이대로 놔두고 다른 취미 생활이나 할까 합니다.
노후 대비로 개발이나 할까 했으나, 이런 간단한 서비스를 만드는 데도 신경써야 할 게 여간 많지 않은 것으로 봐서는.. 농장이나 알아봐야 겠습니다.

Monday, March 28, 2011

google appengine url fetch 제약사항

mechanize로 네이버 로그인하기 에서 카페글 쓰기 때문에 고생하고 있다는 얘기를 썼었는데.. 결론부터 얘기하자면 헛고생이었습니다...
문제는, 카페에 로그인한 뒤 카페글 읽는 것이 firefox에서는 제대로 되는데 appengine에서는 제대로 동작하지 않는다는 것.

문제 해결을 위해 다음과 같이 진행했습니다.
1. firefox 의 javascript를 disable
2. firefox plug-in HttpFox를 이용해 request header와 response header를 한줄한줄 비교.
3. mechanize로 한줄한줄 작성하고 결과를 비교
4. appengine 으로 옮기고 실행

문제는, 1~3까지는 정상적으로 동작을 하는데 appengine으로 코드를 옮기기만 하면 에러가 난다는 것. 사실 에러까지는 아니고, IP가 틀리게 나와서 로그인을 다시해야 한다는 둥..의 메시지가 나옵니다.

이 문제로 며칠동안 삽질을 했었는데, 원인을 따라가다 보니 문제는 Host 헤더에 있는 것으로 보입니다. 즉, 카페글을 읽으려면 Host:cafe.naver.com 으로 표시가 되고, 실제로 mechanize에서도 해당 헤더를 포함시키면 정상동작합니다.
문제는 appengine에서는 보안 문제로 Host 헤더의 수정을 허용하지 않는다는 점입니다.

이 문제를 해결하자면, appengine이 아닌 다른 서버를 이용하거나, 네이버 검색글 읽기 같은 꽁수를 이용하는 방법이 있을텐데.. 개인적으로는 그만큼의 여력이나 의지가 있지 아니하여 그냥 이정도 선에서 정리했습니다.

결론은 네이버 카페글 스크래핑 포기.

Monday, March 21, 2011

mechanize로 네이버 로그인하기

네이버 웹스크래핑을 하던 중, 네이버에 로그인할 일이 생겼습니다.
그런데 제대로 동작하지를 않더군요. 검색을 해보니, 동일한 문제를 겪고 있는 분이 있었습니다:
mechanize를 이용해서 네이버 로그인을 시도하

문제는 mechanize가 javascript를 지원하지 않기 때문에 발생한 겁니다.
즉, 로그인을 시도하면 다음과 같은 코드가 내려오는데:

<html>
<script language=javascript>
location.replace("http://www.naver.com");
</script>
</html>


해당 코드는 http://www.naver.com으로 이동시키는 명령입니다. 하지만 javascript를 지원하지 않는 mechanize는 이를 처리하지 못하기 때문에.. open() 을 사용해서 직접 열어줘야 합니다.

즉 아래와 같이 하면 됩니다(위 링크에서는 직접 데이터를 날렸는데, 저는 form field에 직접 값을 채운 뒤 submit하는 코드로 작성했습니다).:

browser = mechanize.Browser(factory=mechanize.RobustFactory())
browser.set_handle_robots(False)

browser.open('https://nid.naver.com/nidlogin.login?url=http://naver.com/이동할 페이지 주소')
browser.select_form(name="frmNIDLogin")
browser["id"] = '네이버 ID'
browser['pw'] = '패스워드'
browser.submit() # (A) 이제 로그인이 되었습니다.

browser.open(http://naver.com/이동할 페이지 주소') # (B)애초에 가고자 했던 페이지로 이동

이렇게 하더라도, 카페글을 읽으려면 여전히 험난한데요. 이에 대해서는 조금더 연구해보고 글을 올려보도록 하지요.