IOC 보충자료

IoC(Inversion of Control, 제어의 역전)

1. IoC란 무엇인가?

IoC(Inversion of Control, 제어의 역전)는 프로그램의 흐름을 제어하는 주체를 개발자가 아닌 외부 프레임워크나 컨테이너에 위임하는 설계 원칙입니다. 객체가 의존성을 직접 관리하지 않고 외부에서 주입받아 사용하는 방식을 통해 유연성과 확장성을 높이는 데 목적이 있습니다.


2. IoC의 주요 개념

전통적인 객체 생성 방식

  • 객체가 필요한 의존 객체를 직접 생성합니다.

  • 예: Car 클래스 내부에서 Engine 객체를 직접 생성하여 사용.

    public class Car {
        private Engine engine;
        
        public Car() {
            this.engine = new Engine(); // 직접 생성
        }
    }

IoC 방식

  • 의존 객체의 생성 및 관리 책임을 외부 컨테이너가 담당합니다.

  • 객체는 필요한 의존성을 외부로부터 주입받아 사용합니다.

    public class Car {
        private Engine engine;
    
        public Car(Engine engine) { // 의존성 주입
            this.engine = engine;
        }
    }

3. IoC의 장점

  1. 유연성 증가

    • 객체 간의 결합도를 낮추고, 코드 변경 없이도 다른 구현체로 쉽게 교체 가능.

  2. 테스트 용이성

    • 의존성을 외부에서 주입받으므로, 테스트 시 Mock 객체를 쉽게 주입 가능.

  3. 재사용성 향상

    • 객체의 생성 및 관리 책임이 분리되므로 객체 자체는 독립적으로 설계 가능.

  4. 유지보수 용이

    • 객체 간의 의존 관계를 한 곳에서 관리하므로, 유지보수가 쉽고 오류 발생 가능성을 줄임.


4. IoC의 실제 구현 방식

의존성 주입(Dependency Injection)

IoC의 가장 일반적인 구현 방법으로, 외부에서 객체의 의존성을 주입받는 방식입니다.

1. 생성자 주입(Constructor Injection)

  • 생성자를 통해 의존성을 주입받는 방식.

  • 장점: 의존성이 명확하고 불변성을 보장.

    public class Car {
        private final Engine engine;
    
        public Car(Engine engine) { // 의존성 주입
            this.engine = engine;
        }
    }

2. 세터 주입(Setter Injection)

  • 세터 메서드를 통해 의존성을 주입받는 방식.

  • 장점: 선택적인 의존성 주입 가능.

    public class Car {
        private Engine engine;
    
        public void setEngine(Engine engine) {
            this.engine = engine;
        }
    }

3. 필드 주입(Field Injection)

  • 필드에 직접 의존성을 주입받는 방식.

  • 단점: 테스트 시 Mock 객체 주입이 어려움.

    public class Car {
        @Autowired
        private Engine engine;
    }

5. IoC 컨테이너의 역할

IoC 컨테이너는 객체의 생명 주기와 의존성을 관리하는 역할을 합니다. 대표적인 예는 스프링 컨테이너입니다.

주요 기능

  1. 빈 관리

    • 컨테이너에 등록된 객체(빈)의 생성, 초기화, 소멸 관리.

  2. 의존성 주입

    • 객체 간의 의존성을 컨테이너에서 주입.

  3. 설정 관리

    • XML, Java Config, 어노테이션을 통해 객체 설정.

스프링 컨테이너 예제

@Configuration
public class AppConfig {
    @Bean
    public Engine engine() {
        return new Engine();
    }

    @Bean
    public Car car(Engine engine) {
        return new Car(engine); // 의존성 주입
    }
}

6. IoC 적용의 사례

스프링 프레임워크

  • 스프링은 IoC 컨테이너를 통해 객체의 생성과 의존성 주입을 관리합니다.

  • 개발자는 빈 설정만 정의하고, 객체 생성과 관리는 스프링 컨테이너가 처리합니다.

@Component
public class Engine {
}

@Component
public class Car {
    private final Engine engine;

    @Autowired
    public Car(Engine engine) { // 의존성 주입
        this.engine = engine;
    }
}

실행 시

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class); // 스프링이 객체 생성 및 주입

7. IoC의 핵심 목표

IoC는 객체 간의 결합도를 줄이고, 코드의 유연성과 재사용성을 극대화하는 데 있습니다. 개발자는 객체의 생성 및 의존성 관리에서 벗어나, 객체의 본래 역할에만 집중할 수 있습니다.

Last updated