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발생 - 직접 확인해보는 것이 가장 효과적인 학습 방법