Spring의 IoC (제어의 역전) & Bean 관리 정리

민준·2025년 3월 14일
post-thumbnail

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

객체의 생성과 주입을 Spring이 대신 담당하는 개념

  • 객체가 필요할때 개발자가 직접 생성(new)로 생성하여 사용할것인가?
  • 아니면 어떤 주체가, 객체가 필요할때 객체를 대신 생성하여 필요한곳에 주입해줄것인가?

기존 방식 vs IoC 방식

기존 방식 (개발자가 직접 객체 생성)IoC 방식 (Spring이 객체 생성 & 주입)
개발자가 new 키워드로 직접 객체 생성Spring이 대신 객체를 생성하고 주입
객체 관리가 어려움객체 관리를 Spring이 자동으로 수행
테스트 시 Mock 주입이 어려움테스트 시 Mock 객체 주입 가능

2. IoC 5가지 구현 방법

IoC 구현 방법설명
Template Pattern상속을 통해 일부 로직을 미리 구현
Delegate (위임)실행을 다른 객체에 위임
Event이벤트를 발생시키고 리스너가 처리
Service Locator개발자가 직접 Locator에서 Bean을 가져와 사용
DI (Dependency Injection)Spring이 Bean을 대신 주입 (Spring이 사용하는 방식!)

3. Service Locator vs DI 비교

Service Locator (개발자가 직접 Bean 가져옴) - 예전방식

public class UserController {
    private final UserService userService;

    public UserController() {
        this.userService = ServiceLocator.getUserService(); // 직접 가져옴
    }
}
  • 의존성 파악 불가능
  • 테스트 시 Mock 주입 어려움

DI (Spring이 Bean 주입)

@Service
@RequiredArgsConstructor
public class UserController {
    private final UserService userService; // Spring이 자동 주입
}
  • Spring이 생성자 주입을 통해 객체를 주입
  • 의존성 파악 가능
  • 테스트 시 Mock 주입 가능

4. Spring Bean 관리

Bean이란?

Spring이 관리하는 객체 (싱글톤으로 관리됨)


Bean 등록 방법

방법설명
@ComponentScan + @Component특정 패키지 내 자동 Bean 등록
@Controller, @Service, @RepositorySpring이 자동으로 Bean 등록
@Configuration + @Bean직접 Bean을 등록

Bean 사용 방법

Bean 사용 방식설명
구체 클래스 사용UserService userService 직접 사용
부모 클래스 사용ServiceInterface userService 인터페이스 활용
Collection 사용여러 개의 Bean을 리스트로 주입

5. Spring Bean 주입 방법 (DI)

1. 생성자 주입 (Spring 공식 추천)

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository; // final 필드 자동 주입
}
  • 순환 참조 방지 가능
  • Bean 불변성 (final 필드 사용 가능)
  • 테스트 시 Mock 주입 용이

2. 필드 주입 (권장 X)

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository; // 필드 직접 주입
}
  • 테스트 시 Mock 객체 주입 어려움
  • 순환 참조 문제 발생 가능

3. 수정자 주입 (Setter Injection)

@Service
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository; // Setter를 통한 주입
    }
}
  • 필요한 경우만 의존성 변경 가능
  • 객체가 불변하지 않음 (final 사용 불가)

0개의 댓글