[Spring / 스프링] DI | 의존성 주입 | IoC 컨테이너 | 사용법

DI(Dependency Injection)는 스프링의 핵심 기능 중 하나 입니다. 기존 자바처럼 new를 이용해서 객체를 생성하지 않아도 객체를 주입하는 기능 입니다. 이 방법은 모듈 간 의존도를 낮추어 '느슨한 결합'을 추구할 수 있는 장점이 있습니다.

DI(Dependency Injection)

객체 자향적인 자바는 여러 클래스가 조립되는 형태로 프로그래밍 됩니다. Dependency의 사전적 의미는 의존인데, 이처럼 조립된 객체 간에는 의존성이 형성되기 때문에 이름을 이렇게 붙인 거 같네요. Dependency Injection는 의존성 주입이라고 번역되긴하지만, 그냥 객체를 주입한다고 이해하면 무리가 없을 듯 합니다.

 

스프링이 객체를 생성하고 꺼내오는 공간을 IoC 컨테이너라고 부릅니다. 스프링을 구성하는 핵심 개념이죠. 근데 막상 IoC 컨테이너의 존재는 웹 애플리케이션 개발 시엔 자동으로 생성되고 동작하기 때문에 그 실체가 희미한 측면이 있긴 합니다. 그래도 알고는 있어야겠죠. 


DI의 목적은 객체 간 느슨한 결합력을 만드는 것입니다. 코드 유지 보수와 관련이 있습니다. 예를 들어 객체 간 결합력이 높을수록 A라는 클래스 하나를 바꾸고 싶을 때 그와 연관된 B, C, D... 도 모두 바꿔 줘야하는 환경인 것입니다. 반면 객체 간 결합력이 낮으면 A 클래스 하나만 새로운 코드로 갈아 끼는, 마치 부품을 갈아끼는 것처럼 수정이 손쉽습니다.

사용법

DI를 하는 방법은 1. xml 파일에 코딩해주는 방법과 2. 클래스에서 어노테이션(@)을 사용하는 방법 두 가지 입니다. 둘 다 알아야 됩니다. 

1. xml 파일에 기입

xml 파일은 객체를 어떻게 조립할지 명시하는 지시서 역할을 합니다. new 대신 bean 태그를 이용해서 객체를 생성합니다. 가령 객체를 만드는 코드를 xml 파일에서 구현하면

<bean id="id" class="패키지명을 포함한 클래스명">
    <property name="변수명" value="값"/> <!--문자열 또는 기본 데이터 타입-->
    <property name="변수명" ref="참조값"/> <!--객체인 경우-->
</bean>

이런식으로 할 수 있습니다. property 태그를 통해서는 변수의 값을 저장 합니다. 네임스페이스 p를 이용하면 property 부분의 코드를 아래와 같이 줄일 수도 있습니다. 

<bean id="a" class="" p:변수명-ref="bean id" p:변수명="값" />

아래처럼 생성자를 이용하는 방법도 있습니다.

<bean id="" class="">
	<constructor-arg ref=""/>
	<constructor-arg value=""/>
</bean>

 

생성자와 프로퍼티 방식 중에는 프로퍼티 방식 사용이 좀더 권장됩니다. 생성자의 경우 매개변수를 다양하게 다루는 것이 불편한 반면 프로퍼티 방식의 경우 재구성하기가 좀더 쉽기 때문이죠.

2. annotation(@) 사용

어노테이션(@)을 이용하면 코드파일에 설정 정보를 심을 수 있습니다. xml 파일에 bean 태그를 만들 필요가 없고 단지 "어노테이션을 사용할 테니 어노테이션이 표시된 객체를 잘 검사해달라"는 코드만 넣어주면 됩니다. 아래 코드가 그런 명령입니다.

<context:component-scan base-package="com.mvc.exam,spring.controller" />

com.mvc.exam,spring.controller 패키지 경로에 있는 클래스의 어노테이션을 검사하겠다는 의미입니다.

어노테이션의 종류는 많지만 목적에 따라 자주 쓰이는 일부만 살펴보겠습니다.

주입받을 때

@AutoWired : 타입을 기준으로 주입. 해당 타입의 변수에 맞춰서 해당 타입 또는 자손 타입의 객체를 자동으로 주입
@Resource : 이름을 검색하고 이름이 없으면 타입을 검사해서 주입
@Value : String, int 등 타입에 주입

 

Ex)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Foo {
    @Autowired
    Bar bar; 
    @Value("test")
    String name;

    public void setName(String name) {
        this.name = name;
    }
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

Bean 자동 생성

@Component
@Repository
@Service
@Controller

네 개의 어노테이션은 기본적으로는 Bean을 생성해준다는 면에서 기능이 동일합니다. 다만 @Component가 기본적인 어노테이션이고 @Repository, @Service, @Controller는 각 상황에 좀더 특화된 어노테이션이라고 보면 됩니다. 예를 들어 스프링 MVC 패턴에의 컨트롤러 클래스에는 @Component 대신 @Controller를 사용합니다. 

반응형

댓글

Designed by JB FACTORY