DI(의존관계 주입) / 스프링 컨테이너

DI(의존관계 주입)는 애플리케이션 실행 시점에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달하는 과정을 의미합니다. 이를 통해 클라이언트와 서버의 실제 의존관계가 연결됩니다.

IoC 컨테이너, DI 컨테이너

IoC(Inversion of Control) 컨테이너는 객체의 생성과 관리를 담당합니다. AppConfig와 같은 클래스가 이 역할을 수행합니다.

@Bean 어노테이션

@Bean 어노테이션은 스프링 컨테이너에 의해 관리될 객체를 선언할 때 사용됩니다. 예를 들어:

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

ApplicationContext를 사용하여 스프링 컨테이너에 접근하고 빈을 가져올 수 있습니다.

스프링 컨테이너

스프링 컨테이너는 ApplicationContext로 표현됩니다. AppConfig와 같은 설정 클래스에서 @Bean으로 등록된 메서드들을 호출하여 객체를 생성하고 관리합니다.

public class Main {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
    }
}

그럼 왜 IoC와 DI가 졸을까?

IoC(Inversion of Control)와 DI(의존관계 주입)의 장점

IoC(Inversion of Control)

1. 코드의 분리 및 관리 용이성

  • IoC는 객체의 생성과 의존성 관리를 외부(컨테이너)에 맡깁니다. 이로 인해 개발자는 객체 간의 연결, 생명주기 관리에 대한 부담 없이 비즈니스 로직에만 집중할 수 있습니다.

2. 재사용성 및 확장성 향상

  • IoC를 통해 생성된 객체들은 재사용이 용이하며, 새로운 객체를 추가하거나 변경하는 것이 간편해집니다. 이는 애플리케이션의 확장성을 크게 향상시킵니다.

3. 테스트 용이성

  • 외부에서 객체를 주입받기 때문에, 테스트 환경에서 모의 객체(Mock)를 사용하는 등의 테스트가 용이해집니다. 이는 유닛 테스트의 효율성을 높여 줍니다.

DI(의존관계 주입)

1. 결합도 감소

  • DI를 사용하면 클래스 간의 결합도가 낮아집니다. 클래스가 직접적으로 의존 객체를 생성하지 않고, 외부에서 주입받기 때문에 코드 수정 없이 의존 객체를 교체할 수 있습니다.

2. 유연한 코드

  • 의존성이 외부에서 주입되기 때문에, 상황에 따라 다른 객체를 주입할 수 있어 코드가 더 유연해집니다. 이는 코드의 재사용성을 높이고 유지보수를 용이하게 합니다.

3. 구성의 중앙화

  • 의존성이 한 곳(AppConfig와 같은 설정 클래스)에서 관리되므로, 애플리케이션 구성을 쉽게 파악하고 변경할 수 있습니다.

IoC와 DI를 사용함으로써, 코드는 더욱 모듈화되고 테스트, 유지보수가 용이해집니다. 또한, 애플리케이션의 확장성과 유연성이 향상되며, 개발자는 비즈니스 로직에 더 집중할 수 있게 됩니다.