this.addListener('appear', function (e) { // 현재 로딩이 완료되어 나타난 상태

});


this.addListener('mousewheel', function (e) { // 마우스 휠 이벤트

    console.log(e.getWheelDelta());  // + 휠업, - 휠다운

});


마우스

mousemove : 1,

      mouseover : 1,

      mouseout : 1,

      mousedown : 1,

      mouseup : 1,

      click : 1,

      dblclick : 1,

      contextmenu : 1,

      mousewheel : 1


// 찾은 핸들러 이벤트 

문서 

"complete" : 완료

"loaded" : 

"success":

"fail":

"error":

"readystatechange":


Animation

"animate" : statics.animate,

"fadeIn" : statics.fadeIn,

"fadeOut" : statics.fadeOut,

"play" : statics.play,

"pause" : statics.pause,

"stop" : statics.stop,

"isEnded" : statics.isEnded,

"isPlaying" : statics.isPlaying


"setup" : 시작 "finish" : 끝


IFrame, Script

"uninitialized" : 1,

"loading"       : 2,

"loaded"        : 2,

"interactive"   : 3,

"complete"      : 4


프로그래스바

"complete" : 완료

"change" : 변경

원문 : http://hbr.org/tip/2012/04/26/3-ways-to-handle-a-colleague-you-dislike
 
싫어하는 동료를 다루는 3가지 방법

어려운 사람과 일하는 것은 미칠  같고 심신을 지치게 만든다다음에 동료가 끝없이 귀찮게 한다면 다음 3가지 방법을 시도해보라: 

·         반응을 관리하라. 만약 누가 그대를  견디게 한다면 사람에게 신경을 꺼라대신일반적으로 제어할  있는 유일한것인 당신의 반응을 주목하라.

·         속으로 표현하라. 감정은 전염되기 쉽다따라서 동료에 대해 불평을 한다면 모두가 기분이 가라 앉을 것이다그리고 너에게도 부정적으로 영향을 미칠 것이다만약 분노를 표출하려면사무실 밖으로 나가서 하라.

·         함께 일하라. 이상하게 들리겠지만함께 시간을 보낼수록 동료를 공감할  있다아마도 그의 행동의 이유를 찾을 수도 있을 것이다가정불화상사의 압박.

    하기” 에서by Amy Gallo.

웹 에디터

http://www.coderun.com/ide/

 


Google Code 에서 이제 CodeMirror 자바스크립트 에디터를 적용해, 웹브라우저 상에서 직접 코드 수정이 가능하게 되었습니다 http://j.mp/idozTS , CodeMirror 는 코드편집용 온라인 에디터 자바스크립트 라이브러리로 JS/CSS/파이썬/루아/C# 등 다양한 언어 컬러링/들여쓰기를 지원합니다. http://CodeMirror.net


아이패드 사파리에서 현재 웹사이트의 소스를 쉽게 보기 위한 북마클릿 http://j.mp/gD3ayi 아이패드용 웹 페이지 개발할때 유용하겠네요


TestFlight -- 아이폰 앱 베타테스트를 손쉽게! IPA업로드하고 이메일 적으면 배포완료. 업데이트 역시 Over-The-Air 로 가능한 웹 서비스. 개발자에겐 무료 http://j.mp/hkmyCs , 기존 아이폰 앱 베타테스트는 UDID를 적고 업데이트할 때 마다 재 배포 하는 작업이 귀찮았는데, 이걸 더욱 편하게 만들어줍니다


Wire It -- 웹에서 와이어링을 가능하게 해주는 오픈소스 자바스크립트 라이브러리. 데이터플로우,비주얼 프로그래밍,그래픽 모델링등에 사용 http://j.mp/f0PyJK 야후Pipes의 에디터를 똑같이 만들수 있겠네요.


Appcelerator vs. Phonegap vs. Adobe Air Mobile 3가지 크로스 플랫폼 개발툴 비교표 http://j.mp/gqt2xN


http://MediaQueri.es -- 다양한 해상도/디바이스를 지원하는 Responsive 웹 디자인이 적용된 사이트들 모음. 올해는 타블렛때문에 이 Responsive Design 이 대세가 될 겁니다. 꼭꼭 참고하시고 사이트 개발시 적용해보세요. Handcrafted Pixels http://j.mp/fPhmWP , 같은 사이트도 있습니다. 데스크탑에서 접속해서 브라우저 사이즈를 조정해보시거나 스마트폰에서 접속해 보세요


크로스 브라우징 가능한 HTML5 Form 개발 방법 http://j.mp/hDN61l


Fake it ’til you make it http://j.mp/g8E5Va 네이티브앱처럼 느껴지는 모바일 웹앱 만들기. 정리가 잘된 슬라이드네요 총 82페이지


Beyond the Mobile Web http://j.mp/evkVa2 모바일과 웹에 대해 멋진 인사이트를 담고 있는 총 132페이지 짜리 초강력 추천 슬라이드.


Rare Javascript Operators http://j.mp/i7OIhV 잘 안쓰는 자바스크립트 오퍼레이터들을 설명하는 슬라이드. 꽤 재미있네요. ~(틸데),get과set,콤마,==와===의 퍼포먼스 차이


개발자/디자이너가 알아야 할 50가지 http://j.mp/jEOyGY , 글의 원 제목은 ‘Graphic Design Student 가 알아야 할 50가지’ 입니다만, 꼭 그래픽 디자인 뿐만 아니라 개발자들에게도 적용되는 리스트입니다. 정말 좋은 리스트 업.


320 and up -- 작은 사이즈의 모바일 화면을 위한 Bolierplate http://j.mp/kChpGn 여기저기서 얘기되는 Mobile First! 전략과 딱 맞는군요


MSDN 블로그에 올라온 jQuery Mobile 강좌 http://j.mp/fBJuPs , MS 블로그에 모바일웹기술, 그것도 크롬 브라우저를 활용한 강의가 올라온 것이 이채롭습니다. jQuery Mobile 에 관련해서는 KTH 기술연구소 웹 플랫폼랩 장동수 ( @iolothebard ) /김민태 ( @ibare ) 두분 차장님이 이 글 쓴 친구보다 훨씬 더 잘 알고 계시니 편하게 물어보시면 됩니다. 두분 다 jQueryMobile 에 관련해서는 외부 강의를 뛸 수준의 실력자들 이십니다 ;)


폼 기반 웹사이트 인증에 관한 완벽 가이드 로그인 정보 기억하기/패스워드 암호화해서 저장하기 등.. 여러가지 이슈를 하나하나 설명한 스택오버플로우의 좋은 질문 답변 포스트 // http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication


링크드인의 새 아이폰앱은 HTML5를 이용한 하이브리드 방식 모바일서버쪽은 전체 Node.JS로 구성. 모바일웹/iOS/안드로이드 가 소스를 공유. 멋진 하이브리드사례가 하나 더 나왔군요 // http://venturebeat.com/2011/08/16/linkedin-node/


CodeAcademy -- 온라인으로 코딩하며 자바스크립트 프로그래밍 배우기. 아직 초급강좌만 있지만 내용이 많아지면 쓸만할 듯 // http://www.codecademy.com/#!/exercises/0


WebAPI -- 모질라가 만드는 Device API. 댓글에서도 말이 많은데.. API만 봐서는 이게 W3C DAP 이랑 WAC 이랑 뭐가 다른건지 잘 모르겠군요 // http://hacks.mozilla.org/2011/08/introducing-webapi/


jQuery Scroll Path 마우스 또는 키보드로 스크롤할때 커스텀 경로를 지정해서 스크롤할수 있게 해주는 플러그인. 데모 필감. // http://joelb.me/scrollpath/


Codiqa -- jQueryMobile 을 이용한 Rapid Prototyping 툴. 드래그앤 드랍으로 후다닥 모바일웹앱 UI를 구성가능// http://codiqa.com/


Javascript Pattern Collection 여기저기서 공유되었던 다양한 JS 패턴들을 한자리에 모은 페이지 // http://shichuan.github.com/javascript-patterns/


Java로 만들어진 RESTful 웹서비스를 Node.js 로 포팅한 이야기 벤치마크부분이 재미있네요. 리소스 사용은 확실히 node 쪽이 적은듯 // http://www.ziggytech.net/technology/web-development/experiences-with-node-js-porting-a-restful-service-written-in-java/


내 앱이 죽었어요, 어떡해야 하죠 ? iOS 개발자들을 위한 버그잡기 팁들을 순차적으로 깔끔하게 정리. 파트1이니 후속편도 기대됩니다 // http://www.raywenderlich.com/10209/my-app-crashed-now-what-part-1


URI.js -- URL을 jQuery처럼 핸들링하는 자바스크립트 라이브러리 // http://medialize.github.com/URI.js/


Backbone.js 를 이용해 싱글 페이지 웹앱 만들기 API가 잘 갖춰진 서비스라면 고려해볼만한 시도 // http://blog.sendhub.com/post/19349219519/single-page-web-apps-with-backbone-js


HTML5 기반 웹 슬라이드 제작 툴킷 모음 22종이나 되는군요. 누군가 비교표를 만들어주길 기다려야 할듯 // http://www.impressivewebs.com/html-slidedeck-toolkits/


Hacker News 모바일웹앱 개발기 http://t.co/t9n0zC2q 아이폰 네이티브앱과 거의 같은 느낌을 주기위해 프레임웍을 사용하지 않고 직접 개발한 내용들을 잘 정리했네요. 모바일웹앱 만드시는분들 필독


iOS 앱의 퍼포먼스 향상 팁 by Pulse 팀 http://t.co/rwgDqTOQ 이미지압축/NOOperationQueues 와 GCD활용/불필요한 이미지 캐슁 하지 않기


SQL.js -- C소스인 SQLite를 Emscripten을 이용하여 JS로 컴파일한 라이브러리. 이제 정말 혹시나 차후에 WebSQL 지원이 끊긴다고 해도, 현재의 소스를 그대로 활용할 방안이 생긴걸까요? ㅎㅎ 재미난 세상입니다. // http://cheeaun.com/blog/2012/03/how-i-built-hacker-news-mobile-web-app


Morris.js -- 타임시리즈 그래프를 쉽게 그리기 위한 경량 JS라이브러리. jQuery & Raphae"l 사용. 모바일도 잘 지원해서 통계툴 만들때 좋겠군요 // http://oesmith.github.com/morris.js/


NameBench -- 인터넷 접속환경에 따라 가장 빠른 DNS서버를 찾아주는 벤치마크툴. 약 4500개의 서버를 테스트. 구글의 20% 프로젝트를 통해 시작되었다고.. // http://code.google.com/p/namebench/


웹&모바일용 UI Kit 모음 Get Your Kits: Fresh Web and Mobile UI Kits, Wireframe Kits and PSD’s  Get Your Kits: Fresh Web and Mobile UI Kits, Wireframe Kits and PSD’s Page 2 // http://www.noupe.com/design/get-your-kits-fresh-web-and-mobile-ui-kits-wireframe-kits-and-psds.html // http://mgmt.noupe.com/get-your-kits-fresh-web-and-mobile-ui-kits-wireframe-kits-and-psds-page-2


Effective Scala -- 트위터가 공개한 Scala 개발가이드 ( Best Practices 모음 ) 스칼라는 트위터의 메인개발 언어중 하나입니다. 한국어로 정리된 Scala 시작가이드 도 참고하세요. // http://twitter.github.com/effectivescala/ // http://ppassa.wordpress.com/2012/02/19/getting_started_scala/


웹개발자와 관리자를 위한 캐슁 튜토리얼 -- HTTP 상의 헤더/메타태그를 이용한 캐쉬방법들을 총 정리한 문서. // http://www.mnot.net/cache_docs/


자바스크립트 메타 프로그래밍 고차원 프로그래밍인 메타프로그래밍에 대해서 예제들을 통해 설명해드립니다. // http://dev.paran.com/2012/02/16/javascript-meta-programming/


turn.js -- HTML5 로 만든 책넘김효과. iBooks의 그 책넘김효과를 자바스크립트로 만든 라이브러리. 스마트폰/태블릿에서도 꽤 부드럽게 실행됩니다 // http://turnjs.com/


Weave -- 누구나, 어떤 데이터라도 쉽게 시각화를 할수있는 것을 목표로 하는 웹기반의 Analysis & Visualization 플랫폼. 오픈소스(GPL/MPL) // http://www.oicweave.org/


Flotr2 -- HTML5 를 이용한 차트/그래프 라이브러리. Prototype에 의존성을 가진 Flotr에서 의존성을 제거하고 향상시킨 오픈소스. // http://humblesoftware.com/flotr2/


mitmproxy -- Path의 주소록업로딩 이슈를 발견하는데 사용되어 유명해진 SSL지원 가능한 man-in-the-middle HTTP Proxy. 모바일패킷 분석용으로 딱 // http://mitmproxy.org/


Ice -- 뉴욕타임스가 공개한 Integrated Content Editor 자바스크립트 라이브러리. 여러 사용자가 추가/삭제한 내용에 대해 트랙킹/하이라이팅 가능. 뉴스룸에서 파일롯 사용중이라고.. // https://github.com/NYTimes/ice/


Open-Advice 무료e북 공개. 총 308p “FOSS : 우리가 시작했을때부터 알았으면 좋았을 것들” 다양한 자유 소프트웨어 프로젝트의 멤버들이 공유한 42개의 이야기와 레슨들 // http://open-advice.org/


조직내에 새로운 프로그래밍 언어를 소개하면서 배운 교훈들 Lessons Learned while Introducing a New Programming Language 새 언어를 도입하려고 하는 회사가 있다면 읽어보면 좋을듯. 여기서는 Java 기반의 회사에서 Clojure를 도입했네요 // http://blog.jayfields.com/2012/01/lessons-learned-while-introducing-new.html


Raphae"l JS 로 만든 벡터 아이콘 182종 확대해도 보기좋고, 각종 효과를 주기에도 좋군요. MIT 라이선스 // http://raphaeljs.com/icons/


모든 워드프레스 사이트에 써야할 필수 Snippet 7종 // http://wp-snippets.com/articles/7-code-snippets-you-should-use-on-every-site/


현재 프로그래머블웹에 등록된 스토리지 API 가 총 76가지 레드오션이라고 볼수도 있고, 어떤 포지셔닝이냐에 따라 블루오션을 찾을수도 있을것 // http://blog.programmableweb.com/2012/01/31/76-storage-apis-box-net-amazon-s3-dropbox/


Android Strict Mode 활용 가이드 안드로이드 개발시 Strict Mode는 옵션이 아닌 필수사항입니다. 앱의 성능개선을 위해 꼭 사용해보세요! // http://dev.paran.com/2012/01/31/android-strict-mode-howto/


The Edge of HTML5 HTML5 관련 최신 기술변경사항들을 정리한 슬라이드. 올해 1월까지의 사항들이네요. //

http://html5-demos.appspot.com/static/html5-therealbleedingedge/template/index.html#1


What’s New in HTML5 Media HTML5 미디어 관련 기술 최신정리 슬라이드. Media Capture / Web RTC / Web Audio API // http://kinlan-presentations.appspot.com/sfmediahtml/template/index.html#1


자바스크립트 어플리케이션 스케일링하기 세개의 비디오 세션. “중소규모 앱을 위한 아키텍쳐/모듈라코드 작성하기/대규모 개발을 위한 패턴들”// http://addyosmani.com/scalable-javascript-videos/


ShareJS -- 전 구글웨이브 엔지니어가 만든 실시간 멀티유저 협업 편집가능한 서버와 라이브러리. 라이브위키등 사용처가 정말 많을 듯 합니다. // http://sharejs.org/


자바스크립트에서 읽을수 있는 각종 파일 포맷 용 라이브러리 링크 모음  PNG/JPG/GIF/BMP/SVG/WebP/Flash/PDF/HTML/Audio/MP3/Java/PSD/Zip // https://github.com/bebraw/jswiki/wiki/File-Formats


Welcome to the Jungle 무어의 법칙은 끝났다! 하드웨어 발전방향을 빼곡히 짚은 초 강추 포스트. 또한 이와 연결해서 지금 소프트웨어 개발자들은 어떤 것에 주목해야 하는가 부분을 꼭 읽어두세요. // http://herbsutter.com/welcome-to-the-jungle/


JSDev -- 더글라스 크록포드옹이 개발하신 자바스크립트 개발용 도구. 실제 코드에 영향 없도록 코멘트에 넣은것을 실행가능한 형태로 바꿔주는 프리프로세싱 방식 // https://plus.google.com/118095276221607585885/posts/CTZ7BNx7a8z


Resumable.js -- HTML5 파일 API와 자바스크립트로 구현된 안정적이고 끊어졌다가도 이어서 전송 가능한 다중 파일 업로드 라이브러리. FF 4+ 와 크롬 11+ 에서 사용가능 // https://github.com/23/resumable.js


Client-Side 템플릿엔진 18종 비교 15항목 비교로 최종4개 구글클로저/Mustache/Handlebars/dust.js 를 뽑고 링크드인이 자신들 엔진으로 선정한건 dust.js // http://engineering.linkedin.com/frontend/client-side-templating-throwdown-mustache-handlebars-dustjs-and-more


http://html5please.us/ -- 현재 HTML5 의 특정 기능들을 써야할지, 말아야 할지, 사용하되 조심해야 할지, Polyfill 로 써야할지를 알려주는 사이트. 깔끔하군요


자바스크립트 MVC 프레임워크 탑10 리뷰 UI 바인딩/뷰 조합/웹 프리젠테이션 레이어/호환성 등 4개주요 피쳐로 비교하여 장단점 정리. 이 친구의 최종선택은 Ember.js // http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/


The Power Of Open 개방과 공유가 가지는 힘에 대한 이야기들. 많은 분들이 한글화에 참여해 주셨네요. PDF로 다운로드 가능합니다. // http://tpookorea.tistory.com/category/DOWNLOADS


Funf -- MIT가 공개한 안드로이드용 오픈소스 센싱 프레임웍. 모바일기기의 모든 센서정보(30+개의 Probe들)를 계속적으로 저장해서 트래킹&분석 가능 // http://funf.media.mit.edu/


Share에 대해 한번 정리해 봅시다 + 여담 게이오대 법학부 4학년 @d_ringo 님의 슬라이드를 @5wlim 님이 깔끔하게 번역정리! 공유(Share)에 대한 멋진 자료. 공유에 대한 개념을 알고, 실제 어떤 서비스들로 형상화 되는지까지 알아볼 수 있는 자료입니다. // http://sangwooklim.blogspot.com/2012/01/share.html


Sencha의 HTML5 위시리스트 2012 HTML Media구현 / HTML5 audio 품질향상 / 향상된 오프라인 캐슁 / Web Intents / Web GL / IndexedDB / 기기별 적절한 이미지 사이징 / Contacts API / 백그라운드서비스 / 향상된 모바일 브라우저 디버깅. http://www.sencha.com/blog/sencha-the-2012-html5-wishlist


directCanvas -- AppMobi의 HTML5 가속 SDK. iOS지원,안드로이드도 나올예정. HTML5 게임을 위해 캔바스 가속 및 멀티채널 사운드를 지원. 거의 10배정도의 속도라고 // http://www.appmobi.com/?q=node/226


#2011결산 -- 게임의 흐름을 바꾼 20개의 HTML5 사이트들 웹 개발자 분들께서는 꼭 보셔야 할 사이트들 // http://www.netmagazine.com/features/2011-review-20-html5-sites-changed-game


24시간만에 자바스크립트만으로 VNC 클라이언트 짜기 Node.js , Socket.io , HTML5 Canvas 조합. 오픈소스. 링크드인 인턴이 핵데이때 개발 // http://engineering.linkedin.com/javascript/vncjs-how-build-javascript-vnc-client-24-hour-hackday


Server-Side Javascript Injection (PDF) SQL인젝션과 비슷하게 NoSQL 과 Node.JS를 공격하는 방법과 이에 대한 방어법에 대한 글 // t.co/35TrYAPy

이 글은 HTML5 로 아이폰 앱 만들기 라는 제목으로 월간 W.e.b. 에 연재하는 글에서 발췌한 것입니다. ( 잡지에 기고한 글이라 원래 제 블로그의 글과 어투가 다릅니다. )

이 글 전에 먼저 “HTML5 API 강좌 #1 – Web Storage 와 Application Cache” , “HTML5 API 강좌 #2 – Web SQL Database 와 GeoLocation” 글을 읽어보시기 바랍니다.

지난글 까지 HTML5 API 중 Mobile Web App 을 만드는데 중요한 API 들을 살펴보았다. 이번 회에서는 아이폰에서 Web App 을 만드는 방법을 배워보고, 이전 회에서 만든 CheckList App 을 아이폰 웹 앱으로 바꿔보자.

아이폰 Web App 개발하기

현재 Mobile Web App 을 가장 잘 지원하는 것은 아이폰이다. 국내에 출시되지 않았던 아이폰 OS의 1.0 버전 때에는 App Store 가 없었기에 애플 측에서 Web App 의 사용을 권장했었기 때문이고, 아이폰 OS 2.0 버전부터 App Store 가 런칭 되면서 사용용도가 많이 줄기는 했지만, 아직도 애플 웹사이트의 Web App Directory ( http://www.apple.com/webapps )에는 약 5천개 정도의 Web App 들이 등록되어 있다. 현재도 계속 새로운 WebApp 들이 개발되고 추가되고 있으며, iPad의 출시와 함께 큰 화면에서 사용 가능한 웹 앱들도 개발되고 있다. 아이폰 상에서 어떻게 HTML5 Mobile Web App 을 만드는지를 알아보자.

iPhone 환경에서의 Web App 지원

먼저, iPhone 환경에서는 데스크탑용 웹 브라우저와 달리 사이트에 접근하는 방식이 차이가 있기 때문에 특이한 사항이 몇 개 있다. HTML5 지원과는 조금 다른 얘기이지만, HTML5 를 이용한 Mobile Web Application 을 만든다면 꼭 알아둬야 것 중의 하나다.

아이폰 사파리는 웹 사이트에 대해 “홈 화면에 추가 ( Add to Home Screen )” 이라는 기능을 제공한다. 사파리 브라우저에서 맨 아래 + 버튼을 누르면 “책갈피추가 / 홈 화면에 추가” 선택팝업이 뜨고, 이를 통해 아이폰 메인화면에 웹 사이트에 대한 바로가기 기능을 추가 할 수 있다. ( iOS 4.2 에서는 + 버튼에 Print 기능이 추가되면서 화살표 같은 형태로 아이콘이 바뀌었다. )

iPhone WebAppiphone WebApp 2

iPhone WebApp 3iphone webapp 4

추가된 아이콘은 일반 앱과 같은 형태이며, 삭제하는 방식도 똑같다. 클릭하면 바로 모바일 사파리가 실행되면서 해당 웹사이트로 이동하는 URL 바로가기 형태로 보면 된다. 이것은 데스크탑 크롬 웹브라우저의 “웹 애플리케이션 바로가기 만들기” , Mozilla 의 Prism ( Firefox 에선 확장기능으로 제공 ) 과 비슷한 기능이다.

안드로이드 에서도 비슷한 기능을 제공하긴 하지만 단계가 조금 복잡하다.

  1. 홈스크린에 추가하고자 하는 웹 페이지를 Bookmark 한다.
  2. 메뉴 버튼을 눌러서 Bookmarks 페이지로 간다.
  3. 홈스크린에 추가할 북마크를 길게 누른다.
  4. “Add to Home Screen” 을 선택하면 현재 페이지에 추가된다. (빈 공간이 있어야만 가능)

원하는 페이지에 직접 추가하려면 일단 웹페이지를 먼저 북마크 한후 홈스크린으로 간다.

  1. 추가할 홈스크린으로 가서 빈 공간을 길게 누른다.
  2. 나온 “Add to Home Screen” 메뉴에서 Shortcuts > Bookmark 선택
  3. 원하는 북마크 선택

안드로이드의 Add to Home Screen 기능은 단지 북마크를 화면에 추가하는 것일 뿐 추가적인 기능은 제공하지 않는다. 하지만 아이폰 사파리에서 웹 페이지에 대해 이렇게 + 를 눌러 “홈 화면에 추가”후 실행하면 iPhone 에서는 Mobile Web App 으로 동작하게 된다. 이때 Web App 의 지원을 위해 모바일 사파리는 몇 가지 태그를 지원한다.

모바일 웹 앱 개발자는 head 섹션에 아래의 4가지 태그를 추가할 수 있다.

1
2
3
4
<link rel="apple-touch-icon" href="/apple-touch-icon.png"/>
<link rel="apple-touch-startup-image" href="/startup.png">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

각각은 다음과 같은 기능을 지원한다.

  1. <link rel=”apple-touch-icon” href=”/apple-touch-icon.png”/ >

    등록되는 웹 사이트의 아이콘을 지정할 수 있다. apple-touch-icon.png 가 기본 이름

    일반적으로 아이폰에서 웹사이트 아이콘을 추가하게 되면 웹사이트 화면을 캡쳐한 내용을 아이콘으로 사용하는데 apple-touch-icon 이라는 링크를 추가하여 아이콘을 내가 지정한 것으로 사용할 수 있다. favicon 의 아이폰 버전이라고 생각하면 된다.

    아이폰은 57×57 , 아이패드는 72×72, 아이폰4는 114×114 사이즈의 png 이미지를 사용한다. 가능하면 114×114 이미지로 만들어두면 아이폰에서 자동으로 크기 리사이즈를 한다.

    이 아이콘은 기본적으로 아이폰이 제공하는 UI 처리 ( 모서리를 둥글게 하고 반원형의 밝은 부분을 추가해 주는 것) 가 된다. 원하지 않을 때는 rel 속성의 값을 apple-touch-icon-precomposed 라는 이름으로 지정하여 사용하면 된다.

    <link rel=”apple-touch-icon-precomposed” href=”/apple-touch-icon-precomposed.png”/>

    → 이렇게 지정한 precomposed 아이콘 이미지는 안드로이드의 Add to Home Screen 기능에서도 지원된다. 사이즈는 48×48 이다.

  2. <link rel=”apple-touch-startup-image” href=”/startup.png”>

    화면이 로딩될 때 스타트업 이미지를 지정할 수 있다. Web App 이지만 앱 처음 로딩시 로고화면 같은걸 보여줄 수 있다. 아이폰 기본 앱에 들어있는 Default.png 와 비슷한 역할이다.

    단, 이미지의 크기가 정확히 맞아야 한다. 아이폰은 320×460 , 아이폰4는 640×920 , 아이패드는 768×1004 로 정확히 맞춰야만 제대로 화면에 표시된다.

  3. <meta name=”apple-mobile-web-app-capable” content=”yes” />

    Web App으로 선언하여 브라우저의 UI ( URL 바 ) 를 안 보이도록 할 수 있다.

    즉, Web App 이 마치 일반 Native App 처럼 화면 전체 ( 최상단 상태바 20px 제외) 를 활용할 수 있도록 한다.

  4. <meta name=”apple-mobile-web-app-status-bar-style” content=”black” />

    상태바의 색상을 지정할수 있다. 바탕화면이 검정색인 어플리케이션의 경우 상태바만 회색인 이질감을 줄이기 위해 사용한다.

    3가지 스타일 : default (회색) , black , black-translucent ( 반투명 )

이렇게 4가지 기능을 지원함으로써 HTML5 기반의 Local 또는 Online Web Application 들이 마치 Native App 처럼 실행하는 효과를 지원할 수 있다.

아이폰 개발 환경 꾸미기

Web App 은 아이폰 Native App 과 달리 개발환경으로 꼭 Mac을 필요로 하지 않는다. 기존의 웹 개발 할때와 마찬가지로 손에 익은 툴을 이용하여 개발할 수 있다. 아이폰 상에서의 동작 화면을 테스트하기 위해서는 맥의 개발환경인 XCode 에 포함된 iPhone Simulator 가 테스트용으로 아주 적절하지만, Mac 사용자가 아니라면 사용이 어렵다. 또한 Web App 개발시 iPhone Simulator는 디버깅을 하는 용도로는 적합하지 않다.

Safari 의 개발자 도구 활용하기

Webkit 기반의 브라우저 최신버전들에는 개발자 도구가 들어있다. 이를 활용해 보자

Safari 의 메뉴에서 편집->기본설정 또는 “ Ctrl + , “ 를 눌러서 설정창을 연다. 우측 끝 고급탭을 선택하여 맨 밑에 “메뉴 막대에서 개발자용 메뉴 보기” 를 활성화 한다.

사파리 개발자 메뉴 활성화 시키기

활성화 하면 아래와 같이 개발자용 메뉴가 추가된다. 이 개발자 도구는 같은 WebKit 기반인 Chrome 브라우저에도 비슷한 기능이 있지만, Safari 가 더 많은 기능을 가지고 있다.

사파리 개발자 메뉴

개발자용 메뉴중 주요 기능을 몇 개 살펴보자.

  1. 사용자 에이전트

    만들고 있는 웹 사이트를 iPhone / iPad 및 각 브라우저별로 어떻게 표시되는지를 테스트해보기 위해 UserAgent 를 쉽게 바꾸는 기능을 제공한다

    Safari User Agent

    Chrome 이나 Firefox 에서는 확장기능을 설치해야 가능했던 동작인데 기본으로 포함하고 있다. Mobile Safari 로 설정시 거의 아이폰 화면과 비슷한 화면을 보여주기 때문에 아이폰용 Web App 개발후 테스트시 아주 유용하다.

    실제로 아이폰/아이패드의 UserAgent 앞부분은 아래와 같다.

    Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543 Safari/419.3
    Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML,like Gecko) Version/4.0.4…
    

    즉, 각 웹페이지 개발시 아래와 같은 방법으로 현재 접속한 브라우저에 맞는 화면을 보여줄 수 있다.

    Javascript : if((navigator.userAgent.match(/iPhone/i)) { }
    PHP : if (strpos($_SERVER['HTTP_USER_AGENT'],'iPad') !== false) { }

    아래는 사파리 브라우저 사이즈를 아이폰과 비슷하게 맞춘후, UserAgent 를 iPhone 으로 설정하고, 아이폰용 UI 라이브러리인 jQTouch 데모 사이트를 불러온 화면 이다. 거의 비슷한 형태의 화면을 볼 수 있으며, Webkit 애니메이션들도 그대로 볼 수 있다. 아이폰용 Web App 을 만든다면 꼭 알고 있어야 할 필수 테스트 방법이다.

    jQtouch on Safari

  2. 웹 속성보기 – Web Inspector ( Ctrl – Alt – I , ⌥ – ⌘ – I )

    현재 웹 페이지의 상세 속성을 보는 창이다. 앞서 HTML5 API 를 설명할 때 잠깐 설명한 기능으로 조금 자세히 살펴보자.

    Safari Web Inspector

    • 요소 : 현재 페이지의 HTML 소스를 보여준다.
    • 리소스 : 현재 페이지에서 로딩한 리소스 파일들 ( CSS, JS , 이미지 등 ) 및 각 리소스의 로딩에 걸린시간을 보여준다.
    • 스크립트 : 현재 페이지내의 Javascript 소스를 확인하고 디버깅 할 수 있다.
    • 타임라인 : 리소스 로드/스크립트수행/렌더링 시간들의 타임라인을 볼 수 있다.
    • 프로파일 : 현재 페이지내의 스크립트가 CPU 자원을 얼마나 소모하는지 프로파일링
    • 스토리지 : Database , Local/Session Storage , Cookie 들을 일목요연하게 볼 수 있다.
    • 콘솔 : 에러 확인 및 자바스크립트 실행이 가능한 커맨드 라인 창

    마치 Firefox 에서의 Firebug 플러그인을 보는 것처럼 잘 만들어져 있다.

아이폰 브라우저 화면 & Viewport 알기

모바일 웹 개발시 브라우저의 화면에 대해 먼저 알아둘 필요가 있다. 아이폰/아이패드의 브라우저 화면에 대해 알아보자.

iPhone Viewport

아이폰/아이패드 공히 상단 20px 의 상태바와, 60px 의 URL 바 를 가지고 있다. 그리고, 실제 보이는 View Port는 아이폰의 경우 아무것도 지정안할 경우 980px 로 세팅되어있다. 즉 모바일웹에 대응안한 웹 사이트 접속시 980px 이내라면 축소되어서 한 화면에 보이도록 되어있다. 아이패드는 일반 웹브라우저와 같다.

만드는 모바일 웹앱이 화면에 정확하게 맞도록 하려면 위에 보이는 것처럼 태그를 이용하여 viewport 의 width 를 device-width로 맞추면 된다. 또한 사용자가 확대를 할 수 있도록 할지 말지를 user-scalable 로 조정이 가능하다. 일반적으로 사진확대가 필요한 페이지가 아니라면 no로 지정하면 웹 앱 사용시 터치하여 이동이 편하게 된다.

이 device-width viewport 옵션은 안드로이드에서도 동일하게 동작된다.

앞에서 태그에 대해 설명했다. 이 태그를 추가한 후에 Add to Home Screen 을 한 Web App 은 다시 실행했을 때 앞에서 말한 URL Bar 와 Button Bar 를 모두 제거하고 아래처럼 전체 화면인 320x460px 를 웹 앱에서 쓸 수 있다. ( 아이폰 4에서는 640x920px 로 정확히 가로세로 2배로 확대 되었다고 보면 된다. )

iphone web app viewport

이렇게 지정 했을 경우 URL Bar 가 아예 없어지기 때문에, 사용자는 현재 웹페이지만 사용가능하고 다른 페이지로 브라우징이 불가능하게 된다. 즉 독립된 앱 처럼 사용이 가능하다. 작성중인 Mobile Web App 이 다른 페이지로 갈 이유가 없는 앱이라면 이 방식으로 해주면 된다.

만약 개발중인 Web App 이 URL Bar 가 필요는 하지만, 화면에 꼭 보일 필요가 없다면 앞에 Meta 태그 대신 아래의 자바스크립트를 사용하여 자동으로 URL Bar 를 스크롤 시킬 수 있다.

window.addEventListener('load', function(){
    setTimeout(scrollTo, 0, 0, 1);
}, false);

CheckList 를 아이폰 앱으로 바꾸기

이전 회에서 만들었던 Checklist App 를 좀더 아이폰 앱 처럼 변경해보자. HTML 파일을 다음과 같이 변경한다.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html manifest="webapp.manifest">
<head>
 <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0"/>
 <meta name="apple-mobile-web-app-capable" content="yes" />
 <meta name="apple-mobile-web-app-status-bar-style" content="black" />
 <link rel="apple-touch-icon" href="iphone_icon.png"/>
 <link rel="apple-touch-startup-image" href="startup.png" />
 
<script src="app.js"></script>
<script>
    window.addEventListener('load', function(){
    setTimeout(scrollTo, 0, 0, 1);
   }, false);
</script>
 
 <title>Checklist WebApp ( Offline )</title>
</head>
<body>
<div id="checklist">
    <div id="add">
        New Check List <input type="text" id="description"/>
        <input type="button" value="Add" id="addbutton" onclick="newToDo();"/>
    </div>
    <div id="items">
    </div>

앞에서 본 viewport 및 meta 태그들을 모두 추가한다.

<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0"/>
Viewport 를 Device 크기에 맞게 고정하고, 스크롤이 불가능하게 설정한다.
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
Add To Home Screen 했을 경우, URL Bar 를 없애고, 상태바를 검은색으로 보이게 한다.
<link rel="apple-touch-icon" href="iphone_icon.png"/>
Add To Home Screen 할 때 보일 아이콘을 지정한다.
<link rel="apple-touch-startup-image" href="startup.png" />
Add To Home Screen 한 후에 실행시 보일 Start Up 이미지를 지정한다.
<script>
  window.addEventListener('load',
      function(){ setTimeout(scrollTo, 0, 0, 1);}
  , false);
</script>
기본으로 웹페이지가 보일시에도 자동으로 URL Bar 가 가려지도록 한다. 단, 이 코드는 아이템리스트가 화면크기보다 많을 경우, 즉 페이지가 아래로 스크롤이 가능할 때에만 자동으로 실행된다.

이렇게 모두 수정하고 iphone_icon.png 와 startup.png 를 같은 폴더에 업로드 한다. 실행화면은 다음과 같다.

iPhone Checklist WebApp 1

Add to Home Screen 할 때 위와같이 지정한 아이콘 이미지가 보인다.

iPhone Checklist WebApp 2

이렇게 추가된 아이콘으로 실행시 지정한 startup.png 이미지가 보이게 된다.

iPhone Checklist WebApp 3

실행하고 나면 위와 같이 URL 바가 모두 사라지고, 상태바만 남은 형태로 사용할 수 있게 된다.

이렇게 해서 모바일 Web App 를 아이폰에 맞는 형태로 만들어보았다. 다음 회에서는 터치기반의 모바일 UI 를 만들어 볼 것이다.


출처 : http://xguru.net/625

이 글은 HTML5 로 아이폰 앱 만들기 라는 제목으로 월간 W.e.b. 에 연재하는 글에서 발췌한 것입니다. ( 잡지에 기고한 글이라 원래 제 블로그의 글과 어투가 다릅니다. )

이 글 전에 먼저 “HTML5 API 강좌 #1 – Web Storage 와 Application Cache” 글을 읽어보시기 바랍니다.

지난 글에서는 모바일에서 HTML, CSS, JS 와 이미지파일을 캐슁할 수 있는 Application Cache 와 브라우저에 Key Value 값을 저장할 수 있는 Web Storage ( LocalStorage , Session Storage ) 를 사용하는 법을 배웠다. 이번 회에서는 데이터베이스 형식을 사용하여 좀 더 다양한 데이터를 저장할 수 있는 Web SQL Database 와 GeoLocation API 의 사용방법을 알아보자

Web SQL Database – http://dev.w3.org/html5/webdatabase/

이름에서 의미하듯이 Web SQL Database 는 클라이언트인 웹 브라우저에 Database 엔진을 심어서, 로컬에서 자바스크립트로 사용할 수 있도록 하는 것이다. 즉 예전에는 Database는 웹 서버 뒷 단에서 구조화된 데이터를 저장하고 웹 서버에서 이를 조회하여 페이지 구성 후 브라우저에서 불러다 보여주는 용도로만 사용했는데, 이제는 클라이언트(브라우저) 에도 이런 데이터를 저장할 수 있게 된 것이다. 이는 Offline 기능 지원 및 속도향상을 위해 다양하게 사용될 수 있다.

Web SQL Database의 실제 구현에는 SQLite 데이터베이스를 사용하고 있다. SQLite는 소스가 완전 공개된 Public Domain 오픈 소스 ( 소스코드를 가져다 마음대로 수정해서 사용해도 되고 상용으로 써도 아무런 문제가 없다 ) 로 iPhone OS 및 Android OS 에서도 기본 데이터베이스 형식으로 사용되고 있으며 간단한 Embedded Database를 구현할 때 많이 사용되는 오픈소스이다.

이를 이용해서 개발자는 브라우저 내에 테이블을 구성하고 데이터를 추가/수정/삭제할 수 있으며, 안정성을 보장하기 위해 일련의 작업을 하나의 논리적 작업으로 그룹화 해주는 트랜잭션 메커니즘까지도 지원된다.

현재 Webkit 기반 브라우저 (Safari, Chrome 및 iPhone, Android 의 브라우저) 에서는 이 Web SQL Database 를 지원하고 있지만, Firefox 및 IE 에서는 지원이 안되고 있다. 이것은 현재 HTML5 스펙을 작성하고 있는 W3C 에서 SQLite에 종속적인 SQL 언어기반의 Database 기술을 사용하는것이 웹 개발 형식과는 잘 맞지 않아서, 이 대신 B-Tree 기반의 key/value 저장소인 IndexedDB를 지원하는 것으로 가닥을 잡고 있기 때문이다. 즉 현재 모바일 브라우저들은 다 지원을 하기는 하지만, 실제 HTML5 표준스펙에서는 빠질 것으로 보인다. 하지만 현재로선 Firefox 4 베타버전을 제외한 모든 데스크탑/모바일 브라우저에서는 IndexedDB 지원이 불가능한 상태 이기 때문에, 지금은 모바일 웹 앱 개발시 Web SQL Database를 지원하도록 작성하고, 차후에 IndexedDB 지원이 완벽해지면 그때 다시 수정을 하는 방식으로 개발을 진행하는 방법이 좋을 것이다.

( 참고로 IndexedDB 의 오픈소스 구현체는 http://code.google.com/p/indexeddb/ 에서 받아서 사용해 볼수 있다. )

Web SQL Database 의 가장 중요한 메소드는 아래 3가지 이다.

  • openDatabase : 데이터 베이스 열기
  • transaction : 트랜잭션 시작
  • executeSql: SQL 문장 실행

각 함수를 좀더 자세히 살펴보도록 하자. 각 함수의 선언부에서 { } 는 생략이 가능한 인자를 의미한다.

Web SQL Database 는 스펙상 Asynchronous/Synchronous ( 비동기/동기 ) 두 가지 방식을 다 지원하지만, 현재 브라우저의 구현체들은 주로 Async 모델만을 지원한다. 즉 메소드의 리턴값으로는 적절한 객체나 결과를 얻을 수 없고, 콜백 함수를 메소드 인자로 전달하고 작업이 끝난 후 이 콜백 함수가 호출되는 형식으로 처리되어야 한다.

openDatabase

Database openDatabase(name, version, displayName, estimatedSize {, creationCallback } );

openDatabase 는 데이터베이스를 열거나 생성하는데 사용된다. 데이터베이스가 없다면 자동으로 생성된다. 이 메소드는 4개의 필수 인자와 1개의 옵션 인자를 가지고 있다.

  1. name : 데이터베이스 이름
  2. version : 버전 번호
  3. displayName : 데이터베이스 설명
  4. estimatedSize : 예상 크기
  5. { creationCallback : 생성후 호출될 콜백함수 }

버전번호는 약간 설명이 필요하다. 각 데이터 베이스는 버전번호를 가질 수 있는데, 개발자는 이 버전번호를 통해 데이터베이스의 스키마 변경 등의 작업을 지정할 수 있다. 단, 각 버전이 따로 존재 하는 것이 아니라, 항상 DB는 한 개의 버전만을 가질 수 있다. ( 실제로는 openDatabase 를 호출할 때 이 version 이 필수인자이기 때문에, DB 버전 업데이트를 자동으로 처리하기가 좀 곤란하다. 보통은 한 개의 버전번호를 고정적으로 붙여서 데이터베이스 오픈은 항상 가능하게 한 뒤, 내부에 관리자용 테이블을 만들어 데이터베이스의 스키마 버전번호를 저장하거나 하는 방식을 사용하기도 한다. )

예상크기는 데이터베이스의 크기를 결정하는 것으로, 일반적으로 브라우저 구현에 따르지만 기본값은 5MB로 되어있다. 예상크기가 5MB 보다 작다면 아무것도 묻지 않고 그냥 생성된다. 처음부터 5MB 보다 큰 예상크기를 요청하면 아래처럼 브라우저가 displayName 을 이용하여 이 크기의 디스크 공간을 사용해도 되는지를 사용자에게 묻는다. ( 사파리 브라우저만 이 확인창이 보이며 크롬 브라우저에서는 묻지 않고 그냥 생성한다. )

201011171529.jpg

아이폰 ( 모바일 사파리 ) 에서도 똑같이 확인창이 뜨게 된다.

201011171530.jpg

위의 DB 생성을 시도한 코드는 동일한 것으로 다음과 같다.

var db = openDatabase(‘mydb’,1.0, ‘guru test db’, 10 * 1024 * 1024);

데스크탑용 사파리와 모바일 사파리 둘 다, 정확히 10MB 의 크기를 요청하였지만 실제 생성되는 디스크공간이 차이가 있다. 이것은 브라우저에 따라 구현상의 차이가 있기 때문이다. 주의할 점은 데스크탑용 사파리에선 500MB, 1GB 까지의 데이터베이스도 생성이 가능하지만, 아이폰의 경우는 50MB 가 넘어가는 크기를 요청할 시 에러가 나면서 openDatabase 가 null 을 리턴한다. 안드로이드의 경우는 확인창이 뜨지않아서 정확히 체크는 불가능하지만 아이폰과 비슷할 것이므로, 모바일 웹 앱 개발시에는 무조건 DB 사이즈를 50MB 이하로 활용하도록 한다. ( 안정적으로 하려면 10메가 이상은 안 쓰는 것이 좋다. 그리고, 이것은 모바일 브라우저의 스펙에 따라 언제라도 바뀔 수 있다. )

마지막의 옵션인자인 creationCallback 은 데이터베이스가 생성될 때 호출되는 함수이다. 처음 데이터베이스가 생성 되었을 때 꼭 실행되어야 할 테이블 생성 스크립트 같은걸 처리하면 된다.

transaction / readTransaction

void transaction(callback {, errorCallback, successCallback} );

void readTransaction(callback {, errorCallback, successCallback} );

Web SQL Database 는 트랜잭션 메커니즘을 제공한다. 하나의 트랜잭션 안에서 여러 개의 SQL 문장을 실행하다가 에러가 발생했을 시에 앞에 했던 동작들을 모두 없었던 것으로 처리함으로써, 복잡한 데이터베이스 작업 도중에 발생한 에러로 데이터베이스에 문제가 생기는걸 방지해 준다. 또한 errorCallback 과 successCallback 인자를 통해 트랜잭션 전체의 에러/성공 시에 호출될 콜백함수도 지정가능하다.

transaction 함수는 보통 아래 형태로 호출된다.

var db = openDatabase(‘mydb’,1.0, ‘guru test db’, 10 * 1024 * 1024);
 
db.transaction(function (tx) {
 
   // 트랜잭션 내부
 
   // 롤백을 위해 SQL 함수는 tx 객체를 이용한다.
 
})

그리고 readTransaction 함수는 transaction 과 호출방식은 똑같지만, 트랜잭션내부에서 데이터베이스 쓰기 동작은 불가능하고 오로지 읽기 동작만 가능한 트랜잭션을 만들어준다.

executeSql

void executeSql(sqlStatement {, arguments, callback, errorCallback } );

executeSql 은 실제로 SQL 문장을 실행하는 함수로 일반적으로 Transaction 을 사용할경우 아래와 같은 형태로 호출된다.

 
var db = openDatabase(‘mydb’,1.0, ‘guru test db’, 10 * 1024 * 1024);
 
db.transaction(function (tx) {
 
    tx.executeSql(‘CREATE TABLE test (id INTEGER PRIMARY KEY, content TEXT));
 
})

4개의 인자가 있는데, 뒤의 2개는 성공/실패시 콜백함수를 지정하는 인자이며, 2번째 인자인arguments 는 SQL 문장에 있는 ? 문자들을 치환한 변수들의 배열이다. 즉 일반적인 INSERT 문의 경우 다음처럼 사용된다.

 
tx.executeSql( ‘INSERT INTO test (id,content) VALUES( ?, ? ), [ id , contentStr ] );

SQL 문장을 + 와 같은 연산자를 이용한 스트링 연산으로 동적으로 만들 수도 있지만, SQL Injection 이라고 불리는 기법에 의해 해커의 표적이 되기 쉽다. 위와 같이 파라미터 치환자를 이용한 방식으로 하는 것이 훨씬 안전하다.

executeSql 의 3번째 인자인 Callback 에는 SQL 문장 실행후 transaction 객체와 Resultset 이 리턴된다.

 
tx.executeSql( ‘SELECT * FROM test’, [ ] , function ( tx, results) {
 
   for ( var i = 0 ; I < results.rows.length ; i++) {
 
      document.write(results.rows.item(i).id +-+ results.rows.item(i).content);
 
   }
 
} );

Resultset 은 insertId , rowsAffected, rows 3개의 속성을 가지고 있다. insertID에는 실행한 SQL 문장이 INSERT 문 일 경우에 추가된 데이터의 Row ID 가 리턴되며, 만약 여러 개의 행이 추가되었을경우엔 마지막 ID가 리턴된다. rowsAffected 는 실행한 SQL 문장이 UPDATE 문 일경우에 변경된 Row 수가 리턴된다. rows 는 SELECT 문장일 경우 선택된 데이터들이 item 배열로 리턴 ( 실제로는 배열이 아니다. item 은 getter 함수일 뿐이다 ) 되며 length 를 통해 데이터의 개수를 알 수 있다. 위의 예제에서 보는 것처럼, test 테이블의 id 와 content 필드를 item(i).id , item(i).content 와 같이 각 테이블의 컬럼 이름을 이용해서 직접 item 객체의 속성인 것처럼 꺼내서 사용할 수 있다.

Web SQL Database 는 openDatabase, transaction , executeSql 세개의 함수만으로 로컬 브라우저상에서 유용하게 사용할 수 있는 데이터베이스를 제공한다. 실제로 Gmail 의 모바일버전 사이트는 이 Web SQL Database 를 사용하여, Offline 시에도 Inbox 의 최근 메일들을 보거나, 새로운 메일 작성 등을 가능하게 하고 있다.

Web SQL Database 역시 이전회에서 살펴본 LocalStorage 처럼 Safari Browser 의 Web Inspector 나 크롬 브라우저의 Developer Tools 를 통해 테이블과 그 내용들을 확인할수 있다.

201011171532.jpg

Chrome : Ctrl+Shift+J (윈) 또는 Command+Option+J (맥) 을 눌러 Developer Tools 실행

Safari : Ctrl+Alt+I (윈) 또는 Command+Option+I (맥) 을 눌러 Web Inspector 실행

GeoLocation API

HTML5 의 API 중 모바일환경에서 가장 많이 사용되고 있는 API 는 GeoLocation API 이다. 최근의 스마트폰들이 대부분 GPS를 내장하고 있어서, 모바일 웹에서도 위치정보에 기반한 구글맵과 같은 다양한 웹 서비스들이 이용되고 있다. 실제로 GeoLocation API 는 구글에서 제안한 것으로 HTML5 표준이 아니라 Geolocation API 라는 다른 스펙에서 정의되고 있다.

GeoLocation API 는 3개의 메소드로 이루어져 있다.

 
void navigator.geolocation.getCurrentPosition ( successCallback , errorCallback, options );
 
long navigator.geolocation.watchPosition ( successCallback , errorCallback, options );
 
void clearWatch ( watchID )

브라우저상에서 위치정보를 얻는 방법은 2가지인데, 첫번째는 getCurrentPoisition 함수를 이용하여 한번만 얻어오는 것이고, watchPosition 은 브라우저(디바이스)가 판단하여 위치가 바뀌었을 때마다 계속적으로 콜백 함수를 불러주는 방법이다. 전자의 방법은 주로 현재 위치의 지도를 보여주거나 근처의 POI ( Places of Interest ) 들을 불러올 때 사용하며, 후자는 사용자가 움직인 거리들을 기록하거나 지도에서 계속적으로 위치를 바꾸면서 보여주고 싶을 때 사용한다.

보통은 다음과 같은 형태로 호출한다.

navigator.geolocation.getCurrentPosition( show_position , show_error ) ;

성공시에 호출되는 successCallback 함수는 다음과 같은 위치정보를 리턴한다.

 
function show_position ( position ) {
 
var lat = position.coords.latitude;
var lon = position.coords.longitude;
 
}

이 위도경도 값으로 지도 API 를 호출하면 된다. 실제로 coords 는 altitude ( 고도 ) , heading ( 방향 , 360도 ) , speed ( 속도 m/s ) 와 같은 몇 개의 속성을 더 가지고 있지만, 이것은 모바일 브라우저에 따라 지원될 수 도 있고 안될 수도 있다. ( 지원 된다고 해도 부정확할 수 있다 ) 위도 경도값은 꼭 GPS 정보 뿐만이 아니라 모바일 브라우저 구현에 따라 IP 주소, WiFi/블루투스의 MAC 주소, GSM/CDMA 의 셀타워 정보등으로부터 위치정보를 얻게 된다.

Web SQL Database 를 이용한 Offline 실행지원 어플리케이션 – CheckList

이제 앞에서 배운 Application Cache 와 Web SQL Database 를 활용해서 Offline 에서도 실행이 가능한 Application 을 만들어 보자. 만들어볼 CheckList Application 은 모바일에서 활용가능한 간단한 체크리스트이다.

  • Application Cache 적용을 위해 Manifest 를 지정한다.
  • Web SQL Database 를 이용하여 아이템을 저장한다.

* 이 예제는 http://www.berttimmermans.com/2009/02/checklist/ 의 CheckList Web Application을 좀 더 간략하게 만든 것이다.

먼저 Offline 에서도 실행 가능한 Web App 의 HTML 내용은 다음과 같다.

 
<!DOCTYPE html>
 
<html manifest=”webapp.manifest”>
 
<head>
 
<script src=”app.js”></script>
 
<title>Checklist WebApp ( Offline )</title>
 
</head>
 
<body>
<div id=”checklist”>
<div id=”add”>
 
New Check List 
<input type=”text” id=”description”/>
<input type=”button” value=”Add” id=”addbutton” onclick=”newToDo();”/>
</div>
<div id=”items”>
</div>
</div>
 
</body>
 
</html>

앞서 설명한대로 간단한 체크리스트를 Offline 에서 등록/관리 하는 Application 이다. 추가버튼만 있고 모든 아이템은 items 라는

div 에 표시되도록 되어있다. 주요 기능은 app.js 에 있다. app.js 를 살펴보자.

// BUILD DATABASE ———————————————————————
var db;
 
// 데이터베이스를 오픈한다. 사이즈는 넉넉히 20만바이트로 지정한다.
try {
 
    if (window.openDatabase) {
 
        db = openDatabase(“Checklist”,1.0, “HTML5 Database API”, 200000);
 
        if (!db)
 
        alert(“DB를여는데실패했습니다.버전이틀리거나이도메인에할당된공간이꽉찻기때문입니다”);
 
        else
 
        var highestId = 0;
 
    } else
 
    alert(“Web SQL Database가지원되지않는브라우저입니다.”);
 
} catch (err) {
 
}
 
function loaded() {
 
    // 페이지가 로드되면 테이블이 있는지 확인하여 없으면 새로 테이블을 생성한다.
    // 이미 생성한 경우라면 BuildList() 함수를 호출하여 리스트에 아이템을 채운다.
    db.transaction(function (tx) {
 
        tx.executeSql(“SELECT COUNT( * ) FROM ToDos”, [], function (result) {
 
            BuildList();
 
        }, function (tx, error) {
 
            tx.executeSql(“CREATE TABLE ToDos(id REAL UNIQUE, description TEXT, status REAL), [], function (result) {
 
                BuildList();
 
            });
 
        });
 
    });
 
}
 
// 페이지 로드후 이벤트에 등록한다.
addEventListener(‘load’, loaded, false);
 
// 새 아이템 입력 —————————————————————————————
 
function newToDo() {
 
    if (document.getElementById(‘description’).value != “”) {
 
        highestId++;
 
        var description = document.getElementById(‘description’).value;
 
        var status = 0;
 
        // INSERT 문으로 테이블에 새 아이템 추가
        db.transaction(function (tx) {
 
            tx.executeSql(“INSERT INTO ToDos(id, description, status) VALUES(+ highestId +, ‘” + description + ”’,+ status +), [],
 
            function (result) {
 
                document.getElementById(‘description’).value = “”;
 
                BuildList();
 
            }, function (tx, error) {
 
                alert(error);
 
            }
 
            );
 
        });
    }
 
}
 
// 아이템 삭제 —————————————————————————————
 
function deleteToDo(id) {
 
    // DELETE 문으로 테이블에서 아이템 삭제
    db.transaction(function (tx) {
 
        tx.executeSql(DELETE FROM ToDos WHERE id =+ id +;, [],
 
        function (result) {
 
            document.getElementById(id).style.display = “none”;
 
        }, function (tx, error) {
 
            alert(error);
 
        }
 
        );
 
    });
 
}
 
// CHANGE STATUS —————————————————————————————
 
function updateToDo(id, status) {
 
    if (status ==1) {
 
        status =0;
 
    } else {
 
        status =1;
 
    }
 
    // 해당 체크리스트 아이템을 수행했는지 안했는지를 체크한다. 체크한 아이템은 흐리게 만든다.
    db.transaction(function (tx) {
 
        tx.executeSql(“UPDATE ToDos SET status =+ status + ”WHERE id =+ id +;, [],
 
        function (result) {
 
            if (status ==1) {
 
                document.getElementById(id + ”box”).removeAttribute(“onclick”);
 
                var newfunction = document.createAttribute(“onclick”);
 
                newfunction.nodeValue = “updateToDo(+ id +,+ status +);
 
                document.getElementById(id + ”box”).setAttributeNode(newfunction);
 
                document.getElementById(id).style.opacity =0.2;
 
            }
 
            if (status ==0) {
 
                document.getElementById(id + ”box”).removeAttribute(“onclick”);
 
                var newfunction = document.createAttribute(“onclick”);
 
                newfunction.nodeValue = “updateToDo(+ id +,+ status +);
 
                document.getElementById(id + ”box”).setAttributeNode(newfunction);
 
                document.getElementById(id).style.opacity =1;
 
            }
 
        }, function (tx, error) {
 
            alert(error);
 
        }
 
        );
 
    });
 
}
 
// BUILD LIST —————————————————————————-
 
function BuildList() {
 
    // DB 에서 전체 체크리스트 아이템을 읽어온다.
    document.getElementById(‘items’).innerHTML = “”;
 
    db.transaction(function (tx) {
 
        tx.executeSql(“SELECT id, description, status FROM ToDos”, [], function (tx, result) {
 
            for (var i = 0; i < result.rows.length; ++i) {
 
                var row = result.rows.item(i);
 
                ToDo(row[‘id’], row[‘description’], row[status]);
 
                if (row[‘id’] > highestId)
 
                highestId = row[‘id’];
 
            }
 
        }, function (tx, error) {
 
            alert(‘DB에서아이템을읽어오는데실패했습니다 -+ error.message);
 
            return;
 
        });
 
    });
 
}
 
// TODO ————————————————————————————-
 
function ToDo(id, description, status) {
 
    // 각 아이템 등록
    var ToDoItem =< div id = ’” + id + “’class = ’part“;
 
    if (status == 1) {
 
        ToDoItem += ”done”;
 
    }
 
    ToDoItem += “’ > < input type = ’checkbox’”;
 
    if (status == 1) {
 
        ToDoItem += “checked = ’checked’”;
 
    }
 
    ToDoItem += ”onclick = ’updateToDo(+ id +,+ status +)’id = ’” + id + “box’class = ’checked’ / >;
 
    ToDoItem +=< span >+ description +< /span>;
 
ToDoItem +=<input type=’button’ value=Delete’ onclick=’deleteToDo(+ id +)class=’dbtn’ id=’Dbtn” + id + “’/ > < /div>
 
 “;
 
document.getElementById(‘items’).innerHTML = document.getElementById(‘items’).innerHTML + ToDoItem;
 
}

그리고, 오프라인 실행을 위해 webapp.manifest 를 만든다.

<blockquote>
 
CACHE MANIFEST
app.js
 
# 캐시를 선언한 index.html 은 자동으로 추가되므로 적지 않아도 된다.
 
# Version 20100905-054
</blockquote>

실행한 화면은 다음과 같다. 한번 온라인상태에서 로딩만 되면 오프라인시에도 동작된다.

201011171533.jpg 201011171533.jpg

우측의 화면은 아이폰을 Airplane 모드로 바꾸어서 오프라인에서도 동작하는지를 테스트해본 것이다.

현재 실행에 필요한 파일은 index.html 파일과 app.js 파일 2가지 밖에 없다. webapp.manifest 파일에 의해 index.html , app.js 두 개의 파일이 캐쉬되므로 webapp.manifest 파일이 수정되지 않는한 index.html 이나 app.js 의 수정내용이 변경되지 않는다는 것을 명심하자. 코드를 업데이트 하였다면 webapp.manifest 파일의 마지막 #주석문에 버전번호를 바꾸어주도록 하자.

다음 회에서는 아이폰용 Web App 을 만드는 방법에 대해 알아보자.


출처 : http://xguru.net/624

1.         기타 자료와 도구

Git 패키지에는 많은 뛰어난 도구들이 직접 포함돼있다.
하지만 Git apt-get이나 MacPorts 같은 패키지 관리자로 설치했다면, 이런 도구들을 별도로 설치해야 할 수도 있다.

 

gitk

gitk는 저장소 이력을 시각화하여 모든 브랜치가 어떻게 존재하고 있는지 보여준다.
gitk
Git 저장소의 이력을 탐색하기 위한 순수하게 Tcl/Tk로만 작성된 GUI로 발표되었다.

home 디렉터리의 .gitk 파일에 인터페이스를 자신에 맞게 변경하는 설정값을 추가할 수 있다.

11포인트 크기의 Panic Sans폰트를 사용하는 .gitk파일

set mainfont {{Panic Sans} 11}

set textfont {{Panic Sans} 11}

set uifont {{Panic Sans} 11 bold}

 

git-gui

git-gui: 저장소를 사용할 때 필요한 기본 명령어에 대한 인터페이스를 제공한다.

git-gui를 사용하여 추적되지 않는 파일이나, 변경된 파일, 스테이징된 파일을 볼 수 있으며, 변경 사항을 스테이징하거나 커밋할 수도 잇다.

 

gitweb Git 저장소에 대한 웹 클라이언트다.

gitweb은 저장소를 확인하는데 필요한 모든 기능을 웹 인터페이스로 제공한다.

 

GitX OS X 전용으로 개발된 gitk의 복제본이다.
OS X
애플리케이션 고유의 UI를 빼면 모든 기능이 동일하다
.
gitk
와 동일하게 한 번에 하나의 브랜치 혹은 여러 개의 브랜치를 동시에 확인할 수 있으며, 가장 최신 버전의 경우 git-gui처럼 커밋하는 기능도 포함한다.

 

Komodo IDE : ActiveState Git을 포함한 몇 종류의 분산 버전 관리 시스템을 Komodo IDE 5.0 릴리스에 통합하여 지원하기로 발표했다. Komodo는 스크립트 언어와 웹 개발에 특화된 통합 개발 환경이다.

 

이클립스 Git 플러그인 : www.eclipse.org/egit

 

TextMate Git 번들 : 스크립트 언어를 위한 놀라운 지원과 사용의 편리함으로 OS X을 사용하는 개발자들에게 인기 있는 편집기. gitorious.org/projects/git-tmbundle

 

VCSCommand : 편집기 Vim의 플러그인이다.
VCSCommand
.vimrc 파일에 추가된 몇 개의 단축키를 조합하면, 모든 플랫폼에서 프로그래밍 프로젝트를 대부분 시작할 수 있다.

 

GitNub : gitk와 비슷한 맥 전용 도구. 기본적인 이력 보기 기능을 제공하며, GitNub의 호스팅 서비스를 이용하고 있다면 GitHub의 타임라인 뷰어와 통합해서 사용할 수 있다.
github.com/Caged/gitnub

 

TicGit : 티켓 추적 시스템은 누가 무슨 일을 하고 있는지 추적한다. 기존의 티켓 추적 시스템을 도입하면 분산 도구 모음 속에서 중앙 집중식 시스템을 사용할 수 밖에 없게 된다.
TicGit
Git안에서 동작하는 간단한 분산 티켓 시스템으로 연결이 끊긴 분산 환경ㅇ르 유지하도록 해준다.

 

git-sh : Git명령어를 입력할 때 git을 입력하지 않아도 된다. 체크아웃을 할 때는 checkout, 커밋할 때는 commit만 입력하면 된다.

git-sh Git에 특화된 쉘을 실행하고 모든 Git 명령어에 대해 별칭을 생성한다.
또한 명령 프롬프트가 위치한 현재 저장소명과 브랜치명을 추가하면 현재 브랜치를 보려고 git branch를 입력할 필요가 없다.

 

 

 

2.         GitHub로 저장소 호스팅하기

직접 Git 서버를 운용하지 않을 때 사용할 만한, 저장소 호스팅 서비스가 몇 개 있다.

오픈 소스로만 사용이 가능한 서비스부터 상업적으로 이용 가능한 서비스까지 존재.

 

repo.or.cz : 오픈 소스 프로젝트를 위한 무료 Git 저장소를 제공.

GitHub : 오픈 소스 프로젝트에는 무료지만, GitHub를 이용하여 프로젝트를 관리하려는 회사가 비용을 지불하면, 사용할 수 있는 접근이 제한된 사설 호스팅도 사용할 수 있다.

Gitorious : 무료 Git 호스팅 서비스.

 

git.or.cz : Git과 관련된 모든 소스가 있는 Git의 주요 웹사이트.

Git 매뉴얼 : www.kernel.org/pub/software/scm/git/docs/

Git 메일링 리스트 : git@vger.kernel.org

#git IRC 채널

forums.pragprog.com/forums/64

 

 

 

출처: [인사이트]Git, 분산버전 관리시스템


출처 : http://youmin3.egloos.com/1991175

1.         Git 명령어 요약

1.1.        설정과 초기화

전역 사용자명/ 이메일 구성하기

$ git config --global user.name YOUR NAME

4 git config --global user.email YOU@EXAMPLE>COM

 

저장소 하나에 사용자명 / 이메일 구성하기

주의: 저장소마다 사용자명과 이메일 주소를 설정할 수 있다. 따라서 프로젝트마다 각각 다른 사용자명과 이메일 주소를 사용할 수 있다.

$ cd /path/to/repo

$ git config user.name YOUR NAME

$ git config user.email YOU@EXAMPLE.com

 

Git의 출력결과 색상 활성화하기

$ git config --global color.ui auto

 

새로운 저장소 초기화하기

$ mkdir /path/to/repo

$ cd /path/to/repo

$ git init

$ git add .

$ git commit m initial import

 

저장소 복제하기

$ git clone <저장소 url>

 

기존 디렉터리에 Git 추가하기

$ cd /path/to/existing/directory

$ git init

$ git add .

$ git commit m initial import of some project

 

새로운 원격 저장소 추가하기

저장소 디렉터리에서 실행한다

$ git remote add <원격 저장소> <저장소 url>

 

 

 

1.2.        기본적인 사용법

새로운 파일을 추가하거나 존재하는 파일 스테이징하고 커밋하기

$ git add <file>

$ git commit m <message>

 

파일의 일부를 스테이징하기

$ git add p [<file> [<file> [기타 파일들 ]]]

커밋하려는 헝크를 선택한다.

 

add 명령에서 Git 대화모드를 사용하여 파일 추가하기

$ git add i

 

수정되고 추적되는 파일의 변경 사항 스테이징하기

git add u [<경로> [<경로>]]

 

수정되고 추적되는 모든 파일의 변경 사항 커밋하기

$ git commit m <message>a

 

작업 트리의 변경 사항 돌려놓기

$ git checkout HEAD <file> [<file>]

 

커밋되지 않고 스테이징된 변경 사항 재설정하기

$ git reset HEAD <file> [<file>]

 

마지막 커밋 고치기

.. 변경하고 스테이징한다

$ git commit m <message>amend

 

이전 커밋을 수정하고 커밋 메시지를 재사용하기

$ git commit C HEAD --amend

 

 

 

1.3.        브랜치.

지역 브랜치 목록 보기

$ git branch

 

원격 브랜치 목록 보기

$ git branch r

 

지역과 원격을 포함한 모든 브랜치 목록 보기

$ git branch a

 

현재 브랜치에서 새로운 브랜치 생성하기

$ git branch <새로운 브랜치>

 

다른 브랜치 체크아웃하기

$ git checkout <branch>

 

현재 브랜치에서 새로운 브랜치 생성하고 체크아웃하기

git checkout b <새로운 브랜치>

 

다른 시작 지점에서 브랜치 생성하기

브랜치는 저장소 이력에 존재하는 어떤 위치에서도 생성될 수 있다.
브랜치를 생성할 위치는 다른 브랜치나 커밋명 혹은 태그가 될 수 있다.

$ git branch <새로운 브랜치> <브랜치를 생성할 위치>

 

기존의 브랜치를 새로운 브랜치로 덮어쓰기

$ git branch f <기존 브랜치> [<브랜치를 생성할 위치>]

 

브랜치를 옮기거나 브랜치명 변경하기

<새로운 브랜치>가 존재하지 않을 경우

$ git checkout m <기존 브랜치> <새로운 브랜치>

 

브랜치를 무조건 덮어쓴다.

$ git checkout M <기존 브랜치> <새로운 브랜치>

 

다른 브랜치를 현재 브랜치로 합치기

$ git merge <브랜치>

 

커밋하지 않고 합치기

$ git merge --no-commit <브랜치>

 

선택하여 합치기

$ git cherry-pick <커밋명>

 

커밋하지 않고 선택하여 합치기

$ git cherry-pick n <커밋명>

 

브랜치의 이력을 다른 브랜치에 합치기

$ git merge --squash <브랜치>

 

브랜치 삭제하기

삭제할 브랜치가 현재 브랜치에 합쳐졌을 경우에만

$ git branch d <삭제할 브랜치>

 

삭제할 브랜치가 현재 브랜치에 합쳐지지 않았어도

$ git branch D <삭제할 브랜치>

 

 

 

1.4.        이력

모든 이력 보기

$ git log

 

변경 사항을 보여주는 패치와 함께 로그 표시하기

$ git log p

 

1개의 항목만 보이도록 로그 개수 제한하기

$ git log -1

 

20개의 항목과 패치만 보이도록 로그제한하기

git log -20 p

 

6개월 동안의 커밋 로그 보기

$ git log since=6 months

 

2일 전까지의 커밋 로그 보기

$ git log before=2 days

 

HEAD 보다 3개 이전의 커밋 로그 보기

$ git log -1 HEAD-3

or

$ git log -1 HEAD^^^

or

$ git log -1 HEAD~1^^

 

두 지점 사이의 커밋 로그 보기

<시작 지점> <끝 지점>은 커밋명이나 브랜치명 혹은 태그명이며, 조합하여 사용할 수 있다.

$ git log <시작 지점><끝 지점>

 

각 항목의 로그 이력 한 줄씩 보기

$ git log pretty=oneline

 

각 항목마다 영향 받은 줄의 통계보기

$ git log --stat

 

커밋할 시점의 파일 상태 보기

$ git log --name-status

 

현재 작업 트리와 인텍스의 차이점 보기

$ git diff

 

인덱스와 저장소의 차이점 보기

$ git diff --cached

 

작업트리와 저장소의 차이점 보기

$ git diff HEAD

 

작업트리와 특정 위치 간의 차이점 보기

<시작지점>은 커밋명이나 브랜치명 혹은 태그명이다.

$ git diff <시작지점>

 

저장소의 두 지점 사이의 차이점 보기

$ git diff <시작지점> <끝 지점>

 

차이점의 통계보기

$ git diff --stat <시작지점> [<끝지점>]

 

파일의 커밋 정보 줄 단위로 보기

$ git blame <file>

 

파일의 줄 단위의 복사, 붙여 넣기, 이동 정보 보기

$ git blame C C <file>

 

로그에서 복사와 붙여 넣은 정보 보기

$ git log C C p 1 <특정 지점>

 

 

 

1.5.        원격 저장소

저장소 복제하기

$ git clone <저장소>

 

마지막 200개의 커밋만 포함하여 저장소 복제하기

$ git clone depth 200 <저장소>

 

새로운 원격 저장소 추가하기

$ git remote add <원격 저장소> <저장소 url>

 

모든 원격 브랜치 목록 보기

$ git branch r

 

원격 브랜치에서 지역 브랜치 생성하기

$ git branch <새로운 브랜치> <원격 브랜치>

 

원격 태그에서 지역 브랜치 생성하기

$ git branch <새로운 브랜치> <원격 태그>

 

origin 저장소에서 합치지 않고 지역 브랜치로 변경 사항 가져오기

$ git fetch

 

원격 저장소에서 합치지 않고 지역 브랜치로 변경 사항 가져오기

$ git fetch <원격 저장소>

 

원격 저장소에서 변경 사항을 가져와 현재 브랜치에 합치기

$ git pull <원격 저장소>

 

origin 저장소에서 변경 사항을 가져와 현재 브랜치에 합치기

$ git pull

 

지역 브랜치를 원격 브랜치에 푸싱하기

$ git push <원격 저장소> <지역 브랜치>:<원격 브랜치>

 

지역 브랜치를 동일한 이름의 원격 브랜치에 푸싱하기

$ git push <원격 저장소> <지역 브랜치>

 

새로운 로컬 브랜치를 원격 저장소에 푸싱하기

$ git push <원격 저장소> <지역 브랜치>

 

지역 변경 사항을 origin 저장소에 푸싱하기

이러한 방식은 origin 저장소에 존재하는 브랜치에만 푸싱한다.
새로운 브랜치에 푸싱하려면 반드시 git push <저장소명> <지역 브랜치> 형태로 실행해야 한다.

$ git push

 

원격 브랜치 삭제하기

$ git push <원격 저장소> :<원격 브랜치>

 

원격 저장소에서 쓸모가 없어진 원격 브랜치 제거하기

$ git remote prune <원격 저장소>

 

원격 저장소를 제거하고 관련된 브랜치도 제거하기

$ git remote rm <원격 저장소>

 

 

 

1.6.        GitSVN 연결하기

서브버전 저장소 전체를 복제하기

$ git svn clone <svn 저장소>

 

표준 레이아웃을 사용하는 서브버전 저장소 전체를 복제하기

표준대로 trunkbranches tags를 저장소 구조로 사용하는 저장소를 복제할 때 사용한다.

$ git svn clone s <svn repository>

 

비표준 레이아웃을 사용하는 서브버전 저장소 전체를 복제하기

$ git svn clone T <트렁크 경로> -b <브랜치 경로> -t <태그 경로> <svn 저장소>

 

표준 레이아웃을 사용하는 서브버전 저장소 전체를 복제하기

$ git svn clone s r 2321

 

표준 레이아웃을 사용하는 서브버전 저장소를 복제하고, 모든 원격 브랜치에 접두어를 추가하기

$ git svn clone s --prefix svn/ <svn 저장소>

 

상위의 서브버전 저장소에서 갱신하고 재정렬 하기

$ git svn rebase

 

상위의 서브버전 저장소에 커밋 푸싱하기

$ git svn dcommit

 

상위 서브버전 저장소에 푸싱될 커밋 목록 보기

$ git svn dcommit n

 

서브버전 저장소 로그 보기

$ git svn log

 

서브버전 저장소 파일의 커밋정보 줄단위로 보기

$ git svn blame <파일>

 

출처 : http://youmin3.egloos.com/1991150

1.         Gitosis를 이용하여 Git 서버 운용하기

Git은 분산 버전 관리 시스템이기도 하지만, 파일시스템을 기반으로 사용하고 있으면서, 내용을 버전으로 관리하면, 효과적인 애플리케이션을 구축하기 위한 플랫폼이기도 하다.

Gitosis는 원격 Git 서버와 서버의 저장소를 관리하기 위한 도구이며,
저장소에 Gitosis의 구성을 저장하여 이런 관리 작업을 처리한다
.
서버의 구성을 변경하려고 한다면, 새로운 구성을 Gitosis 저장소에 푸싱하기만 하면 된다.

 

Gitosis .git/hooks/ 디렉터리에 있는 후킹(hooking) 스크립트를 이용해서 이런 작업들을 처리한다.
후킹 스크립트는 커밋 전(pre-commit 스크립트)이나 커밋 후(post-commit 스크립트)와 같은 이벤트에 따라 실행된다.

또한, Gitosis는 후킹 스크립트를 통해 생성한 저장소에 대한 구성 파일도 갱신하는데,
빈 저장소를 만들고, 사용자에게 저장소 읽기, 쓰기 권한을 설정하는 등의 작업을 할 수 있다.

Gitosis 설치 단계는 다음과 같다.

(1)    의존성을 만족하는지 확인하기

(2)    Gitosis 설치하기

(3)    Gitosis를 위한 서버구성

(4)    관리자 인증서(credential) 생성하기

(5)    Gitosis 초기화하기

(6)    Gitosis 구성하기

 

 

 

1.1.        의존성을 만족하는지 확인하기

Gitosis는 몇 가지 의존성을 가진다.
먼저, Gitosis가 파이선으로 작성되었기 때문에 시스템에 파이선이 설치되있어야 한다.

그 다음은 Python Enterprise Application Kit, PEAK에서 EasyInstall 패키지가 필요하다.
EasyInstall
은 개발자들이 파이선 기반 애플리케이션을 설치하고 관련 의존성을 해결하도록 돕는다. EasyInstall도 잘 알려진 패키지이니 먼저 시스템에 설치되어 있는지 다음 명령어를 실행해서 확인해보자.

$ python c import setuptools

EasyInstall setuptools 모듈이 이용 가능하다면 아무런 출력도 보여주지 않는다.

 

 

 

1.2.        Gitosis 설치하기

Gitosis는 지금도 활발히 개발 중에 있으므로 소스 코드로부터 직접 설치해야 한다.

다음 명령어로 Git 저장소를 복제하여 Gitosis의 소스 코드를 바로 받을 수 있다.

$ git clone git://eagain.net/gitosis

이제 gitosis 디렉토리에 Gitosis의 소스 코드가 있다.
Gitosis
를 설치하려면 다음과 같이 gitosis 디렉터리로 이동해서 setup.py를 실행한다.

$ cd gitosis

$ sudo python setup.py install

 

Gitosis를 설치했으니 Gitosis가 이용할 서버의 사용자 계정을 설정해야 한다.
Gitosis
를 위한 사용자 계정을 설정하려면 사용자에 대한 인증서가 필요하다.

 

 

 

1.3.        관리자 인증서 생성하기

SSH에서 사용자의 연결을 검증할 때 비밀번호 대신 SSH 공개키를 사용하므로, Gitosis 관리자에 대한 SSH 공개키를 반드시 생성해야 한다.

사용하던 공개키가 있다면 새로 생성하는 대신 기존의 키를 이용해도 된다. 가지고 있는 공개키가 없다면 새로 생성하자. 공개키는 커맨드 라인에서 ssh-keygen 명령어를 실행해서 생성한다.

ssh-keygen 명령어는 Gitosis가 동작하는 서버에 접속할 때 사용하는 자신의 컴퓨터에서 실행해야 한다. 커맨드 라인에서 다음 명령어를 실행해서 자신의 키를 생성한다.

$ ssh-keygen t rsa

 

ssh-keygen 프로그램은 사용자의 키를 생성하고, 새로 생성된 키에 대한 정보를 알려준다.
생성 위치와 이름을 기본값으로 그냥 뒀다면 다음 경로에 공개키가 생성된다.

/home/<사용자명>/.ssh/id_rsa.pub

이 파일을 서버에 복사한다. 이 파일은 이어지는 내용에서 Gitosis를 초기화할 때 바로 사용한다.

 

 

 

1.4.        Gitosis를 위한 서버 구성하기

Gitosis가 사용자의 서버에서 동작하려면 서버에 Gitosis 전용 사용자 계정이 있어야 하고, 모든 저장소를 저장할 디렉터리도 필요하다.

시스템에 Gitosis를 위한 새로운 사용자가 있어야 한다.
Gitosis
용 사용자 계정의 홈 디렉터리에 Gitosis 관련 구성값과 저장소를 보관한다
.
대부분의 리눅스 시스템에서는
home /path/to/home 형식을 추가하면 홈 디렉터리를 지정할 수 있다.

사용자 홈 경로는 시스템의 어디를 지정해도 상관없지만, Gitosis의 규약은 /srv/example.com/git로 설정하는 것이다. 여기서 example.com을 자신의 도메인으로 바꾸기만 하면 된다.

 

사용자명을 git으로 설정한 예.

$ sudo adduser --shell /bin/sh \

               --group \

               -- disabled-password \

               --home /srv/example.com/git

               git

 

 

 

1.5.        Gitosis 초기화하기

Gitosis에는 초기화 과정을 수행하는 gitosis-init이라는 프로그램이 있다.

gitosis-init을 실행할 때 지정해야 할 옵션은 없지만, 이전 절에서 생성한 사용자 계정으로 실행해야 한다.

$ sudo H u git gitosis-init < /path/to_id_ras.pub

 

프로그램이 실행되면 Gitosis와 저장소가 초기화된다.
오래된 setuptools를 이용하고 있다면, 실행 권한이 빠질 수 있다고 한다. 그런 경우 다음 명령어를 실행해서 실행 권한을 추가하도록 권고하고 있다.

$ sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update

 

$PATH 변수에 존재하지 않는 위치에 Git을 설치했다면, OSError 오류를 겪게 된다. OSError 오류는 gitosis-init 명령어에서 Git을 찾을 수 없을 때 발생한다.

이 문제를 해결하려면 git 사용자가 Git의 명령어들을 이용할 수 있도록 해야 한다.
Gitosis
가 동작하는 사용자의 $PATH 변수를 수정하거나, Gitosis의 사용자 $PATH 변수에 포함된 아무 경로에서나 git 바이너리의 심볼릭 링크를 추가하면 된다.

 

 

 

1.6.        Gitosis 구성하기

Gitosis의 구성 저장소를 복제해야 한다.

구성 저장소는 새로운 저장소를 관리하는 데 필요한 모든 구성값을 가지고 있다. 구성 저장소는 SSH 공개키를 생성한 컴퓨터에서 복제해야 한다.

$ git clone git@example.com:gitosis-admin.git

 

새로 복제한 디렉터리에는 gitosis.conf 파일과 keydir/ 디렉터리가 있다.
gitosis.conf
는 단순한 INI 형식의 파일이다
.
대괄호로 각 영역을 나타내며 각 항목은
이름=의 형식이다
.
파일을 열어보면 다음과 유사한 기본 구성을 볼 수 있다.

[gitosis]

 

[group gitosis-admin]

writable = gitosis-admin

members = travis

 

[group gitosis-admin]이후
첫째 줄에서 이 그룹이 gitosis-admin 저장소에 쓰기 권한을 가진다고 지정한다.

둘째 줄에서는 열거한 사용자들이 이 그룹에 포함된다고 지정한다. 여기서는 travis 한 명만 포함시켰다.

members 필드의 값은 공백으로 구분한다.
이때, members 필드에 기록된 각 사용자의 이름은 keydir/ 디렉터리에 있는 동명의 .pub 확장자를 가진 파일을 참조한다. 예를 들면, 필자의 키는 keydir/travis.pub에 있다.

 

새로운 사용자를 추가하려면, 추가하려는 사용자의 공개 SSH키가 필요하다.
저장소에 접근하려는 모든 개발자는 자신의 컴퓨터에서 SSH 공개키를 생성해야 한다
.
공개키의 생성은 앞에서 이용한 명령어를 그대로 이용하면 되지만, 반드시 접근하려는 개발자의 컴퓨터에서 생성해야 한다. 생성된 공개키는 특정 컴퓨터에 종속적이기 때문이다.

각 개발자의 공개키 복사본을 전달 받으면 공개키에 사용자명을 붙여서 keydir/ 디렉터리에 복사하고, 접근을 허용할 저장소에 파일명에서 이용한 사용자명을 추가한다. 방금 변경한 내용은 지역 저장소에 커밋한 후 git push 명령어를 이용해서 Gitosis 서버에 푸싱해야 한다.

 

 

 

1.7.        새로운 저장소 추가하기

Gitosis가 생성하는 초기 구성에는 하나의 구성 저장소가 있다. 하지만 원하는 만큼의 저장소를 관리할 수 있다. 필요하다면 새로운 writable 영역에 gitosis-admin 그룹에 추가할 수 있다. 하지만 이렇게 하면 저장소에 접근 가능한 모든 사람이 Gitosis 구성을 변경할 수 있다. 보다 안전하게 관리하려면 관리를 위한 그룹과 개발자를 위한 그룹으로 2개의 그룹을 만든다.

[gitosis]

 

[group gitosis-admin]

writable = gitosis-admin

members = travis

[group team]

writable = mysite

members = travis Susannah

 

첫 번째 [group]은 앞에서 작성했던 부분이다.
기존 그룹은 그대로 두고 team이라는 그룹을 새로 추가했다. 추가한 그룹에 포함된 구성원에게는 mysite 저장소에 대한 쓰기 권한을 부여했다. 이렇게 하면 travis susannah가 쓰기 권한을 얻는다.

생성하려는 저장소마다 생성할 저장소 이름을 포함하는 새로운 writable 줄을 추가한다. 다시 한번 변경 사항을 커밋하고 서버에 푸싱한다. 변경사항을 푸싱하고 나면 새로운 원격 저장소에 내용을 추가할 수 있다.

모든 지역 Git 저장소에서는 새로운 원격 저장소로 내용을 보낼 수 있다. 물론 전송하려면 지역 저장소에는 적어도 하나의 커밋이 있어야 한다. 저장소의 작업 트리에서 다음 명령어를 실행하면 원격 저장소를 자신의 구성에 추가할 수 있다.

$ git remove add origin git@example.com:mysite.git

이 명령어는 mysite 원격 저장소를 지역 저장소의 구성에 origin 저장소로 추가한다.

 

자신의 지역 저장소의 내용을 원격 저장소에 푸싱하기

아직 원격 저장소에 존재하지 않는 브랜치이므로 반드시 푸싱 대상 브랜치명을 지정해야 한다.

$ git push origin master

접근 권한을 가진 다른 사용자가 저장소를 복제할 수 있고, 쓰기 권한을 줬다면 변경 사항을 푸싱할 수도 있다.

 

오픈 소스 프로젝트라면 일반 대중이 저장소에 접근할 수 있어야 하며, 지역 가상 사설망(VPN)이라면 자신의 저장소를 회사의 모든 사람에게 열어둬야 한다. 하지만 누가 내용을 읽었는지에 대한 로그를 추적할 필요는 없을지도 모른다.

git daemon을 이용하면 자신의 저장소를 익명의 사용자에게 읽기 전용으로 공개하도록 설정할 수 있다.

 

 

 

1.8.        공개 저장소 설정하기

자신의 저장소를 읽기 전용을 설정하기.

일일이 사용자를 설정하는 게 아니라 자신의 작업을 다른 개발자와 공유하려는 경우에만 읽기 전용으로 설정한다. 읽기 전용 저장소는 누구라도 저장소를 읽을 수 있는 오픈 소스 개발에서 매우 흔한 방식이다.

읽기 전용으로 설정할 때는 2단계를 따른다.
먼저, 자신의 저장소를 Gitosis로 공유할 수 있도록 구성한다
.
다음으로, git daemon을 실행하여 요청에 대해 응답할 수 있도록 한다.

Gitosis를 구성하려면 앞에서 봤던 gitosis.conf를 편집해야 한다.

이번에는 repo라는 영역을 저장소 이름과 함께 추가한다.
예를 들어, 자신의 저장소 이름이 web이라면 다음과 같이 추가하면 된다.

[repo web]

 

이 내용은 새로운 영역을 추가하기 위한 INI 설정이다.
이 부분 이후에 나오는 내용은 모두 이 영역에 포함된 내용임을 표시한다
.
이제 daemon = yes라는 줄을 추가해서 git daemon이 이 저장소를 읽을 수 있다고 표시한다. 지금까지 추가한 내용은 다음과 같다.

[repo web]

daemon = yes

 

이것으로 구성 단계는 모두 마치고, 변경 사항을 커밋하고 서버에 푸싱하자.
이제 git daemon을 설정할 차례다.

 

앞에서 생성한 git 사용자로 git daemon을 실행해야 한다.
명령어 앞에 sudo
u git을 붙여서 실행하는 게 가장 간단한 방식이다.

그 외에 git daemon에 지정해야 하는 매개변수로는 --base-path가 있다.
--base-path
로 저장소의 위치를 지정한다
.
지금까지 사용해온 구성을 따르면 저장소는 /srv/example.com/repositories에 있다.

git daemon을 실행하는 실제 명령어는 다음과 같다.

$ sudo u git git daemon \

       --base-path /srv/example.com/repositories/

 

제대로 동작하는지 확인해보려면 자신의 읽기 전용 저장소 중에 하나를 복제해 본다. web 저장소를 복제할 경우 명령어는 다음과 같다.

$ git clone git://example.com/web.git

 

여기서 실행한 git daemon 명령어는 사용자가 로그인한 동안만 동작한다. 그리고 서버가 부팅할 때마다 실행되지도 않는다. 운영체제에 따라서 이런 문제는 약간씩 다르게 다룰 수 있다.

필자는 서버에서 로그아웃한 후에도 git daemon을 동작하도록 하려고 nohup을 이용한다. 그렇다고 서버를 재부팅한 다음에도 자동으로 실행될 필요는 없었다. 이용한 명령어는 다음과 같다.

$ nohup sudo u git git daemon --base-path /srv/example.com/repositories &

명령어의 마지막 &, 실행되는 명령어를 현재 터미널 세션에서 분리하며,
명령어의 시작에 있는 nohup은 현재 사용자에 종속되지 않도록 한다.

 

출처 : http://youmin3.egloos.com/1990886

1.         Git으로 옮겨가기

1.1.        SVN과 통신하기

 

서브버전 명령어에 해당하는 Git 명령어

svnadmin create

git init

svn checkout

git clone

svn update

git pull

svn add

git add

svn commit

git add

git commit

svn status

git status

svn switch <branch>

git checkout <branch>

svn merge <branch>

git merge <branch>

svn revert <file>

git checkout <file>

 

CVS 명령어에 해당하는 Git 명령어

cvs d<repo> init

git init

cvs d<repo>

checkout <module>

git clone

cvs update dP

git pull

cvs add

git add

cvs commit

git add

git commit

cvs status

git status

cvs co r <branch>

git checkout <branch>

cvs update j

git merge

cvs update C

git checkout <file>

 

서브버전에서 Git으로 옮겨오는 방식에는 2가지가 있다.
첫 번째는 서브버전에서 모든 이력을 가져오고, 서브버전을 대체해서 Git을 버전 관리 시스템으로 이용하는 방식이다.

두 번째는 서브버전을 그대로 유지하고, Git을 활용해 서브버전에서 변경사항을 가져오고, 변경된 내용을 서브버전에 다시 푸싱하는 방식이다.

 

서브버전 저장소 가져오기

서브버전 저장소

git svn clone è

자신의 Git 저장소

 

서브저번 저장소를 상위 저장소로 이용하기

서브버전 저장소

git svn clone è

 

git svn rebase è

çgit svn commit

자신의 Git 저장소

 

 

 

1.2.        git-svn 설치 확인하기

git-svn Git에서 서브버전 저장소와 통신할 때 사용하는 도구이다.
Git
을 어떻게 설치했는지에 따라 git-svn이 이미 설치돼 있을 수도 있다
.
다음 명령어를 실행하여 확인해 보자.

$ git svn version

git-svn version 1.6.0.2 (svn 1.4.4)

 

정상적인 메시지 대신 오류 메시지를 출력한다면 다음 2가지 중 하나이다.

l       Git에서 SVN이 명령어가 아니거나 치명적인 오류(fatal error)라고 알려주는 메시지.

l       SVN/Core.pm을 찾을 수 없다는 메시지

 

 

 

1.2.1.       Git 명령어가 아니거나 치명적인 오류인 경우

이 문제는 우분투의 apt-get이나 OS X MacPorts와 같은 패키지 관리자를 이용해 Git을 설치한 경우 흔히 발생하는데, 패키지 관리자를 통해 패키지를 설치할 때 의존 관계에 있는 패키지를 줄이려고 Git을 여러 개의 작은 패키지로 나눠두었기 때문이다.

리눅스에서 git-svn을 설치하려면 서브버전 하위 명령어를 포함하는 패키지를 찾아야 한다.
우분투에서는 apt-get을 이용해 git-svn을 지정하면 설치할 수 있다.

$ sudo apt-get install git-svn

 

2.1 Git 설치하기에서 설명한 대로 MacPorts를 이용해 설치했다면, 따로 git-svn을 설치하지 않아도 된다. 마찬가지로, 소스에서 컴파일해서 설치한 경우도 추가로 설치하지 않아도 된다.

 

 

 

1.2.2.       SVN/core.pm을 찾을 수 없는 경우

다른 오류로는 SVN/core.pm이 없다는 perl 메시지가 있으며, 설치된 서브버전에 대한 펄 바인딩이 없을 때 발생한다.

필요한 파일을 얻는 데는 몇 가지 방법이 있지만, 대부분의 경우 패키지 관리자를 이용하는 편이 가장 쉽다.

우분투에서는 누락된 페키지를 subversion-perl이라 부르며, 다음 명령어를 실행하여 설치한다.

$ sudo apt-get install subversion-perl

 

맥 사용자라면 MacPorts 패키지 관리자를 이용해 subversion-perlbindings를 설치한다.

$ sudo port install subversion-perlbindings

 

CPAN을 사용하여 펄 라이브러리를 최신 상태로 유지하고 있다면, 필요한 패키지를 바로 설치할 수 있다. 설치할 패키지는 SVN::Core이다.

$ sudo cpan install SVN::Core

 

 

 

1.3.        서브버전 저장소 가져오기

git svn clone 명령어를 이용한다는 차이를 제외하고, 기존에 Git에서 저장소를 가져오던 방식과 동일하게, 서브버전 저장소의 이력을 가져올 수 있다.

git svn clone은 서브버전 저장소의 전체 이력을 가져와서 자신의 Git 저장소에 저장한다.

 

맥에서 CPAN 사용에 주의할 사항.

필자는 MacPorts에서는 필요한 것이 모두 설치됐다고 알려주는데도 Git에서는 왜 인식하지 못하는지 이유를 알아내려고 이틀을 허비했다.
원인은 시스템에 펄 서브버전 바인딩이 2가지 버전으로 설치돼 있었기 때문이다
.
오래된 버전은 처음 컴퓨터에 서브버전을 설정하면서 함께 설치되었고, 새로운 버전은 MacPorts를 이용해 설치됐다
.
상황이 나빠지려고 그랬는지 문제를 파악하지도 못한 상태에서 CPAN을 통해서 하나를 더 설치해버렸다. 그래서 총 3가지 버전의 펄 서브버전 바인딩이 설치되었다
.
CPAN
을 통해 설치한 버전은 잘 동작했지만, Git에서 이용하려고 하면 의존성 오류가 발생했다. CPAN 라이브러리가 필요한 모든 라이브러리를 설치하지 않는다는 사실을 안 후에는 쉽게 해결할 수 있었지만, 결국 이 문제를 해결하는 데 몇 시간 이상을 소비했다.

 

서브버전 저장소를 복제할 때는 Git에 서브버전 저장소의 구조를 알려줘야 한다.
저장소가 서브버전 저장소의 레이아웃으로 권장되는 구조를 따르고 있다면, -s 매개변수를 지정해서 표준 레이아웃을 이용하고 있다고 Git에게 알려준다.

 

branches tag 디렉터리가 다른 위치에 있다면, -b옵션과 -t옵션을 이용해서 위치를 지정할 수 있다. 마찬가지로 트렁크가 trunk말고 다른 이름을 이용하고 있다면 -T옵션으로 위치를 지정할 수 있다.

$ git svn clone prefix svn/ -s svn://svnrepo/sunshine

 

저장소 크기 줄이기

100여개 이상의 커밋 이력을 포함하는 서브버전 저장소를 복제하면, 디스크 공간이 현저히 줄어드는 것을 볼 수 있다.

저장소에 수백 건을 커밋할 때와 마찬가지로, 새로 받은 서브버전 복제본에도 가능하면 빨리 git gc를 실행하여 디스크 공간을 절약하자.

저장소를 복제하고 다른 동작 없이 바로 git gc를 실행할 때는 안심하고 --aggressive 옵션을 지정해도 된다. 물론 옵션을 지정하면 시간이 걸리기는 한다. 개인적으로는 31,000개 이상의 커밋을 가진 복제된 저장소를 압축하는데 14시간 이상 소요되는 경우도 봤다.

 

서브버전은 전체 이력 가져오기와 같은 요청을 처리하지 못한다.
따라서, git-svn은 한 번에 하나의 리비전만 가져온다
.
때문에 저장소가 수만 개의 이력을 포함할 정도로 크다면, 가져오는데 거의 하루 종일 걸릴 수도 있다.

앞에서는 git svn clone 명령어에 --prefix 매개변수를 포함시켰다.
--prefix
매개변수는 서브버전에서 가져온 모든 브랜치에 접두어를 추가한다
.
이를 테면, 원격 브랜치의 이름 앞에 원격 저장소임을 나타내는 이름을 붙일 수 있다
.
매개변수를 지정하지 않으면, 이름으로는 원격 브랜치와 지역 브랜치를 구별하기 어렵다
.
--prefix
매개변수를 지정하지 않으면, git branch
a를 통해 지역 저장소와 원격 저장소를 모두 볼 때 알아보기 어려워진다.

오래된 커밋이 별로 중요하지 않다면, -r옵션을 이용해서 복제를 시작할 리비전을 지정할 수 있다. 리비전을 지정하면, 지정한 리비전의 이력만 복제하므로 이후의 변경 사항을 가져오려면 다른 명령어를 더 실행해야 한다.
프로젝트를 초기에 가져온 다음
상위서브버전 저장소에서 변경 사항을 가져올 때는 git svn rebase 명령어를 이용한다.

 

 

 

1.4.        서브버전 저장소를 최신 상태로 유지하기

현재 사용 중인 서브버전 저장소를 이용하든지, git svn clone r 을 이용해서,
초기에 한 번 최신 사항을 가져와야 한다면
,
서브버전 저장소의 변경 사항을 가져오는 2가지 방법이 있다.

첫 번째 방법은 git svn fetch이다.
이 명령어를 이용하면, 모든 원격 변경 사항을 원격 브랜치에 풀링 하지만, 로컬 브랜치와 합치지는 않는다. 이 명령어는 서브버전에 추가된 새로운 브랜치를 가져올 때도 사용한다.

둘째는 git svn rebase를 이용한 방법이며, 더 많이 사용된다.
이 명령어는 git svn fetch를 실행한 다음에 바로 git rebase를 실행하는 것과 동일하다
.
명령어를 실행하면 상위 서브버전 저장소에서 모든 커밋을 가져오고 원격 브랜치에 맞춰서 현재 브랜치를 재정렬한다.

git rebase를 이용할 때와 마찬가지로, 이미 서브버전에 적용한 지역 커밋이 있다면 재정렬할 때 다시 적용하지 않으며, 작업 트리에 커밋 하지 않은 변경 사항이 있다면 git svn rebase를 실행할 수 없다.

 

이 오류는 무슨 의미지?

복제하려는 프로젝트가 서브버전 저장소의 가장 오래된 리비전에 없다면, 다음과 같은 에러가 발생한다.

W: Ignoring error from SVN, path probably does not exist: (175002): RA layer request failed:

(경고: SVN에서 발생한 오류를 무시했음. 요청한 경로가 존재하지 않는 것으로 보임: )

REPORT request failed on /test/!svn/bc/100:

REPORT of /test/!svn/bc/100:Could not read chunk size: Secure connection truncated (svn://svnrepo)

W: Do not be alarmed at the above message

git-svn is just searching aggressively for old history.

(경고: 겁먹지 말 것. git-svn이 오래된 이력을 계속 찾기 때문에 나오는 메시지다)

 

두번째 경고 메시지에서 알 수 있듯이 걱정할 필요가 없다. git-svn은 서브버전 저장소를 복제할 때 접근할 수 있는 가장 오래된 리비전부터 요청한 코드를 포함하는 리비전을 찾을 때가지 최신 리비전 방향으로 이동한다.

경고 메시지는 단지 가장 오래된 리비전에서 요청한 코드를 찾을 수 없을 때 발생한다.
이후 복제하기로 한 프로젝트가 처음 존재하는 리비전을 찾을 때까지 계속해서 이력을 조사한다.

 

서브버전 저장소 복제하기의 대안

서브버전 저장소를 복제하는 일은 시간이 많이 걸린다.
필자는 복제하는 데에 20시간 이상 소요된 큰 저장소를 복제한 적이 있다
.
기존의 저장소가 크다면 복제를 시작하기 전에 먼저 부트스트랩(bootstrap) 저장소를 찾아보자.

부트스트랩 저장소는 추적하려는 서브버전 저장소를 복제한 Git 저장소를 tar 파일로 묶어둔 형태다. 오픈 소스 커뮤니티에서는 부트스트랩 저장소를 보통 매주 업데이트한다.

부트스트랩 저장소를 이용하면, git svn rebase를 실행해서 부트스트랩 저장소 이후의 변경 사항만 가져오면 된다. 전체 이력을 복사하는 것보다 훨씬 빠르다.

 

 

 

1.5.        변경 사항을 SVN에 푸싱하기

다른 유명한 분산 버전 관리 시스템과 비교해서, Git이 가지는 장점은,
서브버전 저장소에서 풀링 해 올 수 있을 뿐만 아니라
,
변경한 내용을 다시 푸싱할 수도 있다는 점이다.

변경 사항을 다시 서브버전 저장소로 푸싱하는 명령어는 git svn dcommit이다.
이 명령어를 이용하면, 자신의 컴퓨터에서 커밋한 내용을 서브버전 저장소에 하나씩 커밋한다.

커밋하는 동안 지역 커밋이 서브버전 서버에서 가져온 정보를 반영하도록 복사본을 재정렬한다.
git svn rebase
와 마찬가지로 git-svn이 이미 동기화된 이력을 파악하기 쉽게 해준다.

-n 옵션을 지정하면 가상 수행(dry run)을 수행할 수도 있는데, 이를 통해 모든 이력과 서브버전 저장소에 보낼 수 있는 커밋 목록을 확인할 수 있다.

 

 

 

1.6.        CVS에서 가져오기

CVS 저장소를 Git으로 변환하는 가장 확실한 방법은,
cvs2svn
명령어를 이용해서 CVS 저장소를 먼저 서브버전 저장소로 변환하는 것이다
.
cvs2svn
CVS 저장소를 서브버전 저장소로 변환하는 도구이다. (http://cvs2svn.tigris.org)

Git에는CVS 저장소를 가져오기 위한 git cvsimport 도구도 있지만, cvs2svn 명령어를 이용하는 편이 더 안정적이기에 cvs2svn의 사용법만 다룬다.

 

변환을 시작하려면 CVS 저장소에서 리비전 제어 시스템(Revision control System, RCS)파일을 가져와야 한다.
이 파일들을 가져온 다음 cvs2svn 도구를 이용해 svn 덤프 파일로 변환한다.

$ cd /path/to/cvs-rcs-files

$ cvs2svn dumpfile=svndump

 

도구를 이용해 덤프 파일을 생성하면, svndumpfilter와 같은 불필요한 데이터를 필터링 해준다.
새로운 svndump가 준비됐다면, 이 정보를 가져와서 서브버전 저장소를 생성한다
.
svnadmin create
명령어를 이용해서 새로운 저장소를 생성한다.

$ cd ..

$ svnadmin create ./tmpsvn

$ svnadmin load ./tmpsvn < /path/to/cvs-rcs-files/svndump

 

tmpsvn 저장소로 전체 이력을 불러오는데 성공했다면, 이제 Git 저장소로 가져올 준비가 됐다. tmpsvn 저장소의 내용을 Git 저장소로 옮기는 절차는 10.1 SVN과 통신하기에서 다룬 내용과 동일하다.

$ git svn clone file:///path/to/tmpsvn

 

출처 : http://youmin3.egloos.com/1990844

1.         기본을 넘어서

Git은 풍부한 도구 모음을 가지고 있다. 지금까지는 매일 사용하는 Git의 기본 기능만 다루었다.
Git
은 현재 140개가 넘는 명령어를 가지고 있으며, 아마도 이 중에서 상당수는 앞으로도 전혀 사용할 일이 없을 것이다
.
예를 들어, Git 내부적으로 문자열이 유효한 브랜치나 태그명인지 판단하려고 사용하는 git check-ref-format과 같은 명령어는, Git의 확장을 만드는 경우가 아니라면 사용할 일이 없다.

 

하지만, 매일 사용하는 명령어는 아니겠지만, 필요할 때 사용하면 정말로 유용한 명령어도 있다.
*
저장소 이력 압축하기

l       저장소 내보내기

l       브랜치 이력 재정렬하기

l       reflog를 이용해서 저장소 고치기

l       저장소를 양분하여 어떤 변경이 버그를 발생시켰는지 찾기

 

$ git clong git://github.com/tswicegood/mysite-chp8.git

Initialized empty Git repository in /work/mysite-chp8/.git/

remote: Counting objects: 56, done.

 

 

 

1.1.        저장소 이력 최적화 하기

일상 생활에서 주변을 좋은 상태로 유지하려면 약간의 관리가 필요하다.
자동차 오일도 교환해주어야 하고, 바닥 청소도 해야 한다
.
마찬가지로 Git에서는 git gc run을 실행해야 한다.

 

Git은 모든 것을 저장한다.
모든 것을 저장하기에 불필요한 찌꺼기 데이터를 포함하기도 한다
.
예를 들어, git commit --amend 매개변수를 지정해서 커밋을 수정해도, Git은 수정되기 이전 리비전을 기억하고 있다
.
또 다른 예로, git branch
D로 실험용 브랜치를 지워서 해당 브랜치에 대한 연결고리가 없는데도, Git은 브랜치에 어떤 내용이 들어 있었는지 알고 있다.

이런 경우에 git gc를 이용한다.
100
번 커밋한 후나 한 달에 한 번 정도 git gc를 실행하도록 주기를 정해놓으면
,
Git
이 내부적으로 이력을 저장하는 방식을 최적화하므로 지저분한 내용을 깔끔하게 정리할 수 있다
.
이때 git gc를 실행한다고 해서 이력이 변경되지는 않는다. 단지 이력을 저장하는 방식만 바꾼다.

 

저장소에 따라서 git gc를 실행해서 변경되는 정도에도 차이가 있다.
일단 git gc를 실행하면, 앞으로 최적화가 필요할 정도로 변경하기 전까지, 다시 실행하지 않아도 된다.

그럼 출력 결과를 보고 무엇이 최적화 됐는지 알 수 있을까? 디스크 공간이다.
Git
은 속도와 효율 모두를 취하려고 한다. 최적화 일부는 나중에 속도가 문제되지 않을 때 실행할 수 있도록 남겨둔다.

git gcaggressive 매개변수를 지정하면, 한층 더 깊이 최적화한다.

 

Git은 변경 사항을 델타(delta, 델타는 두 비교 대상간의 차이를 나타내는 단위이다) 단위로 저장한다. git gc를 실행하면 이렇게 저장된 델타를 압축하지만 다시 계산하지는 않는다.
최적화를 수행할 때 --aggressive를 추가하면 이런 변경 사항 델타를 처음부터 다시 계산한다.

 

 

 

1.2.        저장소 내보내기

성공적인 프로젝트라면 만든 소프트웨어를 릴리스해야 한다.
작성한 소프트웨어를 파이선, 루비, php같이 유행하는 스크립트 언어로 작성했다면 최종 사용자가 실행할 수 있도록 소스도 함께 포함시켜야 한다.

소스를 직접 받아서 쓸 수 있도록, 공용 Git 저장소의 접근 권한을 줘도 되겠지만,
프로젝트의 스냅샷에 해당하는 공식
릴리스를 만들어서 제공하면
,
사용자가 소프트웨어를 설정하고 실행할 때 알아야 할 내용을 줄일 수 있다.

 

Git은 스냅샷을 찍을 수 있는 편리한 도구로 git archive를 제공한다.
git archive
는 지정한 저장소의 위치에 해당하는 코드의 복사본을 생성해서 tar zip 형식으로 내보낸다.

git archive에는 매개변수 몇 개를 지정해야 한다.
먼저, --format=(파일형식)을 지정해서 어떤 포맷으로 내보낼지 지정해야 한다
.
tar, zip
이 유요한 값이며 반드시 지정해야 한다.

다음은, 압축 파일을 생성하려는 저장소 이력의 위치이며, 반드시 지정해야 한다. 커밋명 브랜치, 태그를 지정할 수 있다.

이외에 유용한 매개변수로 --prefix가 있는데, 내보낼 파일들의 이름 앞에, 원하는 이름을 추가할 수 있다.  --prefix에 디렉터리를 지정하면 내보낼 릴리스를 특정 디렉터리 아래 둘 수 있다.

$ git archive --format=zip \

             --prefix=mysite-release/ \

             HEAD > mysite-release.zip

첫째 줄은 앞에서 얘기한 --format 매개변수를 지정했다.
둘째 줄은 --prefix매개변수다. mysite-release/ 이름에서 볼 수 있듯이 마지막에 슬래시 문자를 넣어서 디렉터리를 나타낸다. 슬래시 문자를 넣지 않고 git archive를 실행하면 파일을 디렉터리에 넣는 대신에 모든 파일명 앞에 해당 문자열을 추가한다.

마지막 줄은 2가지를 나타낸다. 먼저, HEAD에서 압축 파일을 생성하도록 지정했다.
그 다음, > 부호를 사용해서 git archive의 출력을 mysite-release.zip으로 내보내도록 지정했다.

tar 파일을 만드는 명령어도 유사하다. 다만, git archive 출력을 직접 파일로 내보내는 대신에 추가적인 명령어를 지정해야 한다. mysite-release.tar.gz 파일을 만드는 명령은 다음과 같다.

$ git archive --format=tar \

             --prefix=mysite-release/ \

             HEAD | gzip > mysite-release.tar.gz

HEAD 다음에 파이프(|)를 사용해서, 내용을 gzip 명령어로 전달했음을 알 수 있다.
gzip
명령어에서 mysite-release.tar.gz 파일을 생성한다
.
gzip
대신 bzip2로 바꾸면 bzip2를 이용해 압축할 수 있다.

 

tar, zip 파일 형태로 저장소를 내보내면, 저장소의 스냅샷을 편리하게 배포할 수 있다.
저장소의 전체 이력을 알 필요가 없는 사람이나, 특정 지점만 알고 싶어하는 사람에게 유용하다.

 

 

 

1.3.        브랜치 재정렬하기

브랜치를 이용하는 것이 작업을 조직화하는데 훌륭한 방법이지만,
브랜치 간에 모든 것을 동기화하는 작업은 브랜치의 약점이다
.
물론 Git에서 제공하는 합치기 추적을 이용하면 동기화할 때 드는 비용을 급격히 줄일 수 있지만, 여기에서는 합치기 추적이 아닌 다른 방법을 알아본다.

 

예를 들어, 8.2 릴리스 브랜치 다루기에서 RB_1.0.1에 코드를 추가했다.
그래서 1.0.1 태그에는 master 브랜치가 모르는 새로운 코드가 들어있다
.
RB_1.0.1
의 변경 사항을 master의 이력에 합치도록 RB_1.0.1 태그를 이용해서 master를 재정렬할 수 있다. 이렇게 하면 master가 처음부터 해당 변경 사항을 가지고 있던 것처럼 된다.

 

git rebasei 매개변수 없이 사용하면, 다른 브랜치의 변경 사항을 현재 브랜치의 이력에 재정렬하거나 고쳐 쓸 수 있다.
다른 브랜치의 변경 사항이 현재 브랜치에 원래부터 있던 것처럼 이력을 생성하는 방식으로 볼 수 있다.

 

git rebase에 재정렬에 이용할 태그를 지정하고 실행한다.

$ git rebase 1.0.1

 

실행하면 바로 오류가 발생한다.

5.4 충돌 다루기에서 충돌에 대처하는 방법을 다뤘다.
git mergetool
을 이용하는 것이 가장 무난한 방법이겠지만 이번에는 직접 수정하는 편이 더 쉽다.

사용자가 직접 합치는 편이 좋은 이유는 2중에서 선택해야 하는 상황이 아니기 때문이다.
1.0.1
에서 가져온 새로운 문단과 1.0 태그를 생성한 이후에 추가했던 순서 없는 목록 모두 필요하다.

따라서 파일을 직접 합치는 편이 가장 쉽다.

<<<<<<< HEAD:index.html

<p>

  Fixed

</p>

=======

<ul>

  <li><a href=bio.html>Biography</a></li>

</uul>

>>>>>>> add in a bio link:index.html

 

그냥 보통 파일처럼 보이도록 충돌 영역을 표시하는 3줄을 제거한다.
파일을 저장하고 다음 명령어를 실행하면, Git에 충돌이 해결됐음을 알리고 계속해서 재정렬을 수행하도록 한다.

$ git add index.html

$ git rebase continue

Applying: add in a bio link

 

다른 상황으로는 충돌이 있다.
절차는 거의 동일하다
.
이전과 같이 충돌을 수정하고, git add git rebase --continue를 호출한다.

물론 git rebase를 호출할 때, --skip을 지정해서 특정 커밋만 건너뛰거나 abort를 지정해서 재정렬하는 과정을 취소할 수 있다.

--onto 매개변수를 지정하면 이력을 또 다른 방식으로 고쳐 쓸 수 있다.
예를 들어 3개의 브랜치가 있다고 하자
.
master
브랜치와 master브랜치로부터 생성된 contact 브랜치, 그리고 contact 브랜치에서 생성된 search 브랜치다
.
3 브랜치에서 작업했던 내용은 다음과 같다. 연락처 작업 때문에 contact 브랜치의 코드를 이용했지만 도중에 검색 관련 코드를 추가하기로 결정했다
.
새로운 검색 코드를 끝마치고서 난 다음에야 contact 브랜치의 모든 변경 사항이 검색 관련 작업에 필요하지 않다는 사실을 깨달았다.

이런 경우에 --onto 매개변수를 이용한다.

--onto에는 재정렬 대상이 되는 하나의 브랜치를 지정한다.
search
master 브랜치로 재정렬하려는 명령어는 다음과 같다.

$ git rebase onto master contact search

search 브랜치를 contact 브랜치에서 떼어내서 master 브랜치로 옮긴다.

search 브랜치를 master 브랜치로 합치려고 하지만, contact 브랜치의 내용이 필요하지 않은 경우에 유용하다.
물론, 재정렬을 시작해서 변경 사항을 반영할 때 합쳐지면서 충돌이 발생하지 않으려면, search 브랜치의 내용은 완전히 독립적이어야 한다.

 

6.2 리비전 범위 지정하기에서 알아봤던 방식을 이용해서 --onto와 커밋 범위를 조합하면 다른 일도 할 수 있다.
예를 들어, git rebase를 이용해서 리비전을 지울 수 있다
.
2
단계 이전 커밋(HEAD^)을 지우는 명령어는 다음과 같다.

$ git rebase --onto HEAD^^ HEAD^ HEAD

이 명령어는 현재 HEAD로부터 2단계 이전 커밋에 현재 HEAD를 재정렬해서 HEAD^를 지운다.

 

물론 브랜치의 이력을 고쳐 쓰려면, 먼저 무언가 잘못됐을 때 어떻게 돌아올지에 대한 백업 계획을 준비해두는 게 좋다. 사용하고 있는 브랜치에 바로 반영하지 않고 실험용 브랜치를 만들 수도 있다.

Git에서는 브랜치를 생성하는 비용이 저렴하기 때문에 재정렬을 연습할 때는 사용하고 있는 브랜치 대신 연습용 브랜치를 만드는 것도 좋은 생각이다.

 

 

 

1.4.        Reflog 이용하기

리누스 토발스가 Git를 만들면서 정해둔 원칙 중 하나는 안전하다는 것이다.
비 파괴적이라는 말은 저장소의 어떤 시점으로도 다시 돌아갈 수 있어야 함을 의미한다
.
그러기 위해서는 상태에 따른 변경을 추적할 수 있는 기법이 필요하다.

 

Git을 이용하면 대부분의 버전 관리 시스템에서는 할 수 없는 일도 가능하다.
오래된 커밋을 변경하고, 커밋 하나를 여러 개로 쪼개고, 커밋을 제거하고, 중간에 커밋을 추가하는 동작은 Git에서는 가능하지만, 서브버전이나 CVS 같은 버전 관리 시스템에서는 불가능하다.

물론 이런 기능에는 위험이 따른다. git branch D를 이용해서 실수로 브랜치를 지웠거나 git rebase i를 잘못 조작했다면 어떻게 해야 할까?
이럴 때 reflog를 이용한다.

 

reflog는 브랜치가 변경될 때마다 계속해서 추적한다.
5
브랜치 이해하고 활용하기의 내용을 보면 브랜치는 단지 최신 커밋을 가리키고 있을 뿐이었다. reflog는 모든 변경을 추적한다. reflog를 이용하면 삭제한 브랜치를 복원할 때 체크아웃 해야 할 커밋을 찾을 수 있다.

 

예제로 확인할 수 있도록 간단한 저장소를 만든 다음 망쳐버리자.
저장소를 만들어 하나만 커밋하고, 그 다음 브랜치를 만들어 2개의 커밋을 추가한다
.
제대로 된 위치에 커밋하기만 하면 되니 아무 내용이나 넣어서 커밋하자.

이제 git rebase git rebase i를 이용해서 두번째 브랜치의 첫번째 커밋을 삭제한다.

 

git log를 이용해서 저장소의 이력이 어떻게 되었는지 확인해 볼 수 있다.

당연히 git rebase i가 커밋 하나를 지우고 나면 이력에는 2개의 커밋만 있다.

이제 reflog를 실행해보면 사실 더 많은 커밋이 있음을 확인할 수 있다.

$ git reflog

1b41334HEAD@{0}: commit: third commit

5e685deHEAD@{1}: checkout: moving from reflog to 5e685de

0cb04adHEAD@{2}: commit: third commit

71bc515HEAD@{3}: commit: second commit

5e685deHEAD@{4}: checkout: moving from master to reflog

 

git log의 출력 결과와 마찬가지로 최신 커밋이 가장 먼저 나타나며,
출력 결과에는
third commit이라는 메시지를 가진 커밋이 2개가 있다
.
0cb04ad
이 먼저 한 커밋이고, 1b41334 git rebase 71bc515를 지운 다음에 한 2번째 커밋이다.

따라서 먼저 했던 third commit을 복구하려면 단지 해당 커밋을 체크아웃 받으면 된다.

$ git checkout 0cb04ad

note: moving to 0cb04adwhich isnt a local branch

if you want to create a new branch from this checkout, you may do so (now or later) by using b with the checkout command again. Example: git checkout b <new_branch_name>

HEAD is now at 0cb04adthird commit

 

출력 메시지를 보면 알 수 있듯이 지금은 실제 브랜치 위에 있지 않다.
브랜치가 아니라고 해서 이력을 보지 못하는 건 아니지만
,
간단히 git checkout
b 를 실행하면 브랜치를 생성할 수 있다
.
이제 git log를 실행해보면 2번째 커밋이 복구되어 있다.

$ git log pretty=format:%h %s

0cb04ad third commit

71bc515 second commit

5e685de initial commit

 

당연한 얘기지만 브랜치를 생성하려고 체크아웃 받을 필요는 없다.
브랜치를 생성하기 전에 이력을 확인해야 하는 게 아니라면
,
그냥 간단히 git branch를 이용해서 브랜치를 바로 생성할 수 있다.

$ git branch reflog-restored 0cb04ad

$ git checkout reflog-restored

Switched to branch reflog-restored

 

git gc는 오래된 reflog 항목을 더 이상 유효하지 않게 만들 수 있다.
예를 들어, 방금 복구한 커밋은 보통 사흘 후에는 삭제되며, gc.reflogExpireUnreachable 설정을 바꾸면 변경이 가능하다
.
마찬가지로 보통의 reflog 항목들도 gc.reflogExpire를 변경하지 않으면 9일 후에는 유효하지 않게 된다 reflog가 너무 커지지 않도록 하기 위해서이다.

 

 

 

1.5.        저장소 양분하기

사람은 완벽하지 않기 때문에 이따금씩 발생하는 버그에 대비해야 한다.
단위테스트와 같은 도구는 버그의 위치를 찾을 수 있도록 돕는다
.
단위 테스트를 통해서도 버그의 위치를 찾지 못했다면, 저장소를 활용해서 버그가 발생한 시점을 찾아볼 수 있다
.
git bisect
는 버그가 나타난 시점을 찾을 때 이용하는 도구다.

 

git bisect는 이미 알고 있는 안전하지 않은 커밋과 안전한 커밋을 기반으로 한단계씩 옮겨가는 방식으로 동작한다. 버그를 야기한 커밋을 고립시킬 때까지 안전(good)과 안전하지 않음(bad)으로 표시하면서 이력을 따라간다.

먼저 버그를 확인하는 테스트 케이스를 만든다.
안전하지 않다고 확인된 커밋에서 테스트 케이스가 실패하는지 확인한다
.
그리고 안전하다고 확인된 커밋에서 테스트 케이스가 통과하는지도 확인한다.

 

 

안전한 커밋

 

 

 

안전하지 않은 커밋

 

 

v

?

?

?

X

 

 

이제 저장소의 위치를 안전하지 않은 커밋으로 돌려두고 git bisect start를 호출해서 저장소를 쪼개는 과정을 시작하자. 그 다음 git bisect bad를 실행하고, 마지막으로 git bisect good <커밋이나 태그>를 실행한다.
전체 과정은 다음과 같다.

$ git bisect start

$ git bisect bad

$ git bisect good 1.0

 

안전하지 않은 지점과 안전한 지점을 표시하면 git bisect는 사용자의 현재 위치를 저장소의 다른 위치로 변경한다.
2
지점 사이의 커밋을 취한 다음 이를 절반으로 쪼갠다. 그리고 나서 중간지점을 체크아웃 받는다. 이제 저장소는 다음과 같다.

 

git bisect는 중간 지점에서 시작한다.

 

 

안전한 커밋

 

양분화 시작 지점

 

안전하지 않은 커밋

 

 

v

?

?

?

X

 

 

이제 테스트를 다시 실행해서 이 커밋이 안전한지 아닌지를 확인해보자. 이번에는 커밋이 안전하지 않은 것으로 확인됐으니 해당 커밋을 git bisect bad로 안전하지 않다고 표시한다.

git bisect bad

 

이제 안전하지 않은 커밋과 안전한 커밋 사이에는 하나의 커밋만 남아있다.
논리적으로 생각해보면 이전 커밋은 안전하고 이 지점 이후의 커밋은 모두 안전하지 않으니, 이 지점이 안전하다면 다음 커밋이 버그의 원인이고, 이 지점이 안전하지 않다면 이 커밋이 버그의 원인이다
.
단위테스트를 해보자. 여기서는 이 커밋에서 버그가 발생했다고 여기자.

이 커밋도 안전하지 않다고 표시하면 Git은 버그를 발생시킨 커밋을 찾았음을 알아채고 이에 대한 로그를 보여준다. 지금까지 이력의 범위를 좁혀서 안전하지 않은 커밋을 파악했다.
이제 남은 일은 커밋에서 정확히 어떤 변경이 문제를 야기했는지 파악하고 문제를 고치는 일이다.

git bisect는 각 커밋을 확인하는 과정에서 사용자의 브랜치를 변경한다.
따라서 변경을 반영하기 전에 다시 이전에 작업하던 브랜치로 돌아가야 한다
.
git bisect reset
을 실행하면 된다.

$ git bisect reset

Switched to branch master

 

Git의 다른 명령어들과 마찬가지로 git bisect는 이렇게 단순한 형태보다 더 많은 것을 지원한다. git bisect visualize를 이용하면 변경 이력을 시각적으로 보여주므로 이해하기가 쉽다.

git bisect log를 이용하면 텍스트 형태로 어떤 커밋이 안전하다고 표시됐고, 어떤 커밋이 안전하지 않다고 표시됐는지를 볼 수 있다. 이 명령어는 잘못 표시한 커밋을 나중에 찾을 때도 유용하다.

 

잘못 표시한 커밋을 다시 제대로 표시하려면 git bisect log의 출력을 파일로 저장하고, 파일에서 실수한 시점 이후의 모든 내용을 제거하고 저장한다. 그러고 나서 저장한 파일을 git bisect replay <파일> 명령어의 매개변수로 지정하면 파일에 기록된 지점까지만 수행한다.

 

git bisect를 이용해서 버그가 발생된 커밋을 찾아가는 작업이 정말 좋기는 하지만, 수많은 작업을 일일이 손으로 해야 한다. 해야 할 일의 양도 양이지만, 사람이 하는 일이므로 오류가 발생할 수도 있다. 자동화된 테스트 스위트(test suite)가 있다면 수작업이 어느 정도는 줄겠지만, git bisect가 테스트 스위트를 알아서 실행하도록 만들면 수작업을 더 줄일 수 있다.

이렇게 하려면 커맨드 라인에서 실행할 수 있는 스크립트가 필요하다.
작성한 스크립트는 테스트가 통과하면 종료코드가 0으로 끝나고, 실패하면 종료코드가 0보다 큰 수로 끝나야 한다. 대개 실패하면 종료코드로 1을 사용한다.

이때, 125를 종료코드로 사용하면 현재 커밋에 표시하지 않고 다음 커밋으로 건너뛰므로 이런 용도가 아니라면 125를 사용하면 안 된다.
안전한지 아닌지를 테스트 할 수 없는 경우가 아니라면 보통은 커밋을 건너뛰려고 하지는 않을 것이다.

 

git bisect run을 실행하면 자동적으로 작성한 스크립트를 실행한다.
예를 들어, run-tests라는 스크립트를 만들었다면 다음과 같이 실행할 수 있다.

$ git bisect start HEAD 1.0

$ git bisect run /work/run-tests

running /work/run-tests

 

/work/run-tests라는 스크립트의 종료 코드를 이용한다는 차이를 제외하고는,
git bisect
는 사용자가 직접 하던 대로 계속해서 동작한다
.
스크립트에서 0이 아닌 숫자를 반환할 때마다 안전하지 않은 커밋으로 취급한다.

이 명령어에서는 저장소가 밖의 다른 디렉터리에 있는 스크립트 파일을 지정했음을 볼 수 있다. 실행할 스크립트 파일을 저장소 밖에 두면 git bisect가 실행되면서 저장소가 변경돼도 스크립트 파일이 바뀌지 않음을 보장할 수 있다. 꼭 저장소 밖의 파일을 이용해서 테스트를 진행해야 하는 것은 아니지만 불필요한 문제를 피할 수 있다.

 

출처 : http://youmin3.egloos.com/1990779

+ Recent posts