[기술 면접] Spring IoC (Inversion of Control)와 DI (Dependency Injection)에 대하여

송진영·2023년 8월 12일
0

기술면접

목록 보기
10/24

개요

Spring을 사용하며 IoCDI라는 말을 굉장히 많이 들어봤고, 그것을 활용한다는 말을 굉장히 많이 들어왔는데 IoC와 DI가 정확히 무엇이고, 어떤 식으로 활용되는지는 자세히 알지 못한다. 오늘은 그것에 대해서 알아볼 것이다.

IoC (Inversion of Control)란?

IoC는 말 그대로 제어의 역전을 의미하며, 전통적인 프로그래밍에서는 개발자가 프로그램의 흐름과 제어를 직접 다루는 반면, IoC는 프레임워크가 객체의 생성, 관리, 제어 흐름을 담당하도록 변경하는 개념이다. Spring은 이를 지원하기 위해 ApplicationContext라는 컨테이너를 제공한다.

ApplicationContext는 애플리케이션의 컴포넌트를 생성하고 조립하며, 객체의 라이프사이클을 관리한다.

과정

1. 객체의 생성 및 관리:

  • ApplicationContext를 사용하여 빈(Bean)을 생성하고, 관리한다.
  • 빈은 일반적으로 Spring이 제어하며, 개발자는 객체의 생성과 관리를 직접 처리하지 않는다.

2. 의존성 관리:

  • 객체 간의 의존성을 Spring이 주입(DI)한다.
  • 객체가 필요로 하는 다른 객체를 직접 생성하거나 찾는 대신, Spring 컨테이너가 의존성을 주입해주다.

3. 제어 흐름의 역전:

  • 개발자가 코드의 제어 흐름을 결정하지 않고, 프레임워크가 객체의 라이프사이클 및 실행 흐름을 관리한다.

DI (Dependency Injection)란?

DI는 객체 간의 의존성을 프레임워크가 주입하는 개념이다. 객체가 직접 의존하는 객체를 생성하거나 참조하는 대신, 이러한 의존성을 외부에서 주입받도록 한다. Spring은 다양한 방법으로 DI를 지원한다.

DI를 사용하지 않은 경우

public class UserService {
    private UserRepository userRepository;

    public UserService() {
        this.userRepository = new UserRepository(); // 직접 생성
    }
    
    // ...
}

위의 코드에서는 'UserService'는 직접적으로 'UserRepository'를 생성하고 의존하고 있다. 이로 인해서 'UserService'와 'UserRepository' 간에 강한 결합이 형성되어 있다. 이런 경우 유지 보수성이 떨어지며, 코드 변경 시 여러 클랠스에 영향을 줄 수 있다.

DI를 사용한 경우

  • 1. Constructor Injection: 생성자를 통해 의존성을 주입하는 방식이다. 클래스의 생성자를 정의하고, 의존하는 객체를 매개변수로 받아 필드에 할당한다.
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    // ...
}
  • 2. Setter Injection: Setter 메서드를 통해 의존성을 주입하는 방식이다. Setter 메서드를 정의하고, 해당 메서드를 통해 의존하는 객체를 주입한다.
public class OrderService {
    private PaymentGateway paymentGateway;

    @Autowired
    public void setPaymentGateway(PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }
    
    // ...
}
  • 3. Field Injection: 필드에 직접 의존성을 주입하는 방식이다. 주로 '@Autowired' 어노테이션을 사용하여 필드에 의존성을 주입한다.
@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;
    
    // ...
}
  • 4. Method Injection: 메서드의 매개변수로 의존성을 주입하는 방식이다.
@Component
public class ReportGenerator {
    private EmailService emailService;

    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }
    
    public void generateReport() {
        // Use the emailService here...
    }
}
  • 5. @Qualifier 어노테이션 사용 (빈의 특정 구현체 주입): 같은 타입의 여러 빈 중에서 어떤 빈을 주입할지 선택할 때 사용
public class OrderService {
    private PaymentGateway paymentGateway;

    @Autowired
    public OrderService(@Qualifier("creditCardGateway") PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }
    
    // ...
}
  • 6. XML 설정을 통한 의존성 주입: XML 파일을 사용하여 의존성 주입을 정의할 수 있다.
<bean id="userService" class="com.example.UserService">
    <constructor-arg ref="userRepository" />
</bean>

<bean id="userRepository" class="com.example.UserRepository" />
  • 7. Java Config: Java 설정 클래스를 사용하여 의존성 주입을 정의할 수 있다.
@Configuration
public class AppConfig {
    @Bean
    public UserService userService(UserRepository userRepository) {
        return new UserService(userRepository);
    }
    
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
}

정리

Spring의 IoC와 DI는 코드의 모듈화, 테스트 용이성, 유지보수성 등을 향상시키는 중요한 원리로서, Spring의 핵심 기능 중 하나로, 우리가 Spring으로 프로젝트를 구현하기 위해 항상 사용하던 것들이었다.

profile
못하는 건 없다. 단지 그만큼 노력을 안 할 뿐이다.

0개의 댓글