반응형

IoC와 DI: 개념과 Spring Boot에서 의존성 주입 방법

1. IoC(Inversion of Control)란?

IoC(Inversion of Control, 제어의 역전)는 객체의 생성 및 흐름의 제어 권한을 개발자가 직접 관리하는 것이 아니라 프레임워크(Spring Container)가 관리하도록 하는 개념입니다. 이를 통해 결합도를 낮추고 유연한 애플리케이션을 설계할 수 있습니다.

2. DI(Dependency Injection)란?

DI(Dependency Injection, 의존성 주입)는 IoC를 구현하는 방식 중 하나로, 객체 간의 의존성을 직접 생성하는 것이 아니라 외부에서 주입하는 방식입니다. 이를 통해 코드의 유지보수성과 테스트 용이성이 향상됩니다.

Spring Boot에서는 다양한 방식으로 의존성을 주입할 수 있습니다. 주요 방식은 다음과 같습니다:

  1. 생성자 주입(Constructor Injection)
  2. 세터 주입(Setter Injection)
  3. 필드 주입(Field Injection)
  4. 인터페이스 기반 주입(Interface-based Injection)

3. Spring Boot에서 의존성 주입하는 4가지 방법

3.1 생성자 주입 (Constructor Injection)

가장 권장되는 방식으로, final 키워드를 활용할 수 있어 불변성을 유지할 수 있으며, 단위 테스트가 용이합니다.

import org.springframework.stereotype.Service;

@Service
public class UserService {
    private final UserRepository userRepository;

    // 생성자를 통한 의존성 주입
    public UserService(UserRepository userRepository) {
	    this.userRepository = userRepository;
    }

    public void createUser(String name) {
    	userRepository.save(new User(name));
    }
}
import org.springframework.stereotype.Repository;

@Repository
public class UserRepository {
    public void save(User user) {
	    System.out.println("User saved: " + user.getName());
    }
}

3.2 세터 주입 (Setter Injection)

객체를 생성한 후 setter 메서드를 통해 의존성을 주입하는 방식입니다. 선택적인 의존성을 주입할 때 유용하지만, 객체의 상태가 변경될 가능성이 있어 주의가 필요합니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
	    this.userRepository = userRepository;
    }

    public void createUser(String name) {
    	userRepository.save(new User(name));
    }
}

3.3 필드 주입 (Field Injection)

가장 간단한 방법이지만, 필드에 직접 @Autowired를 사용하면 의존성이 명확하게 보이지 않고, 테스트 시 객체의 변경이 어려울 수 있습니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public void createUser(String name) {
	    userRepository.save(new User(name));
    }
}

3.4 인터페이스 기반 주입 (Interface-based Injection)

DI 원칙을 더욱 철저하게 준수하기 위해 인터페이스를 활용하는 방식입니다. 다양한 구현체를 손쉽게 교체할 수 있어 확장성이 뛰어납니다.

import org.springframework.stereotype.Service;

@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
	    this.userRepository = userRepository;
    }

    public void createUser(String name) {
    	userRepository.save(new User(name));
    }
}
public interface UserRepository {
	void save(User user);
}
import org.springframework.stereotype.Repository;

@Repository
public class UserRepositoryImpl implements UserRepository {
    @Override
    public void save(User user) {
	    System.out.println("User saved: " + user.getName());
    }
}

4. 의존성 주입 방식 비교

방식 장점 단점
생성자 주입 불변성 유지, 테스트 용이 순환 참조 발생 가능
세터 주입 선택적 의존성 주입 가능 불변성이 깨질 위험
필드 주입 코드가 간결 테스트 및 유지보수 어려움
인터페이스 기반 주입 유연성과 확장성 증가 초기 설계가 복잡할 수 있음

 


5. 결론

Spring Boot에서는 다양한 방식으로 의존성을 주입할 수 있으며, 상황에 맞게 적절한 방식을 선택해야 합니다. 일반적으로 생성자 주입이 가장 권장되며, 필요에 따라 세터 주입이나 인터페이스 기반 주입을 활용할 수 있습니다. 필드 주입은 유지보수성과 테스트 용이성 측면에서 권장되지 않습니다.

IoC와 DI를 올바르게 활용하면 결합도를 낮추고 확장성이 높은 애플리케이션을 만들 수 있습니다.

뭔가 쓰는 중…

반응형

+ Recent posts