2016년 1월 28일 목요일

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:

댓글 1개: