제어의 역전(Inversion of Control, Ioc)
는 소프트웨어 엔지니어링에서 매우 중요한 개념입니다.
이 시간에는 함께 제어의 역전이 무엇을 의미하는지 알아보도록 하겠습니다.
편의상 예제 코드는 Java
를 사용하도록 하겠습니다!
제어의 역전 IoC(Inversion of Control)
전통적인 동작 방식
class TraditionalService {
private Dependency dependency;
public TraditionalService() {
this.dependency = new Dependency();
}
public void doSomething() {
dependency.performAction();
}
}
class Dependency {
public void performAction() {
// 비즈니스 로직
}
}
기존의 전통적인 방식에서는, 객체를 직접 생성하고 관리하였습니다.
웹 서버에서도 마찬가지로, 클라이언트 구현 객체가 스스로 필요한 서버 구현 객체의 생성, 연결, 실행을 모두 담당하였습니다. 한마디로 프로그램의 제어 흐름을 프로그램 그 자체가 주도권을 가지고 실행되었습니다.
위 코드에서도 마찬가지로 TraditionalService
가 객체를 직접 생성하고 의존성을 사용합니다.
IoC의 동작 방식
class IocService {
private Dependency dependency;
public IocService(Dependency dependency) {
this.dependency = dependency;
}
public void doSomething() {
dependency.performAction();
}
}
class IocContainer {
public static void main(String[] args) {
Dependency dependency = new Dependency();
IocService service = new IocService(dependency);
service.doSomething();
}
}
하지만 위 코드에서는 동작 방식이 전혀 다릅니다.
IocContainer
에서 의존성을 생성하고, IocService
에 주입합니다.
그리고 생성자를 통해 의존성을 주입받은 서비스 클래스가 비즈니스 로직을 수행합니다.
즉, IocService 는 자신의 로직을 실행하는 역할만 담당합니다. 프로그램에 대한 제어의 흐름은 IocContainer 가 관리합니다.
이렇듯 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 제어의 역전이라고 합니다.
이렇게 되면 객체의 생성과 의존성을 외부에서 관리하므로 코드는 더 깔끔하고 유지 보수가 쉬워집니다.
또 컴포넌트를 교체하는 형태로 프로그램을 업데이트할 수 있기 때문에 확장성과 유연성이 증가합니다.
IoC의 장점
@Service
class Service {
private final Repository repository;
@Autowired
public Service(Repository repository) {
this.repository = repository;
}
public void perfromAction() {
repository.saveData();
}
}
@Repository
class Repository {
public void saveData() {
// 데이터 저장
}
}
낮은 결합도
Service
클래스는 Repository
클래스의 구체적인 구현에 대해 알 필요가 없습니다. 이를 통해 Repository 의 구현이 변경되어도 Service 클래스에는 영향을 주지 않죠.
테스트하기 좋은 코드
의존성 주입을 통해 Service 클래스를 테스트할 때, 실제 객체 대신 Mock
객체를 사용하고 Stub
을 사용해서 테스트 코드를 작성할 수 있습니다. 이렇게 하면 데이터베이스와 같은 외부 시스템에 의존하지 않고 Service 클래스를 독립적으로 테스트할 수 있습니다.
코드 재사용성 및 유지보수 용이성
Repository 와 같은 클래스는 다른 서비스에서도 재사용될 수 있습니다. 각 서비스는 필요한 의존성만 주입받아 사용하면 되므로 코드의 재사용성이 높아집니다.
유지 보수에 용이해집니다. 예를 들어 Repository 클래스의 로직이 어떤 데이터베이스에 저장하냐에 따라 다르다고 하더라고, 이를 사용하는 서비스 코드를 바꿀 필요가 없기 때문에 유지 보수하기 좋아집니다.
이처럼 IoC는 객체의 생성과 관리를 외부에 위임하여 이러한 장점들을 제공할 수 있기 때문에, 특히 대규모 어플리케이션의 개발과 유지 보수에 도움이 되는 장점입니다.
IoC의 단점
이러한 IoC를 구현하기 위해 많은 프레임워크
가 도움을 줍니다. 자바에서는 예를 들어 Spring Framework
가 있겠죠?
저희는 이 스프링 프레임워크를 효율적으로 다룰 수 있도록 자바 언어를 공부했을 때만큼 혹은 그 이상으로 스프링을 공부하기도 합니다. 이런 식으로 초기 학습 곡선을 가파르게 하는 단점 또한 지니고 있습니다.
또한 IoC를 구현하는 데에 있어서 추가적인 처리가 필요하기도 합니다. 이는 성능 저하를 일으킬 수 있는 요인입니다.
프레임워크 VS 라이브러리
위에서 본 IoC는 프레임워크 와 라이브러리 를 구분하기 좋은 기준입니다.
프레임워크와 라이브러리는 모두 소프트웨어 개발을 돕는 도구들이지만, 프레임워크를 사용하게 되면 그 프레임워크에 종속되어 유연성이 제한될 수 있습니다.
즉, 실행 흐름을 제어하고 대신 실행하는 제어의 역전이 발생하는 것은 프레임워크라고 할 수 있습니다.
반대로 실행 흐름을 제어하는 제어권이 나에게 있다면 그것은 프레임워크가 아니라 라이브러리라고 할 수 있겠습니다.
보통 라이브러리를 사용한다고 그 라이브러리를 전부 사용하거나 이해할 필요 없이 부분적으로 사용하게 되니까요!
제어의 역전은 오늘날 많은 프레임워크가 지원하는 개념입니다. 대표적으로 위에서 예시를 든 스프링이나 레일즈 등이 있겠죠? 이러한 제어의 역전을 잘 이해하고 왜 우리가 프레임워크를 사용하는지 아는 데 도움이 되었길 바랍니다.
오늘은 의존성 주입 (Dependency Injection)
에 대해서도 가볍게 다루어 보았는데요, 다음 글에서는 DI에 대해 작성해 보도록 하겠습니다 😊
'Computer Science > 프로그래밍 이론 💬' 카테고리의 다른 글
일급 컬렉션이란? (0) | 2024.02.07 |
---|---|
비동기 프로그래밍 (0) | 2024.02.06 |
Dependency Injection이란? (0) | 2024.02.06 |
객체지향 프로그래밍이란? (0) | 2024.02.02 |
안녕하세요, 저는 주니어 개발자 박석희 입니다. 언제든 하단 연락처로 연락주세요 😆