1HOON
논리적 코딩
1HOON
전체 방문자
오늘
어제
  • HOME (186)
    • ☕️ JAVA (28)
      • WhiteShip Java LIVE Study (6)
      • Effective JAVA (10)
    • 🔮 KOTLIN (4)
    • 🌱 SPRING (51)
      • 스프링 인 액션 (22)
      • JPA (18)
    • ☕️ JAVASCRIPT (6)
    • 📃 DATABASE (40)
      • ORACLE (37)
      • MSSQL (2)
    • 🐧 LINUX (4)
    • 🐳 DOCKER (5)
    • 🐙 KUBERNETES (4)
    • 🏗️ ARCHITECTURE (8)
    • 📦 ETC (26)
      • TOY PROJECT (5)
      • RECRUIT (1)
      • 그냥 쓰고 싶어서요 (14)
    • 🤿 DEEP DIVE (1)
    • 🚽 Deprecated (9)
      • PYTHON (3)
      • AWS (2)
      • HTTP 완벽가이드 (3)
      • WEB (1)

블로그 메뉴

  • 홈
  • 방명록
  • 관리

인기 글

최근 글

티스토리

hELLO · Designed By 정상우.
1HOON

논리적 코딩

🌱 SPRING/스프링 인 액션

종속객체 주입 (DI, Dependency Injection)

2018. 5. 6. 13:33

종속객체 주입 (DI, Dependency Injection)

아래와 같은 코드가 있다고 가정해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class DamselRescuingKnight implements Knight
{
    private RescueDamselQuest quest;
 
    public DamselRescuingKnight ()
    {
        this.quest = new RescueDamselQuest ();
    }    
 
    public void embarkOnQuest ()
    {
        quest.embark();
    }
}
Colored by Color Scripter
cs


이 코드에서는 DamselRescuingKnight 클래스를 생성했을 때 RescueDamselQuest 객체를 생성한다.

이 경우에는 새로운 RescueDamselQuest 객체의 값이 변경될 수 없다. DamselRescuingKnight 객체가 생성될 때, 생성자로써 RescueDamselQuest 객체를 만들어 private 전역변수에 저장해두기 때문이다.

이 코드와 같은 경우 DamselRescuingKnight 가 RescueDamselQuest 에 강하게 결합되어 있다고하며, DamselRescuingKnight 에 대한 단위테스트가 몹시 어렵다.


그렇다면 DI를 활용하면 이 코드를 어떻게 바꿀 수 있을까?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class BraveKnight implements Knight
{
    private Quest quest;
 
    public BraveKnight (Quest quest)
    {
        this.quest = quest;
    }
 
    public void embarkQuest ()
    {
        quest.embark();
    }
}
Colored by Color Scripter
cs


BraveKnight 클래스에서는 RescueDamselQuest 의 인터페이스인 Quest 타입으로 전역변수 quest를 생성한다. 그렇기 때문에 RescueDamselQuest 뿐만 아닌 Quest를 구현하는 어떤 클래스도 부여받을 수 있다.

그리고 BraveKnight는 생성자를 오버라이딩해 Quest 객체를 주입받는다. 그렇기 때문에 BraveKnight는 특정 구현체에 결합되지 않는다. 이것이 바로 DI의 주요 이점인 느슨한 결합도 이다.


좀 더 쉽게 비교해보자면, RescueDamselQuest 클래스의 내용이 '공주를 구해라!' 라고 가정을 했을 때, DamselRescuingKnight 는 어떤 짓을 해도 '공주를 구하는 것' 외에는 어떤 것도 하지 못한다.

반면, BraveKnight의 경우는 확연히 다르다. Quest의 구현 클래스의 내용이 '용이 있으면 용을 무찔러라!' 이면 BraveKnight는 용을 무찌른다.

또 다른 Quest의 구현 클래스의 내용이 '머리가 노란색인 공주를 구해라!' 라면 BraveKnight는 노란 머리의 공주를 구한다.


그렇다면, 이제 BraveKnight에게 부여할 임무를 만들자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SlayDragonQuest implement Quest
{
    private PrintStream stream;
 
    public SlayDragonQuest (PrintStream stream)
    {
        this.stream = stream;
    }
 
    public void embark ()
    {
        stream.println ("Embarking on quest to slay the dragon!");
    }
}
Colored by Color Scripter
cs


이제 중대한 문제가 생겼다! 어떻게 BraveKnight에게 이 임무를 부여하고 임무에게 PrintStream 객체를 넘길 것인가?

애플리케이션 컴포넌트 간의 관계를 정하는 것을 와이어링 이라고 하는데, 스프링에서는 와이어링을 XML로 할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<beans xmls="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="knight" class="com.test.logicalCode.knight.BraveKnight">
        <constructor-arg ref="quest" />  ← quest라는 이름을 가진 Bean을 생성자에 넘김
    </bean>
 
    <bean id="quest" class="com.test.logicalCode.quest.SlayDragonQuest">
        <constructor-arg value="#{T(System).out}" />  ← SpEL을 이용해 System.out을 생성자에 넘김
    </bean>
 
</beans>
Colored by Color Scripter
cs


이렇게 와이어링까지 된 애플리케이션은 .ApplicationContext()로 XML을 로드해 스프링 컨텍스트를 로드한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
public class KnightMain
{
    public static void main(String[] args) throws Exception
    {
        ClassPathXmlApplicationContext context = new new ClassPathXmlApplicationContext("META-INF/spring/knights.xml");
 
         Knight knight = context.getBean(Knight.class);
 
         knight.embarkOnQuest();
 
         context.close();
    }
}
Colored by Color Scripter
cs

 


 이 포스트는 스프링 인 액션을 읽고 개인적으로 필요하다고 생각되는 내용을 정리한 포스트입니다.

 

일부 내용, 소스코드는 스프링 인 액션의 내용일 수 있습니다.

반응형
저작자표시 비영리 변경금지 (새창열림)

'🌱 SPRING > 스프링 인 액션' 카테고리의 다른 글

조건부 빈  (0) 2018.05.21
XML로 빈 와이어링하기  (0) 2018.05.07
자바로 빈 와이어링하기  (0) 2018.05.07
빈 와이어링 - 자동 와이어링  (0) 2018.05.07
스프링 컨테이너  (0) 2018.05.06
    '🌱 SPRING/스프링 인 액션' 카테고리의 다른 글
    • XML로 빈 와이어링하기
    • 자바로 빈 와이어링하기
    • 빈 와이어링 - 자동 와이어링
    • 스프링 컨테이너
    1HOON
    1HOON

    티스토리툴바