1. 제어의 역전 (IoC)
제어의 역전은 소프트웨어 개발에서 중요한 개념 중 하나로, 기존의 제어 흐름을 바꾸는 개념.
기존에는 개발자가 애플리케이션의 제어 흐름을 직접 다루었지만, 제어의 역전은 이를 반전시키는 개념.
일반적으로 프로그램이 실행될 때는 개발자가 정한 흐름대로 실행된다.
예를 들어, 함수 A에서 함수 B를 호출하고, B에서 C를 호출하는 경우, 제어 흐름은 A에서 B, B에서 C로 흘러간다..(일반적인 제어 흐름)
제어의 역전은 이런 제어 흐름을 프레임워크나 컨테이너에게 넘기는 것을 의미.
프레임워크나 컨테이너가 언제, 어떻게, 어떤 객체(클래스)를 생성하고, 실행할지를 제어.
이렇게 하면 개발자는 자신이 작성한 코드를 프레임워크나 컨테이너에 등록하고, 이를 통해 실행 흐름을 변경하거나 확장할 수 있다.
예를 들어, 스프링 프레임워크에서는 IoC 컨테이너를 사용하여 객체의 생성과 관리를 위임하고, 개발자는 이를 통해 애플리케이션의 제어 흐름을 조절한다.
예시코드
- 기존 방식
- 기존에는 은행 계좌 관리 시스템을 개발할 때, 개발자가 직접 객체를 생성하고 관리했다.
public class AccountService {
private AccountRepository accountRepository = new AccountRepository();
public void deposit(int accountNumber, double amount) {
Account account = accountRepository.findAccountByNumber(accountNumber);
account.deposit(amount);
accountRepository.saveAccount(account);
}
}
- 이 코드에서 AccountRepository와 Account 클래스는 개발자가 직접 생성하고 사용한다.
- IoC를 적용한 방식
- IoC를 적용하여 제어의 역전을 실현하면 Spring Framework를 사용하여 IoC 컨테이너를 만들고 객체 관리 위임
public class AccountService {
private AccountRepository accountRepository;
// IoC 컨테이너로부터 AccountRepository 객체를 주입받음
public AccountService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
public void deposit(int accountNumber, double amount) {
Account account = accountRepository.findAccountByNumber(accountNumber);
account.deposit(amount);
accountRepository.saveAccount(account);
}
}
- AccountRepository 객체는 IoC 컨테이너에서 주입받아 사용
- 개발자가 직접 객체를 생성하고 관리하는 것이 아니라, IoC 컨테이너가 제어 흐름을 역전시킨다.
2. 의존성 주입 (DI)
의존성 주입은 제어의 역전을 실현하기 위한 방법 중 하나.
객체 지향 프로그래밍에서는 다양한 객체(클래스)들이 서로 협력하여 동작한다.
한 객체가 다른 객체에 의존한다면, 이를 '의존성'이라고 한다.
의존성 주입은 이런 의존 관계를 외부에서 객체에 주입하는 방식을 의미.
객체가 자신이 필요로 하는 다른 객체를 직접 생성하지 않고, 외부에서 주입받는 것.
의존성 주입을 사용하면 객체 간의 결합도를 낮추고 유연한 코드를 작성할 수 있다.
데이터베이스 연결 객체를 주입받는 클래스는 어떤 데이터베이스를 사용할지를 외부에서 결정할 수 있고, 테스트 시에 모의 데이터베이스 객체를 주입하여 테스트하기도 쉬워진다.
예시코드
- 기존 방식
- DI를 사용하지 않는 경우, 의존하는 객체를 직접 생성.
public class AccountService {
private AccountRepository accountRepository = new AccountRepository();
public void deposit(int accountNumber, double amount) {
Account account = accountRepository.findAccountByNumber(accountNumber);
account.deposit(amount);
accountRepository.saveAccount(account);
}
}
- DI를 적용한 방식
- DI를 적용하여 객체 간의 의존성을 외부에서 주입.
public class AccountService {
private AccountRepository accountRepository;
// 의존성 주입을 통해 AccountRepository 객체를 주입받음
public AccountService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
public void deposit(int accountNumber, double amount) {
Account account = accountRepository.findAccountByNumber(accountNumber);
account.deposit(amount);
accountRepository.saveAccount(account);
}
}
- AccountRepository 객체를 외부에서 주입받아 사용.
- 계좌 서비스 클래스는 어떤 AccountRepository 구현체를 사용할지를 외부에서 결정할 수 있으며, 유연성이 높아진다.
3. IoC와 DI의 관계
제어의 역전과 의존성 주입은 밀접한 관련이 있습니다. IoC는 제어 흐름을 역전시키는 개념.
DI는 이를 실현하기 위한 방법 중 하나.
일반적으로 IoC 컨테이너를 사용할 때, 이 컨테이너가 DI를 활용하여 객체 간의 의존 관계를 관리한다.
개발자는 이 IoC 컨테이너에게 필요한 객체를 등록하고, IoC 컨테이너는 객체를 생성하고 필요한 의존성을 주입한다.
종합하면, IoC는 제어 흐름을 역전시키는 개념이고, DI는 이를 실현하기 위한 방법 중 하나로, 두 개념은 소프트웨어 개발에서 유연하고 확장 가능한 코드를 작성하는 데 도움을 준다.
IoC와 DI를 이해하고 활용하면 코드의 유지보수성과 테스트 용이성을 향상시킬 수 있다.
결론
IoC와 DI는 소프트웨어 개발에서 코드의 유지보수성, 확장성, 테스트 용이성을 높이는 데 도움을 주는 중요한 개념이다.
IoC 컨테이너를 사용하여 제어의 역전을 실현하고, DI를 통해 객체 간의 의존성을 외부에서 주입함으로써, 더 효과적인 개발을 할 수 있다.
'TIL(Today I Learned)' 카테고리의 다른 글
[TIL] JPA(Java Persistence API) (0) | 2023.11.13 |
---|---|
[TIL] IoC Container와 Bean (0) | 2023.11.10 |
[TIL] 3 Layer Architecture (0) | 2023.11.08 |
[TIL] 데이터 베이스 (0) | 2023.11.07 |
[TIL] Spring MVC (0) | 2023.11.06 |