제어의 역전과 의존성 주입 (IOC 와 DI)

현정재·2024년 7월 13일
1
post-thumbnail

IOC(Inversion of Control)

IOC(Inversion of Control)이란 제어의 역전이라는 개념으로, 객체의 생성과 생명주기의 제어 권한을 개발자가 아닌 프레임워크가 가지는 것을 말한다.

DI는 IOC의 한 예이다.

IOC(Inversion of Control): 제어의 역전이라는 개념으로, 객체의 생성과 생명주기의 제어 권한을 개발자가 아닌 프레임워크가 가지는 것을 말한다. 이를 통해 코드의 결합도를 낮추고, 객체 간의 의존성을 줄일 수 있다.

IOC의 작동 방식

  1. 객체 생성의 제어권 역전: 일반적으로 객체는 개발자가 직접 생성하고 제어하지만, IOC에서는 프레임워크가 대신 객체를 생성하고 관리한다.
  2. 의존성 주입: 객체가 필요로 하는 의존성을 프레임워크가 주입해준다.
  3. 생명주기 관리: 객체의 생성, 초기화, 소멸 등의 생명주기를 프레임워크가 관리한다.

IOC의 예시

IOC 컨테이너: 스프링의 IOC 컨테이너는 Bean을 생성하고 주입하는 역할을 담당한다. 이는 개발자가 객체의 생성과 관리를 직접 하지 않고, 프레임워크가 이를 대신 수행하게 함으로써 제어권이 역전되는 것을 의미한다.

// 서비스 클래스
public class UserService {
    private UserRepository userRepository;

    // 생성자 주입
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // 비즈니스 로직
    public void createUser(User user) {
        userRepository.save(user);
    }
}

// 설정 파일 (Java 기반)
@Configuration
public class AppConfig {
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }

    @Bean
    public UserService userService() {
        return new UserService(userRepository());
    }
}

UserService 클래스: 
UserServiceUserRepository 객체를 필요로 한다. 
여기서 UserServiceUserRepository를 직접 생성하지 않고, 생성자를 통해 주입받는다.

AppConfig 클래스: 
자바 기반의 설정 파일로, @Configuration 애노테이션을 통해 설정 클래스로 지정된다. 
@Bean 애노테이션을 사용하여 스프링 컨테이너가 관리할 객체들을 정의한다.

userRepository 메서드: 
UserRepository 객체를 생성하여 반환한다.

userService 메서드: 
UserService 객체를 생성하고, userRepository 메서드를 호출하여 
생성된 UserRepository 객체를 주입한다.


IOC의 작동 과정:
스프링 컨테이너는 AppConfig 클래스를 읽어 @Bean 애노테이션이 붙은 메서드를 호출하여 
UserRepositoryUserService 객체를 생성한다.

UserService 객체를 생성할 때 UserRepository 객체가 필요하므로, 
userRepository 메서드를 호출하여 생성된 객체를 주입한다.

이렇게 생성된 UserService 객체는 스프링 컨테이너에 의해 관리되며, 필요한 곳에 주입될 수 있다.

이와 같이 IOC를 통해 스프링 컨테이너가 객체를 생성하고 주입함으로써 
제어권이 개발자에서 프레임워크로 역전된다. 이를 통해 코드의 결합도를 낮추고 유연성을 높일 수 있다.

이와 같이 IOC를 통해 스프링 컨테이너가 객체를 생성하고 주입함으로써 제어권이 개발자에서 프레임워크로 역전된다. 이를 통해 코드의 결합도를 낮추고 유연성을 높일 수 있다.

DI(Dependency Injection)

의존성 주입(Dependency Injection)이란 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, 객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식이다. DI(의존성 주입)을 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.

첫 번째 그림

객체1이 A와 B 객체를 New 생성자를 통해서 직접 생성하는 방법이다.

두 번째 그림

객체2에서는 외부에서 생성된 객체를 생성자 또는 setter()를 통해 사용하는 방법이다. 이는 의존성 주입의 예시로, 객체2가 A, B 객체를 사용할 때 직접 생성하지 않고 외부(IOC 컨테이너)에서 생성된 A, B 객체를 주입받아 사용하는 방식이다.

세 번째 그림

세 번째 그림에서는 스프링의 의존성 주입을 좀 더 구체적으로 보여준다. 스프링에서는 객체를 Bean이라고 부르며, 프로젝트가 실행될 때 사용자가 Bean으로 관리하는 객체들의 생성과 소멸에 관련된 작업을 자동적으로 수행해주는 데, 이 객체가 생성되는 곳을 스프링에서는 Bean 컨테이너라고 부른다.

스프링의 Bean 컨테이너는 두 번째 그림에서 보인 것처럼 객체를 직접 생성하지 않고, 외부에서 생성된 객체들을 관리하고, 필요한 곳에 주입해준다. 예를 들어, 두 번째 그림의 객체2가 A객체와 B객체를 필요로 할 때, 스프링의 IOC 컨테이너는 A객체와 B객체를 생성하고, 이를 객체2에 주입해준다. 이렇게 함으로써 객체2는 A객체와 B객체의 생성 및 라이프사이클을 관리할 필요 없이, 스프링 컨테이너가 이를 대신 관리해준다.


보충 설명

의존성 주입(Dependency Injection, DI): 객체가 다른 객체를 필요로 할 때, 필요한 객체를 직접 생성하는 것이 아니라 외부에서 주입해주는 방식이다. 이를 통해 코드의 재사용성과 테스트 용이성이 향상된다. DI에는 크게 세 가지 방식이 있다:

  1. 생성자 주입 (Constructor Injection): 생성자를 통해 필요한 의존성을 주입받는다.
  2. 세터 주입 (Setter Injection): 세터 메서드를 통해 필요한 의존성을 주입받는다.
  3. 필드 주입 (Field Injection): 필드에 직접 주입하는 방식이다. (권장되지 않음)

IOC (Inversion of Control): 제어의 역전이라는 개념으로, 객체의 생성과 생명주기의 제어 권한을 개발자가 아닌 프레임워크가 가지는 것을 말한다. DI는 IOC의 한 예이다.

Bean: 스프링이 관리하는 객체를 의미하며, 스프링 컨테이너에 의해 생성되고 소멸된다. 스프링 컨테이너는 빈의 생성, 초기화, 주입, 소멸을 관리한다.

스프링 컨테이너: 스프링 애플리케이션에서 객체를 관리하고 DI를 통해 객체 간의 의존성을 설정해주는 컨테이너이다. 스프링 컨테이너는 빈 설정 파일이나 애노테이션 기반 설정을 통해 빈을 정의하고 관리한다.

profile
wonttock

0개의 댓글