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

Publication

Category

Recent Post

2012. 11. 14. 08:50 Git, GitHub

Git을 가장 효율적으로 사용할 수 있는 방법에 대하여 번역해 놓은 글을 읽었다. 가장 합리적이면서 다양한 경우의 수에 대비한 적용 방식이  아닐까 하는 생각이 든다

원문 : Git Branch 전략

  • origin/master <-> origin/develop 영원히 가져가는 핵심 브랜치
    • master –>(create) develop –>(merge) master
    • 이름 : develop-*, master-*
    • master : production ready 코드
    • develop : integration 코드 (통합) – daily CI build
    • master 로 merge 할 때 배포 버전 태그 달음 : master commit 시 자동 빌드 수행
    • develop –> master로 가기 전 release 브랜치를 반드시 거친다
  • feature / release / hotfix 보조 브랜치
    • feature 브랜치
      • 조만간 배포할 기능을 개발 (배포할 수도 안 할 수도 있는 기능)
      • 이름 : feature-*
      • develop –>(create) feature –>(merge) develop
      • 맘에 안드는 기능이면 delete 한다.
      • feature는 개발자 저장소에 commit 하고,  origin에 push하지 않는다
    • release 브랜치
      • 제품 배포를 준비하는 브랜치
      • 이름 : release-*
      • 버전 번호를 부여함
      • develop->(create) release –>(merge) develop, master
      • 발견된 버그가 있다면  release에서 해결하고 develop에 merge
      • 진짜 배포할 상태가 되었을 때 master로 merge 하고 tag를 단다 (명령어들은 원문 참조)
    • hotfix 브랜치
      • 이미 배포한 운영버전에 문제를 해결하기 위해 만듦
      • 이름 : hotfix-*
      • master –> (create) hotfix –> (merge) develop, master
      • 치명적 버그의 발견 즉시 해결하기 위해 master 브랜치의 tag에서 create 한다

 

각 브랜치 정책에 따라 개발을 해보자 

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

[Git] commit 사용하기  (0) 2012.11.26
[Git] diff 사용하기  (0) 2012.11.22
[Git] Ubuntu 에 설치하기  (0) 2012.11.14
SVN에 대하여 이해하기  (0) 2012.09.20
[Git] 레퍼런스 모음  (0) 2012.09.10
posted by 윤영식
2012. 11. 12. 16:26 Languages/JavaScript

JavaScript를 하면서 어려웠던 새로운 개념이 Closure이다. 이참에 조금 정리해 보도록 하자 


▶ Closure 개념

  - 로컬 변수를 참조하고 있는 함수 내의 함수 (JavaScript 마스터북, Jpub출판, p180)

  - 즉, 클로저는 자신의 범위(Scope) 밖에 있는 변수들에 접근할 수 있는 함수를 의미한다 

  - inner function을 return 할때 closure가 된다 (원문)

function outerFn() {

var count=1;

return function (cnt) {

      count += cnt;

console.log(count);

}

}


var func = outerFn();

func(10); // 결과 값 11

func(10); // 결과 값 21

  1) func가 closure가 됨 : 내부 변수들 closure, private 변수 생성됨

  2) func(parameter) 호출해 줘도 내부 변수들은 다시 생성되는 것이 아니라 상태를 유지시켜서 참조 됨 

  3) 즉, 클로저가 만들어 지면서 내부 변수들은 별도로 유지되면서 상태값을 유지함

  4) 클로저의 참조를 제거하고 GC할려면 명시적으로 func=null; 함



다른 예제를 보자 
예) closure가 아님 
function foo(x) {
  var tmp = 3;
  function bar(y) {
    console.log(x + y + (++tmp));
  }
  bar(10);
}
foo(2); // 결과 값 16
foo(2); // 결과 값 16
foo(2); // 결과 값 16

예) closure 임
function foo(x) {
  var tmp = 3;
  return function (y) {
    console.log(x + y + (++tmp));
  }
}
var bar = foo(2); // bar is now a closure.
bar(10); // 결과 값 16
bar(10); // 결과 값 17
bar(10); // 결과 값 18

var bar2 = foo(2);
bar2(10); // 결과 값 16
bar2(10); // 결과 값 17

  - 로컬 변수를 계속 생성하지 않고 상태를 유지하면 사용할 수 있다 (마치 객체처럼 var bar2 = foo(2); 하면 또 다른 closure가 생성되면서 bar와 별도의 상태공유 변수 x와 tmp가 생성된다. 마치 클래스에서 객체생성하는 것 처럼 된다. closure 생성시에 arguement와 var로 선언된 variable 에 대한 참조가 가능해 진다. 결국 참조자들-x, tmp-가 일정 메모리에 저장되어 상태를 유지한다)


  - 위의 예에서 var bar = foo(2);를 하는 순간 foo function 객체의 x, tmp 변수의 레퍼런스를 closure 가 가진다 (즉, x, tmp 에 대한 변수 상태값이 유지되고, y 값은 bar(10)을 호출할 때 넘겨주는 값이 된다)


  - 클로저는 간단한 객체이다 (엄밀히 따져서 객체는 아니지만 객체식으로 치환해서 살펴보면 다음과 같다)

    + 클로저 : 객체 = 클로저를 감싸고 있는 부모 함수 foo : 생성자

    + 클로저 : 객체 = 클로저로 부터 참조되는 로컬 변수 tmp :  프로퍼티

    + 클로저 : 객체 = 클로저 자신 bar, bar2 : 메소드

    + 클로저 : 객체 = var bar = foo(2) 함수 호출 : 인스턴스화

    + 클로저 : 객체 = 클로저를 대입하는 변수 bar(10), bar2(10) : 인스턴스 <-- 요거 애매함


  - function 내부에 for문을 돌면서 function을 호출하여 callback 을 셋팅하는 오류 제거 (원문1, 원문2)


실제 사용해 보면서 좀 더 이해를 해나가야 겠다. JavaScript Master북의 글이 좀 더 쉽게 이해가 가니, 햇갈릴 때 책을 다시 정독해 보자. 


<참조>

  - 소스니 코브 : Closure 이해하기

  - Closure 정리 : 한글이라 이해하기 쉬울것임

  - Inside.JS : 한글 정리 예제 포함

posted by 윤영식
2012. 11. 12. 11:34 Languages/JavaScript

자바스크립트의 Function에는 Expression (FE) 과 Declaration (FD) 가 있다고 한다. 이에 대한 차이를 연구해 보자. 우선 존경해 맞이하는 소스니코브의 정리 내역과 구글링한 사이트를 읽고 정리한다 



▶ Function Declaration


  - 변수 할당 없는 이름있는 함수를 정의

  - "var"로 시작하지 않고 "function"으로 시작해야 한다(must)

- 명확한 이름을 가져야 한다
- 소스코드중에 오고 function body를 가지면 다른 function 안에도 위치한다
- entering the context stage에서 생성된다 (즉, function 안에 FD 존재않음)
- variable object(VO)에 영향을 준다 
function bar() {
return 3;

}


or


// 1) directly int the global context

function globalFD() {

// inside the body of another function

function innerFD() {}

}




▶ Function Expression


  - 변수 할당이 있는 표현식으로서 함수를 정의

  - 이름있는 또는 익명(anonymous) 함수 가능

  - FE는 "function"으로 시작하지 않아야 한다(must)

- 소스중에 expression position에 정의된다 
- 함수명은 optional 이다 
- variable object(VO)에 저장되지 않는다 
- code execution stage에서 생성된다 
// anonymous function expression
var a = function() {
return 3;
}

// named function expression
var a = function bar() {
return 3;
}

//self invoking function expression or immediately invoked function expression (IIFE, 즉시실행함수)
(function sayHello() {
alert("dowon hi");
})();

// in parentheses (grouping operator) can be only an expression
(function foo() {});

// in the array initialiser - also only expressions
[function bar() {}];

// comma also operators with expressions
1, function baz() {};


// FE is not available neither before the defintion

// because it is created at code execution phase.

alert(foo); // foo is not defined

(function foo() {});

// nor after, because it is not in the VO

alert(foo); // foo is not defined


// parentheses로 grouping 하기 

(function {}) ();

(function {}());


* Name Fuction Expression (NFE)

  - 재귀 호출을 위해 이름으로 자기자신을 호출할 수 있다 (이때 함수를 Variable Object에 저장할 필요가 있을까? 없다!)

  - 부모 context에서 생성할까? 노우!

  - FE로 하면 VO에 영향을 미치지 않는다 

(function foo(bar) {
if(bar) {
return;
}
foo(true); //foo name is available
})();

// but from the outside, correctly, is not  
// 즉, foo는 부모 scope에 없고 function의 [[Scope]]안에 specialObject에 저장한다 (하기 설명 참조)
foo(); // foo is not defined


위 소스 해석 (원문)

  - Interpreter가 code execution stage에서 FE를 만나면 FE를 생성하기 전에 special object를 만들고 현재 scope chain 앞에 놓는다 

  - FE 자신을 생성하고, 자신의 scope 프로퍼티에 scope chain 을 한다 (referencing)

  - special object에 unique 프로퍼티로 FE를 추가한다

  - 마지막에 parent scope chain으로 부터 special object를 제거 한다 

specialObject = {};

Scope = specialObject + Scope;

foo = new FunctionExpression;
foo.__scope__ = Scope;  // or foo.[[Scope]] = Scope;
specialObject.foo = foo; // [DontDelete], {ReadOnly}

delete Scope[0]; // remove specialObject from the front of scope chain



* FE의 특징

  - Variable Object (VO)에 속하지 않다 (스크립트 수행시 Execution Context-EC- 에 한 부분 = VO)

  - 따라서 FE는 Hoist안되고 FD만 Hoist 된다 (원문)

  - 그리고 FE는 자신의 내부 Scope에만 의미가 있지 외부(Outside)에는 의미가 전혀 없다 

  - VO = Function Declaration + Variable Declaration(var) + Arguments 들이 속한다 (FD가 최우선 순위 -> VD 순서로 Hoist됨)

  - FE로 하면 VO를 오염시키지 않기에 사용이 늘어나고 있다

예1)

bar(); // hoist 되어 정상 처리됨 

foo(); // error 발생 


function bar() { .... } // FD 

var foo = function() { .... }; // FE


예2)

var myFunction = function sameFunction() {

return myFunction === sameFunction; // true

};

console.log(myFunction()); // true 

console.log(sameFunction());  // [ReferenceError: contents is not defined] 에러 발생 



* FE에 사용하는 Grouping Operator 와 Immediately Invoked Fuction Expression (IIFE) 특징 

  - Grouping Operator인 () 은 variable과 function을 global scope와 격리된 private scope로 만드는 방법을 제공한다

  - IIFE는 jQuery, Underscore, Prototype, Dojo 등에서 global  scope을 깔끔하게 유지키 위해 private scope로 캡슐화, 모듈화에 중요하게 사용된다

  - 하기 예제는 외부세계로 부터 숨겨진 코드를 정의할 수 있고, private scope에서 동작하는 library variable을 만드는 것이다.

var Box = (function () {
    var contents = [];
    return {
        insert: function (thing) {
            contents.push(thing);
            return this;
        },
        count: function () {
            return contents.length;
        }
    };
})();

console.log(Box.insert('abc').insert(123).insert({
    width: 640, height: 360
}).insert(function () {
    return 'Hello!';
}).count()); // 4 를 출력

// This throws a ReferenceError since the JavaScript engine can't
// resolve the `contents` identifier.
// [ReferenceError: contents is not defined] 를 출력 
try {
    console.log(contents);  
} catch(err) { 
    console.log(err); 


  - IIFE는 function 호출처럼 arguements를 받고, 실행시간에 in-scope에 있는 모든 데이터에 대한 access가 가능한 Closure를 반환할 수 있다 (variable 상태 저장 가능)

var d, Saved, testSubject, i, l, x;

// Capture a start time.
d = new Date().getTime();

// `Saved` exposes a single API method `get` which returns that
// start time: the variable `d` is supplied as the argument
// identified within the function definition as `start`.
// 최기의  시작시간값을 저장하고 있다 
Saved = (function (start) {
    return {
        get: function () {
            return start;
        }
    };
})(d);

testSubject = {
    level1: {
        level2: {
            level3: {
                level4: {
                    val: 'value'
                }
            }
        }
    }
};

for (i = 0, l = 1000000; i < l; i++) {
    x = testSubject.level1.level2.level3.level4.val;
}

// Capture the time after diving five levels into the `testSubject`
// object literal one million times.
// 현재 시간을 구한다 
d = new Date().getTime();

// Output the current value of `d`.
// 현재 시간이 찍힘 
console.log(d); 

// Output the original value of `d`.
// 초기 IIFE의 시간이 찍힘
console.log(Saved.get());

// Output the difference which indicates how many seconds it took
// to do that object crawl.
console.log(d - Saved.get());

//------ 결과 
1352699019341 // d 현재 시간 
1352699019322 // Saved.get() IIFE 시간 
19  // 차이 값 



<참조>

  - javascript 블로그 : 간단하고 명확하게 정의내림 (표현형식만 설명)

  - 소스니 코브 : 너무 심도 있게 설명해서 집중하지 않으면 놓치기 쉬움 (왜 구별해서 사용하는지 설명)

  - 예제로 보는 javascript : Function Expression을 사용하는 이유를 가장 잘 설명함

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

[JavaScript 성능향상] 웹사이트 최적화 방법  (0) 2012.12.12
[JavaScript] Template Engine  (0) 2012.11.26
[JavaScript] Closure 알아가기  (0) 2012.11.12
[JavaScript] Core 요약  (0) 2012.10.12
[JavaScript] Design Pattern  (0) 2012.09.10
posted by 윤영식
2012. 11. 10. 20:19 Middleware, Cloud/OSGi

위키북스의 OSGi & Spring DM을 읽으면서 Spring DM쪽의 내용을 요약해 본다 



▶ 동영상 자료

  - IBM DeveloperWorks : 안영회/이일민 개념 및 개발하기 (맨 하단의 Next 클릭해서 봄)



▶ 간단 요약 (Ch. 11)

  - 서비스 레지스트리를 사용하는 OSGi의 서비스 룩업 메커니즘을 스프링에서 제공하는 의존성 주입 형태로 사용할 수 있게 해준다. (그림 참조)

  - SpringDM은 OSGi상에서 Extender 개념을 이용하여 POJO(Plain Old Java Object) 형태의 일반 스프링 빈을 OSGi번들로 동적으로 바꾸는 작업을 지원한다 (Extender : 동적으로 설치되는 번들/서비스의 설치/삭제 시 이벤트를 받아서 특정 동작을 수행함)

    + SpringDM OSGi Extender : META-INF/spring/*.xml 파일을 읽어서 스피링 빈으로 초기화 한다

    + SpringDM Web Extender : war 확장자 배포하거나 WEB-INF 폴더를 가지고 있으면 웹컨테이너에 등록시킴 


  - POJO A가 BundleActivator -> BundleContext로 Service Registry에 Service A등록이 되고 ServiceTracker -> BundleActivator를 통해 Service A를 찾아 POJO B가 사용한다 (참조)

  - OSGi 번들은 BundleActivator, ServiceTracker Interface에 의존하나 SpringDM은 spring.xml 과 POJO 만을 필요로 한다 

    + POJO기반으로 번들을 만들어 테스트가 용이하다

    + 번들, 라이프사이클, 버젼닝, 동적 추가/수정/삭제 등의 기능을 엔터프라이즈급 애플리케이션을 개발할 때 사용할 수 있게 됨


  - SpringDM 개발 = Eclipse STS(Spring Tool Suite) + Maven Plugin(v 3.0.4) 설치

  - Eclipse에 Target Platform을 설정한다 (T.P = 번들을 개발하고 실행하는 환경을 의미함. 사용자 Target Platform 만들기 참조)

  - OSGi로 관련 Bundle을 별도의 Plug-In Project로 만들다 보면 Working set으로 묶어서 관리하고 싶어진다. 이를 위한 설정은    WhiteShip 브로깅을 참조한다

  - SpringDM은 Spring Application Context : Bundle = 1:1 관계이다 



▶ Eclipse에서 SpringDM 간단히 만들고 등록하기 

1. Plug-in Project를 생성한다 (이클립스 플러그인 프로젝트는 기본적으로 이클립스 Equinox OSGi를 이용한다)


2. 적절한 이름을 입력하고 하단 Options에서 Activator를 상속받지 않은 POJO로 개발을 할 것이다 


3. 생성하면 자동으로 MANIFEST.MF 파일이 생성된다


4. META-INF/spring.xml 파일을 생성한다 


5. spring.xml 스프링 프레임워크 빈등록 환경설정 이전에 프로젝트를 선택하고 Spring Tools에서 "Add Spring Project Nature"를 선택한다 


6. 프로젝트 폴더 우측 상단에 S 자가 표현된다


7. spring 폴더에 "Spring Bean Configuration File"을 생성한다 


8. 명칭은 spring.xml 로 생성한다


9. spring.xml에 osgi 관련 xsd 내역이 없으니 코딩하고, 인식하고자 하는 bean을 등록한다 


10. Run Configuration... 에서 해당 프로젝트의 실행 환경을 새로 생성한다 


11. Bundle로 HelloSpringDM을 선택한다 (Target Platform을 적절히 선택해 주어야 한다. 여기선 오류가 있다. Spring이 선택되어야 한다)



12. Active한 bundle을 확인하고 HelloSpringDM의 RESOLVED 상태를 start 시켜주어 Active 상태로 만든다 

posted by 윤영식
2012. 11. 9. 16:23 Testing, TDD/Tools, FitNesse

간단하게 특정 URL에 대한 성능 측정을 Command Line에서 수행하고 결과를 얻을 수 있는 툴로 Apache Benchmark가 있다. 손쉽게 사용해 보자


  • 테스트 url의 결과값을 확인해 보자 : curl <URL> 
  • 성능을 측정해 보자 : ab <Options> <URL>


* 참조 : ab 사용법




posted by 윤영식