2025-05-12

스프링 내부 구조 정리

SpringIoCAOPDIBean

스프링 내부 구조 정리

스프링의 핵심 내부 구조를 실제 코드와 테스트를 통해 정리합니다.


1. IoC 컨테이너

스프링의 자동 Bean 등록 메커니즘을 실제로 테스트한 내용입니다.

@Component
public class HelloService {
    public String hello() {
        return "Hello, Spring!";
    }
}

테스트 코드:

@SpringBootTest
class IocTest {
 
    @Autowired
    ApplicationContext context;
 
    @Test
    void testGetBean() {
        HelloService helloService = context.getBean(HelloService.class);
        System.out.println(helloService.sayHello());
    }
}

실행 결과: Hello from Bean!

@Component 애노테이션만으로 스프링은 해당 클래스를 Bean으로 등록하여 ApplicationContext가 관리하게 됩니다. ApplicationContext.getBean()으로 직접 객체를 검색할 수 있으며, 의존성도 자동으로 주입됩니다.

@Component 제거 시:

public class HelloService {
    public String sayHello() {
        return "Hello again!";
    }
}

결과: NoSuchBeanDefinitionException: No qualifying bean of type 'HelloService' available


2. Bean 생명주기

Bean의 생성과 소멸 시점을 추적하기 위해 @PostConstruct@PreDestroy를 사용합니다.

@Component
public class LifeCycleBean {
 
    @PostConstruct
    public void init() {
        System.out.println("Bean 초기화 완료");
    }
 
    @PreDestroy
    public void destroy() {
        System.out.println("Bean 소멸 전 처리");
    }
}

실행 로그:

Bean 초기화 완료
(앱 종료 시)
Bean 소멸 전 처리
  • @PostConstruct: 의존성 주입 후 초기화 시점에 호출
  • @PreDestroy: 애플리케이션 종료 직전에 호출 (단, singleton 범위에만 적용)

3. AOP

메서드 실행 전후 처리를 선언적으로 구현합니다.

@Aspect
@Component
public class LogAspect {
 
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore() {
        System.out.println("메서드 실행 전 로그 출력");
    }
}

실제 Bean은 "프록시 객체"이며, 프록시가 중간에 가로채서 logBefore()를 실행한 후 실제 로직을 호출합니다.


4. 의존성 주입 방식

필드 주입

@Autowired
private HelloService helloService;

특징: 간단하지만 테스트 시 리플렉션 필요, 순환 참조 문제 발생 가능

Setter 주입

@Autowired
public void setHelloService(HelloService helloService) {
    this.helloService = helloService;
}

특징: 유연하지만 누락 시 초기화 미완료 가능

생성자 주입

@RequiredArgsConstructor
@Service
public class MyService {
    private final HelloService helloService;
}

특징: final 선언으로 의존성 누락 시 컴파일 에러 발생, 테스트 작성 용이


정리

  • @Component를 붙이면 IoC 컨테이너가 자동으로 Bean으로 등록
  • 등록된 Bean은 ApplicationContext에서 조회 가능
  • 의존성 주입도 자동으로 수행됨 (생성자 기반 DI 권장)
  • Bean 등록이 없으면 NoSuchBeanDefinitionException 발생
  • 직접 확인해보는 것이 가장 효과적인 학습 방법