JaeniWorld

[Spring Framework] 스프링 프레임 워크의 구조 (Spring Framework Architecture)/Coupling /PoJo /재사용성/IOC/Bean Definition 본문

프로그래밍/Framwork

[Spring Framework] 스프링 프레임 워크의 구조 (Spring Framework Architecture)/Coupling /PoJo /재사용성/IOC/Bean Definition

jaeni 2020. 8. 5. 16:59
반응형

1. Framework

Framework는 여러가지 모듈이 합쳐진 것이다. 동일한 말로 각각이 완벽한 Component의 집합이자 library의 모듈화 이다.

우리가 자주 접하는 Spring Framework로 예를 들면 아래와 같은 형태로 구성되어있다.

 

출처 : https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/overview.html

크게 CoreContainer(DI ; Dependency Injection) / MVC / JDBC / Aop / Security등으로 나눌 수 있으며, 각각의 모듈들은 꼭 스프링프레임워크의 것을 사용하지 않아도 된다.

 

2.Spring MVC Architecture

출처: https://www.java4coding.com/contents/spring/spring-mvc-architecture

위 사진과 같이 서비스 요청 흐름과 개발자 시점은 다르다. 특히 어디에 의존(Dependency)하느냐에 따라 순서가 굉장히 중요해진다. 그렇기 때문에 DB에서 값을 주입 받는 DAO가 제일 중요하다. DB와 DAO 사이에 있는 JDBC도 중요하지만 이 번에는 DAO위주로 정리를 하겠다.

 

3.Coupling /재사용성

기존 우리가 VO를 만들땐 아래와 같이 생성한다. 이와 같이 상속, implements를 하지 않는 Java Class를 POJO(Plain Old Java Object)라 한다. (참고로 Serializable가 implements 되어도 pojo class이다. 왜냐면 serializable은 jvm 메모리에 상주 되어있는 객체 데이터를 바이트 형태로 변환하거나 직렬화 된 바이트 형태의 데이터를 객체로 변환해 jvm에 상주시키는 기술을 칭하기 때문)

 

package spring.service.hello;

public class Hello{
	
	private String message;
	
	public Hello() {}
	public Hello(String message) {this.message = message;}

	
	public String getMessage() {return message;}
	public void setMessage(String message) {this.message = message;}
	
    public void printMsg(){
    	System.out.prinln(message);
    }
}

하지만 이렇게 작성해 비즈니스로직이나 단위테스트에 객체를 생성한 뒤 사용할 경우, VO 내부의 필드나 메소드가 변경되면 이 객체가 생성된 곳을 찾아 일일히 변경해줘야 한다.

 

이러한 상황을 Coupling이 심하다고 이야기한다 (= 재사용성이 낮다). 즉 둘이 결합도가 높아 VO가 변경될 시 이를 사용한 곳에서 모두 손봐줘야 한다는 소리이다. Coupling을 완화시키기 위해서는 위의 Hello Class를 InterFace로 변환시키고 이를 Implements받은 HelloImpl을 사용해 Setter로 값을 주입하여 준다. (Hello Type으로 구상객체인 HelloImpl 객체를 생성한다.)

 

4. IOC(Inversion of Control)

여기서 끝이 아니고 interface를 사용한 방법에서 재사용성을 한단계 더 높일 수 있다. 바로 DI에게 객체 생성을 맡기는 것이다.

DI Container( Core Container)가 구상객체를 생성하는 방법

프로그래머가 직접 객체를 생성하던 이전과 달리 객체 생성의 주체가 Container로 변경된다. Container 내에서는 구상객체에 대한 Bean을 생성하고 이를 저장한뒤, 프로그래머가 필요할 때 getBean()함수를 통해 이를 반환받을 수 있도록 한다. 이 때, 하나의 Bean은 하나의 Instance이고, DAO impl이 SingleTone이면 생성되는 Bean도 Singletone으로 만들어진다.

 

5. BeanFactory / ApplicationContext

Bean을 생성하기 위한 BeanContainer는 BeanContainer가 Interface이기 XmlBeanFactory로부터 반환받아 사용할 수 있다.  BeanFactory를 직접 사용해보면 Lazy Loading의 형태를 띄고 있는 걸 알 수 있다.

LazyLoading은 getBean()을 호출하면 그때 생성해 메모리에 할당하는 형태이다. 그리고 코드를 쳐보면 아래 사진과 같이 취소선이 그어져 있는 것을 알 수 있다.

안쓴다는 뜻이다. 현재는 ApplicationContext를 통해 BeanFactory를 생성하고 있으며 ApplicationContext는 BeanFactory와 달리 PreLoading( 호출 전에 생성하고 미리 메모리에 올려놓음)는 형태를 띄고 있다.

 

6. Bean

Bean은 API Bean과 User Definition Bean으로 나눠진다. API Bean는 이미 존재하는 API Bean에 대한 설정으로 아래와 같이 사용된다.

<bean id="password" class="java.lang.String"/>

User Definition Bean은 Class를 만들고 유저가 선언하는 것으로

<bean id="user" class="spring.service.domain.User"/>

위와 같은 방식으로 사용하면 된다.

 

 

이때, Bean의 값을 주입하는 방법도 두가지로 나뉜다. 생성자 주입과 Setter주입이다. 생성자 주입은 <construct -arg/> Tag를 사용하는데 주의 할 점이 있다. 꼭 생성자 순서대로 값을 넣어주어야 에러가 나지 않는다. 이를 방지하기 위해서 index, name, type등의 속성을 사용하는데 이들은 서로 혼합해서 사용가능하다.

<bean id="user" class="spring.service.domain.User">
		<constructor-arg value="유저" index="1"/>
		<constructor-arg value="패스워드" index="0"/>
        <constructor-arg value="05" type="int"/>
	</bean>

이보다는 안정성을 위해 setter주입을 권장한다. setter주입은 <property />Tag를 사용하며 아래와 같이 사용한다.

<bean id="user" class="spring.service.domain.User">
		<property name="userId" value="유저"/>
		<property name="age" value="01"/>
	</bean>

 

반응형
Comments