(종속성 주입과 제어의 역전의 개념 구분하여 서술하기)
먼저, Dependency Injection은 의존 주입을 의미합니다. 여기서 의존이란 객체 간의 의존을 의미합니다. 의존은 한 클래스가 다른 클래스의 메서드를 실행할 때 를 ‘의존한다’고 표현합니다. 의존하는 대상이 있으면 그 대상을 구하는 방법이 필요합니다. 가장 쉬운 방법은 의존 대상 객체를 직접 생성하는 것이지만, 유지보수의 관점에서 문제점이 유발될 수 있습니다. 그렇게 의존하는 객체를 직접 생성하는 대신 의존 객체를 전달받는 방식을 DI(Dependency Injection)라고 합니다. 객체 사이의 의존 관계를 스프링 설정 파일에 등록된 정보()을 바탕으로 컨테이너가 자동으로 처리해줍니다. 이는 객체가 필요로하는 어떤 객체를 생성자(constructor) 혹은 새터(setter)를 통해서 주입을 합니다.
다음으로 Inversion of Control은 제어의 역전현상을 의미합니다. 프로그램의 제어 흐름 구조가 거꾸로 뒤집는 개념으로 작업을 수행하는 쪽에서 Object를 생성하는 제어 흐름의 개념을 뒤집습니다. IoC에서는 Object가 자신이 사용할 Object를 생성하거나 선택하지 않습니다. 또한 Object는 자신이 어떻게 생성되고 어떻게 사용되는지 알 수 없고 모든 Object는 제어권한을 위임받는 특별한 Object에 의해서 만들어지고 사용됩니다. IoC의 구현 방법으로 의존성 검색 (Dependency Lookup)과 의존성 주입(Dependncy Injection)이 존재합니다.

'An example of spring DI container'
그림의 경우 초기화 인터페이스를 이용한 의존성 삽입에 해당합니다. 의존성을 주입하는 함수를 포함한 인터페이스를 작성하고 이 인터페이스를 구현하도록 함으로써 실행시에 이를 통하여 의존성을 주입합니다.
Dependency Injection의 주요 목적은 Business Logic 클래스와 Irepository 구현체 사이의 의존성을 없애는 것입니다. Without Dependncy Inversion 그림 예시에서는 Business Logic 클래스는 데이터를 직접 접근하여 받아옵니다. 이런 경우에는 SqlDatabase가 다른 경우로 바뀌거나 추가되는 경우 Business Logic 클래스의 코드까지 변경을 해야합니다. 이런 경우 Solid 원칙에서 OCP 원칙에 위배됩니다. 이러한 문제점을 해결한 것이 With Dependency Inversion 그림입니다. 구체적인 SqlDatabase와 의존 관계를 맺고 있는 Business Logic 클래스를 추상화된 인터페이스 Irepository 클래스와 의존관계를 맺게 만들어줍니다. 따라서 SqlDatabase가 어떤 형태로 변경이 되더라도 Bean Container를 통해서 Data Access 영역의 Bean들을 생성해주고 해당 Bean과 IRepository와의 의존관계를 주입시켜 Business Logic 클래스에는 변경이 없이 xml 파일만의 변경으로 제어할 수 있게 됩니다.
Dependncy Injection의 장점 첫번째로는 DI를 사용하면 객체 변경에 있어 유연함을 가질 수 있습니다. 의존 객체를 직접 생성하는 방식에서는 필드나 생성자에서 new 연산자를 이용해서 객체를 생성합니다. 예를 들어 회원 등록 기능을 제공하는 MemberRegisterService 클래스에서 new 연산자를 통해 객체를 다음과 같이 생성합니다.

MemberDao 클래스는 회원 데이터를 데이터베이스에 저장한다고 가정하고, 이 상태에서 회원 데이터의 빠른 조희를 위해 캐시를 적용해아 하는 상황이 발생하여 MemberDao 클래스를 상속받은 CachedMemberDao 클래스를 생성하였다.

캐시 기능을 적용한 CachedMemberDao를 사용하려면 MemberRegisterService 클래스의 코드를 변경해주어야 합니다.
생성할 의존 클래스의 변경에 따른 소스 코드를 다음과 같이 수정합니다.

만약 MemberDao 객체가 필요한 클래스가 네 개라면 네 클래스 모두 동일하게 소스 코드를 변경해야 합니다. 동일한 상황에서 DI를 사용하면 수정할 코드가 줄어듭니다. 다음과 같이 생성자를 통해서 의존 객체를 주입 받도록 구현하였습니다.

그리고 클래스의 객체를 생성하는 코드는 다음과 같습니다.

MemberDao 대신 캐시 기능을 적용한 CachedMemberDao를 사용하도록 수정하려면 코드를 수정해야 할 곳은 MemberDao 객체를 생성하는 코드 부분만 변경하면 됩니다.

따라서 DI를 사용하면 MemberDao 객체를 사용하는 클래스가 네 개여도 변경할 곳은 의존 주입 대상이 되는 객체를 생성하는 코드 한 곳뿐입니다. 앞서 의존 객체를 직접 생성했던 방식에 비해 객체 변경에 있어서 의존성을 줄여 유연함을 가지며 코드 수정의 유지보수가 편리해집니다. 따라서 재사용성을 높여주고 테스트에 용이해지는 장점을 가집니다.
2) Tracing, Transactions, and Exception Handling를 사용하지만 AOP 기법을 사용 하지 않는 시스템이 가지는 두가지 문제점에 대해 설명하고, 이를 어떻게 해결할 수 있는지 설명하라.

Tracing, Transcations, Exception Handing을 사용하지만 AOP 방식을 사용하지 않는 다면 code Tangling과 code Scattering 문제를 야기할 수 있습니다. Code Tangling은 코드 얽힘으로서 각 클래스, 각 방법은 Tracing, Transcations, Exception Handing과 비즈니스 논리를 포함하며 얽힌 코드에서는 메소드에서 실제로 어떤 일들이 일어나고 있는지 파악하기가 어렵습니다. 다음으로 Code Scattering 문제는 코드 흩어짐으로서 트랜잭션과 같은 측면에서 코드 전체에 흩어져 있으며 시스템의 단일 특정 부분에 구현되지 않는 문제점이 있습니다. 이러한 문제는 관점 지향 프로그래밍 AOP 기법을 활용하여 프로그램의 구조를 보다 명확하게 모듈화함으로써 해결할 수 있습니다. Tracing aspect, transaction aspect, exception handling aspect로 각각의 aspect로 구분하여 나누어 모듈화시킵니다. 즉, AOP는 비즈니스 로직을 담당하는 소스 코드 외에 로깅, 예외처리, 트랜잭션과 같은 부가 기능들이 어플리케이션 소스 코드의 전체 영역에 걸쳐서 비슷한 패턴으로 산재되어 유지보수의 어려움을 발생시키는 것에 대한 해결책을 제공하여 문제들을 해결해줍니다.
Maven은 자바 프로젝트의 빌드(build)를 자동화 해주는 빌드 툴입니다. 즉, 자바 소스를 compile하고 package해서 deploy하는 일을 자동화 해주는 것 입니다.
Maven을 사용하는 목적 첫 번째로는 작업 환경이 다른 개발자들이 소스코드를 공유하기 위해 메이븐을 사용할 때 pom.xml을 같이 공유하면 개발환경이 다르더라도 에러가 나지 않고 정상적으로 실행되기 때문입니다. 두 번째 목적으로는 프로젝트의 작성부터 컴파일, 페트스 등 프로젝트 라이프 사이클에 포함되는 각 테스트를 지원해주기 때문에 사용됩니다. 추가적으로 라이브러리의 관리가 쉽고, 종속성 관련된 문제들을 해결 할 수 있으며 메이븐이 제공하는 다양한 플러그인을 활용하여 다양한 통합개발 환경, 프로젝트 자동변환, 데이터베이스 통합등이 가능하기 때문에 Maven을 사용합니다.
(compile, test, package, install)
먼저 Compile Phase는 소스 코드를 컴파일 해서 클래스를 에 생성합니다. 이 단계는 compileer:compile goal이 실행됩니다. 그 다음으로 Test Phase는 junit과 같은 테스트 코드를 실행, 테스트가 실패하면 빌드를 멈춥니다. Target/surefie-reports 디렉토리 안에 test 리포트 파일을 생성하고 단위 테스트 코드가 깨져도 빌드를 성공시키려면 maven.test.skip 속성을 true로 설정하면 됩니다. 이 단계에서는 surefile:test goal이 실행됩니다. Package Phase는 package를 실행하면 compile, test_compile, test 순으로 실행된 다음 jar, war 파일이 target 디렉토리 아래에 생성됩니다. 이 단계에서는 패키징에 따라 jar and war:war이 실행됩니다. Install Phase는 로컬 리파지토리에 패키지를 배포하고 install:install이 실행됩니다.
Maven의 scpoe로 compile은 아무런 scope를 명시하지 않았을 때 사용되는 기본 값입니다. 테스트 및 런타임에도 classpath에 포함됩니다. Provided scope는 JDK 또는 컨테이너에 의해서 runtime에 제공되는 모듈이며 이 scope는 이미 컨테이너가 해당 라이브러리를 제공하고 있을 때 유용하고 그러므로 실제로 배포시에 제외 대상입니다. 예를 들면 아래 servlet api의 경우 이미 웹서버에서 제공하고 있는 경우에 maven scope를 provided로 기재한 경우입니다.

다음으로 runtime scope는 런타임시 필요하지만 컴파일시에 필요하지 않는 경우에 사용됩니다. 테스트와 런타임에는 사용되지만 컴파일 시에는 사용되지 않습니다. 대표적으로 JDBC Driver가 있습니다.
