반응형
스프링을 공부하다보면 제어의 역전에 대한 얘기가 많이 나온다. 이번 포스트에서 간단히 알아보자
제어의 역전(IoC, Inversion of Control)은 스프링 프레임워크를 이해하는데 핵심적인 개념이야. 그리고 이게 무엇인지, 왜 중요한지, 그리고 스프링에서 어떻게 구현되는지 쉽고 이해하기 좋은 방식으로 설명해줄게.
1. 제어의 역전(IoC)이란?
제어의 역전은 소프트웨어 엔지니어링에서 중요한 원칙 중 하나야. 이 원칙의 핵심은 프로그램의 흐름 제어를 사용자가 아닌 프레임워크가 담당한다는 것이지.
1-1. 기존의 프로그래밍 방식
- 사용자 중심의 흐름 제어
- 보통 프로그래밍에서는 개발자가 작성한 코드가 프로그램의 흐름을 제어한다. 메인 함수나 사용자 정의 함수들이 서로를 호출하며 로직을 수행한다.
- 보통 프로그래밍에서는 개발자가 작성한 코드가 프로그램의 흐름을 제어한다. 메인 함수나 사용자 정의 함수들이 서로를 호출하며 로직을 수행한다.
- 개발자가 모든 것을 관리
- 객체의 생성부터 소멸까지, 모든 것을 개발자가 직접 관리해야 한다.
- 객체의 생성부터 소멸까지, 모든 것을 개발자가 직접 관리해야 한다.
1-2. IoC의 접근 방식
- 프레임워크 중심의 흐름 제어
- IoC에서는 이런 흐름이 바뀌어서 프레임워크가 사용자의 코드를 적절한 시점에 호출해 준다.
- IoC에서는 이런 흐름이 바뀌어서 프레임워크가 사용자의 코드를 적절한 시점에 호출해 준다.
- 프레임워크가 관리
- 이로써 개발자는 비즈니스 로직에만 집중할 수 있고, 나머지(객체의 생명주기 관리, 의존성 관리 등)는 프레임워크가 담당하게 된다.
- 이로써 개발자는 비즈니스 로직에만 집중할 수 있고, 나머지(객체의 생명주기 관리, 의존성 관리 등)는 프레임워크가 담당하게 된다.
1-3. 스프링 프레임워크에서의 IoC
- IoC 컨테이너
- 스프링에서는 'IoC 컨테이너'를 통해 이 원칙을 구현한다. 이 컨테이너는 객체의 생성, 의존성 주입, 생명주기 관리 등을 담당하면서 프로그램의 흐름을 효율적으로 관리해 준다.
- 스프링에서는 'IoC 컨테이너'를 통해 이 원칙을 구현한다. 이 컨테이너는 객체의 생성, 의존성 주입, 생명주기 관리 등을 담당하면서 프로그램의 흐름을 효율적으로 관리해 준다.
1-4. IoC의 이점
- 모듈화와 재사용성 증가: 코드가 더 모듈화되고, 재사용하기 쉬워진다.
- 유연성 향상: 프레임워크에 의해 관리되기 때문에, 코드 변경이 용이해지고, 유지보수가 편리해진다.
2. 스프링에서의 IoC
스프링 프레임워크에서 IoC 컨테이너는 매우 중요한 역할을 한다. 이 컨테이너는 빈(Bean)의 생성, 초기화, 의존성 주입, 생명주기 관리 등을 수행하는데, 이 모든 것은 개발자 대신 프레임워크가 관리해 준다. 이제 이 과정을 코드로 살펴보자.
2-1. 서비스 인터페이스와 구현체 정의
- 먼저, 서비스 인터페이스 GreetingService와 이를 구현하는 GreetingServiceImpl 클래스를 정의한다.
- GreetingService 인터페이스는 간단한 greet 메소드를 정의하고 있고, GreetingServiceImpl 클래스는 이 인터페이스를 구현하여 "Hello, Spring IoC!"를 출력한다.
public interface GreetingService {
void greet();
}
@Component
public class GreetingServiceImpl implements GreetingService {
@Override
public void greet() {
System.out.println("Hello, Spring IoC!");
}
}
2-2. 컴포넌트에서 서비스 사용
- 다음으로, 이 서비스를 사용할 MyComponent 클래스를 정의한다.
@Component
public class MyComponent {
private final GreetingService greetingService;
@Autowired
public MyComponent(GreetingService greetingService) {
this.greetingService = greetingService;
}
public void execute() {
greetingService.greet(); // Output: Hello, Spring IoC!
}
}
- MyComponent 클래스는 GreetingService에 의존하고 있으며, 이 의존성은 생성자를 통해 스프링 IoC 컨테이너에 의해 주입된다 (@Autowired). 이 클래스의 execute 메소드가 호출될 때, 주입된 GreetingService의 greet 메소드를 실행한다.
2-3. IoC 컨테이너의 역할
- 이 예시에서, GreetingService의 구체적인 인스턴스를 생성하고 관리하는 일은 모두 스프링 IoC 컨테이너가 담당한다. 개발자는 단지 서비스의 인터페이스만 정의하고, 필요한 의존성을 선언하기만 하면 된다. 스프링 IoC 컨테이너는 이런 선언에 따라 자동으로 필요한 객체를 생성하고 연결해 준다. 이를 통해 코드의 결합도가 낮아지고, 다른 구현체로 쉽게 교체할 수 있게 된다. 또한, 개발자는 비즈니스 로직에 집중할 수 있으며, 코드의 유연성과 재사용성이 향상된다.
스프링의 IoC는 프로그래밍에서의 "제어의 역전"을 구현한 사례로, 개발자가 객체의 생명주기와 의존성 관리에서 벗어나게 해 주어, 보다 깔끔하고 유지보수가 쉬운 코드 작성을 가능하게 한다.
스프링 @Bean 어노테이션이 뭔지 궁금하다면?
반응형
'Spring 기초 > Spring 기초 지식' 카테고리의 다른 글
@ControllerAdvice, @RestControllerAdvice - 중앙집중 예외처리 (0) | 2023.08.07 |
---|---|
스프링의 핵심: Singleton 패턴 알아보기 (0) | 2023.08.07 |
[스프링, 스프링부트] Spring - 의존성 주입(DI - Dependency Injection) (0) | 2023.08.07 |
[스프링, 스프링부트] Spring Container (스프링 컨테이너) (0) | 2023.08.07 |
[스프링, 스프링부트] Spring - @Bean과 @Component (0) | 2023.07.20 |