Dependency Injection (의존성 주입)
DI(의존성 주입)는 객체의 의존성을 외부에서 주입받는 기법입니다.
의존관계란? 'A가 B를 의존한다' 라고 했을 때, B가 변하면 A에도 영향을 끼치는 관계를 의미합니다.
특정 기능이나 서비스를 외부에서 받아와서 사용하는 방식인데요. DI를 사용하면 클래스 내부에서 새로운 객체를 직접 생성하는 대신 외부에서 필요한 객체를 받아 사용할 수 있습니다. 이를 통해 모듈 결합도를 낮추고 코드 재사용성과 테스트 용이성을 향상할 수 있습니다.
의존성 주입 방법 - 생성자 주입 방식
class Eat {
private Fruit fruit;
public Eat() {
this.fruit = new Fruit();
}
}
위 코드와 같이 Eat 클래스에 직접 Fruit 클래스를 생성할 경우, 의존성 주입이 일어나지 않았습니다.
Eat 클래스가 Fruit 클래스에 전적으로 의존하고 있기 때문에, 다른 과일을 먹고 싶은 경우에 Eat 클래스 내부를 수정해야 합니다.
class Eat {
private Fruit fruit;
public Eat(Fruit fruit) {
this.fruit = fruit;
}
}
class Fruit {}
class Banana extends Fruit{}
class Apple extends Fruit {}
이렇게 생성자를 통해 주입을 하게 된다면, Fruit 클래스를 상속받은 다른 과일들도 먹을 수 있게 되는 겁니다.
이러한 이유로 우리는 Spring이라는 DI 컨테이너를 필요로 하는 것이다. Eat에서 Fruit 객체를 주입하기 위해서는 애플리케이션 실행 시점에 필요한 객체(빈)를 생성해야 하며, 의존성이 있는 두 객체를 연결하기 위해 한 객체를 다른 객체로 주입시켜야 한다.
예를 들어 다음과 같이 Apple 이라는 객체를 만들고, 그 객체를 Eat로 주입시켜주는 역할을 위해 DI 컨테이너가 필요한 것이다.
public class BeanFactory {
public void eat() {
// Bean의 생성
Fruit apple = new Apple();
// 의존성 주입
Eat eat = new Eat(apple);
}
}
Injection of Control (제어의 역전)
IoC(제어 역전)은 프로그램 제어를 프레임워크 등의 외부 요소(Spring Container)에 위임하여 코드의 결합도를 낮추는 디자인 패턴입니다.
기존 전통적인 JAVA 의존성 주입 - 직접 객체 생성
public class OrderService {
private ProductRepository productRepository;
public OrderService() {
this.productRepository = new ProductRepository(); // 직접 생성
}
public void placeOrder() {
// 로직 수행
}
}
- OrderService는 내부에서 ProductRepository 객체를 직접 생성합니다.
- 이 경우 ProductRepository에 변경이 생기면 OrderService도 함께 수정해야 한다.
Spring의 IoC - 외부에서 주입
@Component
public class ProductRepository {
// DB 처리
}
@Service
public class OrderService {
private final ProductRepository productRepository;
@Autowired
public OrderService(ProductRepository productRepository) {
this.productRepository = productRepository; // 외부에서 주입
}
public void placeOrder() {
// 로직 수행
}
}
- 객체 생성과 의존성 주입은 스프링 컨테이너가 담당합니다.
- 개발자는 객체 간 관계만 선언하고, 실제 객체의 생명 주기나 생성 방식은 신경 쓰지 않아도 됩니다.
모듈간 결합도를 낮추는 이유
- 결합도가 낮으면 모듈 수정 시 다른 모듈에 미치는 영향이 줄어들어 유지보수가 쉬워집니다.
- 낮은 결합도는 모듈을 다른 프로젝트나 환경에서도 쉽게 재사용할 수 있게 해줍니다.
- 확장성과 유연성이 높아져 기능 변경이나 추가가 용이해집니다.
- 모듈 간 의존성이 줄어들어 시스템 전체 구조를 이해하기 쉬워집니다.
- 오류가 발생해도 다른 모듈로 전파되지 않아 안정성이 향상됩니다.
'Interview Question' 카테고리의 다른 글
[백엔드 면접 질문 준비] (6) JVM이란 무엇인가? (0) | 2025.04.05 |
---|---|
[백엔드 면접 질문 준비] (5) 프로세스와 스레드의 차이는 무엇인가요? (0) | 2025.04.04 |
[백엔드 면접 질문 준비] (4) CI/CD란? (0) | 2025.04.03 |
[백엔드 면접 질문 준비] (3) HTTP 상태 코드에 대해 말해보세요. (0) | 2025.04.02 |
[백엔드 면접 질문 준비] (2) HTTP METHOD에 대해서 설명해 보세요. (0) | 2025.04.02 |