IoC(Inversion of Control)와 DI(Dependency Injection)는 소프트웨어 디자인 및 구현에서 중요한 개념 중 하나다. 이 두 가지 개념은 의존성 관리와 코드의 느슨한 결합을 촉진하여, 객체 지향 프로그래밍에서 모듈화와 유지보수성을 향상시키는데 도움을 준다.
IoC란 제어의 역전이라는 말이다. 즉, 메서드나 객체의 호출작업을 개발자가 결정하는 것이 아니라, 외부에서 결정되는 것을 의미한다.
기존의 프로그램 흐름을 바꾸는 개념으로, 일반적으로 프로그램의 제어 흐름을 개발자가 제어하는 것이 아니라 프레임워크나 컨테이너에 의해 제어되는 것을 의미한다.
예를 들어, 스프링 프레임워크에서는 객체의 생성, 생명 주기 관리, 의존성 관리 등을 스프링 컨테이너가 수행하며 개발자는 객체의 사용에 집중할 수 있다.
DI는 의존성 주입이라는 말이다. 의존성 주입은 제어의 역전이 일어날 때 스프링이 내부에 있는 객체들간의 관계를 관리할 때 사용하는 기법이다.
DI는 IoC의 한 형태로, 의존성을 주입하는 것을 말하며, 클래스나 객체가 필요로 하는 의존성(다른 클래스나 객체)을 직접 생성하는 것이 아니라 외부에서 주입받는 방식이다.
이를 통해 객체 간의 결합도를 낮추고 테스트 용이성을 향상시킨다. 주로 생성자 주입, Setter 주입, 인터페이스 주입 등의 방식으로 의존성을 주입한다.
// IoC를 활용한 예제
public class Application {
public static void main(String[] args) {
Service service = new Service(); // 개발자가 직접 객체 생성
service.doSomething();
}
}
class Service {
public void doSomething() {
// 비즈니스 로직 수행
}
}
위 코드는 개발자가 Service 객체를 직접 생성하고 사용하는 전통적인 방식이다. 이제 DI를 적용한 예제로 바꿔보자.
// DI를 활용한 예제
public class Application {
public static void main(String[] args) {
Service service = new Service(new Repository()); // 외부에서 의존성 주입
service.doSomething();
}
}
class Service {
private Repository repository;
public Service(Repository repository) {
this.repository = repository;
}
public void doSomething() {
// repository를 사용하여 비즈니스 로직 수행
}
}
class Repository {
// 데이터베이스와 상호작용하는 코드
}
DI를사용하면 Service 클래스가 직접 Repository를 생성하지 않고 외부에서 주입 받는다. 이로써 의존성의 역전과 결합도의 감소가 이루어진다. 스프링 프레임워크는 이러한 DI 패턴을 지원하여 객체 간의 결합도를 낮추고 유지보수성을 향상시킨다.