반응형

[Spring] 의존성 역전(IoC)와 스프링 컨테이너(Spring Container)

반응형


| 의존성 역전(Inversion of Control) 


의존성 역전은 스프링 프레임워크(Spring Framework)에서 지원하는 중요한 개발 컨셉인 의존성 주입(Dependency Injection)을 이해하기 위해 알고있어야 하는 개념입니다.


의존성 역전은 객체 간의 결합도를 줄이고 유연한 코드를 작성하게 하여 가독성 및 코드의 중복, 유지보수를 편하게 할 수 있게 합니다.


그렇다면 의존성 역전이란 개념을 우리가 작성하는 코드에 적용하면 어떤 문제를 해결하고 코드 품질을 향상시킬 수 있는지 구체적인 예를 통해 알아보겠습니다.



| 객체 간의 결합도 (Coupling)


RPG게임을 하는 도중에는 게임 플레이어가 여러 무기를 적재적소에 활용하여 게임을 즐기게 됩니다. 이것을 코드상으로 옮기며 게임 플레이어를 나타내는 Player 클래스 무기를 나타내는 Weapon 클래스를 작성하게 될 것입니다.


그리고 Player는 무기를 꼭 필요하기 때문에 Weapon 클래스의 객체를 꼭 가지고 있어야합니다. 이것을 나타내는 용어가 바로 의존성(Dependency)입니다. 어떤 특정 객체가 존재하기 위해 꼭 존재해야하는 것! 그리고 그 관계! 그게 바로 의존성입니다.


코드 상에서는 바로 new 키워드로서 객체간의 의존성이 생성됩니다. 그렇습니다 의존성은 바로 new 키워드로 이루어 집니다. 다음과 같이요.


class Player {
private Weapon weapon;

Plyaer(){
}

void setWeapon(){
this.weapon = new Weapon();
}
// 나머지 코드
}


이걸 그림으로 나타내면 다음과 같습니다. 



하지만 이러한 방식은 객체 간의 강결합(Tightly Coupled)으로 묶여지면서 코드의 유연성을 떨어트리고 코드의 중복 및 가독성을 떨어뜨리는 원인이 됩니다. 


만약 Weapon클래스가 Weapon만 아닌 Knife, Gun, Spike 등 여러 종류의 무기를 사용하게 될 경우 코드 상에 무수한 if else 문이 작성되게 되고 그 부담은 프로그래머에게로 돌아오게 됩니다.


이 강결합을 없애고 코드의 유연성을 확보한 방법 중 하나가 의존성 역전입니다.


class Knife implements Weapon{

public void useWeapon() {
System.out.println("Use Knife");
}
}

class Gun implements Weapon{

public void useWeapon() {
System.out.println("Use Gun");
}
}

class Spike implements Weapon{

public void useWeapon() {
System.out.println("Use Spike");
}
}

interface Weapon {

void useWeapon();
}

public class Player {

private Weapon weapon;

Player(){
}

public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}

public void usePlayerWeapon() {
weapon.useWeapon();
}
}

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub
Player player = new Player();

player.setWeapon(new Gun());
player.usePlayerWeapon();

player.setWeapon(new Spike());
player.usePlayerWeapon();

player.setWeapon(new Knife());
player.usePlayerWeapon();
}
}

// Result :
Use Gun
Use Spike
Use Knife


< Weapon 인스턴스에 대한 Player의 의존성을 약화>


위와 같이 코드가 설계되면 Player가 특정 상황에서 어떤 무기가 필요하다고 하면 코드 상에서 if else문이 아니라 interface에 맞춰서 구현된 무기들의 인스턴스를 갈아 끼우면 되므로 코드가 유연해 지고 가독성이 높아질 뿐만아니라 코드의 중복이 필연적으로 제거됩니다.


| IoC 컨테이너(Container)


스프링(Spring)에서는 위와 같은 Knife, Gun Spike등을 컨테이너(Container)라는 곳에서 Bean이라는 인스턴스 형태로 관리합니다. 나중에 이야기할 xml이나 java config 파일로부터 설정값들을 입력한 후 이 정보를 토대로 스프링이 컨테이너를 생성하여 설정 파일들에 등록되어 있는 Bean 객체들을 관리합니다. 


또한 각 Bean이 가지고 있는 의존성을 설정파일에 입력해둔 정보를 토대로 컨테이너가 생성될 시 자동적으로 해당 의존성을 주입해줍니다. 의존성 역전(IoC) 원칙을 지키면서요.


이것을 스프링에서는 해당 컨테이너를 IoC 컨테이너라고 부르고 이런 의존성을 주입시키는 행위를 나중에 설명해드릴 DI(Dependency Injection)라고 부릅니다.


반응형

이 글을 공유하기

댓글

Designed by JB FACTORY