블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2013. 1. 13. 21:14 Git, GitHub

원격저장소로 GitHub을 이용하고 있고, Branch를 만들고 삭제하는 방법에 대해서 알아보자. 


1) 브랜치 생성, 삭제 순서 

  - local 저장소에 branch를 만든다 

  - remote 저장소로 branch를 push 하여 추적(tracking) 한다 

  - 사용하지 않는 branch는 삭제한다 

////////////////////////////////////////////////

// 새로운 브랜치를 생성하고 checkout 한다 

$ git checkout -b shopping_cart

Switched to a new branch 'shopping_cart'


////////////////////////////////////////////////

// 원격 저장소로 브랜치를 push 한다 

$ git push origin shopping_cart

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

Total 0 (delta 0), reused 0 (delta 0)

To https://github.com/ysyun/pro_git.git

 * [new branch]      shopping_cart -> shopping_cart


// github에 새로운 브랜치가 추가 되었다. 


///////////////////////////////////////////////

// 새로운 파일을 추가하고 원격으로 push 한다 

$ touch cart.js

$ git add cart.js

$ git commit -m "add cart javascript file"

[shopping_cart 4856f8d] add cart javascript file

 0 files changed

 create mode 100644 cart.js


$ git push

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

Counting objects: 3, done.

Delta compression using up to 2 threads.

Compressing objects: 100% (2/2), done.

Writing objects: 100% (2/2), 245 bytes, done.

Total 2 (delta 1), reused 0 (delta 0)

To https://github.com/ysyun/pro_git.git

   f42a865..4856f8d  shopping_cart -> shopping_cart


///////////////////////////////////////////////

// 로컬 브랜치 내역 과 원격 브랜치 내역을 본다 

$ git branch

  master

* shopping_cart


$ git branch -r

  origin/HEAD -> origin/master

  origin/master

  origin/shopping_cart


////////////////////////////////////////////////////

// 로컬의 새로 추가한 shopping_cart 브랜치를 삭제한다

$ git checkout master

Switched to branch 'master'


$ git branch -d shopping_cart

error: The branch 'shopping_cart' is not fully merged.

If you are sure you want to delete it, run 'git branch -D shopping_cart'.


$ git branch -D shopping_cart

Deleted branch shopping_cart (was 4856f8d).


$ git branch

* master


///////////////////////////////////////////////

// 로컬에 이제 shopping_cart 브랜치가 없다 다시 복구 하고 싶다면

// 원격 저장소를 통하여 checkout 하면 된다 

$ git checkout shopping_cart

Branch shopping_cart set up to track remote branch shopping_cart from origin.

Switched to a new branch 'shopping_cart'


$ git branch

  master

* shopping_cart


///////////////////////////////////////////////

// 원격의 브랜치 내역을 보자

// 어떤 브랜치들이 존재하는지 한눈에 알 수 있다 

$ git remote show origin

* remote origin

  Fetch URL: https://github.com/ysyun/pro_git.git

  Push  URL: https://github.com/ysyun/pro_git.git

  HEAD branch: master

  Remote branches:

    master        tracked

    shopping_cart tracked

  Local branches configured for 'git pull':

    master        merges with remote master

    shopping_cart merges with remote shopping_cart

  Local refs configured for 'git push':

    master        pushes to master        (up to date)

    shopping_cart pushes to shopping_cart (up to date)


///////////////////////////////////////////////

// 원격에 있는 브랜치를 삭제 하자 

$ git push origin :shopping_cart

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

To https://github.com/ysyun/pro_git.git

 - [deleted]         shopping_cart


// shopping_cart 브랜치가 삭제되었음을 알 수 있다

$ git remote show origin

* remote origin

  Fetch URL: https://github.com/ysyun/pro_git.git

  Push  URL: https://github.com/ysyun/pro_git.git

  HEAD branch: master

  Remote branch:

    master tracked

  Local branch configured for 'git pull':

    master merges with remote master

  Local ref configured for 'git push':

    master pushes to master (up to date)


///////////////////////////////////////////////

// remote 브랜치 clean up 하기 

$ git remote prune origin


UserXP@NUKNALEA /d/Git_repositories/pro_git (master)

$ git remote show origin

* remote origin

  Fetch URL: https://github.com/ysyun/pro_git.git

  Push  URL: https://github.com/ysyun/pro_git.git

  HEAD branch: master

  Remote branch:

    master tracked

  Local branch configured for 'git pull':

    master merges with remote master

  Local ref configured for 'git push':

    master pushes to master (up to date)


2) master가 아닌 local 브랜치를 remote 저장소의 master 브랜치에 push 하기 

  - 조건 : local 저장소의 브랜치가 master가 아닌 다른 브랜치로 checkout 되어 있을 경우 예) shopping_cart

  - 명령 :  git push [원격저장소 주소 alias] [로컬저장소명칭]:master

  - 예 : git push origin shopping_cart:master

  - 의미 : origin 원격 주소의 master 브랜치에 local저장소의 shopping_cart 브랜치를 push 한다


posted by 윤영식
2013. 1. 13. 20:40 Git, GitHub

Git clone후에 두명 이상이 작업을 한다. 그리고 같은 파일을 수정하여 Remote 저장소에 Push 할 경우 merge conflict가 발생한다. 이를 해결하기 위한 과정을 알아보자 


1) merge conflict 조건

  - 한명이 같은 파일을(예, README.md) 수정하고 GitHub(remote repository)에 push하였다. 

  - 다른 사람이 README.md 파일 내역을 수정하고 GitHub에 push 하려고 한다. 

  - 이때 git은 fail 메시지를 뱃으면서 push 되지 않는다. 

   

  - github에 한명이 push하여 분홍색으로 있고, gregg는 local 저장소에 commit된 내역을 push 하려고 할 경우


2) merge conflict 해결하기 

  - push : GitHub에 push하려 했더니 conflict가 발생함 

  - pull : GitHub 변경내용을 local 저장소와 merge 하기 

  - edit : 충돌나는 부분이 있다면 직접 편집하기 

  - commit -a : 다시 모든 파일을 commit 하기 

  - push : 변경된 내역을 다시 GitHub에 push하기 

/////////////////////////////////////////////////////////////////////

// 이미 github에는 README.md 파일이 수정되어 있음 (위 그림의 분홍색)

// "It was changed in Github directly by yun dowon" 메시지 commit

///////////////////////////////////////////////////////////////////////////////////////

// README.md  파일에 

// "checkout merge conflict with same file when another change it differently." 내용을 추가함

// (위 그림의 초록색 gregg로 보면 됨)

$ cat README.md

pro_git

=======


test pro git books

checkout merge conflict with same file when another change it differently.


// 추가된 내용을 commit 함 

$ git commit -am "change README.md"

[master fbf9382] change README.md

 1 file changed, 2 insertions(+), 1 deletion(-)


/////////////////////////////////////

// GitHub에 반영할려고 함 

$ git push

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

To https://github.com/ysyun/pro_git.git

 ! [rejected]        master -> master (non-fast-forward)

error: failed to push some refs to 'https://github.com/ysyun/pro_git.git'

hint: Updates were rejected because the tip of your current branch is behind

hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')

hint: before pushing again.

hint: See the 'Note about fast-forwards' in 'git push --help' for details.


////////////////////////////////////////////////

// pull 을 수행 

$ git pull

remote: Counting objects: 5, done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 3 (delta 1), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

From https://github.com/ysyun/pro_git

   9ae6fb2..c917ae5  master     -> origin/master

Auto-merging README.md

CONFLICT (content): Merge conflict in README.md

Automatic merge failed; fix conflicts and then commit the result.


// 현재 상태를 확인

$ git status

# On branch master

# Your branch and 'origin/master' have diverged,

# and have 1 and 1 different commit each, respectively.

#

# Unmerged paths:

#   (use "git add/rm <file>..." as appropriate to mark resolution)

#

#       both modified:      README.md

#

no changes added to commit (use "git add" and/or "git commit -a")


////////////////////////////////////////////////////////////////

// README.md 파일이 GitHub내용과 Local 저장소 내용이 합쳐졌다

$ cat README.md

pro_git

=======


test pro git books

<<<<<<< HEAD

checkout merge conflict with same file when another change it differently.  <-- Local 저장소 내역

=======

It was changed in GitHub directly by yun dowon  <-- Remote 저장소 내역

>>>>>>> c917ae5f7787844b63826a460d82a998bad08a7f 


///////////////////////////////////////////

// 변집기를 통하여 직접 내용을 적절히 수정함

$ vi README.md

$ git status

# On branch master

# Your branch and 'origin/master' have diverged,

# and have 1 and 1 different commit each, respectively.

#

# Unmerged paths:

#   (use "git add/rm <file>..." as appropriate to mark resolution)

#

#       both modified:      README.md

#

no changes added to commit (use "git add" and/or "git commit -a")


///////////////////////

// 다시 commit을 한다 

$ git commit -a

[master f42a865] Merge branch 'master' of https://github.com/ysyun/pro_git


UserXP@NUKNALEA /d/Git_repositories/pro_git (master)

$ git status

# On branch master

# Your branch is ahead of 'origin/master' by 2 commits.

#

nothing to commit (working directory clean)


/////////////////////////////////////////////////

// conflict가 해결되었으면 다시 push 하여 통합한다

$ git push

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

Counting objects: 10, done.

Delta compression using up to 2 threads.

Compressing objects: 100% (6/6), done.

Writing objects: 100% (6/6), 734 bytes, done.

Total 6 (delta 3), reused 0 (delta 0)

To https://github.com/ysyun/pro_git.git

   c917ae5..f42a865  master -> master


////////////////////////

GitHub에 push된 내용 


3) merge conflict 시에 pull 의미 

  - git fetch : remote 브랜치 하나가 local 저장소로 내려온 것이고, local 저장소에 commit 된 상태는 아님 

  - git merge origin/master : local 저장소의 master와 origin/master 브랜치를 merge 함 

  - pull = git fetch + git merge origin/master 두개가 동시에 수행된 것임 

posted by 윤영식
2013. 1. 13. 20:00 Git, GitHub

git에서 merge를 할 경우 내용으로 fast-forward merge라는 용어가 나온다. 이에 대해서 알아보자.


1) fast-forwad merge 의 조건

  - master에서 새로운 branch를 만든다 

  - 새로운 branch에서 추가한 파일을 commit한다. 이때 master에서는 아무런 commit 내용도 없다.

   

//////////////////////////////////////////////////////

// cat branch를 만들고 cat으로 checkout 한다 (-b 옵션)

$ git branch -b cat


$ git branch

* cat

 master


///////////////////////////////////////////////////////////////

// 파일을 하나 만들고 commit 한다. 새로운 commit 이 생긴 것이다. 

$ echo "dowon" > cat.txt

$ git add cat.txt

$ git commit -m "add cat.txt"

[cat 1e6ea90] add cat.txt

The file will have its original line endings in your working directory.

 1 file changed, 1 insertion(+)

 create mode 100644 cat.txt


// cat branch안에 cat.txt 파일이 보인다

$ ls

README.md  build.gradle  cat.txt  todo.txt


// master branch로 이동을 한다 

$ git checkout master

Switched to branch 'master'

Your branch and 'origin/master' have diverged,

and have 1 and 3 different commits each, respectively.


////////////////////////////////////////////

// master에는 cat.txt 파일이 존재하지 않는다. 

$ ls

README.md  build.gradle  todo.txt


////////////////////

// merge를 수행한다

$ git merge cat

Updating 8ee3f5e..1e6ea90

Fast-forward

 cat.txt | 1 +

 1 file changed, 1 insertion(+)

 create mode 100644 cat.txt


////////////////////////////////////////////////
// 사용하지 않는 cat branch는 삭제한다. (-d 옵션)
$ git branch -d cat 


posted by 윤영식
2013. 1. 13. 19:32 Git, GitHub

로컬에서 Git을 사용하다가 실수로 Commit을 할 경우 다시 이전 상태로 원복하고 싶을 때 가장 많이 사용하는 명령를 알아보자.


1) 방금 commit한 내용을 staging area로 돌려 놓고 싶을 경우 

  - 명령 : git reset --soft HEAD^

  - HEAD : 현재 commit의 포인터,  ^ : 이전 것,  --soft : staging으로 옮기기

$ git reset --soft HEAD^


// commit 했던 LICENSE 파일이 staged area에 존해함

$ git status

# On branch master

# Changes to be committed:

#   (use "git reset HEAD <file>..." to unstage)

#

#       new file:   LICENSE

#


2) 방금 commit 한 것에 다른 파일로 추가 하여 넣고 싶을 경우 (commit은 증가하지 않음)

  - 명령 : git commit --amend -m "add new file"

  - --amend : 최근 기존 commit에 추가하기 

// 새로운 파일을 만든다 

$ touch todo.txt

$ touch add todo.txt 


// 기존 commit에 todo.txt 파일 추가하기 

$ git commit --amend -m "new thing file"

[master 18b3bb7] new thing file

  1 file changed, 3 insertions(+)

 create mode 100644 todo.txt

 create mode 100644 LICENSE


3) 현재 commit한 것을 없애버리고 싶을 경우 (방금 commit한 내용이 staging 가지 않고 없어진다)

  - 명령 : git reset --hard HEAD^

//현재 commit 내역을 본다 

$ git log

commit 18b3bb76c5d16c76221d45b1bc61b483001191d4

Author: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Sun Jan 13 18:43:03 2013 +0900


    new thing file


commit 329db048ff7af2d417588e28da50a6c53fb1bd84

Author: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Thu Dec 27 11:07:26 2012 +0900


    add content in build.gradle


// 최신 commit 18b3bb76c5d16c76221d45b1bc61b483001191d4 을 삭제했다

$ git reset --hard HEAD^

HEAD is now at 329db04 add content in build.gradle


UserXP@NUKNALEA /d/Git_repositories/pro_git (master)

$ git log

commit 329db048ff7af2d417588e28da50a6c53fb1bd84

Author: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Thu Dec 27 11:07:26 2012 +0900


    add content in build.gradle


4) 그럼 현재 commit 에서 두단계 이전 commit으로 이동하면서 앞 두단계를 삭제하고 싶다면 

  - 명령 : git reset --hard HEAD^^

  - ^ 이전, ^^ 이전에 이전 (두단계 이전)

posted by 윤영식
2013. 1. 13. 12:42 NodeJS/Modules

Socket.io안에서 사용되는 WebSocket 에 대한 프로토콜의 위치에 대하여 알아보자.


1) WebSocket 등장배경

  - 처음엔 iframe을 활용

  - 그다음은 XMLHTTPRequest를 이용

  - HTML5에 와서 Websocket 등장

  - SPDY 포로토콜을 통한 전송 압축 (성능향상)

  - Server Send Events (SSE)에 대한 이해


2) SPDY 프로토콜 등장배경

  - 실시간 Push 효과적 (압축 및 암호)

  - Node-SPDY 

  - Chrome/Firefox 지원


  - chrome://net-internals/#spdy  명령을 통해서 Chrome의 다양한 통신 내역을 살펴볼 수 있다.


3) 결론
  - Chrome이나 Firefox에서만 구동 될 수 있는 솔루션을 만들경우
  - Real-time Push 서비스를 할 경우 성능을 높이기 위해 사용
  - Node.js를 사용할 경우도 지원 


posted by 윤영식
2013. 1. 13. 12:34 HTML5, CSS3/jQuery

jQuery를 통하여 DOM 조작을 할때 HTML안에 span 또는 div의 id 또는 class의 조작을 하면 편하게 할 수 있다. 이때 span과 div는 어떤 차이가 있을까 알아보자. 


1) Span & Div 차이점

  - div 가로폭을 전부 차지함. span 태그안의 내용만 차지함

   


  - div 폭과 넓이 지정가능, span 못함

  - div 필연적으로 줄 바꿈을 동반, span 줄 바꿈 없고 문장 중간에 들어갈 수 있음

  - table 태그 대신 div와 span 태그로 더욱 간결한 html을 구성할 수 있다.

        

<참조>

http://chatii.tistory.com/45 : div와 span 태그의 차이점 비교 

http://ccoma.tistory.com/746 : table 태그를 대신하여 div 와 span 태그를 사용하여 화면 구성을 어떻게 하는가?

http://yongja.tistory.com/15 : div/span 과 id/class에 대한 이해.

posted by 윤영식
2013. 1. 11. 09:52 Languages/Java

1) Korea Spring User Group의 세미나 자료  


1. Spring MVC를 손쉽게 테스트하기 (백기선) : 동영상 , 발표 자료

2. RESTful API(including Mobile) with Spring 3.1 (윤성준) : 동영상발표 자료

3. Spring 3.1에서 Ehcache 활용전략  (김흥래) : 동영상발표 자료

4. SpringFramework in Scala (석종일) : 동영상발표 자료

5. Type-safe querying using Querydsl (김영한) : 동영상발표 자료



2) 내 관심 사항

  - 테스트하기 

  - RESTful API 만들기 

  - Ehcache 활용전략

posted by 윤영식
2013. 1. 11. 09:20 Middleware, Cloud/Linux

제목과 같은 경우 w 명령어가 있다. 


1) w - show who is logged on and what they are doing  : 로그인 사용자가 지금 수행중인 명령어를 볼 수 있다.

  - 예로 상대가 NFS(Network File System)를 마운트하고 있는데, 정확한 위치의 File을 상대가 마운트했는지 알려면 w 하라

  - w를 치면 누가 접속을 했고, 어떤 명령을 수행했는지 알 수 있다.

[jboss@host01 ~]$ w

 09:15:34 up 113 days,  6:32,  3 users,  load average: 0.05, 0.11, 0.10

USER     TTY         FROM           LOGIN@  IDLE   JCPU   PCPU   WHAT

jboss    pts/1        10.222.111.2     07:19     32:33    0.90s  0.83s    tail -100f xxxDomain.out

comc01 pts/0        10.222.111.2     Thu17   15:58m  0.11s  0.10s     vim company-log.log

jboss    pts/2        10.222.111.2     09:15     0.00s    0.01s  0.00s     w


<참조>

http://linux.about.com/library/cmd/blcmdl1_w.htm

'Middleware, Cloud > Linux' 카테고리의 다른 글

[Linux] Bash Shell for Log Backup  (0) 2013.02.20
[Linux] CPU 갯수 알아내기  (0) 2013.02.07
[Linux] Free Memory 사이즈 알기  (0) 2012.12.07
[Linux] Ubuntu 에 Maven 2 설치  (0) 2012.11.23
[Linux] vsftpd 설치하기  (0) 2012.11.21
posted by 윤영식
2013. 1. 11. 00:04 AngularJS/Concept

1) Single Page Application을 만들기 위한 기본기 다지기

  - CoffeeScript을 사용한다 : JavaScript 문법오류에서 해방 될 수 있다

  - Backbone을 사용한다 : CoffeeScript와 함께 사용한다 

  - JSON을 통하여 Rest API를 사용한다 

  - 대표적 SPA 서비스 : Trello, Facebook, Gmail


2) Single-Page Application을 위한 Backbone과 Node.js

  - Airbnb 서비스 사용예

  - I18n 


- SPA를 위한 Toolchain

posted by 윤영식
2013. 1. 10. 23:33 Backbone.js

1) Backbone의 탄생

  - Clean Code를 위한 UI 단의 MVC Framework 

  - Single Page Application (SPA)를 구현하는 가벼운 Framework


2) Backbone과 함께 협력하는 모듈들

  - Backbone과 함께 쓸 수 있는 모듈은?

  - 프로젝트 구조는?

  - Underscore.js, jQuery 의존. MIT 라이센스


3) Backbone의 아키텍쳐 

  - DOM UI + View(Template) + Model(Collection) 동작방식 및 설명

  - Large Scale Application 개발시 사용하라

  - Backbone으로 만들어 보는 Chaplin : https://github.com/chaplinjs/chaplin (Real-World Single-page application)

  - Chaplin에 대한 설명 : 다양한 패턴을 사용한다


posted by 윤영식

프로젝트 및 클래스를 생성하는 빠른 방법에 대해서 알아보자 


1) Project 생성

  - File -> New Project...

  - 프로젝트 명칭, 소스디렉토리, SDK 버전, 개발프레임워크등을 선택한다

  - .idea 와 [프로젝트명].iml 내부 환경파일이 생성됨 


2) Package 생성

  - Alt + Insert 키를 눌러서 package를 생성한다 

  - com.dowon.smart.dashboard 식의 full package를 넣는다


3) Class 생성

  - Alt + Insert 키를 눌러서 class를  생성한다

  - 상속받을 class wizard는 안나타남 : Ctrl+Shift+O 키를 누르면 상속받은 클래스의 메소드가 나옴 선택하여 Overriding 또는 implement 하면 됨 


4) 빠르게 코딩하기 

  - public static void main... 은 psvm TAB 키를 넣으면 자동 생성됨 

  - System.out.println 은 sout TAG 키를 넣으면 자동 생성됨

  - Alt + Backspace == ctrl + z in eclipse 이전 코딩으로 돌아가기 


5) Test Class 및 Method 만들기

  - Ctrl + Shift + T

  - 위저드가 뜨면 JUnit4 선택해서 만들기 


<참조>

  - JetBrains Wiki

  - DZone reference cardz

posted by 윤영식

Eclipse사용자가 IntelliJ IDEA로 옮겨 갈 때 가장 힘든 부분이 단축키 찾는 것이 아닐까 한다. 요약해 보자


1) 프로젝트의 참조 Libraries 관리 : ctrl + alt + shift + s  (설정참조)

2) JetBrains Wiki (참조)

ShortcutDescription
Alt+F1Switch between views (Project, Structure, etc.).
Ctrl+TabSwitch between the tool windows and files opened in the editor.
Alt+HomeShow the Navigation bar.
Ctrl+JInsert a live template.
Ctrl+Alt+JSurround with a live template.
F4Edit an item from the Project or another tree view.
Alt+EnterUse the suggested quick fix.
Ctrl+Slash or Ctrl+Divide 
Ctrl+Shift+Slash orCtrl+Shift+Divide
Comment or uncomment a line or fragment of code with the line or block comment.
Ctrl+N
Ctrl+Shift+N
Find class or file by name.
Ctrl+DDuplicate the current line or selection.
Ctrl+W and Ctrl+Shift+WIncremental expression selection.
Ctrl+F or Alt+F3Find text string in the current file.
Ctrl+Shift+FFind in the current folder.
Ctrl+Shift+F7Quick view the usages of the selected symbol.
Ctrl+Add or Ctrl+Equals 
Ctrl+Subtract or Ctrl+Minus
Expand or collapse a code block.
Ctrl+SpaceInvoke code completion.
Ctrl+Shift+EnterSmart statement completion.

3) Eclipse와 IntelliJ 비교 키 (참조)
EclipseIntelliJ IDEADescription
F4ctrl+hshow the type hierarchy
ctrl+alt+gctrl+alt+F7find usages
ctrl+shift+uctrl+f7finds the usages in the same file
alt+shift+rshift+F6rename
ctrl+shift+rctrl+shift+Nfind file / open resource
ctrl+shift+x, jctrl+shift+F10run (java program)
ctrl+shift+octrl+alt+oorganize imports
ctrl+octrl+F12show current file structure / outline
ctrl+shift+mctrl+alt+Vcreate local variable refactoring
syso ctrl+spacesout ctrj+jSystem.out.println(“”)
alt + up/downctrl + shift + up/downmove lines
ctrl + dctrl + ydelete current line
???alt + hshow subversion history
ctrl + hctrl + shift + fsearch (find in path)
“semi” set in window-> preferencesctrl + shift + enterif I want to add the semi-colon at the end of a statement
ctrl + 1 or ctrl + shift + lctrl + alt + vintroduce local variable
alt + shift + salt + insertgenerate getters / setters
ctrl + shift + fctrl + alt + lformat code
ctrl + yctrl + shift + zredo
ctrl + shift + cctrl + /comment out lines (my own IDEA shortcut definition for comment/uncomment on german keyboard layout on laptop: ctrl + shift + y)
ctrl + alt + hctrl + alt + h (same!)show call hierarchy
none ?ctrl + alt + f7to jump to one of the callers of a method
ctrl + shift + ialt + f8evaluate expression (in debugger)
F3ctrl + bgo to declaration (e.g. go to method)

posted by 윤영식
2013. 1. 8. 21:54 Testing, TDD/Test First

1) Clean Code를 만들기 위한 Unit Testing에 대한 이해


2) Test Driven Development(TDD)를 위한 Unit Testing

* 2)번 슬라이드중 TDD를 가장 잘 설명한 그림 : 설계->Test(Fail) -> 구현 -> Test(Success)



3) Unit Testing을 위한 가장 효과적인 방법들


4) 테스트를 위한 도구들에 대한 생각


* 4) 슬라이드에서 나온 도구 그림

posted by 윤영식
2013. 1. 8. 21:26 CI

이제 Maven에서 Gradle로 옮겨가자. Maven의 XML의 복잡함과 의존관계에 머리 좀 아팠다면 이제 Gradle로 옮겨서 Human Readable하게 생활하자. 


* 참조서적 : Building and Testing with Gradle


1) http://www.gradle.org/ 에서 설치 파일을 다운로드 받는다 

  - gradle-1.3-all,zip 파일

  - 특정 디렉토리에 풀어 놓는다 


2) Window라면 환경변수의 Path에 <gradle설치디렉토리>/bin을 잡아준다 (필수)



3) 역시 환경변수로 GRADLE_HOME=<gradle설치디렉토리> 를 잡아준다 (옵션)


4) build.gradle 파일을 만들어서 수행해 보자 

// build.gradle 파일 

task helloworld << {

  println 'hello dowon'

}

  - 수행 결과 


이제 Gradle로 시작해 보자. 

posted by 윤영식
2013. 1. 8. 20:42 Git, GitHub/Git Lec02

Git의 열거형 명령을 하나의 Alias로 지정할 수 있다. 설정 방법을 알아보자 


1) Alias 설정하기 : git config --global alias.[Alias명] '[명령]'

  - Ustage상태로 변경 : git config --global alias.unstage 'reset HEAD --' 로 설정하면 하기 명령은 동일하다 

    $ git unstage fileA

    $ git reset HEAD fileA 

  - last 명령 : git config --global alias.last 'log -l HEAD'

$ git config --global alias.last 'log -l HEAD'


$ git last

commit 329db048ff7af2d417588e28da50a6c53fb1bd84

Author: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Thu Dec 27 11:07:26 2012 +0900


    add content in build.gradle


commit f856853c5b0ac53483f9d14fe1b3ec6ef0fdbca7

Author: 윤도원 (영식) <ysyun@yuwin.co.kr>

Date:   Thu Dec 27 11:01:23 2012 +0900


    Update build.gradle


commit 03ca40a6026b9144f15cc8988ad6539049d36486

Author: 윤도원 (영식) <ysyun@yuwin.co.kr>

Date:   Wed Dec 26 17:55:01 2012 -0800


    Create build.gradle


2) 많이 사용하는 git alias : 참조사이트 

[alias]

git config --global alias.st status

git config --global alias.co checkout

git config --global alias.ci commit

git config --global alias.br branch

git config --global alias.unstage 'reset HEAD --'

git config --global alias.cs "commit -s"

git config --global alias.last 'log -1 HEAD'

git config --global alias.visual '!gitk'


* 현 브랜치의 히스토리를 short SHA값, author 정보, 커밋 트리 그리고 히스토리에서 특정 커밋을 가르키는 refs(브랜치, 태그)보기

  $ git config --global alias.lg "log --name-status --color --abbrev-commit --date=relative --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'"


  $ git lg 결과를 색깔별로 보여줌 


* 브랜치를 중심으로 히스토리를 보고 싶을 경우

  $ git config --global alias.tree "log --graph --decorate --pretty=oneline --abbrev-commit --all"

  또는 $ git config --global alias.lol 'log --oneline --graph --decorate'

  $ git tree 또는 git lol 수행 결과


* Visual 윈도우에서 변경 내역 보기 

  $ git config --global alias.visual '!gitk'

  $ git visual 을 수행하면 하기 화면이 뜬다 


<참조>

  - dogfeet alias 설정

  - 개발자 하루 alais 설정

  - 자료 : 민트기술

   Git-Guide-r1.pdf

posted by 윤영식
2013. 1. 8. 20:12 Git, GitHub/Git Lec02

SVN의 Tag처럼 Git에도 Tag가 있다. 어떻게 사용하는지 보자 


1) Tag 조회하기 : git tag 

  - 특정 버전 조회시 git tag -l 'v1.4.2.*' 식으로 조회한다


2) Annotated Tag 붙이기 : git tag -a [버전] -m '[메시지]'

  - Tag를 만든 사람의 이름, 이메일, 날짜, 메시지를 저장함. 단순 Tag일때는 Lightweight Tag를 사용함 

  - Tag 정보와 커밋 정보 보기 : git show [버전]

$ git tag -a v1.1 -m 'pro git version 1.1'


$ git tag

v1.1


$ git show v1.1

tag v1.1

Tagger: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Tue Jan 8 19:40:20 2013 +0900


pro git version 1.1


commit 329db048ff7af2d417588e28da50a6c53fb1bd84

Author: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Thu Dec 27 11:07:26 2012 +0900


    add content in build.gradle


3) Lightweight Tag : git tag [버전]

  - 브랜치처럼 가리키는 지점을 최신 커밋으로 이동시키지 않는다. 단순 특정 커밋에 대한 포인터일 뿐임 (체크섬만을 저장할 뿐)

  - -a, -s, -m 등의 옵션을 사용하지 않는다 

$ git tag v1.1w


$ git tag

v1.1

v1.1w


// 단순히 커밋 정보만 보여준다

$ git show

commit 329db048ff7af2d417588e28da50a6c53fb1bd84

Author: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Thu Dec 27 11:07:26 2012 +0900


    add content in build.gradle


4) Tag 검증하기 : git tag -v [버전]

  - GPG 서명을 검증하는 것으로 공개키가 필요하다

  - 서명 메시지가 없으면 하기와 같은 error 메시지가 나옴 (다음 기회에 다시 알아보자)

 $ git tag -v v1.1

object 329db048ff7af2d417588e28da50a6c53fb1bd84

type commit

tag v1.1

tagger Yun DoWon <ysyun@yuwin.co.kr> 1357641620 +0900


pro git version 1.1

error: no signature found

error: could not verify the tag 'v1.1'


5) 나중에 Tag 하기 : git tag -a v1.2 [해쉬값 앞 7자리] -m '[메시지]'

  - 과거 특정 커밋에 대해서 Tag를 달 수 있다. 커밋 내역 확인하기 : git log --pretty=oneline

$ git log --pretty=oneline

329db048ff7af2d417588e28da50a6c53fb1bd84 add content in build.gradle

f856853c5b0ac53483f9d14fe1b3ec6ef0fdbca7 Update build.gradle

03ca40a6026b9144f15cc8988ad6539049d36486 Create build.gradle

49c657f59b787b0ee8409782cd1d5ff16b78033d Initial commit


// 메시지를 -m을 넣지 않으면 하기와 같이 오류 발생함

$ git tag -a v1.2 03ca40a

fatal: no tag message?


$ git tag -a v1.0.1 03ca40a -m 'v1.0.1'


$ git tag

v1.0.1

v1.1

v1.1w


$ git show v1.0.1

tag v1.0.1

Tagger: Yun DoWon <ysyun@yuwin.co.kr>

Date:   Tue Jan 8 19:57:06 2013 +0900


v1.0.1


commit 03ca40a6026b9144f15cc8988ad6539049d36486

Author: 윤도원 (영식) <ysyun@yuwin.co.kr>

Date:   Wed Dec 26 17:55:01 2012 -0800


    Create build.gradle


6) Tag 공유하기 : git push origin [버전]

  - 서버로 Branch를 push 하는 것과 동일하다 

  - 한번에 여러 개의 tag를 push 하기 : git push origin --tags

$ git push origin v1.1

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

Counting objects: 1, done.

Writing objects: 100% (1/1), 169 bytes, done.

Total 1 (delta 0), reused 0 (delta 0)

To https://github.com/ysyun/pro_git.git

 * [new tag]         v1.1 -> v1.1


$ git push origin --tags

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

Counting objects: 1, done.

Writing objects: 100% (1/1), 159 bytes, done.

Total 1 (delta 0), reused 0 (delta 0)

To https://github.com/ysyun/pro_git.git

 * [new tag]         v1.0.1 -> v1.0.1

 * [new tag]         v1.1w -> v1.1w


posted by 윤영식
2013. 1. 7. 22:42 CI/Jenkins, Travis

Jenkins를 설치하고 로그인 Security 설정하는 법을 알아보자. 


1) 우선 jenkins.war 을 다운로드 받는다. 

  - http://jenkins-ci.org 사이트 방문

  - war 파일 다운로드 하기 (윈도우의 exe 버전은 받지 말자)

    


2) 특정 디렉토리에 jenkins.war파일을 놓고, bat 파일을 만들자

  - d:/jenkins/jenkins.war 파일 놓기 

  - d:/jenkins/startJenkins.bat 파일 만들기 (물론 JDK1.5 이상 버전으로 pre-install 되어 있어야 한다)

java -jar ./jenkins.war


3) jenkins를 실행하고 브라우져에서 호출하기 

  - startJenkins.bat파일을 수행하였다면 다음과 같은 메세지가 나온다

   


  - 브라우져에서 호출을 한다. 이때 http://yourdomain.wowip.kr:8080/ 방식으로 호출하고 싶다면 jenkins 설치 PC에 WOWIP를 설치하자. (설치가 안되었다면 우선 http://127.0.0.1:8080/ 으로 호출한다)


  - "Jenkins 관리" 메뉴 클릭 -> "Configure Global Security" 클릭 한다


4) Security를 설장한다

  - "Enable security" 를 체크한다 

  - Security Realm 그룹에서 "Jenkins's own user database"를 클릭하고 하위의 "Allow users to sign up"을 체크한다

  - Authroization 그룹에서 "Matrix-based security"를 체크한다

 


5) "Matrix-based security"를 체크하였다면 로그인 아이디를 입력하고 "add" 한 후 설정하고 싶은 권한을 체크한다

 

- 화면 하단의 "Save" 버튼을 클릭하여 적용한다 


6) 등록된 아이디에 대해서 "가입"을 한다. 

  - 메인 화면으로 나오면 상단 오른쪽의 "가입"을 클릭한다

  


  - 등록된 계정에 대하여 입력하고 설정하려는 패스워드와 e-mail주소를 입력한다

  


7) 이제 로그인을 하면 설정된 권한의 메뉴가 좌측에 나온다

  


* 참조 : Jenkins Standard Security Setup

'CI > Jenkins, Travis' 카테고리의 다른 글

[Travis] GitHub과 Travis CI 연동하기  (0) 2013.08.14
[Jenkins] Jenkins와 Gradle 그리고 JavaScript  (0) 2012.12.26
posted by 윤영식
2013. 1. 5. 17:06 MongoDB

http://mongoosejs.com (GitHub)에 대하여 알아보자. (mongoose의 light-weight ORM version으로 몽고리안-mongolian-도 존재한다)


1) mongoose의 schema는 extension = controller 이다 : Node.js 소스 

/**

* Module dependencies.

*/


var express = require('express')

, routes = require('./routes');


var mongoose = require('mongoose');

var Schema = mongoose.Schema;


mongoose.connect('mongodb://localhost/mydb');


var UserSchema = new Schema({ // MVC controller

age : Number,

name: String,

sex: Boolean

});


var UserModel = mongoose.model('users', UserSchema); // Model ---> collection


var app = module.exports = express.createServer();


// Configuration


app.configure(function(){

app.set('views', __dirname + '/views');

app.set('view engine', 'jade');

app.use(express.bodyParser());

app.use(express.methodOverride());

app.use(app.router);

app.use(express.static(__dirname + '/public'));

});


app.configure('development', function(){

app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));

});


app.configure('production', function(){

app.use(express.errorHandler());

});


// Routes


app.get('/', routes.index);


app.param('name', function (req, res, next, name) {

UserModel.find({ name: name }, function (err, docs) {

req.user = docs[0];

next();

});

});


app.get('/users/:name', function (req, res) {

// res.json({ user: req.user });

res.render('./show',{ title: 'Express User',user: req.user });

});


app.get('/users/:name/edit', function (req, res) {

res.render('./edit',{ title: 'Express User',user: req.user });

});


app.get('/users', function (req, res) {

// res.json({ user: req.user });

UserModel.find({},function(err,docs) {

res.render('./users', { title: 'Express User', users: docs });

});

});


app.get('/user/new', function (req, res) {

res.render('new',{layout:false}); //,user:{name:'',age:0,sex:false}}); //,{ title: 'Express User'});

});


app.del('/users/:name', function (req, res) {


UserModel.remove({ name: req.params.name }, function (err) {

res.redirect('/users');

});


});


app.post('/users', function (req, res) {

var b = req.body;

new UserModel({

name: b.name,

age: b.age,

sex:b.sex

}).save(function (err, user) {

if (err) res.json(err);


res.redirect('/users/' + user.name);

});

});


app.put('/users/:name/edit', function (req, res) {

var b = req.body;

UserModel.update(

{ name: req.params.name },

{ name: b.name, age: b.age, sex: b.sex },

function (err) {

res.redirect('/users/' + b.name);

}

);


});


app.listen(process.env.port || 3000);

console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);


  - Jade 소스

h1 Edit User


form(method='POST', action('/users/#{user.name}'))

input(type='hidden',name='_method',value='PUT')

p Name:

input#name(type='text', name='name', value='#{user.name}')

p Age:

input#age(type='number', name='age', value='#{user.age}')

p Sex:

input#sex(type='boolean', name='sex', value='#{user.sex}')

p

button(type='submit') Update


h1 New User


form(method='POST', action= '/users')

p Name:

input#name(type='text',name='name')

p Age:

input#age(type='number',name='age')

p Sex:

input#sex(type='boolean',name='sex')

button(type='submit') Create


h1 #{user.name}


ul

li Age: #{user.age}

li Sex: #{user.sex}


ul

li: a(href='/users/#{user.name}/edit') Edit

li

form(action='/users/#{user.name}' , method='POST')

input(type='hidden',name='_method',value='DELETE')

button(type='submit') Delete


h1 All Users


ul

each user in users

li: a(href='/users/#{user.name}') #{user.name} #{user.age} #{user.sex}


2) v3에서 변경된 것들



< 참조 > 

- Mongoose 2.3.9 온라인 매뉴얼

http://nodejs-kr.org/insidejs/archives/536


- Mongoose : Elegant MongoDB object modeling for Node.js (GitHub)

http://mongoosejs.com/


- Node.js 

http://www.mongodb.org/display/DOCS/Node.js


- masylum / mongolia 

https://github.com/masylum/mongolia

'MongoDB' 카테고리의 다른 글

[MongoDB] Ubuntu 에 설치하기  (0) 2012.11.14
posted by 윤영식
2013. 1. 5. 16:26 MongoDB/Prototyping

MongoDB에서 Replica Set을 구성하였을 때 mongodb를 접속하는 client에 대하여 routing 서비스를 하는 mongos(몽고스)에 대해 알아보자.



1. 구성 아키텍쳐

  - Shard 한개에 mongod 한개를 맵핑한다

  - config 한개에 mongod 한개만 사용한다



2) 구성하기 

  - shard1, shard2, shard3, config, mongos를 간단히 만들어 보자 (shard를 replica set으로 구성은 배재, 참조)

  - Shard server 3개 띄우기 : sdb01, sdb02, sdb03 디렉토리는 미리 만들어 놓는다. (기동은 개별 콘솔에서 실행함)

$ ./mongod --shardsvr --dbpath /home/dowon/MongoDB/sdb01 --port 10000

Fri Jan  4 22:25:03 

Fri Jan  4 22:25:03 warning: 32-bit servers don't have journaling enabled by default. Please use --journal if you want durability.

.. 중략 ...

Fri Jan  4 22:25:03 [initandlisten] build info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_49

Fri Jan  4 22:25:03 [initandlisten] options: { dbpath: "/home/dowon/MongoDB/sdb01", port: 10000, shardsvr: true }

Fri Jan  4 22:25:03 [websvr] admin web console waiting for connections on port 11000


./mongod --shardsvr --dbpath /home/dowon/MongoDB/sdb02 --port 20000
./mongod --shardsvr --dbpath /home/dowon/MongoDB/sdb03 --port 30000

////////////////////////////
// config srever를 띄웠다. 
$ ./mongod --configsvr --dbpath /home/dowon/MongoDB/sdb04c --port 40000
Fri Jan  4 22:29:47 
Fri Jan  4 22:29:47 warning: 32-bit servers don't have journaling enabled by default. Please use --journal if you want durability.
Fri Jan  4 22:29:47 
Fri Jan  4 22:29:47 [initandlisten] MongoDB starting : pid=8201 port=40000 dbpath=/home/dowon/MongoDB/sdb04c 32-bit host=localhost.localdomain
Fri Jan  4 22:29:48 [initandlisten] waiting for connections on port 40000
Fri Jan  4 22:29:48 [websvr] admin web console waiting for connections on port 41000

////////////////////////////
// mongos 띄우기 : chunksize 정하지 않으며 1Mbytes이다. 
$ ./mongos --configdb localhost:40000 --chunkSize 1
Fri Jan  4 22:32:04 warning: running with 1 config server should be done only for testing purposes and is not recommended for production
Fri Jan  4 22:32:04 [mongosMain] MongoS version 2.2.2 starting: pid=8239 port=27017 32-bit host=localhost.localdomain (--help for usage)
Fri Jan  4 22:32:04 [mongosMain] git version: d1b43b61a5308c4ad0679d34b262c5af9d664267
Fri Jan  4 22:32:04 [mongosMain] build info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_49
Fri Jan  4 22:32:11 [Balancer] distributed lock 'balancer/localhost.localdomain:27017:1357367525:1804289383' unlocked. 
Fri Jan  4 22:32:17 [Balancer] distributed lock 'balancer/localhost.localdomain:27017:1357367525:1804289383' acquired, ts : 50e7c8f1b1a36d7262b31138


3) mongos 에서 환경 구성하기

  - mongo shell로 들어가서 shard 환경을 만든다 : 자동으로 mongos로 들어간다 (프롬프트 명칭이 mongos가 됨)

$ ./mongo

MongoDB shell version: 2.2.2

connecting to: test

mongos> use admin

switched to db admin

mongos> db

admin

mongos> show dbs

config 0.046875GB

mongos> use peopleDB
switched to db peopleDB
// config 셋팅을 하지 않고 사용하면 다음과 같은 에러가 발생한다. 
mongos> db.people.save({_id:1, age:11, name:'dowon1', sex:false});
Fri Jan  4 22:38:03 uncaught exception: error {
"$err" : "error creating initial database config information :: caused by :: can't find a shard to put new db on",
"code" : 10185
}
mongos> 

/////////////////////////
// 다시 mongo로 들어온다. 
// 그리고 shard에 서버를 추가해 준다.
$ ./mongo
MongoDB shell version: 2.2.2
connecting to: test
mongos> db
test
mongos> use admin
switched to db admin
mongos> db
admin
mongos> db.runCommand({addshard:'localhost:10000'});
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand({addshard:'localhost:20000'});
{ "shardAdded" : "shard0001", "ok" : 1 }
mongos> db.runCommand({addshard:'localhost:30000'});
{ "shardAdded" : "shard0002", "ok" : 1 }

////////////////////////////////
// mongos를 통하여 CRUD를 한다
// 과연 입력한 데이터는 Shard가 되었을까? 
mongos> 
mongos> use testShard
switched to db testShard
mongos> db
testShard
mongos> db.people.save({_id:1, age:11, name:'dowon1', sex:false});
mongos> db.people.save({_id:2, age:22, name:'dowon2', sex:true});
mongos> db.people.save({_id:3, age:33, name:'dowon3', sex:false});
mongos> db.people.find();
{ "_id" : 1, "age" : 11, "name" : "dowon1", "sex" : false }
{ "_id" : 2, "age" : 22, "name" : "dowon2", "sex" : true }
{ "_id" : 3, "age" : 33, "name" : "dowon3", "sex" : false }

/////////////////////////////////////
// 결과 확인 : auto shard가 안되어 있다
// sdb01에만 데이터가 저장되어 있다. 이유 : config server를 가동시키지 않았기 때문이다.
[dowon@localhost MongoDB]$ cd sdb01
[dowon@localhost sdb01]$ ll
total 65548
-rwxrwxr-x. 1 dowon dowon        5 Jan  4 22:25 mongod.lock
-rw-------. 1 dowon dowon 16777216 Jan  4 22:43 testShard.0
-rw-------. 1 dowon dowon 33554432 Jan  4 22:42 testShard.1
-rw-------. 1 dowon dowon 16777216 Jan  4 22:43 testShard.ns
drwxrwxr-x. 2 dowon dowon     4096 Jan  4 22:42 _tmp
[dowon@localhost sdb01]$ cd ../sdb02
[dowon@localhost sdb02]$ ll
total 4
-rwxrwxr-x. 1 dowon dowon 5 Jan  4 22:25 mongod.lock
[dowon@localhost sdb02]$ cd ../sdb03
[dowon@localhost sdb03]$ ll
total 4
-rwxrwxr-x. 1 dowon dowon 5 Jan  4 22:25 mongod.lock


4) Shard 테스트를 위한 데이터 만들고 확인하기 

  - shard 연결 환경을 설정한다. (참조 동영상, Shard Guide blog)

////////////////////////////////

// 10000 port mongodb로 들어가자

// 이것은 10000 port의 mongodb로 direct 들어가는 것이다. 

$ ./mongo localhost:10000

MongoDB shell version: 2.2.2

connecting to: localhost:10000/test

> show dbs

local (empty)

testShard 0.0625GB

> use testShard

switched to db testShard

> db

testShard

> show collections

people

system.indexes

> db.people.find();

{ "_id" : 1, "age" : 11, "name" : "dowon1", "sex" : false }

{ "_id" : 2, "age" : 22, "name" : "dowon2", "sex" : true }

{ "_id" : 3, "age" : 33, "name" : "dowon3", "sex" : false }


////////////////////////////
// 20000, 30000 port로 mongos를 통하지 않고 mongodb로 바로 접속하면 
// testShard DB는 없다. 
$ ./mongo localhost:20000
MongoDB shell version: 2.2.2
connecting to: localhost:20000/test
> show dbs
local (empty)

/////////////////////////////////
// mongos로 들어간다. use admin 
// Sharding 환경설정하기
$ ./mongo
MongoDB shell version: 2.2.2
connecting to: test
mongos> dbs
Fri Jan  4 22:54:15 ReferenceError: dbs is not defined (shell):1
mongos> show dbs
config 0.046875GB
testShard 0.0625GB
mongos> use admin
switched to db admin
mongos> db
admin
mongos> db.runCommand({enablesharding:'testShard'});
{ "ok" : 1 }
mongos> db.runCommand({shardcollection:'people', key:{_id:1}});
{ "ok" : 0, "errmsg" : "bad ns[people]" } <-- namespace 에러 
mongos> db.runCommand({shardcollection:'testShard.people', key:{_id:1}});  // _id:1 의 1은 sorting
{ "collectionsharded" : "testShard.people", "ok" : 1 }

//////////////////////////////////////////////
// people collection에 데이터를 넣어보자
mongos> for(var i=6 ; i<100000 ; i++) {
      db.people.save({_id:i, age:44, name:'dowon'+i, sex:true});
   }

//////////////////////////////////////////////////////////////////////////
// 다른 mongo에서 show dbs를 해보면 testShard DB가 생성되었음을 볼 수 있다. 
// chunkSize 1Mbytes 이상이면 sharding이 이루어진다. 
[dowon@localhost mongodb]$ ./mongo localhost:20000
MongoDB shell version: 2.2.2
connecting to: localhost:20000/test
> show dbs
local (empty)
> show dbs
admin (empty)
local (empty)
testShard 0.0625GB
> use testShard
switched to db testShard
> db.people.find();
{ "_id" : 54053, "age" : 44, "name" : "dowon54053", "sex" : true } // 54053 번부터 Sharding 되었다. 
{ "_id" : 54054, "age" : 44, "name" : "dowon54054", "sex" : true }
{ "_id" : 54055, "age" : 44, "name" : "dowon54055", "sex" : true }
{ "_id" : 54056, "age" : 44, "name" : "dowon54056", "sex" : true }
{ "_id" : 54057, "age" : 44, "name" : "dowon54057", "sex" : true }

[dowon@localhost mongodb]$ ./mongo localhost:30000
MongoDB shell version: 2.2.2
connecting to: localhost:30000/test
local (empty)
> show dbs
admin (empty)
local (empty)
testShard 0.0625GB
> use testShard
switched to db testShard
> db.people.find();
{ "_id" : 22200, "age" : 44, "name" : "dowon22200", "sex" : true } // 22200 번부터 Sharding 되었다. 
{ "_id" : 22201, "age" : 44, "name" : "dowon22201", "sex" : true }
{ "_id" : 22202, "age" : 44, "name" : "dowon22202", "sex" : true }
{ "_id" : 22203, "age" : 44, "name" : "dowon22203", "sex" : true }

< 결론 > 
Sharding 시켜놓은 서버로 ChunkSize 크기에 따라 데이터가 분산되어 저장된다. 

 

* 요약 (명령 참조)

  - mongo admin 으로 들어간다

  - runCommand 통하여 세가지 설정을 수행한다. 

  - chunkSize에 따라서 Sharding이 이루어진다.


* Sharding 개념 다시 정리 하기


* MongoDB의 철학은?

데이터와 데이터로직의 분리 

 - 데이터 : JSON (실제 BSON : binary json 형태로 저장됨)

 - 데이터로직 : JavaScript


<참조>

  - 10gen 설정 튜토리얼

posted by 윤영식
2013. 1. 5. 14:56 MongoDB/Prototyping

MongoDB의 Replica Set을 만들어 보자. 먼저 Master/Slave와 Primary/Secondary 순으로 본다. Master/Slave는 Slave에서 Read가 된다. 그러나 Primary/Secondary에서 Secondary는 Read도 되지 않는다.  



1. Replica Set 만들기 위한 Master / Slave 에 대해 알아보자. (Replica Set은 아니다)

  - Master로 DB 수행하기 : master의 mongo에서 CRUD 가능

$ ./mongod -dbpath /home/dowon/MongoDB/db01 --master &

만일 db가 비정상 종료되었다면 

$ ./mongod -dbpath /home/dowon/MongoDB/db01 --master --repair &

수행후에 다시 $ ./mongod -dbpath /home/dowon/MongoDB/db01 --master & 를 수행한다. 


... 하기 메세지 나오면 정상 부팅

Fri Jan  4 19:29:59 [initandlisten] Unable to check for journal files due to: boost::filesystem::basic_directory_iterator constructor: No such file or directory: "/home/dowon/MongoDB/db01/journal"

Fri Jan  4 19:29:59 [initandlisten] waiting for connections on port 27017

Fri Jan  4 19:29:59 [websvr] admin web console waiting for connections on port 28017

   

  - Slave로 DB 수행하기 : -slave 옵션 

    + slave의 mongo에서 CUD 안됨. Read만 가능하다. 

    + source 지정하여 replica set 만들 master가 누구인지 알려준다. 

    + 기존에 single로 사용하던 mongod를 master/slave로 묶고자 할 경우 기존 데이터를 slave로 복제하기 잘 안됨

       -> 다른 디렉토리로 복사해서 그런가? 테스트 필요함

    + 신규로 master/slave를 띄워서 save 또는 insert 하였을 때 slave 쪽 디렉토리에 db 파일이 제대로 복제됨 

$ ./mongod --dbpath /home/dowon/MongoDB/db02 --port 27018 --slave --source localhost:27017 &

...

Fri Jan  4 19:12:46 [initandlisten] Unable to check for journal files due to: boost::filesystem::basic_directory_iterator constructor: No such file or directory: "/home/dowon/MongoDB/db02/journal"

Fri Jan  4 19:12:46 [initandlisten] waiting for connections on port 27018   <-- 정상 부팅

Fri Jan  4 19:12:46 [websvr] admin web console waiting for connections on port 28018

// 하기 메세지는 master에 있는 데이터 파일을 slave로 복사해 온다. 마치 git의 pull과 유사한 느낌 ^^ 

Fri Jan  4 19:12:47 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db02/local.ns, size: 16MB,  took 0.001 secs

Fri Jan  4 19:12:48 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db02/local.0, filling with zeroes...

Fri Jan  4 19:12:48 [replslave] build index done.  scanned 0 total records. 0 secs


// db02 디렉토리에 가보면 db01에 있던 데이터베이스 mydb가 copy되어 있는 것을 볼 수 있다. 

Fri Jan  4 19:12:48 [replslave] resync: dropping database mydb

Fri Jan  4 19:12:48 [replslave] resync: cloning database mydb to get an initial copy

Fri Jan  4 19:12:48 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db02/mydb.ns, filling with zeroes...

Fri Jan  4 19:12:48 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db02/mydb.ns, size: 16MB,  took 0.045 secs

Fri Jan  4 19:12:49 [replslave] resync: done with initial clone for db: mydb

Fri Jan  4 19:12:49 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db02/mydb.1, size: 32MB,  took 0.085 secs



2. Replica Set default 만들기 

  - replica set 구동하기 : db11, db12, db13 3개를 띄운다. replica set 명칭은 dowon01 이다. 

  - 디렉토리를 3개 만들고 각 디렉토리별로 서로 다른 port로 replica set 1개를 만들어 본다.

  - mongod를 shutdown 시키고 싶을 경우 : mongo 쉘에서 db.shutdownServer({timeoutSecs: 60});  - 메뉴얼

  - 결론 : mongod를 여러개 띄워서 파일시스템의 약점을 극복한다 (High Availability - HA 구성)

//////////////////////////////////////

// Replica Set 을 1개 만든다 

$ ./mongod --replSet dowon01 --port 30000 --dbpath /home/dowon/MongoDB/db11

$ ./mongod --replSet dowon01 --port 40000 --dbpath /home/dowon/MongoDB/db12

$ ./mongod --replSet dowon01 --port 50000 --dbpath /home/dowon/MongoDB/db13


// 하기 환경설정관련 에러가 나온다 (정상 - 아직 환경설정 안했기 때문에 ^^)

... 중략 ...

Fri Jan 25 23:14:06 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)

Fri Jan 25 23:14:23 [initandlisten] connection accepted from 127.0.0.1:34440 #1 (1 connection now open)

Fri Jan 25 23:14:26 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)


/////////////////////////////////////

// mongo client 접속 하기

[dowon@localhost mongodb]$ ./mongo localhost:30000

MongoDB shell version: 2.2.2

connecting to: localhost:30000/test

> show dbs

local (empty)

> exit

bye

[dowon@localhost mongodb]$ ./mongo localhost:40000

MongoDB shell version: 2.2.2

connecting to: localhost:40000/test

> show dbs

local (empty)

> exit

bye

[dowon@localhost mongodb]$ ./mongo localhost:50000

MongoDB shell version: 2.2.2

connecting to: localhost:50000/test

> show dbs

local (empty)


  - Configuration 작업하기 

///////////////////////////////////////////////////

// PRIMARY + SECONDARY Replica Set 만들기 

[dowon@localhost mongodb]$ ./mongo localhost:30000

MongoDB shell version: 2.2.2

connecting to: localhost:30000/test

> var config={_id:'dowon01', members:[{_id:0, host:30000},

... {_id:1, host:40000}^C


// 환경 객체를 만든다 

var config={_id:'dowon01', members:[

    {_id:0, host:'localhost:30000'},

    {_id:1, host:'localhost:40000'},

    {_id:2, host:'localhost:50000'}]

  }


// replica set을 초기화 한다. 

> rs.initiate(config);

{

"info" : "Config now saved locally.  Should come online in about a minute.",

"ok" : 1

}


// 3000 port의 메세지를 보면 다음과 같다. 

// 1) config 없을 때 나오는 메세지이다. 

Fri Jan  4 21:20:29 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)

Fri Jan  4 21:20:39 [rsStart] replSet can't get local.system.replset config from self or any seed (EMPTYCONFIG)

// 2) rs.initiate를 수행하면 하기와 같은 메세지가 나온다. 

Fri Jan  4 21:20:44 [conn2] replSet replSetInitiate admin command received from client

Fri Jan  4 21:20:44 [conn2] replSet replSetInitiate config object parses ok, 3 members specified

Fri Jan  4 21:20:44 [conn2] replSet replSetInitiate all members seem up

Fri Jan  4 21:20:44 [conn2] ******

Fri Jan  4 21:20:44 [conn2] replSet info saving a newer config version to local.system.replset

Fri Jan  4 21:20:44 [conn2] replSet saveConfigLocally done

Fri Jan  4 21:20:44 [conn2] replSet replSetInitiate config now saved locally.  Should come online in about a minute.

Fri Jan  4 21:20:44 [conn2] command admin.$cmd command: { replSetInitiate: { _id: "dowon01", members: [ { _id: 0.0, host: "localhost:30000" }, { _id: 1.0, host: "localhost:40000" }, { _id: 2.0, host: "localhost:50000" } ] } } ntoreturn:1 keyUpdates:0 locks(micros) W:431969 reslen:112 477ms

Fri Jan  4 21:20:49 [rsStart] replSet I am localhost:30000

Fri Jan  4 21:20:49 [rsStart] replSet STARTUP2

Fri Jan  4 21:20:49 [rsHealthPoll] replSet member localhost:40000 is up

Fri Jan  4 21:20:49 [rsHealthPoll] replSet member localhost:50000 is up

Fri Jan  4 21:20:50 [initandlisten] connection accepted from 127.0.0.1:43880 #3 (2 connections now open)

Fri Jan  4 21:20:50 [rsSync] replSet SECONDARY

... 중략 ...
>                                   <== enter key를 치면 하기와 같은 프롬프트로 자동 변경된다
dowon01:PRIMARY>   <== "replicaSet명칭:PRIMARY>" 명칭이 나온다 

////////////////////////////////////////////
// 40000, 50000 번의 client를 들어가 보자 
[dowon@localhost mongodb]$ ./mongo localhost:40000
MongoDB shell version: 2.2.2
connecting to: localhost:40000/test
dowon01:SECONDARY> 

[dowon@localhost mongodb]$ ./mongo localhost:50000
MongoDB shell version: 2.2.2
connecting to: localhost:50000/test
dowon01:SECONDARY> 

//////////////////////////////////////////
// SECONDARY 에서 하기와같은 에러 발생시 rs.slaveOk() 수행
[mongodb@localhost ~]$ ./mongo localhost:40000
MongoDB shell version: 2.2.2
connecting to: localhost:20000/test
dowon01:SECONDARY> show dbs
dowonDB 0.0625GB
local 0.125GB
test (empty)
dowon01:SECONDARY> use dowonDB
switched to db dowonDB
dowon01:SECONDARY> db
dowonDB
dowon01:SECONDARY> show collections
Fri Jan 25 23:45:06 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
// primary 의 데이터를 가져온다
dowon01:SECONDARY> rs.slaveOk()
dowon01:SECONDARY> show collections
test
system.indexes

//////////////////////////////////////////
// PRIMARY 에서 데이터베이스 생성하기 
dowon01:PRIMARY> db
test
dowon01:PRIMARY> use peopleDB
switched to db peopleDB
dowon01:PRIMARY> db.people.insert({_id:1, age:11, name:'dowon1', sex:false});
dowon01:PRIMARY> db.people.insert({_id:2, age:22, name:'dowon2', sex:true});
dowon01:PRIMARY> db.people.insert({_id:3, age:33, name:'dowon3', sex:false});
dowon01:PRIMARY> db.people.find();
{ "_id" : 1, "age" : 11, "name" : "dowon1", "sex" : false }
{ "_id" : 2, "age" : 22, "name" : "dowon2", "sex" : true }
{ "_id" : 3, "age" : 33, "name" : "dowon3", "sex" : false }

////////////////////////////////////////////////////////////////////////
// SECONDARY에서 데이터베이스를 READ해 보면 에러가 발생한다
// Replica Set의 Secondary는 Slave가 아니기 때문에 사용할 수 없다. 
// 즉, Primary가 down 되어야 사용 가능하다.
// 단, 1)의 Master/Slave 구조에서 Slave는 READ가 가능하다.
[dowon@localhost mongodb]$ ./mongo localhost:50000
MongoDB shell version: 2.2.2
connecting to: localhost:50000/test
dowon01:SECONDARY> show dbs  // 데이터베이스 보기 
local 0.125GB
peopleDB 0.0625GB
dowon01:SECONDARY> use peopleDB // 해당 데이터베이스로 switching하여 사용하기 
switched to db peopleDB
dowon01:SECONDARY> show collections // 해당 데이터베이스의 테이블(?) 보기 
Fri Jan  4 21:31:59 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }
dowon01:SECONDARY> db
peopleDB
dowon01:SECONDARY> db.people.find();  // "db"는 peopleDB를 가르키는 포인터
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }


위 명령의 구조는 다음과 같다. (참조 19page)



  - Primary를 종료하면 Sencodary가 Primary로 자동 변경된다

[dowon@localhost mongodb]$ ./mongo localhost:40000

MongoDB shell version: 2.2.2

connecting to: localhost:40000/test

... 중략

dowon01:SECONDARY> show collections

Fri Jan  4 21:31:33 uncaught exception: error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

dowon01:SECONDARY> 

// 30000 port mongoDB를 down시키고 4000 port의 mongo client에서 enter를 치면 하기와 같이 primary로 바뀐다. 

dowon01:PRIMARY> 

// Primary 이므로 CRUD가 가능해 진다. 

dowon01:PRIMARY> show collections
people
system.indexes
dowon01:PRIMARY> db.people.insert({_id:4, age:44, name:'youngsik', sex:true});
dowon01:PRIMARY> db.people.find();
{ "_id" : 1, "age" : 11, "name" : "dowon1", "sex" : false }
{ "_id" : 2, "age" : 22, "name" : "dowon2", "sex" : true }
{ "_id" : 3, "age" : 33, "name" : "dowon3", "sex" : false }
{ "_id" : 4, "age" : 44, "name" : "youngsik", "sex" : true }

/////////////////////////////////////////////////////////////////////
// 다시 30000 port를 기동시키고, 3000 port client로 접속한다.
// 40000 port가 그대로 Primary로 존재하고, 30000 port는 Secondary로 된다. 
i Jan  4 21:42:46 trying reconnect to localhost:30000
Fri Jan  4 21:42:46 reconnect localhost:30000 ok
dowon01:SECONDARY> 



3) Replca Set 기본과 Master/Slave를 결합한 형태

   * 참조 20page




< 참조 > 

- High Availabiltity & Replica Sets with mongoDB

http://www.slideshare.net/shaolintiger/high-availabiltity-replica-sets-with-mongodb


- Sharding by mongodb/10gen on Nov 28, 2012

http://www.slideshare.net/mongodb/sharding-15392976


- Sharding morning session

http://www.slideshare.net/mongodb/sharding-morning-session


- Sharding - Seoul 2012

http://www.slideshare.net/mongodb/sharding-seoul-2012-15576057


- Replication and Replica Sets

http://www.slideshare.net/mongodb/replication-and-replica-sets-tokyo-2012


- MongoDB Basic Concepts

http://www.slideshare.net/mongodb/mongodb-basic-concepts-15674838


- A Morning with MongoDB - Helsinki

http://www.slideshare.net/mongodb/morning-with-mongo-db-helsinki-1


- MongoDB Roadmap

http://www.slideshare.net/mongodb/next-15674517

posted by 윤영식