[Day 24 | Spring] IoC Container (제어의 역전)

y♡ding·2024년 11월 14일
0

데브코스 TIL

목록 보기
153/163

1. IoC (Inversion of Control)란?

  • 제어의 역전(IoC)은 객체의 생성과 생명 주기를 개발자가 아닌 프레임워크가 관리하도록 제어를 넘겨주는 개념입니다. 이는 객체가 자신이 사용할 의존 객체를 직접 생성하거나 관리하지 않고, 외부에서 주입받도록 하여 객체 간 결합도를 낮추는 방식입니다. IoC를 통해 코드 재사용성 및 유지보수성을 높일 수 있으며, 테스트 환경에서도 Mocking이 수월해집니다.

IoC의 주요 개념

  • 객체의 생성 및 주입을 프레임워크에 위임: 객체는 필요한 다른 객체를 스스로 생성하지 않고, 외부에서 주입받습니다.
  • 결합도 낮추기: 각 객체는 독립적으로 존재하며, 다른 객체에 직접적인 의존을 피하게 되어 변경에 유연해집니다.
  • 유연한 확장성: 객체 간 결합도가 낮아 다른 객체를 쉽게 교체하거나 확장할 수 있습니다.

IoC의 대표적인 구현 방식으로는 DI(Dependency Injection)과 서비스 로케이터 패턴이 있습니다. 스프링은 주로 DI 방식을 사용하여 IoC를 구현합니다.

2. IoC Container란?

IoC 컨테이너는 IoC 개념을 구현하는 스프링의 핵심 컴포넌트로, 객체(빈, Bean)의 생성, 관리, 의존성 주입을 담당하는 객체 생성 및 관리의 중심입니다. IoC 컨테이너는 애플리케이션이 실행되는 동안 빈을 등록하고 필요한 의존성을 주입해 주므로, 개발자는 객체의 생명 주기를 신경 쓰지 않아도 됩니다.

IoC 컨테이너의 주요 역할

  • 빈 생성 및 초기화: 애플리케이션 실행 시 컨테이너가 빈을 생성하고 초기화합니다.
  • 의존성 주입 관리: DI를 통해 필요한 객체 간의 의존성을 자동으로 주입합니다.
  • 빈의 생명 주기 관리: 빈의 생성부터 소멸까지 생명 주기를 관리하여 효율적인 자원 사용을 돕습니다.

IoC 컨테이너는 두 가지로 나눌 수 있습니다:

  • BeanFactory: 스프링에서 가장 기본적인 IoC 컨테이너로, 지연 로딩(lazy loading)을 통해 빈을 필요할 때 생성합니다.
  • ApplicationContext: BeanFactory를 확장한 형태로, 애플리케이션 전체적인 컨텍스트를 관리하며, 지연 로딩뿐만 아니라 이벤트 전파와 국제화(i18n) 등을 지원합니다. 실제 개발에서는 대부분 ApplicationContext를 사용합니다.
graph TD
    subgraph 기존 제어
        A[객체 A]
        B[객체 B]
        A --> B
    end
    subgraph 제어의 역전 IoC
        C[IoC 컨테이너]
        C -->|의존성 주입| A2[객체 A]
        C --> B2[객체 B]
        A2 -->|참조| B2
    end

3. IoC 컨테이너 사용 예제

간단한 DI와 IoC 컨테이너 예제를 통해 이해해 보겠습니다.

예제: 기본적인 의존성 주입과 IoC 컨테이너 활용

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

// Dependency class
@Component
public class DependencyClass {
    public void serve() {
        System.out.println("DependencyClass: Service is being provided.");
    }
}

// Main Service class
@Component
public class MainService {
    private final DependencyClass dependency;

    @Autowired  // Dependency Injection
    public MainService(DependencyClass dependency) {
        this.dependency = dependency;
    }

    public void performService() {
        dependency.serve();
    }
}

// Configuration and usage
public class IoCExample {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("your.package.name");

        MainService mainService = context.getBean(MainService.class);
        mainService.performService();
    }
}
  • 이 예제에서 ApplicationContext가 IoC 컨테이너 역할을 하여 MainServiceDependencyClass 객체를 생성하고, 의존성을 주입합니다.
  • MainServiceDependencyClass에 의존하지만, 이를 스스로 생성하지 않고 IoC 컨테이너가 관리하여 객체 간 결합도가 낮아집니다.

4. IoC의 장점과 주의사항

장점

  • 유연성과 확장성: 객체 간의 결합도가 낮아져 애플리케이션을 쉽게 확장하거나 변경할 수 있습니다.
  • 테스트 용이성: Mocking을 통해 독립적인 테스트가 가능하여 유닛 테스트 작성이 쉬워집니다.
  • 관리 효율성: 빈의 생명 주기와 의존성을 프레임워크가 관리하므로 개발자의 부담이 줄어듭니다.

주의사항

  • 초기 설정의 복잡성: 의존성 주입 설정이 많은 경우, 빈 설정이 복잡해질 수 있습니다.
  • 성능: ApplicationContext를 사용할 때 미리 빈을 초기화하므로 애플리케이션 시작 시 성능에 약간의 영향을 줄 수 있습니다.

관련 자료

0개의 댓글

관련 채용 정보