IoC
의존성 역전은 사용자가 작성한 프로그램이 재사용 라이브러리의 흐름 제어를 받게 되는 소프트웨어 디자인 패턴이다
IoC
는 Spring Framework가 가지는 핵심적인 개발 컨셉인 DI
의존성 주입을 이해하기 위한 필수 개념이다.
우리는 IoC
란, 추상화 원칙 중 한 가지로, 실행에 필요한 객체의 생성 / 사용 등 제어 권한을 Framework에게 위임함으로써, Client Code가 신경써야할 부분을 줄이는 전략으로 이해했다.
이러한 전략을 통해서 우리는 다음과 같은 장점을 얻을 수 있었다.
의존성 역전을 사용함으로써, 객체 간의 결합도를 느슨하게 만들고, 유연한 코드를 작성하게 하여 가독성 / 중복 코드 / 유지 보수를 편하게 한다.
의존성이 가지는 기계적 정의는 무엇일까
의존성
Dependency
이란 어떤 특정 객체가 존재하기 위해서 필수적으로 존재해야하는 것과 그 관계를 나타낸다.
의존성은 코드 상에서 new
키워드로 이루어진다.
class Player {
private Item item;
Player() {}
void setItem() {
this.item = new Item();
}
}
위 작성된 코드를 도식화하면 다음과 같다.
다음과 같은 방식은 객체 간의 강결합 Tightly Coupled
로 묶여지게 되며, 이로 인해 코드의 유연성 / 가독성을 떨어뜨리며, 코드의 중복을 발생시킬 수 있는 원인이 된다.
이 강결합을 없애고, 코드의 유연성을 잃지 않는 방법 중 하나가 바로 의존성 역전이다.
class Potion implements Item {
public void useItem() {
System.out.println("Use Potion");
}
}
class Shoes implements Item {
public void useItem() {
System.out.println("Use Shoes");
}
}
class Gun implements Item {
public void useItem() {
System.out.println("Use Gun");
}
}
interface Item {
void useItem();
}
public class Users {
private Item item;
Users(){
}
public void setItem(Item item) {
this.item = item;
}
public void useUsersItem() {
item.useItem();
}
}
public class Main {
public static void main(String[] args) {
Users user = new Users();
user.setItem(new Potion());
user.useUsersItem();
user.setItem(new Shoes());
user.useUsersItem();
user.setItem(new Gun());
user.useUsersItem();
}
}
// Result :
Use Potion
Use Shoes
Use Gun
위의 코드를 도식화하면 다음과 같다.
이와 같이 코드를 설계함으로써, Item
Instance에 대한 Users
의 의존성이 약화된다. User가 특정 상황에서 Item을 사용하기 원한다면, Interface에 맞춰 구현된 Item의 Instance를 갈아끼우면 된다.
즉, 객체 간의 결합을 느슨하게 함으로써, 코드의 유연성 / 가독성을 높이고, 코드의 중복이 필연적으로 제거된다.
Spring은 Container이다. 사용자가 작성한 코드의 처리 과정을 위임받은 독립적인 존재라는 의미로, 적절한 설정이 되어 있는 경우, 누구의 도움 없이도 작성된 코드를 스스로 참조한 뒤에 자동으로 객체의 생성 / 소멸을 컨트롤한다.
위의 코드를 예시로 들면, Spring은 Potion
/ Gun
/ Shoes
등이 Container라는 곳에서 Bean
이라는 Instance의 형태로 관리하게 된다. 이 Container를 IoC Container
라고 부른다.
xml 설정 파일이나 Java Config 파일로부터 설정값을 입력하게 되면, 이 정보를 토대로 Spring이 Container를 생성하여 설정 파일에 등록되어 있는 Bean 객체들을 관리하게 되는 것이다.
각 Bean 객체들이 가지고 있는 의존성을 설정 파일에 입력한 정보를 바탕으로 Container가 생성되게 될 경우, 자동적으로 해당 의존성을 주입하게 되는데, 이는 뒤에서 설명할 DI
의존성 주입이라 칭한다.
의존성 주입의 과정에서 의존성 역전 원칙을 벗어나서는 안된다.