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

Publication

Category

Recent Post

2012. 12. 29. 14:12 MongoDB/Concept

몽고디비설치를 하고 사용해보자. 설치전 몽고의 기본 개념을 읽고 시작하자


MongoDB는 웹 애플리케이션과 인터넷 기반을 위해 설계된 데이터베이스 관리 시스템이다. 데이터 모델과 지속성 전략은 높은 읽기/쓰기 효율과 자동 장애조치(failover)를 통한 확장의 용이성을 염두에 두고 만들어졌다. 애플리케이션에서 필요한 데이터베이스 노드가 하나거나 혹은 그 이상이거나에 관계없이 MongoDB는 놀라울 정도로 좋은 성능을 보여준다. 관계 데이터베이스를 확장하는 데 어려움을 겪었던 적이 있다면 이것은 대단한 뉴스일 것이다.



1. 설치후 4개파일 별도 디렉토리에 copy 

  + mongodb 폴더 안에 4개 파일 copy

  + mongo.exe : 쉘 / mongod.exe : 서버 / mongofiles.exe : gridFS 빅데이터 핸들링 / mongos.exe : 라우터 서버

[dowon@localhost mongodb]$ ls

bsondump      mongodump    mongooplog    mongosniff  THIRD-PARTY-NOTICES

GNU-AGPL-3.0  mongoexport  mongoperf     mongostat

mongo         mongofiles   mongorestore  mongotop

mongod        mongoimport  mongos        README

[dowon@localhost mongodb]$ pwd

/home/dowon/MongoDB/mongodb <- binary files 위치

[dowon@localhost mongodb]$ cd ..

[dowon@localhost MongoDB]$ pwd

/home/dowon/MongoDB

[dowon@localhost MongoDB]$ ls

db01  db02  db03  mongodb  <- 디렉토리들

[dowon@localhost MongoDB]$ 




2. 별도 디렉토리 만들고 서버 시작

  + mDB01, mDB02, mDB03 디렉토리를 만듦 : Replica Set을 만들 것이다. 

  + 서버 시작하기 

[dowon@localhost mongodb]$ ./mongod --dbpath /home/dowon/MongoDB/db01 &

[1] 5840

[dowon@localhost mongodb]$ Fri Dec 28 19:39:42 

Fri Dec 28 19:39:42 warning: 32-bit servers don't have journaling enabled by default. Please use --journal if you want durability.

Fri Dec 28 19:39:42 

Fri Dec 28 19:39:42 [initandlisten] MongoDB starting : pid=5840 port=27017 dbpath=/home/dowon/MongoDB/db01 32-bit host=localhost.localdomain

Fri Dec 28 19:39:42 [initandlisten] 

Fri Dec 28 19:39:42 [initandlisten] ** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data

Fri Dec 28 19:39:42 [initandlisten] **       see http://blog.mongodb.org/post/137788967/32-bit-limitations

Fri Dec 28 19:39:42 [initandlisten] **       with --journal, the limit is lower

Fri Dec 28 19:39:42 [initandlisten] 

Fri Dec 28 19:39:42 [initandlisten] db version v2.2.2, pdfile version 4.5

Fri Dec 28 19:39:42 [initandlisten] git version: d1b43b61a5308c4ad0679d34b262c5af9d664267

Fri Dec 28 19:39:42 [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 Dec 28 19:39:42 [initandlisten] options: { dbpath: "/home/dowon/MongoDB/db01" }

Fri Dec 28 19:39:42 [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 Dec 28 19:39:42 [websvr] admin web console waiting for connections on port 28017

Fri Dec 28 19:39:42 [initandlisten] waiting for connections on port 27017



3. 쉘사용하기 : JavaScript 코딩을 통하여 작업을 한다. 

   (명령뒤에 s 붙으면 목록이다, MongoDB는 자바스크립트 엔진인 extended Spidermonkey shell을 탑재함)

[dowon@localhost mongodb]$ ./mongo

MongoDB shell version: 2.2.2

connecting to: test

Fri Dec 28 19:45:29 [initandlisten] connection accepted from 127.0.0.1:44889 #2 (1 connection now open)

> 2+3

5

> 'hello dowon'

hello dowon

> var dowon = function() {

... return 'hi youngsik. what are you doing now?'

... }

> dowon()

hi youngsik. what are you doing now?


  - {} : 자바스크립 객체이다. anonymous function이고 일반 find() 시퀀스에 "어나너머스 자바스크립트 객체" = 클로저(Closure) 하나를 집어 넣은 것이다. 

> use peopleDB  // 데이터베이스 만들기

switched to db peopleDB

> db // db 명이 peopleDB를 referencing 한다

peopleDB

> show dbs

local (empty)

test (empty)

> db.people.save({age:37, name:'dowon', sex:'male'})  // collection (table) 만들기. JavaScript객체-JSON

Fri Dec 28 19:53:25 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db01/peopleDB.ns, filling with zeroes...

Fri Dec 28 19:53:25 [FileAllocator] creating directory /home/dowon/MongoDB/db01/_tmp

Fri Dec 28 19:53:25 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db01/peopleDB.ns, size: 16MB,  took 0.012 secs

Fri Dec 28 19:53:25 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db01/peopleDB.0, filling with zeroes...

Fri Dec 28 19:53:25 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db01/peopleDB.0, size: 16MB,  took 0.002 secs

Fri Dec 28 19:53:25 [FileAllocator] allocating new datafile /home/dowon/MongoDB/db01/peopleDB.1, filling with zeroes...

Fri Dec 28 19:53:25 [FileAllocator] done allocating datafile /home/dowon/MongoDB/db01/peopleDB.1, size: 32MB,  took 0.001 secs

Fri Dec 28 19:53:25 [conn2] build index peopleDB.people { _id: 1 }

Fri Dec 28 19:53:25 [conn2] build index done.  scanned 0 total records. 0 secs

Fri Dec 28 19:53:25 [conn2] insert peopleDB.people keyUpdates:0 locks(micros) w:201336 200ms

> show dbs  // collection을 만들때 즉, save 할때 데이터베이스가 생성된다 

local (empty)

peopleDB 0.0625GB

test (empty)

> show collections // collections (테이블)보기

people

system.indexes

> db.people.find()

{ "_id" : ObjectId("50de69359db888890e4126da"), "age" : 37, "name" : "dowon", "sex" : "male" }

> var person=[age:22]

Fri Dec 28 19:55:55 SyntaxError: missing ] after element list (shell):1

> var person={age:22};

> db.people.save(person) // 변수로 차기도 가능

> db.people.find()

{ "_id" : ObjectId("50de69359db888890e4126da"), "age" : 37, "name" : "dowon", "sex" : "male" }

{ "_id" : ObjectId("50de6a0e9db888890e4126db"), "age" : 22 }

> db.people.find({age:22})

{ "_id" : ObjectId("50de6a0e9db888890e4126db"), "age" : 22 }


  - index 넣고 확인하기 

1 : ascending

0 : descending 


> db.people.ensureIndex({age:1});

Fri Dec 28 20:17:20 [conn2] build index peopleDB.people { age: 1.0 }

Fri Dec 28 20:17:20 [conn2] build index done.  scanned 2 total records. 0.002 secs

> db.people.ensureIndex({name:0});

Fri Dec 28 20:17:26 [conn2] build index peopleDB.people { name: 0.0 }

Fri Dec 28 20:17:26 [conn2] build index done.  scanned 2 total records. 0.002 secs

> db.people.getIndexes();

[

{

"v" : 1,

"key" : {

"_id" : 1

},

"ns" : "peopleDB.people",

"name" : "_id_"

},

{

"v" : 1,

"key" : {

"age" : 1

},

"ns" : "peopleDB.people",

"name" : "age_1"

},

{

"v" : 1,

"key" : {

"name" : 0

},

"ns" : "peopleDB.people",

"name" : "name_0"

}

]


  - help 명령 보기 : 펑션이 이미 정의되어 있다

> db.people.help()

DBCollection help

db.people.find().help() - show DBCursor help

db.people.count()

db.people.copyTo(newColl) - duplicates collection by copying all documents to newColl; no indexes are copied.

db.people.convertToCapped(maxBytes) - calls {convertToCapped:'people', size:maxBytes}} command

db.people.dataSize()

db.people.distinct( key ) - e.g. db.people.distinct( 'x' )

db.people.drop() drop the collection

db.people.dropIndex(index) - e.g. db.people.dropIndex( "indexName" ) or db.people.dropIndex( { "indexKey" : 1 } )

db.people.dropIndexes()

db.people.ensureIndex(keypattern[,options]) - options is an object with these possible fields: name, unique, dropDups

db.people.reIndex()

db.people.find([query],[fields]) - query is an optional query filter. fields is optional set of fields to return.

                                             e.g. db.people.find( {x:77} , {name:1, x:1} )

db.people.find(...).count()

db.people.find(...).limit(n)

db.people.find(...).skip(n)

db.people.find(...).sort(...)

db.people.findOne([query])

db.people.findAndModify( { update : ... , remove : bool [, query: {}, sort: {}, 'new': false] } )

db.people.getDB() get DB object associated with collection

db.people.getIndexes()

db.people.group( { key : ..., initial: ..., reduce : ...[, cond: ...] } )

db.people.insert(obj)

db.people.mapReduce( mapFunction , reduceFunction , <optional params> )

db.people.remove(query)

db.people.renameCollection( newName , <dropTarget> ) renames the collection.

db.people.runCommand( name , <options> ) runs a db command with the given name where the first param is the collection name

db.people.save(obj)

db.people.stats()

db.people.storageSize() - includes free space allocated to this collection

db.people.totalIndexSize() - size in bytes of all the indexes

db.people.totalSize() - storage allocated for all data and indexes

db.people.update(query, object[, upsert_bool, multi_bool]) - instead of two flags, you can pass an object with fields: upsert, multi

db.people.validate( <full> ) - SLOW

db.people.getShardVersion() - only for use with sharding

db.people.getShardDistribution() - prints statistics about data distribution in the cluster

db.people.getSplitKeysForChunks( <maxChunkSize> ) - calculates split points over all chunks and returns splitter function


* MongoDB Tutorial 시작하기

posted by 윤영식
2012. 12. 29. 12:23 MongoDB/Concept

> MongoDB 아키텍쳐

- Replica Set : Fail-Over용 백업 Primary가 죽으면 Secondary가 primary가 됨 = Shard 1개를 의미한다. - auto fail-over 가 된다.

  primary와 secondary 각각 데이터 파일을 가지고 있다. secondary는 사용할 수 없다. primary만 서비싱

- MongoDB는 HTTP 즉 World Wid Web(WWW) 상의 모든 데이터를 연결시키는 것과 같다. 상상을 해보자 MongoDB는 웹상의 데이터가 합쳐지고  관리되어 지도록 만들었다는데 의미가 있다. 


- primary와 secondary 자체도 머신이 분리 될 수 있다. 당연히 shard 들도 머신 분리 될 수 있다. 

  Replica Set = Shard 이다 




- shard에 전체 데이터를 나누어 갖는다. mongos(몽고스)가 routing 한다. 즉, client는 mongos로 접속한다.

  * mongoos (몽구스)는 Node.js와 연결하는 driver이다. 

- replica, shard는 disk 서비스이다. memcached 같은 것은 memory 서비스이다. 



- 3개월에 한번씩 major version upgrade 

- 데이터베이스 = 중복되지 않는 데이터들의 집합체

- CAP 개념 : NoSQL의 CAP



> MongoDB 특징

  - Agile and Scalable : 신속하고 확장 가능한 개발을 위한 저장소

    + Agility : 실시간으로 변경된다. Schemeless 이다. 

    + Scalable : 무한 확장 가능하다.  

  - 무조건 64bit로 사용하여 무한 메모리를 사용할 수 있다. 메모리 관리는 OS가 하도록 한다. 32bit는 4G만 사용할 수 있다.

  - High Availability 

  - Auto Sharding 

  - Rich Query : human readerble & 인간의 뇌구조 key=value 즉, 문제=해결

  - Full Indexing 

  - Fast In-Place Update : CRUD 

  - Map/Reduce : version 2.2 의 핵심. MongoDB 자체가 M/R하던가 Hadoop으로 M/R를 주던가 한다. 결국은 Hadoop으로 간다.

    * 참조 : JayData

  - GridFS : BSon = binary json 형태로 저장.


* 10gen 기본개념 소개자료


posted by 윤영식
2012. 12. 29. 11:36 Backbone.js

View단위 MVC Framework으로 알려진 몇가지에 대해서 알아보자. MOVE solution으로 M=Model, O=Operation, VE=View 이다. 특히 View는 Logical DOM을 핸들링하게(Stream을 타고 즉, 동적으로 Storage지까지 가는 것이다. Stream=Function 이다.) 되고 MVC의 Controller 역할을 하게 된다. Operation은 단순 서비스/이벤트 역할이다. 대표적인 프레임워크가 BackBone이다. 

HTML -> Dynamic -> WebApp 그 정점에 SPA(Single Page Application)이 존재하고, 결국 최종 종착점은 고객에게 서비스하기 위한 View 기술이다. 여기에 필요한 전체 구조는 BackBone + Node.js + MongoDB 라고 보면되고, 이들은 Stream(Dynamic)하게 그러면서 Functional로 연력되어 Schemaless하게 움직이게 된다.



1) 전체 레밸의 MVC Framework

  - 브라우저 : BackBone.js

  - 서버 : Node.js위에서 구동되는 Express.js

  - 스토리지 : MongoDB위의 Mongoos 

* Node.js로 구성할 수 있는 Web App의 구성도



> BackBone.js 


> Ember.js


> Angular.js


3가지의 장단점에 대해서 검토해 보자 (다음번에 구체적으로 정리) O;TL

posted by 윤영식
2012. 12. 27. 17:31 Languages/Java

Java 클래스의 bytecode instrument 프레임워크인 ASM Guide 문서를 읽고 간단히 정리해 보자 


* 참조 파일


> Object Based Model

  - ASM 라이브러리는 컴파일된 클래스의 generating 과 transforming API를 제공한다.

  - DOM(예)의 경우 : event 기반 모델로 클래스를 이벤트 시퀀스로 표현한다. (Event Based Model)

  - ASM의 경우 : object 기반 모델로 클래스를 오브젝트 트리로 표현한다. (Object Based Model)

 

> 구성

  - asm.jar : class parster 와 writer  (core API)

  - asm-util.jar : 개발, 디버깅시에 사용 (core 의존)

  - asm-commons.jar : 미리 정의한 class 변환기 (core 의존)

  - asm-tree.jar : object 표현을 event 표현으로 변환

  - asm-analysis.jar : 미리 정의한 분석기와 분석 프레임워크 (tree 의존)


> Core API

  - class methods, annotations, generics에 대한 generate 과 transform을 Core API 활용하여 어떻게 하는지 알아본다

  - 컴파일된 클래스 구조(Structure) : 간단히 3가지로 나뉨

    + modifier 영역 : public, private

    + field 영역 : modifier, type이나 annotation of a field, name 선언

    + method, constructor 영역 : modifier, name, return, parameter type, annotation of a method

  - 컴파일 클래스와 소스의 차이

    + 소스는 여러 클래스를 포함한다 : inner class

    + 컴파일 클래스는 하나 클래스로 표현하고 comment 제거하고 package, import도 포함하지 않는다. 

    + 컴파일 클래스는 "constant pool"가 있다. constant pool은 배열(Array)이다. 한번만 생성이 도고 index로 참조되어 진다. 

      >>> 컴파일 클래스의 전체 구조

    


    + 컴파일 클래스는 타입표현 명명이 틀리다. internal name 은 클래스의 전체 이름을 사용한다. 

       java/lang/String같이 slash(/)로 구분한다.

    + Internal name은 type에도 적용된다. (type descriptor)

      >>> type descriptor 맵핑

     


    + method descriptor는 type descriptor의 목록이다.

      >>> 메소드 예

    


  - ClassVisitor 추상 클래스가 컴파일된 클래스의 생성/변환을 담당한다. AnnotationVisitor, FieldVisitor, MethodVisitor 리턴

   

  - FieldVisitor 추상 클래스 

   


  - Core API는 ClassVisitor API에 기반하여 클래스 generate 와 transform 할 수 있게 3가지 core 컴포넌트를 제공한다

    + ClassReader : byte array 주어진 컴파일된 클래스를 파싱한다. ClassVisitor를 accept 메소드 파라미터로 주면 

                            visitXxx 메소드를 호출한다 (event producer)

    + ClassWriter : ClassVisitor의 subclass이고 컴파일된 클래스를 바이너리로 만든다. toByteArray메소드롤 얻을 수 있는 

                            byte array로 결과물을 생산한다 (event consumer) 

    + ClassVisitor : 다른 ClassVisitor를 받으면 메소드 호출을 위임한다 (event filter)

posted by 윤영식
2012. 12. 27. 11:18 Git, GitHub/Git Lec02

GitHub에 만들어 놓은 저장소 관리를 알아보자. 


1) 리모트 저장소 확인하기 

// 프로젝트 복제 

$ git clone https://github.com/ysyun/pro_git.git

Cloning into 'pro_git'...

remote: Counting objects: 3, done.

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

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


$ cd pro_git


$ git remote

origin


// 같은 프로젝트에 대해서 여러 기여자가 있을 수 있다. 

$ git remote -v  

origin  https://github.com/ysyun/pro_git.git (fetch)

origin  https://github.com/ysyun/pro_git.git (push)


2) 리모트 저장소 추가하기 : git remote add [단축이름] [url] 

$ git remote -v

dowon   $ (fetch)

dowon   $ (push)

origin  https://github.com/ysyun/pro_git.git (fetch)

origin  https://github.com/ysyun/pro_git.git (push)


// 기존 잘 못 설정된 내역 삭제

$ git remote rm dowon


$ git remote -v

origin  https://github.com/ysyun/pro_git.git (fetch)

origin  https://github.com/ysyun/pro_git.git (push)


// 새로운 remote alias 추가 

$ git remote add dowon  https://github.com/ysyun/pro_git.git


// 확인

$ git remote -v

dowon   https://github.com/ysyun/pro_git.git (fetch)

dowon   https://github.com/ysyun/pro_git.git (push)

origin  https://github.com/ysyun/pro_git.git (fetch)

origin  https://github.com/ysyun/pro_git.git (push)


// 리모트 저장소 이름 변경 

$ git remote rename dowon young


// 확인

$ git remote -v

origin  https://github.com/ysyun/pro_git.git (fetch)

origin  https://github.com/ysyun/pro_git.git (push)

young   https://github.com/ysyun/pro_git.git (fetch)

young   https://github.com/ysyun/pro_git.git (push)


3) 리모트 저장소를 Pull, Fetch 하기 : git fetch [remote-name] 

   - fetch : clone 이후 변경된 데이터를 모두 로컬로 가져온다. 그러나 자동 Merge는 하지 않는다. 수동 Merge해야 함

   - pull : 리모트 저장소 브랜치에서 데이터를 가져와서 현재 작업하는 로컬 브랜치와 Merge 한다. 

// fetch로 새로 추가한 build.gradle 파일 가져오기 fetch 수행

$ git fetch origin

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

   49c657f..03ca40a  master     -> origin/master


// 못가져옴 

$ ls

README.md


// pull로 새로 추가한 build.gradle 파일 가져오기 fetch 수행

$ git pull origin

Updating 49c657f..03ca40a

Fast-forward

 build.gradle | 3 +++

 1 file changed, 3 insertions(+)

 create mode 100644 build.gradle


// 가져옴 

$ ls -alrt

total 5

drwxr-xr-x   13 yuwonsys Administ     4096 Dec 27 10:45 ..

-rw-r--r--    1 yuwonsys Administ       38 Dec 27 10:45 README.md

-rw-r--r--    1 yuwonsys Administ       37 Dec 27 10:58 build.gradle

drwxr-xr-x   14 yuwonsys Administ     4096 Dec 27 10:58 .git

drwxr-xr-x    5 yuwonsys Administ        0 Dec 27 10:58 .


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

// 내용확인

$ cat build.gradle

task gzip << {

  println "gzip"

}


// remote에서 build.gradle 내역 수정함 -> fetch로 가져오기 시도 

$ git fetch origin

remote: Counting objects: 5, done.

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

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

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

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

   03ca40a..f856853  master     -> origin/master


// 변경 내역 파일 fetch 못함 

$ cat build.gradle

task gzip << {

  println "gzip"

}

// remote에서 build.gradle 내역 수정함 -> pull로 가져오기 시도 

$ git pull origin

Updating 03ca40a..f856853

Fast-forward

 build.gradle | 1 +

 1 file changed, 1 insertion(+)


// 변경 내역 파일 pull하여 가져왔음 

$ cat build.gradle

task gzip << {

  println "gzip"

  println "ok"

}


4) 리모트 저장소에 Push 하기 : git push [리모트 저장소 이름] [브랜치 이름]

// 맨 하단 내역을 로컬에서 추가한다 

$ cat build.gradle

task gzip << {

  println "gzip"

  println "ok"

  println "are you sure?"

}


// 상태를 확인해 보면 modified 상태이므로 Staging Area -> Git Directory로 이동해야 한다 

$ git status

# On branch master

# Changes not staged for commit:

#   (use "git add <file>..." to update what will be committed)

#   (use "git checkout -- <file>..." to discard changes in working directory)

#

#       modified:   build.gradle

#

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


// -a 옵션으로 Git Directory로 바로 commit 한다

$ git commit -a -m "add content in build.gradle"

[master 329db04] add content in build.gradle

 1 file changed, 1 insertion(+)


// commit 완료 확인

$ git status

# On branch master

# Your branch is ahead of 'origin/master' by 1 commit.

#

nothing to commit, working directory clean


// 변경 내역을 리모트의 master 브랜치로 push 한다 (github 사용시 ID/PWD 입력함)

$ git push origin master

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

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

Counting objects: 5, done.

Delta compression using up to 2 threads.

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

Writing objects: 100% (3/3), 345 bytes, done.

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

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

   f856853..329db04  master -> master


5) 리모트 저장소 살펴보기 : git remote show [리모트 저장소 이름]

$ 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: // pull 하여 오는 리모트 브랜치 목록 보여줌

    master tracked

  Local branch configured for 'git pull': // Merge 브랜치를 알려줌

    master merges with remote master

  Local ref configured for 'git push':  // master 브랜치가 master 브랜치로 push 함 

    master pushes to master (up to date)


posted by 윤영식
2012. 12. 26. 17:53 CI/Jenkins, Travis

JavaScript로 짠 코드를 Gradle로 빌드해서 Jenkins로 자동화 하는 방법에 대해서 알아보자. 슬라이드에 JavaScript 에 대한 압축, 축소에 대해 Gradle Plugin 사용예가 존재한다. http://git.io/gradlejs 로 등록되어 있다.


> JavaScript + Jenkins에 대한 한글 자료


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

[Travis] GitHub과 Travis CI 연동하기  (0) 2013.08.14
[Jenkins] 설치후 Security 설정하기  (0) 2013.01.07
posted by 윤영식
2012. 12. 25. 23:55 Languages/Java

그루비도 Closure를 지원한다. 그렇다면 Closure에 대하여 알아보자. (좀 더 정리할 필요가 있겠음)


> 클로저의 가치

  - 함수 객체(function objects) 또는 익명 함수(anonymous function)로서 작용한다.

  - 유형 시스템(type system)이 데이터뿐만 아니라 코드도 나타낼 수 있어야 한다는 점에 유형 시스템에 대한 결과도 갖는다 (음 무슨 말인지 이해안감ㅜㅠ)

  - 함수들을 퍼스트-클래스 객체들로서 지원한다. 

  - 함수들은 변수에 저장될 수 있고, 매개변수로서 다른 함수에 저장된다.

  - 동적으로 생성되고, 함수들에서 리턴된다. 

  - 클러저는 Scheme, Common Lisp, Smalltalk, Groovy, JavaScript, Ruby, Python에서 찾아 볼 수 있다.


<참조>

  - 클로저 논의 IBM 번역

  - JavaScript에서의 클로저

posted by 윤영식
2012. 12. 25. 23:33 Languages/Java

IntelliJ IDE 에서 그루비를 실행하고 테스트해보자. 우선 Eclipse에서 어떻게 수행되는지 동영상을 보고 따라해 보도록 한다. 


> 이클립스에서 그루비 실행하기 

  - 그루비 한글번역 튜토리얼

  - IntelliJ IDE에서 JUnit 4 테스트를 생성하고 구동시키는 방법 



> IntelliJ IDE에서 그루비 생성하고 클래스 테스트하기 


위의 eclipse 기준 동영상을 IntelliJ IDE에 맞추어 테스트 해본다 

1) 새로운 프로젝트 생성

  - New Project 생성

  - step-01 : Java Module 선택


  - step-02 : src 디렉토리 선택

  - step-03 : Groovy 선택 (사전에 Groovy는 설치되어 있어야 한다)


2) 그루비 테스트 하기  

// collection & closure

def coll = ["groovy", "java", "ruby"]  // javascript처럼 컬렉션을 만들 수 있다

assert  coll instanceof Collection // assert 결과가 true이면 다음 문장으로 계속 수행함 

assert coll instanceof ArrayList

println coll.class

println coll


coll << "perl"  // 추가하기 


println coll


coll[4] = 'python'  // 배열처럼 직접 삽입

println coll


println coll - ['java'] // 값 빼기 


// closure 1

coll.each{  value ->    // 파라미터 명을 value로 설정함 

    println '> ' + value

}

// closure 2

def excite = { word ->

    return "${word}!!"

}

assert 'Dowon!!' == excite('Dowon')

println excite('Dowon')


// key=value의 map 객체를 만듦 

def hash = [name:'yun', 'age':27]

assert hash.getClass() == java.util.LinkedHashMap

println hash


hash.height = 177   // key=value 추가하기 

println hash


hash.put('height', 190)  // put 이용

println hash


3) Song 클래스 만들기

// set, get 메소드가 자동으로 만들어 진다. 

// getGenre() 메소드를 재정의한다

class Song {

    def name

    def artist

    def genre


    String toString() {

        "${name}, ${artist}, ${getGenre()}"

    }


    def getGenre() {

        genre.toUpperCase()

    }

}


4) SongExample로 Song 클래스 수행 : ctrl + shift + F10 으로 수행한다 

class SongExample {

    static void main(args) {

       // 생성자는 그루비가 자동으로 생성해 준다 

        Song sng = new Song(name: "tear's heaven", artist: "singer", genre: "rock")

        sng.name = "hi"

        sng.setArtist("dowon")   // set, get 메소드가 이미 있으므로 호출 가능하다 

        println sng


        Song sng2 = new Song()

        // name 지정을 하지 않았으므로 null이다. ?를 하면 null safety 체크한다  

        // 즉 name 이 null 이면 toUpperCase() 를 수행하지 않는다 

        println sng2.name?.toUpperCase()  

    }

}


5)  테스트 코드를 작성한다 : java의 junit 코드로 짜된다 어차피 그루비도 수행시 컴파일 되면 java와 같이 bytecode로 변경된다

  - ctrl + shift + t 클릭하면 "Create New Test..." 메뉴를 선택한다
   


  - JUnit4를 선택하고 OK 클릭한다
   


  - Test 코드를 작성한다 : Groovy 스타일 Test 케이스를 만들 수도 있고, Java 스타일 Test 케이스도 가능하다 (Bi-direction)

import junit.framework.Assert;
import junit.framework.TestCase;
import org.junit.Test;

public class SongTest  {
    @Test
    public void testToString() {
        Song song = new Song();
        song.setName("Smells like teen spirits");
        song.setArtist("youngsik");
        song.setGenre("hard rock");

        Assert.assertEquals("Smells like teen spirits, youngsik, HARD ROCK", song.toString());
    }
}


'Languages > Java' 카테고리의 다른 글

[ASM4] Core API - 01  (0) 2012.12.27
[Groovy] Closure 지원하는 그루비  (0) 2012.12.25
[Groovy] Domain Specific Language 배우기  (0) 2012.12.25
[JVM] Java란 무엇인가?  (0) 2012.11.21
[BeanShell] 설치하고 사용하기  (0) 2012.10.26
posted by 윤영식
2012. 12. 25. 02:04 Languages/Java

Groovy를 통해 많은 생태계가 만들어지고 있다. 그중 Gradle이라는 Build Automation 툴을 사용하려 한다. Groovy의 생태계와 DSL에 대해 알아보자 


> Groovy가 만들고 있는 생태계

  • Grails와 같은 Framework 에 사용
  • Easyb(BDD)와 같은 Testing 에 사용
  • Gradle 과 같은 Build Automation Tool 에 사용
  • 기타등등

> Groovy 기본 개념과 DSL 그리고 생태계

  • Groovy는 Dynamic 언어 (2003년 시작)
  • SpringSource, JBoss 등 많은 오픈소스진영에서 사용중
  • Fully Object-Oriented, Closures, Properties, Optional typing, wrapper APIs, authoring DSLs, lively ecosystem


> Groovy DSL 배우기 


posted by 윤영식
2012. 12. 24. 11:39 Git, GitHub/Git Lec02

Git 저장소를 만들고 Working Directory, Staging Area, Git Directory를 오가는 명령을 알아보자.


> Git 저장소 만들기 

  • 프로젝트 디렉토리를 만든다
  • 프로젝트 디렉토리로 이동한다
  • git init 명령을 수행하면 .git 디렉토리가 생긴다 (git 뼈대)
  • 버전관리를 시작할려면 git add -> git commit 을 하여 파일을 저장소에 추가해야 시작된다.

$ mkdir pro_git


$ cd pro_git


$ git init

Initialized empty Git repository in d:/git-repositories/pro_git/.git/


$ ls -alrt

total 4

drwxr-xr-x   13 yuwonsys Administ     4096 Dec 24 11:01 ..

drwxr-xr-x    9 yuwonsys Administ     4096 Dec 24 11:01 .git

drwxr-xr-x    3 yuwonsys Administ        0 Dec 24 11:01 .


$ touch README.md


$ git add README.md

$ git commit -a -m "add readme.md file"

[master (root-commit) 3b7d2a8] add readme.md file

 0 files changed

 create mode 100644 README.md



> Git 복제 

  • git clone <url>


> 파일 수정하고 저장소에 저장하기 

  • Tracked(관리대상)와 Untracked(비관리대상) 으로 나뉜다. 즉 한번이라도 commit 되면 관리대상이 된다.
  • Tracked는 Unmodified(수정하지 않음)와 Modified(수정함) 그리고 Staged(커밋전) 상태 중 하나이다.
  • Clone을 하게 되면 모든 파일은 Tracked이면서 Unmodified 상태이다. 또한 자동으로 자동 Checkout도 한다.

untracked <-> unmodified <-> modified <-> staged <-> commited


  • git status : 파일 상태의 확인 tracked와 modified 상태파일이 없거나, Untracked 파일이 있는지 보여준다
// tracked이면서 modified 상태 파일이 없음 표시
$ git status
# On branch master
nothing to commit, working directory clean

// Untracked 파일 추가 
$ touch aa.txt

// Untracked 파일 목록을 보여줌 
$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       aa.txt
nothing added to commit but untracked files present (use "git add" to track)

// tracked 파일인 README.md 파일에 내용을 입력함
$ vi README.md

// Tracked 파일과 Untracked 파일 목록을 보여줌 
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   README.md
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       aa.txt
no changes added to commit (use "git add" and/or "git commit -a")
  • git add <파일명 또는 디렉토리경로명> : Tracked 상태로 만들면서 Staged 상태가 된다 
// aa.txt 파일을 add 하여 tracked+staged 상태로 변경함 
$ git add aa.txt

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   aa.txt
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   README.md
#
  • Modified 상태의 파일을 Stage 하기 

// 수정하여서  Changes not staged for commit: 으로 표현된 README.md파일을 Staged 상태로 변경하기 

$ git add README.md


$ git status

# On branch master

# Changes to be committed:

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

#

#       modified:   README.md

#       new file:   aa.txt

#

  • Stage 된 파일을 다시 Modified 하였을 경우 

// 이미 Staged 상태인것을 다시 수정한다

$ vi README.md


// 상태를 확인해 보면 README.md 파일이 Staged 에도 존재하고 modified 상태에도 존재한다.

// 만일 commit을 하게 되면 Staged 상태의 READM.md파일이 커밋된다. 

// 다시 git add README.md를 해준다

$ git status

# On branch master

# Changes to be committed:

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

#

#       modified:   README.md

#       new file:   aa.txt

#

# Changes not staged for commit:

#   (use "git add <file>..." to update what will be committed)

#   (use "git checkout -- <file>..." to discard changes in working directory)

#

#       modified:   README.md

#


// modified 상태의 파일을 staged 상태로 변경한다 

$ git add README.md


// 다시 상태 확인 

$ git status

# On branch master

# Changes to be committed:

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

#

#       modified:   README.md

#       new file:   aa.txt

#

  • .gitignore : Untracked 파일을 git 목록에서 제거하기 (로그파일, 빌드환경파일, 프로젝트파일등 무시하고자 하는 것을 명시한다)
    • 아무것도 없는 줄이나 # 시작하는 줄 무시
    • 표준 Glob 패턴 사용 (Glob패턴은 정규표현식을 단순하게 만든 것으로 보통 쉘에서 사용)
      • * : 문자가 하나도 없거나 하나 이상을 의미 
      • [abc] : 중괄호 안에 있는 문자중 하나를 의미
      • ? : 문자 하나를 의미
      • [0-9] : 하이픈을 사용하면 그 캐릭터 사이의 문자 하나를 의미
    • 디렉토리는 슬래쉬(/)를 끝에 사용
    • 느낌표(!)로 시작하는 패턴은 해당 패턴의 파일 무시

# comment

*.a  # 확장자 .a 인 파일 무시

!lib.a # lib.a 파일은 무시하지 않음

/TODO # 루트 디렉토리에 있는 TODO 파일 무시

build/  # build/ 디렉토리 모든 파일 무시

doc/*.txt # doc/*.txt는 무시 그러나 doc/another/*.txt 파일은 무시하지 않음

  • git diff : Staged와 Unstaged 상태의 변경 내용을 보기 (git status 는 단순 상태 정보만을 보여주지만 git diff는 변경 내용을 볼 수 있다)
// aa.txt 파일안에 test라고 내용을 입력한다 
$ vi aa.txt

// working directory의 modified상태와 staging area의 staged 상태의 내역 차이를 비교하고 내용을 보여준다
// 즉 staged 상태가 아닌 파일을 비교해 볼 수 있다. (즉, Ustaged 상태인 것들만 보여준다)
$ git diff
diff --git a/aa.txt b/aa.txt
index e69de29..9daeafb 100644
--- a/aa.txt
+++ b/aa.txt
@@ -0,0 +1 @@
+test

// git diff --cached : staged 와 git directory간의 변경내역을 보고 싶을 경우 
// Staging Area 와 저장소에 커밋한 것을 비교해 볼 수 있다. (즉, Staged 상태인 것들만 보여준다)
$ git diff --cached
diff --git a/README.md b/README.md
index e69de29..47086e9 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,2 @@
+hi pro git
+by dowon
diff --git a/aa.txt b/aa.txt
new file mode 100644
index 0000000..e69de29
  • git commit <fileName option> -m <message> : Staging Area 파일을 정일한다. 즉, Staged 파일만 해당 된다. git add 하지 않은 파일은 Modified 상태로 남음.

// master 브랜치에 커밋했고, 체크섬은 9160d86 이라는 의미

$ git commit aa.txt -m "add test file"

[master 9160d86] add test file

 1 file changed, 1 insertion(+)

 create mode 100644 aa.txt

  • git commit -a -m <메세지> : Staging Area 생략하고 commit 하기. 

// 내용 수정

$ vi README.md


// 현재 상태 : modified 상태가 있지만 Staging Area를 거치지 앟고 바로 Git Direcotry (로컬 저장소)로 보내고 싶을 경우 

$ git status

# On branch master

# Changes to be committed:

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

#

#       modified:   README.md

#

# Changes not staged for commit:

#   (use "git add <file>..." to update what will be committed)

#   (use "git checkout -- <file>..." to discard changes in working directory)

#

#       modified:   README.md

#


// -a 옵션 사용 단, 파일은 최소 1회 이상 commit 이 된 것이어야 한다 

// master 브랜치에 6efd594 체크섬으로 commit 되었음

$ git commit -a -m "modified README.md"

[master 6efd594] modified README.md

 1 file changed, 2 insertions(+)


// commit 이 되었음 

$ git status

# On branch master

nothing to commit, working directory clean

  • git rm <파일> : 삭제된 파일은 Staging 상태가 된다. 다시 commit을 하면 삭제가 된다. (삭제확인을 위한 장치). 만일 Staging Area에서 포함되지 않게 제거하는 것은 git rm --cached를 사용한다.
// 파일을 삭제한다 
$ git rm aa.txt
rm 'aa.txt'

// 삭제된 파일이 Staging Area에 Deleted 상태로 있음을 알려준다 
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       deleted:    aa.txt
#

// commit 하여 Staging Area에 있는 Deleted 상태의 파일을 제거한다 
$ git commit -m "delete aa.txt"
[master b5da470] delete aa.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 aa.txt

// aa.txt 파일이 제거되었다. 
$ git status
# On branch master
nothing to commit, working directory clean
  • git mv <from파일> <to파일> : 파일 이름 변경하기를 하면 Staging Area에 Renamed 상태로 된다.
// 이름을 변경(옮긴다)
$ git mv README.md README

// Staging Area에 Renamed 상태
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       renamed:    README.md -> README
#
  • git log : 커밋 히스토리 보기. 가장 최근 커밋이 가장 먼저 나온다. -p 옵션은 커밋의 diff 결과를 보여준다. -2 는 두개의 결과만 보여준다. -p 옵션은 diff이기 때문에 동료의 변경 내용을 빠르게 확인 할 수 있다. --stat 각 커밋의 통계 정보를 보여줌. --pretty는 사용자 정의가능 (oneline, short, full, fuller, format 옵션 예, --pretty=oneline). --graph는 브랜치 그래프를 보여줌
// -p 변경 내역을 포함하고 -2  최근 2개만 보여줌 
$ git log -p -2
commit b5da4702608e2980a38d51416af79a35b7fcd904
Author: Yun DoWon <ysyun@yuwin.co.kr>
Date:   Mon Dec 24 14:01:50 2012 +0900

    delete aa.txt

diff --git a/aa.txt b/aa.txt
deleted file mode 100644
index 9daeafb..0000000
--- a/aa.txt
+++ /dev/null
@@ -1 +0,0 @@
-test

commit 6efd594f461e0e71d655efab90cf2341f8d9e290
Author: Yun DoWon <ysyun@yuwin.co.kr>
Date:   Mon Dec 24 13:54:48 2012 +0900

    modified README.md

diff --git a/README.md b/README.md
index e69de29..00ed50f 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,2 @@
+hi pro git
+by dowon yun

// 통계 정보를 보여줌 
$ git log --stat
commit b5da4702608e2980a38d51416af79a35b7fcd904
Author: Yun DoWon <ysyun@yuwin.co.kr>
Date:   Mon Dec 24 14:01:50 2012 +0900

    delete aa.txt

 aa.txt | 1 -
 1 file changed, 1 deletion(-)

commit 6efd594f461e0e71d655efab90cf2341f8d9e290
Author: Yun DoWon <ysyun@yuwin.co.kr>
Date:   Mon Dec 24 13:54:48 2012 +0900

    modified README.md

 README.md | 2 ++
 1 file changed, 2 insertions(+)

commit 9160d863411cd3ef7c7977bff6d405ad41608b58
Author: Yun DoWon <ysyun@yuwin.co.kr>
Date:   Mon Dec 24 13:48:06 2012 +0900

    add test file

 aa.txt | 1 +
 1 file changed, 1 insertion(+)

commit 3b7d2a8903cd5b02344ce89b3ff4386ff3f3a038
Author: Yun DoWon <ysyun@yuwin.co.kr>
Date:   Mon Dec 24 11:04:33 2012 +0900

    add readme.md file

 0 files changed

// 한줄로 보여주기 : 내용을 많을 경우 유용함 
$ git log --pretty=oneline
b5da4702608e2980a38d51416af79a35b7fcd904 delete aa.txt
6efd594f461e0e71d655efab90cf2341f8d9e290 modified README.md
9160d863411cd3ef7c7977bff6d405ad41608b58 add test file
3b7d2a8903cd5b02344ce89b3ff4386ff3f3a038 add readme.md file

// format 형식을 준다 
$ git log --pretty=format:"%h -%an, %ar : %s"
b5da470 -Yun DoWon, 15 minutes ago : delete aa.txt
6efd594 -Yun DoWon, 22 minutes ago : modified README.md
9160d86 -Yun DoWon, 29 minutes ago : add test file
3b7d2a8 -Yun DoWon, 3 hours ago : add readme.md file

// 브랜치 히스토리까지 본다 
$ git log --pretty=format:"%h %s" --graph
* b5da470 delete aa.txt
* 6efd594 modified README.md
* 9160d86 add test file
* 3b7d2a8 add readme.md file
* format 옵션 내역

Option Description of Output

%H Commit hash

%h Abbreviated commit hash

%T Tree hash

%t Abbreviated tree hash

%P Parent hashes

%p Abbreviated parent hashes

%an Author name

%ae Author e-mail

%ad Author date (format respects the –date= option)

%ar Author date, relative

%cn Committer name

%ce Committer email

%cd Committer date

%cr Committer date, relative

$s  Subject


* git log 옵션들

--since --after : 명시한 날짜 이후의 커밋만 검색. 예)git log --since=2.weeks : 2주 동안 만들어진 커심들만 조회

--until, --before : 명시한 날짜 이전의 커밋만 검색 

--author : 저자를 지정할 수 있다. 

--committer : 입력한 커밋터의 커밋만 조회 

--grep : 커밋 메세지에서 키워드를 검색

-- <path1> <path2> : 해당 경로 밑의 커밋 히스토리를 조회 


// commit hash와 subject만을 보여주고 저작자 Yun DoWon 이라는 사람의 23이전 커밋 내역 검색

$ git log --pretty="%h - %s" --author="Yun DoWon" --since="2012-12-23"

b5da470 - delete aa.txt

6efd594 - modified README.md

9160d86 - add test file

3b7d2a8 - add readme.md file


'Git, GitHub > Git Lec02' 카테고리의 다른 글

[Pro Git] Git Alias 사용하기  (0) 2013.01.08
[Pro Git] Tag 사용하기  (0) 2013.01.08
[Pro Git] 리모트 저장소 관리하기  (0) 2012.12.27
[Pro Git] Git 설치와 최초 설정하기  (0) 2012.12.24
[Pro Git] DVCS역사  (0) 2012.12.24
posted by 윤영식
2012. 12. 24. 10:49 Git, GitHub/Git Lec02

Git 설치에 대해 간단히 알아보고, 설정하는 방법에 대하여 알아보자 


> Git 설치

  • Git은 curl, zlib, openssl, expat, libiconv를 필요로 한다 
// Fedora yum 이용
$ yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel
$ yum install git-core

// 데비안 apt-get 이용
$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
$ apt-get install git-core
// 윈도우 설치
http://code.google.com/p/msysgit  다운로드하여 설치한다

$ tar -zxf git-1.8.1.tar.gz

$ cd git-1.7.2.2
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
  • Git이 이미 설치되었다면 최신버전 소스를 다음과 같이 받을 수 있다. 

git clone https://github.com/git/git.git



> Git 환경파일

  • /etc/gitconfig : 시스템의 모든 사용자와 모든 저장소에 적용되는 설정. git config --system 옵션으로 RW 가능.
  • ~/.gitconfig : 특정 사용자에게만 적용(윈도우는 USER 밑에 존재) git config --global 옵션으로 RW 가능.
  • .git/config : Git Directory(Local Repsoitory)의 현재 작업중인 프로젝트에만 적용. 우선순위 가장 높음.

// user 밑의 .gitconfig 파일 내역 

[user]

name = Yun DoWon

email = ysyun@yuwin.co.kr

[http]

postbuffer = 524288000

[push]

default = upstream

[core]

autocrlf = true

[color]

ui = auto


// 현재 프로젝트의 .git/config 파일 내역 

[core]

repositoryformatversion = 0

filemode = false

bare = false

logallrefupdates = true

symlinks = false

ignorecase = true

hideDotFiles = dotGitOnly

[remote "origin"]

url = https://github.com/ysyun/jmqtt_client.git

fetch = +refs/heads/*:refs/remotes/origin/*

[branch "master"]

remote = origin

merge = refs/heads/master


// 전체 설정 내역 보기 : git config {key} 명령으로 특정 Key에 대한 값 확인 (Help 명령: git help config)

$ git config --list

core.symlinks=false

core.autocrlf=true

color.diff=auto

color.status=auto

color.branch=auto

color.interactive=true

pack.packsizelimit=2g

help.format=html

http.sslcainfo=/bin/curl-ca-bundle.crt

sendemail.smtpserver=/bin/msmtp.exe

diff.astextplain.textconv=astextplain

rebase.autosquash=true

user.name=Yun DoWon

user.email=ysyun@yuwin.co.kr

http.postbuffer=524288000

push.default=upstream

core.autocrlf=true

color.ui=auto

core.repositoryformatversion=0

core.filemode=false

core.bare=false

core.logallrefupdates=true

core.symlinks=false

core.ignorecase=true

core.hidedotfiles=dotGitOnly

remote.origin.url=https://github.com/ysyun/jmqtt_client.git

remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

branch.master.remote=origin

branch.master.merge=refs/heads/master


posted by 윤영식
2012. 12. 24. 10:00 Git, GitHub/Git Lec02

Pro Git에 대한 번역본을 보면서 공부한 내용을 정리한다. 


> 버전 관리 형태 

  • VCS : 초창기 로컬 버전 컨트롤 시스템으로 시작
  • CVCS : 중앙 버전 컨트롤 시스템 (단점 : 중앙 저장소 장애시 모든 개발자 접속 불가. 예: SVN, CVS)
  • DVCS : 분산 버전 컨트롤 시스템 (장점 : CVCS 단점 극복, 중앙 저장소를 그대로 로컬에 복제하여 사용함. 예:  Git)


> Git 역사

  • 리눅스 초창기 개발에서 쓰던 BitKeeper DVCS가 상용화 요구하면서 개발됨
  • 빠른 속도, 단순한 구조, 동시 다발적 브랜치(비선형적 개발), 완벽한 분산, 대형 프로젝트에도 적함(속도, 크기면에서도) 요건 충족토록 개발시작
  • 2005년 탄생

> Git 특성

  • Git 데이터는 파일 시스템의 SnapShot 으로 크기가 작다. 파일 변경이 없으면 버져닝시 이전 파일의 링크만 저장한다.
  • 거의 모든 명령은 로컬에서 수행된다. (CVCS는 네트워크 속도에 영향을 받는다) 오프라인 상태에서도 작업이 가능하다.
  • 데이터 무결성을 위해 모든 데이터 저장전 체크섬(Checksum 또는 Hash)을 구하여 관리한다. SHA01 Hash를 사용하여 체크섬을 만든다. (길이 40자 16진수 문자열)
  • 로컬에 3 단계로 나뉜다 : Working Directory (Modified) - Staging Area (Staged) - Git Directory(Local Repository, Commited)
    • Working Directory : 특정 버전을 Checkout 한 것이다. Git Directory에 압축된 데이터베이스 파일을 가져와 만든다
    • Staging Area : Git Directory에 있고, 단순 파일이고 곧 Commit 할 파일에 대한 정보이다. 종종 인덱스라고 불림.
    • Git Directory : 프로젝트의 메타데이터와 객체 데이터베이스를 저장하는 곳이다. Git의 핵심이다. 


posted by 윤영식
2012. 12. 23. 22:02 Languages/JavaScript

Java의 Spring과 같이 확장성이 높은 JavaScript 프레임워크를 만들기 위한 아키텍쳐에 대하여 알아보자 


  - Module Layer를 두어 모듈 단위로 모든것을 개발한다.

  - SandBox Layer 를 두어 Module이 상호 통신하는 인터페이스와 보안, 가이드 역할을 한다.

  - Core Layer 를 두어 Module의 LifeCycle을 책임진다. 모듈간 통신과 에러 핸들링, 확장을 수행. 

  - Base Library Layer 를 두어 기본 함수와 유틸을 제공한다. : JQuery, YUI 같은 것


> 유지보수 가능한 JavaScript 전략


> 고성능을 내기위한 JavaScript 전략 (Responsive JavaScript 코딩 전략)


  - UI Thread 작업시에는 Queue를 이용하라

  - JavaScript Execution 시간을 50ms 이상으로 하지 마라

  - JavaScript 다운로드하고 파싱하고 실행할때까지 HTML Rendering이 멈춘다. JavaScript은 무조건 HTML 맨 밑에 배치함

  - JavaScript를 쪼개 놓지 말고 합쳐서 다운로드 타임으로 조금이라도 줄여라 

  - 필요한 시점에 동적으로 스크립트 파일을 로딩한다

  - Reflow와 Repaint 횟수를 줄이는 것이 성능 최적화에 중요함

posted by 윤영식
2012. 12. 23. 21:51 Languages/JavaScript

Java에서 할 수 있다면 ECMAScript에서도 할 수 있지 않을까? 테스트를 어떻게 하는지 알아보자 


  - named function을 사용하라 (가급적 anonymous function 사용 배제)

  - namespace를 사용한다

  - 속성, 펑션은 return {key:value} 클로저 객체로 리턴한다

  - 펑션 내부 계산로직에 대해 return 하여 검증할 수 있게 한다

  - Functional Testing

    + gebish.org

    + zombie.labnotes.org

    + phantomjs.org


  - 단위 테스트 

    + QUnit ( docs.jquery.com/QUnit )

    + sinonjs.org

    + mocha

    + JsTestDriver

    + YUITest


> JsTestDriver를 통한 효율적인 JavaScript 테스팅하기



  - JsTestDriver와 Maven 연결 테스트하기

  - JsTestDriver 설정을 통하여 Jenkins에 xUnit Plugin 연동하여 테스트

  - 여러 브라우저에 대하여 테스트하기 

  - http://tddjs.com 참조


> BDD(Behavior Driven Development) JavaScript 


posted by 윤영식

Realtime을 통하여 개발하고 있는 내용을 브라우저에서 확인을 할 수 있다면? Meteor 또는 Derby 를 사용한다면 웹앱을 통하여 그렇게 만들 수 있을 것이다. 그러나 IDE이 개발툴에서 개발한 내용이 브라우저에서 F5 또는 reloading을 하지 않고 확인하면서 개발하는 놀라운 상황. 한마디로 와우!


> JetBrains WebStorm의 Live Edit 

 


> WebStorm 5.0 과 Chrom 브라우저간 Live Edit 기능 설정하기 

  - WebStorm : View 풀다운 메뉴의 중간에 위치한 Live Edit 메뉴를 클릭한다.

  - Chrome 브라워저 : Chrome JetBrains Extension을 설치해야 한다.

    + Extension 파일 다운로드 : 파일 다운로드

    + Chrome 브라우저를 새로 열고 chrome://chrome/extensions/  라고 주소 입력한다

    + 우측 상단에 있는 "개발자 모듬"를 선택한다

    + 다운로드 받은 파일 jb.crx 파일을 브라우저로 drag & drop 하면 extension 설치여부 팝업이 뜨면 설치 OK 클릭


posted by 윤영식
2012. 12. 23. 01:40 NodeJS/Concept

Node.js를 리안달이 만들고 난후 프로그래밍의 패러다임이 바뀌고 있다. 스타트업을 위한 모바일 서비스 또는 솔루션의 기본 플랫폼으로 사용되고 있다. 특히 요즘은 Client + Server + DB 가 인터넷에서 하나로 연결되고 있다. 인터넷이 하나의 운영체제처럼 변해가고 있는 것이다. 


  - JavaScript : Client + Server + DB 프로그래밍을 할 수 있는 랭귀지로 자리 잡고 있다.

  - JSON : MongoDB를 사용하면 Client + Server + DB 를 하나의 데이터로 통일 할 수 있다.

  - Socket.io : 인터넷에 물려있는 모든 Tier의 통신을 HTTP 프로토콜을 통하여 Bi-Direction 양방향 통신을 할 수 있다.


1) 인터넷에 연결된 모든 부분이 JSON을 통하여 데이터를 주고 받는다.


2) Node.js 생태계에 나타난 Framework들 : Realtime쪽에는 전부 Socket.io 가 핵심 모듈로 사용되고 있다.  

  - Backbone에서 본 현재 현황



3) Node.js 소개 + 코딩 + 클라우드 파운드리 


4) Derby 와 Meteor 비교 


5) Node에서도 TDD 개발은 중요하다. Node위에서 Server Side JavaScript 개발을 할 때 Vows와 Twitter를 이용한다.(24page)



'NodeJS > Concept' 카테고리의 다른 글

[Node.js] 기술 발전 방향 4단계  (0) 2013.02.16
[Cham] Express, CoffeeScript, Jade, Stylus boilerplate 코드 생성하기  (0) 2013.01.31
[Jade] Jade 사용하기  (0) 2012.12.15
[EJS] 사용하기  (0) 2012.12.15
[Node.js] Global Objects  (0) 2012.12.10
posted by 윤영식
2012. 12. 22. 17:42 NodeJS/Prototyping

socket.io를 이용하여 간단한 chatting 애플리케이션을 만들어 보자 


* 참조 : socket.io이용하여 chat 구현하기


> Express를 통하여 chat 컨텍스트를 만든다 (참조)

express chat


> app.js 에 socket.io를 위한 /chat 네임스페이스를 설정하고(jade이용), socket.io에 대하여 설정한다

// declaration

var express = require('express');

var app = express()

    , http = require('http').createServer(app)

    , io = require('socket.io').listen(http)

    , routes = require('./routes')

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

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

    , path = require('path');


app.get('/chat', chat.list);


// http listen

http.listen(app.get('port'), function(){

    console.log("Express server listening on port " + app.get('port'));

});


// socket connection event on

var chat = io

    .of('/chat')

    .on('connection', function(socket) {  // /chat uri로 접속이 들어오는 이벤트 처리 

        console.log('>>> chat server connection');


        socket.on('msg', function(data) { // msg 이벤트 처리 

            console.log('>>> data : ' + data.name + ', ' + data.msg);

            chat.emit('new', data); // new 이벤트를 발행하여 data를 다시 클라이언트들에게 전송 

        });

})


> jade 관련 파일 : chat.js 와 chat.jade 

// /routes 디렉토리의 chat.js 파일

exports.list = function(req, res){

    res.render('chat', { title: 'Chatting Example' });

};


//  /views 디렉토리의 chat.jade 파일

doctype 5

html

  head

    title= title

    link(rel='stylesheet', href='/stylesheets/style.css')

    script(src='/socket.io/socket.io.js')

    script(src='http://code.jquery.com/jquery-1.8.3.min.js')

    script(src='chat_module.js')

  body

    h1= title

    div#wrapper

        div#messages  // chat 메세지가 찍힌다 

        div.nic

            input#name(name='name', type='text')  // 이름 입력 창

        div

        textarea#message  // 메세지 입력 창

        br

        input#send(type='submit', value='Send')

    // chat_module.js에서 Chat 오브젝트를 초기화 한다 

    script

        $(document).ready(function() {

            Chat.initialize('/chat');

        });


> chat_module.js 안에 로직을 담는다 : 해당 모듈은 express의 public 디렉토리 밑에 놓는다 (즉시 실행 함수로 만듦)

(function() {

    window.Chat = {

      socket : null,


     // 초기화 시에 /chat uri 네임스페이스를 넣어주었다 

      initialize : function(socketURL) {

          console.log('step1 socketURL : %s', socketURL);

          this.socket = io.connect(socketURL);


          console.log('step2 conneciton ok : %s ', this.socket);


   // send 버튼을 누를 경우 실행 

          $('#send').click(function() {

              Chat.send();

          });


    // textarea 메세지 입력하고 enter key 칠 경우 

          $('#message').keyup(function(evt) {

             if((evt.keyCode || evt.which) == 13) {

                 Chat.send();

                 return false;

             }

          });


          // 서버로 부터 new 이벤트가 오면 메세지를 추가하는 add 콜백 설정  

          this.socket.on('new', this.add);

      },


      // 서버로 부터 발행된 new 이벤트 처리하는 펑션

      add : function(data) {

          console.log('add message : %s', data.name +', '+ data.msg);

          var name = data.name || 'anonymous';

          var msg = $('<div class="msg"></div>')

              .append('<span class="name">' + name + '</span>: ')

              .append('<span class="text">' + data.msg + '</span>');

          console.log('add html : %s', msg);


          $('#messages').append(msg).animate({scrollTop: $('#messages').prop('scrollHeight')}, 0);

      },


      // 메세지 넣고 send 버튼을 클릭할 때 수행하는 펑션 

      send : function() {

          console.log('sending message : %s', $('#name').val() +', '+ $('#message').val());

          this.socket.emit('msg', {

              name: $('#name').val(),

              msg: $('#message').val()

          });


          $('#message').val('');

      }

    };

}());



> node app 명령으로 Node 서버를 실행시킨 후 브라우저로 호출한다 (http://localhost:3000/chat)

youngsik과 dowon 끼리 대화하는 것을 서버가 전송하고 있다 


* Express + Jade + Socket.io 프로젝트 파일 전체  

chat.zip


* js 파일이 변경될 때 마다 Node.js를 restart 하고 싶지 않다면 supervisor를 사용한다 

posted by 윤영식
2012. 12. 22. 14:46 NodeJS/Prototyping

Node.js에서 Express.js를 사용하고 템플릿 엔진은 Jade를 사용한다. 이때 socket.io를 간단히 테스트 해보자 


> 먼저 Socket.io 모듈를 설치한다 (물론 express 모듈도 사전 설치되었다 가정한다)

npm install socket.io


> Express.js를 통하여 만들고자 하는 컨텍스트를 만든다

express day3


> day3 디렉토리로 이동을 하면 app.js 파일이 있고 해당 파일안에 socket.io 모듈를 넣고 http 모듈과 체인닝을 해준다. 그리고 jade 설정이 되어 있는 socketio.js 모듈을 로딩한다 

// app.js 파일 상단 코딩

// 기존 코드 

var express = require('express')

  , routes = require('./routes')  // index.js 파일 

  , user = require('./routes/user') // user.js 파일 

  , dowon = require('./routes/dowon')// dowon.js 파일 

  , http = require('http')

  , path = require('path');


// 변경 코드 

var express = require('express');

var app = express()

  , http = require('http').createServer(app)   

  , io = require('socket.io').listen(http)  // http 모듈을 socket.io 모듈과 체인닝함 

  , routes = require('./routes')

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

  , socketio = require('./routes/socketio') // socketio.js 파일 로딩 

  , path = require('path');


> url rout 설정을 해줌 for jade

// url route

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

app.get('/users', user.list);

app.get('/socketio', socketio.io); //  브라우져에서 /socketio 호출하면 socketio 모듈의 io exports명칭의 펑션을 호출한다


> socketio.jade 파일을 만들어서 views 디렉토리에 놓는다 

// socketio.jade 파일 내역

doctype 5

html

  head

    title= title

    link(rel='stylesheet', href='/stylesheets/style.css')

    script(src='/socket.io/socket.io.js')

    script(src='http://code.jquery.com/jquery-1.8.3.min.js')

    script

        $(function() {

            var ws = io.connect();  // node에서 수행한 app.js의 socket.io listen으로 연결


            ws.emit('server_1');  // 서버쪽으로 server_1 이벤트 발행

            ws.on('client_1', function(msg) {  // 서버로부터 온 client_1 이벤트 처리 

                $('#container').html(msg);

            });

        });

  body

    h1= title

    div#container


> app.js 파일안에 socket.io 서버 코딩을 한다

// socket on

io.sockets.on('connection', function(socket) {

    console.log('server connection');


    socket.on('server_1', function(data) { // 클라이언트로 부터 온 server_1 이벤트 처리

        if(data != undefined) {

            console.log('>>>>>' + data);

        }


        var msg = 'hi youngsik';

        socket.emit('client_1', msg); // 클라이언트쪽으로 client_1 이벤트 발행

    });

});


> 브라우저에서 호출한다 그러면 잠시후 브라우져에서 "hi youngsik" 메세지가 div(id=container)에 뿌려진다


* 테스트 전체 파일

express_socketio.zip


* Socket.io GitHub : 자세한 사용 설명 보기

posted by 윤영식
2012. 12. 21. 16:18 Languages/JavaScript

렌더링 과정에 대하여 알아보고, 렌더링시 성능 최적화할 수 있는 방법들을 살펴보자 (책. 4장 렌더링)



▶ 전체 브라우저 렌더링 처리 과정


  - 전체 브라우저 처리과정 : HTML DOM 트리 + CSS 스타일 구조체 = 렌더 트리 생성 (레이아웃 처리) -> 페인트 (화면에 표현)

  - DOM 트리 생성 : HTML을 DOM 요소 노드 트리 형태로 구성.

  - 스타일 구조체 생성 : CSS 정보를 스타일 구조체(Style Struct)로 생성한다. 

  - 렌더 트리 생성 : DOM 트리와 각 노드에 스타일 정보를 설정하여 화면에 표현할 노드로 구성한다. DOM 트리와 렌더 트리는 1:1 대응하지 않는다.

  - 레이아웃 처리 : 렌더 트리의 각 노드 크기가 계산되어 위치계산한다.

  - 페인트(Paint) : 렌더 트리를 순회하면서 페인트 함수를 호출해 노드를 화면에 표현한다.



▶ 리플로와 페인트


  - 리플로(Reflow) : Ajax와 같은 데이터를 가져와서 화면에 뿌릴라 치면 변경이 필요한 렌더 트리에 대한 유효성 확인 작업과 함께 노드의 크기와 위치를 다시 계산한다. 이과정을 리플로 = 레이아웃(Layout) = 레이아웃팅(Layouting)  이라 한다. (부모 노드의 변경은 자식 노드 변경 리플로도 야기한다)

  - 리페인트(Repaint) : 변경 영역의 결과를 표현하기 위해 화면이 업데이트 되는 것을 의미한다. 리페인트 = 리드로(Redraw) 

  - 리플로 와 리페인트는 비용이 높다. 발생하는 원인을 살펴보자 

    + DOM 노드의 변경 : 추가, 삭제

    + DOM 노드 노출 속성을 통한 변경 : 추가, 삭제, 특성 변경

    + 스크립트 애니메이션 : 애니메이션은 DOM, 스타일 등이 짧은 시간에 수차례 변경되는 것임

    + 스타일 : 추가, 변경

    + 사용자 액션 : 브라우저 크기 변경, 글꼴 크기 변경등 



▶ 리플로 & 페인트 최소화 방법


  - 작업 그룹핑 : DOM 요소 변경시 같은 형태끼리 그룹으로 묶어서 실행한다. 

  - 실행 사이클 : 루핑 구문 즉 setTimeOut같은 구문에서 DOM 요소 핸들링을 배제한다.

  - display 속성 : 루핑이 어쩔 수 없다면 

element.style.display="none"; 

<looping구문> 

element.style.display="block";  


  - 이렇게 하면 루핑구문에서 "리플로+페인트"가 계속 발생하지 않고, none과 block 할때 딱 두번만 발생한다.

  - 노드 복제 : 루핑도는 구문에서 노드 핸들링시 원복 노드를 복제하여 사용함 

var clone = element.cloneNode(true);

<looping 구문>

parentNode.replaceChild(clone, element);


  - createDocumentFragment() 사용 : DOM 객체와 별개의 새로운 DOM 객체를 생성하여 사용하면 렌더링 성능 향상 가능함.

var fragment = document.createDocumentFragment(); 

<looping 구문안에서 fragment.appendChile(elems[e]); 호출 > 


  - 캐싱 : 별도의 변수에 자주 사용하는 속성값 또는 메소드값을 저장하여 사용한다. 

  - 하드웨어 가속 렌더링 : GPU를 이용한다. 브라우져 마다 설정값이 틀림. (크롬 :  chrome://flags 로 GPU 설정 확인 가능)


posted by 윤영식
2012. 12. 21. 11:31 Git, GitHub/Git Lec01

Git 내부 저장소를 최적화 해주는 작업과 zip/tar로 묶는 방법에 대해 알아보자 


  • git gc : 저장소의 크기 압축 및 최적화 (지저분한 내용을 정리)
  • git gc --aggressive : 변경 사항 델타(delta)단위로 저장한다. 저장단위를 처음부터 최적화 한다 
$ git gc
Counting objects: 201, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (123/123), done.
Writing objects: 100% (201/201), done.
Total 201 (delta 57), reused 193 (delta 54)

$ git gc --aggressive
Counting objects: 201, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (177/177), done.
Writing objects: 100% (201/201), done.
Total 201 (delta 61), reused 140 (delta 0)



  • git archive --format=zip --prefix=aa/ HEAD > bb.zip : zip 포멧으로 aa/ 디렉토리 밑으로 모든 파일을 넣어서 HEAD에서 압축 생성하여 bb.zip파일을 만든다 
  • git archive --format=tar --prefix=aa/ HEAD | gzip > bb.tar.gz : 상동. 단, gz에 대하여 gzip 압축 추가 함 
// zip 압축하기 
$ git archive --format=zip --prefix=mqtt_java_client/ HEAD > mqtt_java.zip

// 확인
$ ls
README.md                   jmqtt_client-1.0.jar  mqtt_java.zip  src
eclipse_feature.properties  license.properties    pom.xml

// tar 압축하기 
$ git archive --format=tar --prefix=mqtt_java_client/ HEAD > mqtt_java.tar.gz

$ ls
README.md                   jmqtt_client-1.0.jar  mqtt_java.tar.gz  src
eclipse_feature.properties  license.properties    pom.xml


* 참조 : Git 선화

'Git, GitHub > Git Lec01' 카테고리의 다른 글

[Git] Release 브랜치 다루기  (0) 2012.12.20
[Git] tag 다루기  (0) 2012.12.20
[Git] Remote 저장소 연결 및 관리  (0) 2012.12.17
[Git] History 이용 및 관리하기  (0) 2012.12.13
[Git] Merge 종류와 충돌 해결하기  (0) 2012.12.12
posted by 윤영식