본문 바로가기

Spring

[Spring] Spring Framework & Spring Container & DI(의존성 주입)

[해당 포스트는 개인적으로 공부를 하고 차후에 참고용으로 하고자 작성한 것입니다.
따라서 잘못된 부분이나 부족한 부분이 있을 수 있기에 참고하시기 바랍니다.]

Framework

소프트웨어 개발자가 응용 소프트웨어의 표준 구조를 구현하기 위해 사용하는 소프트웨어 프레임워크로 구성된다.

프로그래밍에서 특정 OS를 위한 응용 프로그램 표준 구조를 구현하는 ClassLibrary모임.

 

특징

  1. Modularity (모듈화)
    • 프레임워크는 구현을 위한 인터페이스 뒤에 감추는 캡슐화를 통해서 모듈화를 강하게 한다.
  2. Reusability (재사용성)
    • 프레임워크가 제공하는 인터페이스는 여러 Application에서 반복적으로 사용할 수 있는 일반적인 Component를 정의할 수 있게 함으로써 재사용성을 높여준다.
    • 프레임워크 Component를 재사용하는 것은 SW의 품질, 성능, 신뢰성, 상호 운용성을 향상할 뿐만 아니라, 프로그래머의 생산성을 상당히 높여준다.
  3. Extensibility (확장성)
    • 프레임워크는 Polymorphism을 통해 Application이 프레임워크의 인터페이스를 확장할 수 있게 한다.
  4. Inversion Of Control (제어역전)
    • 일반적으로 어떤 모듈을 호출함으로써 해당 모듈을 재사용하게 된다. 그러나 프레임워크에서는 이와는 반대되는 제어 흐름으로의 재사용성을 지원한다.
    • "내가 대신 처리할 테니, 넌 니 할 일만 처리해" 원리가 적용된다.  즉, 프레임워크 코드가 전체 Application의 처리 흐름을 제어하며, 특정한 이벤트가 발생할 때 Polymorphism을 통해 Application이 확장한 메서드를 호출함으로써 제어가 프레임워크로부터 Application으로 거꾸로 흐르게 한다.

Framework vs Library

  • Framework란 SW의 구체적인 부분에 해당하는 설계와 구현을 재사용이 가능하게끔 일련의 협업화된 형태로 Class들을 제공하는 것.
  • Library란 자주 사용되는 Logic을 재사용하기 편리하도록 잘 정리한 일련의 코드들의 집합.

Spring Framework

Java EE 개발을 편하게 해주는 경량급 Open Source Application Framework.

동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공하고 있으며, 대한민국 공공기관의 웹 서비스 개발 시 사용을 권장하고 있는 전자정부 표준프레임워크의 기반 기술로서 쓰이고 있다.

 

특징

  1.  Life Cycle 관리 : 경량 Container로서 Java 객체를 직접 관리. 객체 생성, 소멸과 같인 Life Cycle을 관리하며 Spring으로부터 필요한 객체를 얻어올 수 있다.
  2. POJO (Plain Old Java Object) : POJO를 사용함으로써, 코드가 더욱 단순해지고 테스트하기에 좋으며, 유연하고, 요구사항에 따라 기술적 선택을 바꿀 수 있음. 일종의 Setter나 Getter와 같은 Bean 방식을 통해 처리하는 것.
  3. IoC (Inversion of Control) : 컨트롤의 제어권이 사용자가 아니라 Framework에 있어서 필요에 따라 스프링에서 사용자의 코드를 호출한다.
  4. DI (Dependency Injection) : 각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다.
  5. AOP (Aspect-Oriented Programming) : Transaction이나 Logging, Secure과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우 해당 기능을 분리하여 관리한다.

핵심모듈

  1. spring-core : Spring의 핵심인 DI와 IoC를 제공
  2. spring-aop : AOP구현 기능 제공
  3. spring-jdbc : DB를 쉽게 다룰 수 있는 기능 제공
  4. spring-tx : 스프링에서 제공하는 트랜잭션 관련 기능 제공
  5. spring-webmvc : 스프링에서 제공하는 Controller, View, Model을 이용한 MVC기능 제공

Spring Container (IoC)

Spring의 인스턴스는 생성부터 소멸까지의 객체 생명주기 관리를 개발자가 하는 것이 아니라 Spring이 대신한다. 이러한 관리를 Spring Container에서 이루어진다.

Spring Container는 Application을 구성하는 Bean들을 관리하기 위해 IoC를 사용한다.

Spring Container 종류는 BeanFactory와 이를 상속한 ApplicationContext가 존재한다.

 

출처 : https://asfirstalways.tistory.com/334

  1. Web Application이 실행되면 Tomcat에 의해 web.xml이 Loading 된다.
  2. web.xml에 등록되어 있는 ContextLoaderListener가 생성된다. ContextLoaderListener Class는 ServletContextListener 인터페이스를 구현하고 있으며, ApplicationContext를 생성하는 역할을 수행한다.
  3. 생성된 ContextLoaderListener는 root-context.xml을 Loading 한다.
  4. root-context.xml에 등록되어 있는 Spring Container가 구동된다. 개발자가 작성한 비즈니스 로직에 대한 부분과 DAO, VO 객체들이 생성된다.
  5. Client로부터 Web Application 요청이 온다.
  6. DispatcherServlet이 생성된다. DispatcherServlet은 FrontController의 역할을 수행한다. 클라이언트로부터 요청 온 메시지를 분석하여 알맞은 PageController에게 전달하고 응답을 받아 요청에 따른 응답을 어떻게 할지 결정한다.
  7. DispatcherServlet은 servlet-context.xml을 Loading 한다.
  8. 두 번째 Spring Container가 구동되며 응답에 맞는 PageController들이 동작한다. 이때 첫 번째 Spring Container가 구동되면서 생성된 DAO, VO, ServiceImpl 클래스들과 협업하여 알맞은 작업을 처리한다.

DI (Dependency Injection)

하나의 객체에서 다른 객체의 변수나 메서드를 이용하려면, 이용하려는 객체에 대한 정보가 필요하다. 즉 A라는 Class에서 B라는 객체를 사용하려면 new B()를 통해 생성한다. 이때 A는 B에 의존하게 된다.

Spring에선 객체 내에서 별도의 객체를 직접 생성하지 않고 외부에서 생성된 객체를 주입함으로써 의존 관계를 없앨 수 있다. 이러한 방법을 Dependency Injection이라고 한다.

 

* XML을 이용하여 주입

1. 객체 생성 및 객체 주입

<!-- DAO bean 생성 -->
<bean id="wordDao" class="com.word.dao.WordDao"/>
	
<!-- WordRegisterService bean 생성 -->
<bean id="wordService" class="com.word.service.WordRegisterService">
	<!-- wordDao 객체 주입 -->
	<constructor-arg ref="wordDao"/>
</bean>

 

public class WordRegisterService {
	
	WordDao dao;
	
	public WordRegisterService(WordDao dao) {
		this.dao = dao;
	}
}

- WordRegisterService Bean이 생성될 때 <constructor-arg> 태그를 통해 생성자를 호출한다. 이때 WordDao를 주입하여 dao 인스턴스를 생성한다.

 

2. Setter를 이용한 의존 객체 주입.

<!-- DAO 객체 생성 -->
<bean id="wordDao" class="com.word.dao.WordDao"/>
	
<!-- WordRegisterService 객체 생성 -->
<bean id="wordService" class="com.word.service.WordRegisterService">
	<!-- wordDao 객체 주입 -->
	<constructor-arg ref="wordDao"/>
	<!-- Setter를 이용한 의존 객체 주입 -->
	<property name="value" value="setValueByXML"/>
</bean>

 

public class WordRegisterService {
	
	WordDao dao;
	
	public WordRegisterService(WordDao dao) {
		this.dao = dao;
	}
	
	public void setValue(String value) {
		dao.setValue(value);
	}
	
	public String getValue() {
		return dao.getValue();
	}
}

- setValue의 인자는 Application-Context.xml에서 지정한 값으로 대처할 수 있다. <property> 태그를 통해 Setter에 지정된 인자의 이름과 XML에 지정된 이름이 일치할 경우 주입할 수 있다. 따라서 별도의 setValue를 호출하지 않아도 값이 들어간다.