개발/Spring

Spring @Lazy 어노테이션: 빈 로딩 최적화를 위한 핵심 기능

피터JK 2025. 2. 11. 15:46
728x90

Spring Framework에서 @Lazy는 빈(bean)의 초기화를 지연시키는 어노테이션입니다. 일반적으로 스프링 컨테이너는 애플리케이션 시작 시 모든 빈을 즉시 로드하지만, @Lazy를 적용하면 해당 빈이 실제로 필요할 때까지 생성되지 않습니다.


1. @Lazy의 기본 개념

Spring은 기본적으로 모든 빈을 즉시 로드(Eager Initialization) 합니다. 하지만 @Lazy를 적용하면 지연 로딩(Lazy Initialization) 방식으로 변경되어, 해당 빈이 최초로 사용될 때 생성됩니다.

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
@Lazy
public class LazyBean {
    public LazyBean() {
        System.out.println("LazyBean이 생성되었습니다!");
    }

    public void doSomething() {
        System.out.println("LazyBean의 메서드 실행");
    }
}

🔹 LazyBean은 @Lazy가 적용되었으므로, 애플리케이션이 시작할 때 생성되지 않고, 해당 빈을 사용할 때만 인스턴스화됩니다.


2. @Lazy를 적용하는 방법

(1) 클래스 단위에서 적용

클래스에 @Lazy를 선언하면, 해당 빈은 최초 호출 시점에 로드됩니다.

@Component
@Lazy
public class LazyService {
    public LazyService() {
        System.out.println("LazyService가 생성되었습니다!");
    }
}

(2) 특정 빈만 지연 로딩하기 (@Bean과 함께 사용)

@Configuration 클래스에서 특정 빈만 @Lazy로 설정할 수도 있습니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
public class AppConfig {
    @Bean
    @Lazy
    public LazyBean lazyBean() {
        return new LazyBean();
    }
}

3. @Autowired와 @Lazy 함께 사용하기

@Autowired 필드에 @Lazy를 적용하면, 해당 빈이 실제로 필요할 때까지 주입되지 않습니다.

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

@Service
public class MyService {
    @Autowired
    @Lazy
    private LazyBean lazyBean;

    public void useLazyBean() {
        System.out.println("LazyBean을 사용하려고 합니다.");
        lazyBean.doSomething(); // 여기서 실제로 LazyBean이 생성됨
    }
}

📌 lazyBean은 useLazyBean() 메서드를 호출할 때까지 생성되지 않습니다.


4. @Lazy(false) 설정

Spring Boot에서는 @Lazy(false)를 사용하여 빈을 즉시 로딩할 수도 있습니다.

@Component
@Lazy(false)  // 즉시 로딩
public class ImmediateBean {
    public ImmediateBean() {
        System.out.println("ImmediateBean이 즉시 생성되었습니다!");
    }
}

하지만 @Lazy(false)는 기본 동작과 동일하기 때문에 명시적으로 선언할 필요는 없습니다.


5. @Lazy의 동작 방식

  • @Lazy가 적용된 빈은 프록시(proxy) 객체로 감싸진 상태로 주입됩니다.
  • 실제 메서드가 호출될 때 프록시가 대상 객체를 실제 인스턴스로 변환하여 반환합니다.
  • 이를 통해 필요할 때만 객체를 생성하여 불필요한 리소스 낭비를 방지할 수 있습니다.

6. @Lazy를 사용하는 이유

 1. 애플리케이션 초기 로딩 속도 개선

  • @Lazy를 사용하면 애플리케이션 시작 시 불필요한 빈 생성을 줄일 수 있어 초기 로딩 속도를 단축할 수 있습니다.

 2. 리소스 절약

  • 메모리 및 CPU 사용량을 줄일 수 있습니다. 특히 무거운 객체(예: 대량의 데이터를 가지는 DAO, 대형 서비스 클래스 등)에 적용하면 효과적입니다.

 3. 순환 의존성(Circular Dependency) 해결

  • 두 개 이상의 빈이 서로 의존하는 경우, @Lazy를 적용하면 지연 초기화 방식으로 해결 가능합니다.

7. 주의할 점

1. 모든 빈에 @Lazy를 적용하지 말 것

  • 모든 빈을 지연 로딩하면 오히려 최초 요청 시 응답 시간이 느려질 수 있음.
  • 따라서, 무거운 빈이나 애플리케이션 초기 실행 시 필요하지 않은 빈에만 적용하는 것이 좋습니다.

2. AOP, 트랜잭션(@Transactional)과 함께 사용 시 주의

  • @Lazy 빈이 AOP 프록시를 통해 감싸질 경우, 예상치 못한 동작이 발생할 수 있습니다.
  • 트랜잭션이 필요한 빈에는 @Lazy 사용을 지양하는 것이 좋습니다.

8. 결론

항목 설명
@Lazy란? Spring 빈의 초기화를 지연시키는 어노테이션
기본 동작 모든 빈은 기본적으로 즉시 로딩(Eager Initialization)됨
적용 대상 클래스, 특정 @Bean, @Autowired 필드 등에 적용 가능
주요 이점 초기 로딩 속도 개선, 리소스 절약, 순환 의존성 해결
주의할 점 모든 빈에 적용하면 오히려 성능 저하 가능

@Lazy를 적절히 활용하면 애플리케이션의 성능과 리소스 효율성을 크게 개선할 수 있습니다!

 @Lazy를 통해 불필요한 빈 로딩을 줄이고, 애플리케이션 최적화에 활용해 보세요! 

728x90