우당탕탕

[Spring] 빈 라이프사이클과 초기화 실수 feat. @PostConstruct, @Lazy, 순환참조 본문

Tech/Spring

[Spring] 빈 라이프사이클과 초기화 실수 feat. @PostConstruct, @Lazy, 순환참조

모찌모찝 2025. 8. 17. 08:59
빈 라이프사이클과 초기화 실수 feat. Proxy(프록시)

 

이번에는 프록시와 내부 호출에서 벗어나, 스프링에서 자주 실수하는 빈 라이프사이클 및 초기화와 관련된 내용을 다룹니다.

스프링

1. @PostConstruct 초기화 타이밍 실수

스프링 빈이 생성되고 DI가 끝난 후 호출되는  @PostConstruct 하지만 이 시점에 DB 커넥션 등 외부 자원이 완전히 준비됐다고 기대하면 안됩니다.
예를 들어 DB 트랜잭션이나, 다른 빈에서 초기화를 의존할 때 순서 관련 오류가 자주 발생합니다.

@Component
public class MyBean {
    @Autowired
    private UserRepository userRepository;

    @PostConstruct
    public void init() {
        userRepository.initData(); // 아직 DB 커넥션이 준비되기 전일 수 있음
    }
}

해결법: 트랜잭션, DB 연결 등은 보통 별도의  @EventListener(ApplicationReadyEvent.class) 로 분리하거나, 구조를 명확히 관리할 것.

2. Bean 재정의와 Bean Overriding 문제

동일한 이름의 빈을 여러 군데서 등록하면, 스프링 부트 2.x 이후로는 기본적으로 에러가 발생합니다.
의도적으로 빈 재정의를 허용하고 싶을 땐  spring.main.allow-bean-definition-overriding=true  옵션을 사용해야 합니다.

3. Environment 및 설정 값 주입 실수

환경 변수를 주입할 때, property 이름 오타로 인한 빈 생성 오류가 실무에서 매우 빈번하게 발생합니다.

@Value("${app.url}")
private String appUrl;

여기서 환경 변수 app.url이 실제로 설정되어 있지 않으면 빈 초기화 실패로 전체 애플리케이션 부팅이 막힙니다!

4. Lazy Initialization 관련 성능 문제

스프링에서  @Lazy 를 남발하면, 의존성 주입은 늦춰지겠지만, 실제 서비스 구동 중 첫 호출이 느려질 수 있습니다.
반대로, 아주 무거운 객체 또는 잘 안쓰이는 객체엔  @Lazy 가 큰 도움이 됩니다.

5. 의존성 순서와 Circular Reference 주의

빈 초기화 순서가 잘못되면 순환 참조가 쉽게 발생합니다.
스프링 부트 2.x는 순환 참조를 기본적으로 금지시켰으니 설계 시 이 점을 꼭 염두에 둘 것!

실무 팁

초기화용 로직은  @PostConstruct 와  @EventListener(ApplicationReadyEvent.class) 를 구분해서 사용.
• 환경 변수/설정값(property)엔 항상 fallback 값을 지정하거나, 명확한 검증 로직 추가.
빈 이름 중복이나 순환 참조가 일어나는 구조인지 서비스 설계 단계에서 체크.
Lazy Initialization은 성능에 미치는 영향 고려해서 신중하게 사용.
bulk 초기화, 트랜잭션이 필요한 작업은 빈 초기화 타이밍에 넣지 말 것.

스프링 실무에서는 프록시와 트랜잭션 뿐만 아니라, 빈 라이프사이클과 초기화/설정 관련 실수가 장애로 이어질 수 있습니다. 구조와 초기화 타이밍을 세밀하게 관리하는 습관이 안정적인 서비스 운영의 핵심입니다.

Comments