[Groovy] INDY(InvokeDynamic) 버전 사용하기

InvokeDynamic 자체가 좀 어렵다.

http://docs.oracle.com/javase/7/docs/technotes/guides/vm/multiple-language-support.html#invokedynamic

골자는 자바7에 이 기능이 추가됐고 이걸 잘 사용하면 JVM 기반의 동적 언어 시스템에 필요한 컴파일러와 런타임 구현체를 개선할 수 있다는데… 그냥 쓰면 좋다. 정도로 넘어가야겠다.

기존 JDK instruction 중에 invokevirtual에 상반되는 invokedynamic이라는 걸 추가했고 그걸로 동적 언어 구현체를 만들 수 있는 기능인가보다. 이걸 사용해서 구현하면 JVM 기반 동적 언어 컴파일러나 런타임 구현이 좀 더 간편하고 성능도 개선할 수 있고.

좀 더 깊게파려면 dynamic call site, bootstrap 등이 뭔 말인지 이해해야겠지만 뭔 말인지 모르겠다.

A dynamic call site is originally in an unlinked state, which means that there is no method specified for the call site to invoke

정의를 봐도 모르니 이해할 방법이 없다. 패쓰.

http://groovy.codehaus.org/InvokeDynamic+support

여기 잘 설명이 되어이는데 대충 이런 내용이다. 그루비 2.0 부터는 JVM의 invokedynamic 이라는 instruction을 지원하는 기능을 추가했단다. 그런데 이 instruction은 Java 7부터 지원되는 거라서 당근 JDK 1.7 이후부터 사용할 수 있다.

그렇다고 자바 7 쓰고 있으면 기본으로 쓰는건 아니고 groovy-x-y-x-indy.jar 처럼 맨 뒤에 indy가 붙은 jar 파일들을 사용해야지 invokedynamic으로 구현된 라이브러리를 사용할 수 있다.

indy 파일들은 그루비가 설치된 디렉토리/indy라는 곳에 들어있다. 그루비쉘 등에서 기본으로 사용하는 라이브러리는 그루비 홈/lib에 들어있는데 여기 들어있는건 당근.. 뭘까? indy가 아니라 normal이다.

그래서 이걸 굳이 indy 버전으로 쓰고 싶은 나같은 JDK 7 이상 버전 사용자들은 다음과 같은 쉘을 “그루비 홈”에서 실행해주면 한방에 lib 디렉토리에 들어있는 jar 들을 indy로 바꿔준다.

for f in `ls lib/groovy*.jar | cut -d/ -f2`;do k=`basename $f .jar`; mv lib/$k.jar lib/$k.jar.old; cp indy/$k-indy.jar lib/$k.jar ; done

파일이 한두개가 아니라서 수작업으로 indy에 있는걸 옮기지말고 그냥 위에 스크립트 복사해서 실행하는게 좋다.

그리고 사용자가 작성한 그루비 스크립트도 컴파일 할 대 invokedynamic을 사용하도록 컴파일 하려면 indy 옵션을 줘야 한다는데 옵션을 어떻게 줘야 하는지 예제가 없네.

http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.compile.GroovyCompileOptions.html#N1BA24

그래들로 그루비 컴파일 옵션 주는 방법은 여기있는데.. 보통 IDE에 세팅해놓고 쓰는게 좋을텐데 흠.. 어디없나. 모르겠다 패쓰!

[Groovy] 설치하기

http://groovy.codehaus.org/Download#Download-GVMtheGroovyenVironmentManager

오 이 설치 방법 좋네. 아주 깔끔하게 잘 되는구만!!

GVM 홈피는 잘 검색이 안되네. http://gvmtool.net/

git 도 좀 이런식으로 설치 하게 해주면 좋겠는데, 뭔 맨날 rpm 패키지 다운 받아서 어쩌고 저쩌고 아주 귀찮아~

설치 끝.

[생활코딩] 아침에 갑자기 생각난김에 yes24 api server 만들기

어제 저녁 이동국님과 토비님을 만나서 이런 저런 얘길 하다보니 자연스래 책 얘기에 빠졌다. 그러다가 서로의 판매지수와 순위를 이야기하며 이런 정보를 push 받고 싶다는 이야기가 나왔고, 토비님이 “생활코딩좀 해~”라고 하시길래.. 번뜩…

그래 예스24에서 API 서버 안만들어주면 그냥 HTML 긁어서 내가 서버를 만들어도 되겠구나… 이 서버 정보 조회해서 푸쉬하는건 따로 만들고.

아침에 일어났는데 다행히 어젯밤 대화가 기억났고, 12시반까지 광화문으로 가야하는 일정에 맞추려면 남은 시간은 대략 4시간. 그런데 이걸 어쩌나 서연이가 일어났다. 스프링 세팅하기는 귀찮고 play 처럼 명령어 하나만 치면 스캐폴딩을 다 만들어주는 뭔가가 있음 좋겠지만 플레이로 만들기는 죽어도 싫고.

그래서 그레일즈 선택! 했으나.. 지금와서 생각해보니 왜 노드.js를 기억하지 못했나 아쉽. 하지만 그레일즈 재밌었다. 짧은 시간이었지만 플레이보다 100배 좋다고 감히 말할 수 있다.

어쨌든 모니터 80%는 서연이한테 호비와 트니트니를 틀어주고 난 20% 구석에서 그레일즈 어떻게 쓰는지와 HTTP Client 찾기 시작해서 슬슬 대충 HTML 조회 끝. 이제 정규식으로 필요한 부분만 긁으면 되는데 기억이 잘 안나서 윤군한테 물어봤지만 왠지 복잡하게 푸는것 같아서. 그냥 자바 정규식 검색해서 글좀 봤더니 의외로 엄청 단순하게 해결.

이제 다 만들었으니 배포를 해야겠는데… 이제는 서은이가 일어났다.

서연이는 어린이집으로 데려다 주러 유진이가 데리고 나가고 나는 서은이 안고서 서버 세팅 시작. 자바는 다행히 지난번에 깔아놨고, 톰캣, 그레일즈, Git 설치 시작. Git 설치가 젤 힘들었다. yum 기본 저장소엔 왜 git이 없는거야.. 아 귀찮게 rpm 설치하고 어쩌고..

아무튼 서은이 안고서 서버 세팅 거의다 맞추니까 유진이가 돌아왔다.

서은이 얼른 안기고 배포까지 끝내고 구플에 자랑글 하나 올리고 난 이제 나가야겠다.

https://github.com/keesun/yes24-api-server

막 짠거라서 예외처리나 테스트 그런거 모르겠다.

아 재밌었다!!!

http://nullpe.com/yes24-api-server-0.1/book/info?id=8069226

yes24에서 관심있는 책 id만 바꿔가면서 조회해보면 된다.

끝!

[Play] 테스트 로그도 영…

이런 테스트 코드 실행했을 때 아래와 같은 에러가 났다면 대체 13줄이 문제라는거야 14줄이 문제라는거야…

도통 알수가 없어… 왜 라인수를 알갈쳐주는거야… 장난 치는거야 지금? 이게 어디서 났는지 찾아봐라? 머 그런거야? 지금 나랑 한번 해보자는거지? 재미없으니까 테스트 assert  실패한곳 라인수 찍어놔.. 당장 찍어 내라고!!!

[Git/JGit] PullRequest 구현하기

코드를 주고 받는 방법엔 크게 두가지가 있는것 같다. 프로깃이라는 책에서도 두가지를 설명하는데 하나는 고전적인 방법으로 패치 파일을 주고 받을 수 있겠고, 나머지 하난 상대방 브랜치를 merge하거나 rebase하는 식으로 코드를 직접 합치는 방법이 있겠다.

나는 후자를 선택했는데 그전까진 패치 파일 주고 받는 방법을 미처 생각하지 못했었고, pull request가 주는 어감때문에도 왠지 “코드 가져가라는 요청”이니까 merge로 코드를 받아가면 되겠군? 이라고 생각해서 이쪽으로 발상을 한것 같다.

암튼, 그래서 어떻게 하기로 했냐면.. 요청 보내는 쪽에서 가져갈 브랜치가 그 브랜치에 있는 코드를 어느 브랜치에 보낼지 선택하게하고 무슨 코드를 보낸다고 대충 적는다.

그럼 서버에 데이터가 하나 저장되는데 그게 PullRequest라는 도메인으로 저장된다. 그 안에는 어떤 Project(역시 도메인)에서 어떤 Project로 어떤 Branch에서 어디로 보내는지 누가 보내는지 누가 받았는지 등의 정보를 가지고 있다.

그럼 코드를 받는 프로젝트의 “코드 주고받기”라는 메뉴에 가보면 열려있는 풀리퀘 메뉴쪽에 하나가 표시되고 거길 열어보면 누군가 요청 보낸걸 볼 수 있다.

거기서 클릭해서 들어가면 이제 두가지를 할 수 있는데.. 하나는 “수락” 하나는 “거절”.

“수락”을 하면 다음과 같은 일이 발생한다.

일단 Git 저장소는 전부 bare모드로 만들어져있기 때문에 Git  저장소에서 직접 브랜치를 옮기거나 checkout을 받는다거나 하는 작업을 할 수 없다. 그래서 요청을 받아줄 프로젝트의 저장소를 bare모드가 아닌 non-bare 모드로 clone을 한다. 다음으로 ‘요청 받을 브랜치’와 ‘요청 보낸 브랜치’를 두개 만들고 각각을 ‘요청 보내온 저장소’와 ‘요청 받아줄 저장소’의 브랜치에서 fetch 해온다. 그런다음 ‘요청 받을 브랜치의 코드를 받아온 브랜치’로 이동해서 ‘요청 보내온 브랜치의 코드를 받아온 브랜치’의 코드를 머지 한다.

머지가 잘 되면 요청 받을 프로젝트의 브랜치로 ‘요청 받을 브랜치의 코드를 받아와서 요청 보낸 브랜치의 코드를 받아온 브랜치와 머지한 코드’를 푸쉬한다.

이렇게하면 풀리퀘가 된다. 그리고 머지 커밋이 항상 남도록 하려면 merge할때 NO_FF 옵션을 주면 된다.

이제부터 다듬기로, 머지하기 전에 머지가 잘되는지 확인해보고(사실 확인이라기보다 그냥 한번 해보면 되는데.. 암튼) 미리 머지가 잘 될 상황인지 아닌지 알려줄 수 있겠고, 잘 안되는 상황이면 직접 콘솔로 머지하고 컨플릭트 해결하라고 안내해 줄 수 있겠다.

그리고 풀리퀘를 만들어 보낼 시점에도 위와 같이 머지가 잘 되는 상황인지 체크해서 알려줄 수 있겠다. 어디서 하는게 좋을지 생각해 봤는데 어차피 보내느 시점과 받는 시점 사이에 받는 브랜치의 코드가 바뀌면서 처음 보낼 땐 머지가 잘 될것 같아도 나중에 안된느 시점이 있을 수 있으니까 그냥 두번 다 해주는게 좋을 것 같다고 결정했다.

그 다음 다듬기로는 풀리퀘가 어떤 커밋을 보내는 건지 커밋 목록과 브랜치 간의 파일 DIff 정보를 보여주는건데.. 후자는 금방 찾았는데 브랜치간에 차이나는 커밋 목록 만드는게 생각처럼 쉽게 안찾아진다. git show-branch와 비슷한 명령어가 jgit에 없는것 같다. 어떻게 해야할런지.. 흠… 좀 더 고민하거나 팀원에게 도움을 받아야겠다.

갈 길이 멀지만… 일단 포크/풀리퀘 구현은 가능하단걸 알았으니까 끝.