2016년 1월 31일 일요일

면접 스터디 정리

  • 1주차 ( 2016-01-31 )
  1. CI, DI AOP 정리 ->  http://lalwr.blogspot.kr/2016/01/spring-ci-di-aop.html
  2. AJAX의 주요 구성 요소 -> http://lalwr.blogspot.kr/2016/01/ajax.html
  3. SOLID란? -> http://lalwr.blogspot.kr/2016/01/solid.html
  4. 자바스크립트 클로저란? -> http://lalwr.blogspot.kr/2016/01/javascript-closure.html
  5. Restfull이란? -> http://lalwr.blogspot.kr/2016/01/restful.html

  • 2주차 ( 2016-02-14 )
  1. 프로세스와 스레드 -> http://lalwr.blogspot.kr/2016/02/process-thread.html
  2. DB INDEX - > http://lalwr.blogspot.kr/2016/02/db-index.html
  3. 자바 일반예외와 실행예외 -> http://lalwr.blogspot.kr/2016/02/java-exception.html
  4. spring aop, interceptor, filter의 차이 -> http://lalwr.blogspot.kr/2016/02/spring-aop-interceptor-filter.html
  5. MVC1, MVC2, spring mvc 구조 -> http://lalwr.blogspot.kr/2016/02/mvc1-mvc2-spirng-mvc.html
  6. 하나의 배열을 사용해 세 개의 스택을 구현하는 방법 -> https://github.com/lalwr/study/tree/master/oneListStack/

  • 3주차 ( 2016-02-21 )

  1. String, StringBuffer, stringbuilder차이점 -> http://lalwr.blogspot.kr/2016/02/string-stringbuffer-stringbuilder.html
  2. 컬렉션 프레임워크 -> http://lalwr.blogspot.kr/2016/02/collection-framework.html
  3. 데코레이터 패턴과 프록시 패턴 -> http://lalwr.blogspot.kr/2016/02/blog-post_20.html
  4. TDD란? -> http://lalwr.blogspot.kr/2016/02/tdd.html
  5. 데이터가 순회도 자주하고 삽입삭제도 자주하는경우에는 어떤걸 써야하는가? - 속도가 제일 정렬 알고리즘은 무엇인가? -> http://lalwr.blogspot.kr/2016/02/blog-post_20.html
  6. 스프링 AOP 사용시 효율적인 개발전략과 고려해야될 사항 -> http://lalwr.blogspot.kr/2016/02/aop.html
Share:

2016년 1월 28일 목요일

JavaScript Closure 란?

1) CloSure란?
 - 로컬 변수를 참조하고 있는 함수 내의 함수
 - 즉, 자신의 범위 밖에 있는 변수들에 접근할 수 있는 함수를 의미한다.
 - 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



- 로컬 변수를 계속 생성하지 않고 상태를 유지하면 사용할 수 있다 (마치 객체처럼     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) : 인스턴스 <-- 요거 애매함

2) 클로져를 이용해서 private 함수 흉내내기


몇몇 언어(예를들어 자바)는 같은 클래스 내부의 메소드에서만 호출할 수 있는 private 메소드를 지원한다.



자바스크립트는 이를 지원하지 않지만 클로져를 이용해서 흉내낼 수 있다. private 함수는 코드에 제한적인 접근만을 허용한다는 점 뿐만 아니라 전역 네임스페이스를 깔끔하게 유지할 수 있다는 점에서 중요하다.



아래에 모듈 패턴이라고 알려진 클로져를 통해 몇 개의 public 함수가 private 함수와 변수에 접근하는 코드가 있다.
var Counter = (function() {
var privateCounter = 0;

function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
alert(Counter.value()); /* 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* 2 */
Counter.decrement();
alert(Counter.value()); /* 1 */


이전 예제에서는 각 클로져가 자기만의 환경을 가졌지만 이 예제에서는 하나의 환경을 Counter.increment, Counter.decrement, Counter.value 세 함수가 공유한다.



공유되는 환경은 정의되자마자 실행되는 익명 함수 안에서 만들어진다. 이 환경에는 두 개의 private 아이템이 존재한다. 하나는 privateCounter라는 변수이고 나머지 하나는 changeBy라는 함수이다. 이 두 아이템 모두 익명함수 외부에선 접근할 수 없다. 하지만 익명함수 안에 정의된 세개의 public 함수에서 사용되고 반환된다.



이 세개의 public 함수는 같은 환경을 공유하는 클로져이다. 자바스크립트 어휘 스코핑(lexical scoping) 덕분에 세 함수 모두 privateCounter 변수와 changeBy 함수에 접근할 수 있다.



익명 함수가 카운터를 정의하고 이것을 Counter 변수에 할당한다는 걸 알아차렸을 것이다. 이 함수를 다른 변수에 저장하고 이 변수를 이용해 여러개의 카운터를 만들수도 있다.
var makeCounter = function() {
var privateCounter = 0;

function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var Counter1 = makeCounter();
var Counter2 = makeCounter();
alert(Counter1.value()); /* 0 */
Counter1.increment();
Counter1.increment();
alert(Counter1.value()); /* 2 */
Counter1.decrement();
alert(Counter1.value()); /* 1 */
alert(Counter2.value()); /* 0 */

두개의 카운터가 어떻게 독립적으로 존재하는지 주목하라. makeCounter() 함수를 호출하면서 생긴 환경은 호출할 때마다 다르다. 클로져 변수 privateCounter 는 다른 인스턴스를 가진다.


객체지향 프로그래밍을 사용할 때 얻는 이점인 정보 은닉과 캡슐화를 클로져를 사용함으로써 얻을 수 있다.



3) 자주하는 실수: 반복문 안에서 클로져 만들기
helpText 배열은 세개의 도움말을 정의한다. 각 도움말은 입력 필드의 ID와 연관된다. 이 세개의 정의를 반복하며 입력필드에 onfocus 이벤트가 발생했을 때 입력필드에 해당하는 도움말을 표시한다.

이 코드를 실행해보면 제대로 동작하지 않는다는 것을 알 수 있다. 어떤 필드에 포커스를 주더라도 나이에 관한 도움말이 표시된다.

이유는 onfocus 이벤트에 지정한 함수가 클로져라는 것이다. 이 클로져는 함수 본체와 setupHelp 함수의 스코프로 이루어져 있다. 세개의 클로져가 만들어졌지만 각 클로져는 하나의 환경을 공유한다. 반복문이 끝나고 onfocus 콜백이 실행될 때 콜백의 환경에서 item 변수는 (세개의 클로져가 공유한다) helpText 리스트의 마지막 요소를 가리키고 있을 것이다.

여러개의 클로져를 이용해서 문제를 해결할 수 있다. 위에서 언급한 함수 공장을 사용해보자.
예상한대로 작동한다. 콜백이 하나의 환경을 공유하지 않고 makeHelpCallback 함수가 만든 새로운 환경을 가진다. 이 환경에는 helpText 배열로부터 해당하는 문자열이 help 변수에 담겨있다.

4) 성능과 관련해서



클로져가 필요하지 않은 작업인데도 함수안에 함수를 만드는 것은 스크립트 처리 속도와 메모리 사용량 모두에서 현명한 선택이 아니다.

예를들어 새로운 오브젝트나 클래스를 만들 때 오브젝트 생성자에 메쏘드를 정의하는 것 보다 오브젝트의 프로토타입에 정의하는것이 좋다. 오브젝트 생성자에 정의하게 되면 생성자가 불릴때마다 메쏘드가 새로 할당되기 때문이다.


비현실적이지만 설명을 위해 예제를 첨부했다.
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
this.getName = function() {
return this.name;
};
this.getMessage = function() {
return this.message;
};
}


위의 코드는 일일히 메쏘드를 만들면서 클로져의 이점을 살리지 못하고 있다.
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype = {
getName: function() {
return this.name;
},
getMessage: function() {
return this.message;
}
};


또는 다음처럼 하자
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};



* reference 
  • http://mobicon.tistory.com/48
  • https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures
  • http://blog.jui.io/?p=25
Share:

객체지향 프로그래밍 및 설계의 다섯가지 기본 원칙 SOLID 란?

1. The Single Responsibility Principle - SRP ( 단일 책임 원칙 )
어떤 클래스를 변경해야 하는 이유는 오직 하나뿐 이어야 한다.

 어떤 객체가 너무 많은 다른 종류의 행동을 할 수 있다면, 그것은  다른 객체가 변경 될 때 함께 변경되어야 할 가능성이 많다는 것을 의미합니다.

가능한 하나 또는 명확하게 관련이 있는 책임을 부여 함으로써 객체는 보다 명확해(Explicit) 지고, 표현가능해 지며(Expressive), 느슨한 커플링(Loose Coupling) 과 높은 응집력(High Cohesion) 을 얻게 됩니다.



 2. The Open-Closed Principle - OCP ( 개방-폐쇄 원칙 )
 소프트웨어 엔터티(클래스, 모듈, 함수 등등)는 Interface에 대해서는 개방되어야 하지만, 변경에 대해서는 폐쇄되어야 한다.

 단위 테스트를 할 때는 종종 환경에 생기는 변화를 제어하고 싶은 경우가 발생합니다. 예를 들어 Emploee를 어떻게 테스트 할지 생각해 보시죠. Emploee객체는 데이터베이스를 변경합니다. 하지만 테스트 환경에서 실제 데이터베이스를 바꾸고 싶지 않습니다. 그렇다고 해서 단위 테스트를 하기 위해 테스트용 더미 데이터베이스를 만들고 싶지도 않습니다. 그렇다면, 테스트 환경으로 환경을 변경해서 테스트 할 때 Emploee가 데이터베이스에 하는 모든 호출을 가로챈 다음 이 호출들이 올바른지 검증하면 좋을 것입니다.

 엔터티가 외부로 부터 영향을 받지 않고, 내부의 필요에 의해서만 변경하게 하려면 보호막으로 감싸고 노출되지 않아야 합니다. 그러나 다른 객체와 상호 작용하기 위해서는 선택적인 노출이 필요 합니다. 다른 객체와 대화하기 위한 인터페이스와 확장을 위해서는 Open 하고, 이외의 경우에는 Closed 해야 정보가 감추어지고 (Information Hiding) , 객체들끼리 연결하게 되는 끈이 줄어듦으로써 커플링이 타이트 해질 가능성이 줄어 듭니다.

3. Liskov Substitution Principle - LSP ( 리스코프 치환 원칙 )
서브타입(Sub Type)은 언제나 자신의 기반 타입(Base Type)으로 교체할 수 있어야 한다.

LSP에 따르면, 기반 클래스의 사용자는 그 기반 클래스에서 유도된 클래스를 기반 클래스로써 사용할때, 특별한 것을 할 필요 없이 마치 원래 기반 클래스를 사용하는 양 그대로 사용할 수 있어야 한다. 더 자세히 말하자면, instanceof나 다운캐스트를 할 필요가 없어야 합니다. 강조하건데, 사용자는 파생클래스에 대해서 아무것도 알 필요가 없어야 합니다. 파생 클래스가 있다는 사실 조차도.

 LSP는 상속(Inheritance), 다형성(Polymorphism) 과 관련된 원칙이죠. 상속은 코드 재사용 이라는 이유로 과용 될수 있는 기능입니다. 과잉 사용된 상속은 복잡한 계층구조와 커플링을 타이트하게 함으로써 객체지향으로 얻기 위한 유지관리비용 감소에 악영향을 미치는 요소중 하나 입니다. LSP란 상속을 사용할때 지켜야 하는 원칙을 말하는데요. 상속은 코드 재사용을 위해서가 아니라 명확한 가족 관계가 있을때 사용해야 하며, 그 행위(Behavior) 와 연관이 있습니다. 부모와 파생된 객체들이 존재 할때 가능한 모두 동일한 메소드 이름과 갯수를 가지게 함으로써  언제든지 서브 타입이 기반타입으로 교체될 수 있어야 함을 말합니다.

다시 말하면, 상속의 오용은
가족이 아닌 객체를 비슷한 일을 하는 것을 보고 코드 재사용 욕심에 가족 관계로 묶는 것.
다층 상속으로 계층 구조가 깊고 복잡하게 하는 것.
파생 타입에 부모, 형제들과는 전혀 동떨어진 능력을 부여 함으로써 돌연변이를 만들어 버리는 것.
을 의미하며 LSP는 돌연변이(부모, 형제들의 형질과 관련이 없는 능력을 가진 파생타입 이며 이렇게 될때는 이미 가족이 아님을 의미)가 발생하지 않도록 관리해서 상속 관계의 타입들이 유연하게 대체 될 수 있게 하는 원칙 입니다.

LSP의 더욱 자세한 설명은 LSP in Depth  포스트를 참조



4. Dependency Inversion Principle - DIP ( 의존관계 역전 원칙)
고차원의 모듈은 저차원의 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화된 것에 의존한다. 추상화 된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다.
자주 변경되는 구상 클래스(Concreate class)에 의존하지 마라. 만약 어떤 클래스에서 상속받아야 한다면, 기반 클래스를 추상 클래스로 만들어라. 만약 어떤 클래스의 참조(Reference)를 가져야 한다면, 참조 대상이 되는 클래스를 추상 클래스로 만들어라. 만약 어떤 함수를 호출해야 한다면, 호출 되는 함수를 추상 함수로 만들어야 합니다.

DIP는 그 용어 자체의 어려움 때문에 이해하기가 쉽지 않지만 내용은 단순합니다. 추상화된 것 (Absctract Class, Interface) 을 사용해야 커플링을 느슨하게 만들 수 있다는 말 입니다. 예를 들어

abstract class Car {} 로 부터 상속 받은 class Truck : Car {}, class Bus : Car {} 가 존재 할때,

Truck porter = new Truck() 과 같이 사용하지 말고,

Car myCar = new Truck();  과 같이 추상 클래스를 기반으로 작업하거나.



abstract class Car
{
public abstract void Run();
public abstract void Stop();
}

class Truck : Car
{


public override void Run()
{
throw new NotImplementedException();
}

public override void Stop()
{
throw new NotImplementedException();
}
}

class Bus : Car
{

public override void Run()
{
throw new NotImplementedException();
}

public override void Stop()
{
throw new NotImplementedException();
}
}


static void main()
{
Truck myCar = new Truck();
myCar.Run();

Car myCar = new Truck();
myCar.Run();

}
인터페이스를 사용 하는 경우

abstract class Car
{

}

interface IDrive
{
public void Run();
public void Stop();

}

class Truck : Car, IDrive
{



#region IDrive 멤버

public void Run()
{
throw new NotImplementedException();
}

public void Stop()
{
throw new NotImplementedException();
}

#endregion
}

class Bus : Car, IDrive
{


#region IDrive 멤버

public void Run()
{
throw new NotImplementedException();
}

public void Stop()
{
throw new NotImplementedException();
}

#endregion
}


static void main()
{
Car myCar = new Truck();
IDrive drive = (IDrive)myCar;

drive.Run();
drive.Stop();
}


와 같이 추상적인 것에 구체적인 것을 대입해 사용함으로써 커플링을 느슨하도록 만드는 원칙 입니다.

DIP 에 대한 상세한 개념에 대해서는 '의존 관계 역전의 원칙 Dependency Inversion Principle' 포스트를 읽어 보세요.


5. Interface Segregation Principle - ISP ( 인터페이스 분리 원칙)
클라이언트는 자신이 사용하지 않는 메소드에 의존 관계를 맺으면 안된다. 

비대한 클래스(Fat class) 란 메소드를 몇십 몇백개 가지는 클래스를 가르키는 말이다. 대개 시스템 안에 이런 클래스를 두고 싶어 하지 않지만, 가끔 피 할 수 없는 경우도 있습니다.

비대한 클래스가 거대하고 보기 흉하다는 사실 말고도, 한 사용자가 이 비대한 클래스의 메소드를 다 사용하는 일이 매우 적다는 것도 문제입니다. 즉. 메소드를 몇십개 선언한 클래스에서 사용자는 단지 두세 개만 호출 할 지도 모르죠. 불행하게도 이 사용자들은 호출하지도 않는 메소드에 생긴 변화에도 영향을 받습니다.


ISP 인터페이스 분리의 원칙은 가족관계가 아닐때 같은 행동을 하는 객체들에게 인터페이스를 할당 하고 사용 함으로써 DIP 를 가능하도록 만들고 , 그 결과로 느슨한 커플링과 명시성과 표현성을 얻습니다.

* reference 
  • http://vandbt.tistory.com/11
Share:

AJAX의 구성 요소

1) AJAX : Asynchronous JavaScript + XML
JavaScript를 사용한 비동기 통신, 클라이언트와 서버간에 XML 데이터를 주고받는 기술

2) AJAX 장점
-페이지 이동 없이 고속으로 화면 전환
-서버 처리를 기다리지 않고 비동기 요청이 가능
-서버 측 처리를 각 PC에 분산 가능
-수신하는 데이터의 양을 줄임

3) AJAX 단점
-크로스 브라우저화의 노하우 필요
-AJAX를 사용하지 못하는 브라우저
-오픈 소스이므로 차별화가 어려움
-보안에 더욱 신경을 써야 함

4) 기존방식과 AJAX의 차이
1, 기존방식
- 웹 브라우저가 웹 서버에 요청 전송
- 웹 서버는 JSP 등의 서버 어플리케이션을 사용해 사용자의 요청 처리 후 결과를 HTML로 생성해서 웹 브라우저에 전송
- 웹 브라우저는 응답으로 받은 HTML을 분석한 뒤 그 내용을 화면에 그림
- 결과적으로 웹 브라우저가 웹 서버와 통신을 하고 요청 결과는 HTML로 생성되고 사용자 입장에서는 페이지 이동이 발생함


2. AJAX방식
- 사용자가 이벤트를 발생 > 자바스크립트는 DOM을 사용해서 필요한 정보를 구한 뒤, XMLHttpRequest 객체를 통해서 웹 서버에 요청을 전달
- 웹 서버는 XMLHttpRequest로부터의 요청을 알맞게 처리후 결과를 XML이나 단순 Text을 생성해서 XMLHttpRequest에 전송
- 서버로부터 응답이 도착하면 XMLHttpRequest 객체는 자바스크립트에 도착 사실을 알고 자바스크립트는 응답 데이터와 DOM을 이용해 사용자 화면에 반영
- 결과적으로 사용자 입장에서는 페이지 이동이 발생되지 않고 페이지 내부 변화만 일어남



5) AJAX의 주요 구성 요소
- XMLHttprequest : 웹서버와 통신을 담당함. 사용자의 요청을 웹서버에 전송 및 웹서버로부터 받은 결과를 웹브라우저에 전달함
- DOM : 문서의 구조를 나타냄, 폼 등의 정보나 화면 구성을 조작할때 사용함
- CSS : 글자색,배경색,위치,투명도 등 UI관련 부분을 담당
- 자바스크립트 : 사용자가 마우스를 드래그하거나 버튼을 클릭하면 XMLHttpRequest객체를 사용해 웹서버에 요청을 전송함.
XMLHttpRequest 객체로부터 응답이 오면 DOM, CSS등을 사용해 화면을 조작함.

* refrence

  • http://hieroglyph.tistory.com/13
Share:

SPRING CI, DI, AOP란?

1) DI ( Dependency Injection, 의존성 주입) 란?
 - 클래스 사이의 의존관계를 빈 설정 정보를 컨테이너가 자동적으로 연결해주는것.

 Ioc/DI가 적용되지 않은 경우



package kr.co.nextree;
public class Foo {
private Bar bar;
public Foo() {
bar = new SubBar();
}
}


 Ioc/DI가 적용된 경우



//애플리케이션 코드
package kr.co.nextree;
public class Foo {
private Bar bar;
public void setBar(Bar bar) {
this.bar = bar;
}
}

사용할 객체들을 컨테이너에 등록후 seetter를 활용하여 동적으로 의존관계를 설정해줍니다. 결합도는 낮추면서 유연성과 확장성은 향상시킬수 있다.

1-2) DI의 유형 

1. 생성자를 이용한 의존성 삽입 (Constructor Injection : type 1 IoC)
   - 필요한 의존성을 모두 포함하는 클래스의 생성자를 만들고 그 생성자를 통해 의존성을 주입한다.
 즉 생성자에 파라미터를 만들어두고 이를 통해 DI 컨테이너가 의존할 오브젝트 레퍼런스를 넘겨주는 방식입니다.

// PicoContainer
class MovieLister...
public MovieLister(MovieFinder finder) {
this.finder = finder;
}
class ColonMovieFinder...
public ColonMovieFinder(String filename) {
this.filename = filename;
}



2. setter() 메소드를 이용한 의존성 삽입 (Setter Injection : type 2 IoC)
 - 의존성을 입력받는 세터 메소드를 만들고 이를 통해 의존성을 주입한다.

// Spring Container
class MovieLister...
private MovieFinder finder;
public void setFinder(MovieFinder finder) {
this.finder = finder;
}
class ColonMovieFinder...
public void setFilename(String filename) {
this.filename = filename;
}


2) CI ( Continuous Integration ) 지속적인 통합 이란?

- 지속적으로 품질관리를 적용하는 프로세스를 실행하는것.
- 초기에 자주 통합해서 발행사는 문제점을 조기에 발견하고, 피드백 사이클을 짧게하여
  소프트웨어 개발의 품질과 생산성을 향상시키는것.




CI시스템을 구축 하지 않은경우 개발 후반에 모두 장애로 발견된다.


CI서버는 형상관리 서버에 Commit된 소스코드를 주기적으로 폴링하여 컴파일, 단위테스트. 코드 인스펙션 등의 과정을 수행하며 신규 또는 수정된 소스코드가 결함이 있는지의 여부를 지속적으로 검증합니다. 검증 결과는 이메일, RSS 등의 피드백 메커니즘을 통해 개발자들에게 전달되고, 이를 통해 조기에 결함을 발견하여 해결할 수 있는 것입니다.

이제, CI시스템 구축을 위한 핵심 구성요소에 대해서 살펴보겠습니다.

1. CI Server
 - 빌드 프로세스를 관리하는 서버
 - Jenkins, Hudson, CruiseControl.NET, TeamCity

CI시스템을 구축하기 위해서는 우선 CI 서버가 필요하겠지요. 오픈소스인 Jenkins가 가장 널리 사용되고 있는 CI서버입니다.

2. SCM(Source Code Management)
 - 소스코드 형상관리 시스템
 - 소스코드의 개정과 백업 절차를 자동화하여 오류 수정 과정을 도와줄 수 있는 시스템
 - 여러사람이 같은 프로젝트에 참여할 경우, 각자가 수정한 부분을 팀원 전체가 자동으로 동기화할 수 있는 시스템
 - Subversion, Git, Mercurial

두번째, CI서버에서 자동으로 폴링하여 검증할 수 있도록 소스코드를 관리하는 형상관리 시스템이 필요합니다.
SVN(Subversion)과 Git이 가장 널리 사용되고 있습니다.

3. Build Tool 
 - 컴파일, 테스트, 정적분석 등을 실시해 동작 가능한 소프트웨어를 생성
 - Ant, Maven, MSBuild, Make

세번째, 개발하는 언어에 맞는 빌드 툴이 필요합니다.
빌드란, 소스코드 파일을 컴퓨터에서 실행할 수 있는 독립 소프트웨어 가공물로 변환하는 과정을 말하거나 그에 대한 결과물을 일컫는 것으로 빌드에 있어서 가장 중요한 단계는 소스코드 파일이 실행 코드로 변환되는 컴파일 과정입니다.
컴파일과 빌드를 혼동하여 쓰는 경우가 있으나 컴파일은 빌드 과정 중 한 단계일 뿐이며, 빌드는 형상관리 시스템에 있는 소스코드를 가져와 컴파일하여 사용자들이 실행할 수 있도록 실행 파일로 만드는 일련의 과정을 모두 포함합니다.
(참조 : 빌드의 중요성(http://softwaredev.tistory.com/10) / 빌드와 컴파일의 차이(http://allofsoftware.net/19)

4. Test Tool
 - 작성된 테스트 코드에 따라 자동으로 테스트를 수행해주는 도구로, 빌드 툴의 스크립트에서 실행
 - JUnit, CppUnit, CppTest, MSTest, Selenium(사용자테스트 자동화 가능)

네번째, 개발하는 언어에 맞는 테스트 툴이 필요합니다.
테스트는 단위 테스트를 말하며, 개발자라면 익숙한 JUnit(자바 애플리케이션의 단위 테스트 자동화를 위한 프레임웍)이 대표적입니다.
단위 테스트는 테스트 대상이 되는 코드 기능의 아주 작은 특정 영역을 실행해 보는 것으로, 개발자가 작성한 테스트 코드로 특정 메소드(Function)를 시험해보는 것이 일반적입니다.
다시 말해, 개발자가 작성한 메소드가 입력값에 따라 제대로 수행되는지 여부를 체크하는 것이지요.
단위테스트는 언어별로 자동화 테스트 도구들이 잘 만들어져 있어서 테스트코드 작성만 하면 자동으로 수행할 수 있습니다.
그 중 JUnit은 Ant와 같은 빌드 툴과도 쉽게 통합이 되기 때문에 가장 널리 사용되고 있습니다.

5. Test Coverage Tool
 - 테스트 코드가 대상 소스 코드에 대해 어느정도 커버하는지 분석하는 도구
 - Emma, Cobertura, TestCocoon

다섯번째는 테스트 툴과 함께 사용되는 테스트 커버리지 툴입니다.
테스트 커버리지 툴은 용어 그대로 개발자가 작성한 테스트코드가 테스트 대상 소스코드에 대해서 어느정도 테스트를 수행하는지를 코드 라인과 백분율을 통해 리포팅하는 것으로 단위테스트 수행 시 테스트 커버리지를 분석하기 위하여 부가적으로 사용하는 툴입니다.

6. Inspection Tool
 - 프로그램을 실행하지 않고, 소스코드 자체로 품질을 판단할 수 있는 정적분석 도구
 - 코딩 표준 준수 검사, 코드 메트릭 측정, 중복코드 검사, 코드 인스펙션 검사 등이 있음.
 - CheckStyle, FindBugs, Cppcheck, Valgrind

마지막으로 인스펙션 툴이 필요합니다.
인스펙션 툴은 정적분석 도구로, 프로그램을 실행하여 분석하는 동적분석(JUnit도 일종의 동적 분석에 속함)과는 달리 소스코드 자체로 프로그램 상의 예상되는 잠재적인 결함을 검출하는 도구입니다.
정적분석의 개념과 도구에 대한 내용은 추후에 별도의 포스트로 작성하도록 하겠습니다.

3~6번의 도구는 XML 형태의 빌드 스크립트(Ant 등)로 수행 내용을 작성하여 CI서버에서 형상관리 서버에서 폴링한 소스코드를 빌드하면서 자동으로 수행됩니다.

빌드 스크립트를 통한 CI 자동화 수행 절차 예시는 아래와 같습니다.

1. 소스코드를 바이너리 파일로 컴파일 한다.
2. 바이너리 파일을 배포 형태로 패키징 한다.
3. 단위테스트(커버리지 포함)수행한다. (선택)
4. 정적분석을 수행한다. (선택)
5. 분석 결과를 리포팅 한다. (선택)

6. 패키징한 파일을 테스트 서버에 배포한다.

3) OOP의 한계 와 AOP의 등장
 1.OOP의 한계
   - OOP의 대표적인 상속은 컴파일시에 행동이 결정 되므로 실행시에 특징을 바꿀 수 없습니다. 그리고 모든 서브클래스에서 동일한 코드 상속 받게 될 경우 슈퍼클래스의 변경이 이루어 졌을 때 일부 서브클래스에서 원치 않는 변경을 받아들여야만 합니다. 상속은 전혀 유연하지 못합니다. 이를 해결 하기 위해 구성이라는 기법을 사용하죠. 구성은 상속의 모든 단점을 해결해 줍니다. 실행중 동적으로 행동을 바꿀 수 있으며 슈퍼클래스가 없으므로 의존도가 제거 됩니다. 하지만 이런 구성도 단점이 있기 마련입니다. 슈퍼클래스의 코드를 재사용할 수 없고 구성 객체에게 위임 해야하는 번거로움이 있습니다.

 2.AOP의 등장
  - OOP의 한계를 보완하고자 AOP가 등장 했습니다. 상속과 구현만으로 곤란했던 흩어진 중복코드를 제거 할 수 있습니다. AOP의 기본 개념은 횡단 관심사에 대한 모듈화 입니다.
3-2) AOP가 사용되는 경우

1. 간단한 메소드 성능 검사
개발 도중 특히 DB에 다량의 데이터를 넣고 빼는 등의 배치 작업에 대하여 시간을 측정해보고 쿼리를 개선하는 작업은 매우 의미가 있다. 이 경우 매번 해당 메소드 처음과 끝에 System.currentTimeMills();를 사용하거나, 스프링이 제공하는 StopWatch코드를 사용하기는 매우 번거롭다.
이런 경우 해당 작업을 하는 코드를 밖에서 설정하고 해당 부분을 사용하는 편이 편리하다.

2. 트랜잭션 처리
트랜잭션의 경우 비지니스 로직의 전후에 설정된다. 하지만 매번 사용하는 트랜잭션 (try~catch부분)의 코드는 번거롭고, 소스를 더욱 복잡하게 보여준다.

3. 예외 반환
스프링에는 DataAccessException이라는 매우 잘 정의되어 있는 예외 계층 구조가 있다. 예전 하이버네이트 예외들은 몇 개 없었고 그나마도 Uncatched Exception이 아니였다. 이렇게 구조가 별로 안 좋은 예외들이 발생했을 때, 그걸 잡아서 잘 정의되어 있는 예외 계층 구조로 변환해서 다시 던지는 애스팩트는 제 3의 프레임워크를 사용할 때, 본인의 프레임워크나 애플리케이션에서 별도의 예외 계층 구조로 변환하고 싶을 때 유용하다.


4. 아키텍처 검증


5. 기타
- 하이버네티스와 JDBC를 같이 사용할 경우, DB 동기화 문제 해결
- 멀티쓰레드 Safety 관련하여 작업해야 하는 경우, 메소드들에 일괄적으로 락을 설정하는 애스팩트
- 데드락 등으로 인한 PessimisticLockingFailureException등의 예외를 만났을 때 재시도하는 애스팩트
- 로깅, 인증, 권한 등

3-3) AOP의 구성요소

1. 조인포인트(joinPoint) - 횡단 관심 모듈의 기능이 삽입되어 동작할 수 있는 실행 가능한 특정위치
ex) 메쏘드가 호출되는 부분 또는 리턴되는 시점, 필드를 액세스하는 부분, 인스턴스가 만들어지는 지점, 예외가 던져지는 시점, 예외 핸들러가 동작하는 위치, 클래스가 초기화되는 곳 등이 대표적인 조인포인트가 될 수 있다. 각각의 조인포인트들은 그 안에 횡단 관심의 기능이 AOP에 의해 자동으로 추가되어져서 동작할 수 있는 후보지가 되는 것이다.

2. 포인트컷(pointCut) - 어떤 클래스의 어느 조인포인트를 사용할 것인지를 결정하는 선택 기능
AOP가 항상 모든 모듈의 모든 조인포인트를 사용할 것이 아니기 때문에 필요에 따라 사용해야 할 모듈의 특정 조인포인트를 지정할 필요가 있다. 일종의 조인포인트 선정 룰과 같은 개념이다.
AOP에서는 포인트컷을 수행할 수 있는 다양한 접근 방법을 제공한다. AspectJ에서는 와일드카드를 이용한 메쏘드 시그니처를 사용한다.

3. 어드바이스(advise) 또는 인터셉터(intercepter)
어드바이스 - 각 조인포인트에 삽입되어져 동작할 수 있는 코드
  주로 메소드 단위로 구성된 어드바이스는 포인트컷에 의해 결정된 모듈의 조인포인트에서 호출되어 사용된다.
  일반적으로 독립적인 클래스 등으로 구현된 횡단 관심 모듈을 조인포인트의 정보를 참조해서 이용하는 방식으로 작성된다.
인터셉터 - 인터셉터 체인 방식의 AOP 툴에서 사용하는 용어로 주로 한 개의 invoke 메소드를 가지는 어드바이스

3-2. 어드바이스(advise)의 종류
Before advice : 메서드 실행전에 적용되는 실행
After returning advice : 메서드가 정상적으로 실행된 후에 실행  (예외를 던지는 상황은 정상적인 상황에서 제외)
After throwing advice : 예외를 발생시킬 때 적용되는 Advice를 정의 (catch와 비슷)
Around advice : 메서드 호출 이전, 이후, 예외 발생 등 모든 시점에서 적용 가능한 Advice를 정의

4. 위빙(weaving) 또는 크로스컷팅(crossCutting)
위빙 - 포인트컷에 의해서 결정된 조인포인트에 지정된 어드바이스를 삽입하는 과정 (다른 말로 크로스컷팅)
위빙은 AOP가 기존의 핵심 관심 모듈의 코드에 전혀 영향을 주지 않으면서 필요한 횡단 관심 기능을 추가할 수 있게 해주는 핵심적인 처리과정이다. 위빙을 처리하는 방법은 후처리기를 통한 코드생성 기술을 통한 방법부터 특별한 컴파일러 사용하는 것, 이미 생성된 클래스의 정적인 바이트코드의 변환 또는 실행 중 클래스로더를 통한 실시간 바이트코드 변환 그리고 다이내믹 프록시를 통한 방법까지 매우 다양하다.

5. 인트로덕션(Introduction) 또는 인터타입 선언
인트로덕션 - 정적인 방식의 AOP 기술
동적인 AOP 방식을 사용하면 코드의 조인포인트에 어드바이스를 적용해서 핵심관심 코드의 동작 방식을 변경할 수 있다.
인트로덕션은 이에 반해서 기존의 클래스와 인터페이스에 필요한 메소드나 필드를 추가해서 사용할 수 있게 해주는 방법
OOP에서 말하는 오브젝트의 상속이나 확장과는 다른 방식으로 어드바이스 또는 애스팩트를 이용해서 기존 클래스에 없는 인터페이스 등을 다이내믹하게 구현해 줄 수 있다.


6. 애스팩트(aspect) 또는 어드바이저
애스팩트 - 포인트컷(어디에서) + 어드바이스(무엇을 할 것인지) + (필요에 따라 인트로덕션도 포함)
AspectJ와 같은 자바 언어를 확장한 AOP에서는 마치 자바의 클래스처럼 애스팩트를 코드로 작성할 수 있다. AOP 툴의 종류에 따라서 어드바이스와 포인트컷을 각각 일반 자바 클래스로 작성하고 이를 결합한 어드바이저 클래스를 만들어서 사용하는 방법도 있다.



Primary(Core) Concern - 비지니스 로직을 구현한 부분
Cross-Cutting Concern - 보안, 인증, 로그 등과 같은 부가적인 기능으로서 시스템 전반에 산재되어 사용되는 기능
Code - Primary(Core) concern을 구현해 놓은 코드를 이야기

3-4) AOP의 보통 설정 구조





* reference


  • http://www.nextree.co.kr/p11247/
  • http://happystory.tistory.com/89
  • http://jjaeko.tistory.com/21



Share:

2016년 1월 27일 수요일

RestFul이란 무엇인가?

1) REST란?


HTTP URI를 통해 Resource를 명시하고, HTTP Method(Post, Get, Put, Delete)를 통해 해당 Resource에 대한 CRUD Operation을 적용한다. 즉, REST는 ROA(Resource Oriented Architecture) 설계의 중심에 Resource가 있고 HTTP Method를 통해 Resource를 처리하도록 설계된 아키텍쳐를 의미한다.

HTTP Method와 CRUD Operation은 일반적으로 아래 표와 같이 맵핑된다.


2) SOAP와 비교


[일반적인 웹서비스]

[REST] URL로 요청


3) REST의 장점

- OPENAPI를 제공하기 쉽다.
- 멀티플랫폼 지원 및 연동이 용이하다.
- 원하는 타입으로 데이터를 주고받을수 있따. (XML, JSON, RSS )
- 기존 웹 인프라를(HTTP)를 그대로 사용가능하다 ( 방화벽, 장비 요건 불필요 )
- 사용하기 쉽다
- 세션을 사용하지 않는다. 각각의 요청에 독립적.

4) REST의 단점

- 표준이 없어서 관리가 어렵다.
- 사용할 수 있는 메소드가 4가지 밖에 없다.
- 분산환경에는 부적합하다.
- HTTP통신 모델에 대해서만 지원한다.

5) REST의 특징

- 클라이언트/서버 구조 : 일관적으로 독립되어야 한다.
- 무상태(Stateless) : 각요청 간 클라이언트의 Context는 서버에 저장되어서는 안 된다.
- 캐시가능(Cacheable) : WWW에서와 같이 클라이언트는 응답을 Caching 할 수 있어야 한다.
- 계층화(Layered System) : 클라이언트는 보통 대상 서버에 직접 연결 또는 중간 서버를 통     해 연결되는지 모른다.
- Code on demand(option) : 자바 애플릿/ 자바스크립의 제공으로 서버가 클라이언트가 실행   시킬 수 있는 로직을   전송하여, 기능을 확장 할수 있다.
- 인터페이스 일관성 : 아키텍처를 단순화하고, 작은 단위로 분리하여, 클라이언트-서버 파트    별로 독립적으로 개     선 될 수 있도록 한다.
- 자체 표현구조(Self-Descriptiveness) : API 메시지만 보고도 어떤 API인지를 이해 할수 있는 자체 표현 구조    를 가진다.

6) ROA란?

웹의 모든 리소스를 URI로 표현하고 구조적이고 유기적으로 연결하여 비 상태 지향적인 방법으로 정해진 method만을 사용하여 리소스를 사용하는 아키텍처
이는 4가지의 고유한 속성과 연관되어 진다. ( REST는 이 속성들을 지향한다 ) 

  - Addressablilty
  - Connectedness
  - Statelessness
 
 - Homogeneous Interface

+ Addressablilty (주소로 표현 가능함) 
- 제공하는 모든 정보를 URI로 표시할 수 있어야 한다.
- 직접 URI로 접근할 수 없고 HyperLink를 따라서만 해당 리소스에 접근할 수 있다면 이는 RESTful하지 않은 웹서비스이다.
 


+ Connectedness (연결됨) 
- 일반 웹 페이지처럼 하나의 리소스들은 서로 주변의 연관 리소스들과 연결되어 표현(Presentation)되어야 한다.
 - 예를 들면,
<user>
  <name>HJ</name>
</user> 는 연결되지 않은 독립적인 리소스이다.
<user>
  <name>HJ</name>
  <address>HJ/seoul/</address>
  <phone>HJ/010</phone>
</user> 는 관련 리소스(address, phone)가 잘 연결된 리소스의 표현이다.


+ Statelessness (상태 없음) 
- 현재 클라이언트의 상태를 절대로 서버에서 관리하지 않아야 한다.
- 모든 요청은 일회성의 성격을 가지며 이전의 요청에 영향을 받지 말아야 한다.
- 다시 또 코리아닷컴의 예를 들면 메일을 확인하기 위해 꼭 '..코리아닷컴../mailView.crd'에 접근하여 해당 세션을 유지한 상태에서 메일 리소스에 접근해야 한다. 이것이 바로 Statelessness가 없는 예이다.
 - 세션을 유지 하지 않기 때문에 서버 로드 발란싱이 매우 유리하다.
 - URI에 현재 state를 표현할 수 있어야 한다. (권장사항)

+ Homogeneous Interface (동일한 인터페이스)
 - HTTP에서 제공하는 기본적인 4가지의 method와 추가적인 2가지의 method를 이용해서 리소스의 모든 동작을 정의한다.
 - 리소스 조회 : GET
 - 새로운 리소스 생성 : PUT, POST (새로운 리소스의 URI를 생성하는 주체가 서버이면 POST를 사용)
 - 존재하는 리소스 변경 : PUT
 - 존재하는 리소스 삭제 : DELETE
 - 존재하는 리소스 메타데이터 보기 : HEAD
 - 존재하는 리소스의 지원 method 체크 : OPTION
 - 대부분의 리소스 조작은 위의 method를 이용하여 대부분 처리 가능하다. 만일 이것들로만 절대로 불가능한 액션이 필요할 경우에는 POST를 이용하여 추가 액션을 정의할 수 있다. (되도록 지양하자)



*  supplement

  • SOAP : HTTP, SMTP 등을 통해 XML 기반의 메시지를 컴퓨터 네트워크 상에서 교환하는 프로토콜

* Reference
  • http://spoqa.github.io/2012/02/27/rest-introduction.html
  • https://slipp.net/wiki/pages/viewpage.action?pageId=12878219#id-8주차-RESTAPI설계및구현-REST
  • http://egloos.zum.com/killins/v/3092502
  • http://www.hoons.net/Lecture/View/391
  • http://www.seungdols.com/web/restful
  • https://ko.wikipedia.org/wiki/REST
  • http://www.iamcorean.net/22


Share:

2016년 1월 12일 화요일

2016년 1월 11일 월요일

spring xml 기본 사용 양식정리

*WEB-INF/config/action-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
     /* @Controller 표현된 클래스만 빈으로 등록한다.*/
    <context:component-scan base-package="first" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    /*mvc 빈으로 등록한다.*/
    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="first.common.resolver.CustomMapArgumentResolver"></bean>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>
    /* 인터셉터 설정한다.*/
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean id="loggerInterceptor" class="first.common.logger.LoggerInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
   
    <aop:aspectj-autoproxy/> <!-- @Aspect 등록 -->
    <bean id="loggerAspect" class="first.common.logger.LoggerAspect" />
     /* URL 매핑처리 하는 빈 */
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    /* context에 정의된 bean ID를 찾아서 연결 */
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0" />
      /* JSON 처리 */
    <bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />  
     /* VIEW 이름과 실제 VIEW이름이 같을때 사용 */
    <bean
        class="org.springframework.web.servlet.view.UrlBasedViewResolver" p:order="1"
        p:viewClass="org.springframework.web.servlet.view.JstlView"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp">
    </bean>
</beans>
Share:

2016년 1월 7일 목요일