Springboot

🚀 Springboot Bean 생명주기 란?

수아파파's 2025. 3. 19. 20:36
반응형

1️⃣ Bean 생명주기 개요
2️⃣ @PostConstruct와 @PreDestroy를 활용한 초기화 및 종료 처리
3️⃣ InitializingBean, DisposableBean 인터페이스를 활용한 생명주기 관리
4️⃣ BeanFactoryPostProcessor, BeanPostProcessor를 활용한 Bean 초기화 확장
5️⃣ 실전 예제: Connection Pool & 캐시 초기화 & 리소스 정리


1️⃣ Bean 생명주기 개요

🔹 Spring Bean의 기본 생명주기 흐름

  1. 객체 생성 → Spring 컨테이너가 Bean 객체를 생성
  2. 의존성 주입 (DI) → @Autowired 또는 생성자 주입을 통해 의존성 주입
  3. 초기화 (@PostConstruct) → Bean이 완전히 생성된 후 초기화 작업 수행
  4. 사용 → Bean이 애플리케이션에서 동작
  5. 소멸 (@PreDestroy) → 컨테이너가 종료되기 전에 정리 작업 수행

📌 Bean 생명주기 흐름 예제

@Component
public class CustomBean {
    public CustomBean() {
        System.out.println("1️⃣ Bean 생성자 호출");
    }

    @PostConstruct
    public void init() {
        System.out.println("2️⃣ Bean 초기화 완료");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("3️⃣ Bean 소멸 중...");
    }
}

Bean이 생성되면서 초기화(@PostConstruct)가 실행되고, 종료(@PreDestroy) 시 정리 작업이 수행됨!

📌 실행 결과

1️⃣ Bean 생성자 호출
2️⃣ Bean 초기화 완료
(애플리케이션 종료 시)
3️⃣ Bean 소멸 중...

2️⃣ @PostConstruct와 @PreDestroy를 활용한 초기화 및 종료 처리

📌 예제: 데이터베이스 연결 초기화 및 정리

@Component
public class DatabaseConnectionManager {
    
    private Connection connection;

    @PostConstruct
    public void init() {
        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
            System.out.println("✅ DB 연결 성공");
        } catch (SQLException e) {
            throw new RuntimeException("DB 연결 실패", e);
        }
    }

    @PreDestroy
    public void cleanup() {
        try {
            if (connection != null) {
                connection.close();
                System.out.println("🚀 DB 연결 해제 완료");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

애플리케이션이 실행되면 DB 연결을 초기화하고, 종료 시 DB 연결을 해제하여 리소스를 정리함!


3️⃣ InitializingBean, DisposableBean 인터페이스를 활용한 생명주기 관리

📌 InitializingBean, DisposableBean을 활용한 Bean 생명주기 관리

Spring에서는 InitializingBean, DisposableBean 인터페이스를 구현하여 초기화 및 정리 로직을 정의할 수 있음

@Component
public class ResourceLoader implements InitializingBean, DisposableBean {

    private String resource;

    @Override
    public void afterPropertiesSet() throws Exception {
        this.resource = "🚀 리소스 로드 완료";
        System.out.println(resource);
    }

    @Override
    public void destroy() throws Exception {
        this.resource = null;
        System.out.println("❌ 리소스 해제 완료");
    }
}

📌 실행 결과

🚀 리소스 로드 완료
(애플리케이션 종료 시)
❌ 리소스 해제 완료

InitializingBean, DisposableBean 인터페이스를 활용하여 생명주기를 효과적으로 관리 가능!


4️⃣ BeanFactoryPostProcessor, BeanPostProcessor를 활용한 Bean 초기화 확장

📌 BeanPostProcessor를 활용하여 초기화 로직 확장

BeanPostProcessor를 활용하면 모든 Bean의 초기화 전/후에 추가 로직을 적용 가능

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("⚡ Bean 초기화 전: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("✨ Bean 초기화 후: " + beanName);
        return bean;
    }
}

이제 모든 Bean의 초기화 전후에 로그를 남길 수 있음!

📌 실행 결과 (모든 Bean이 초기화될 때 실행됨)

⚡ Bean 초기화 전: customBean
✨ Bean 초기화 후: customBean

5️⃣ 실전 예제: Connection Pool & 캐시 초기화 & 리소스 정리

📌 예제 1: HikariCP Connection Pool 초기화 및 정리

@Component
public class ConnectionPoolManager {
    
    private HikariDataSource dataSource;

    @PostConstruct
    public void init() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        config.setUsername("user");
        config.setPassword("password");
        dataSource = new HikariDataSource(config);
        System.out.println("✅ HikariCP Connection Pool 초기화 완료");
    }

    @PreDestroy
    public void destroy() {
        if (dataSource != null) {
            dataSource.close();
            System.out.println("🚀 Connection Pool 종료 완료");
        }
    }
}

데이터베이스 연결을 위해 Connection Pool을 초기화하고, 종료 시 정리하여 메모리 누수를 방지함!


📌 예제 2: Redis 캐시 초기화 및 정리

@Component
public class RedisCacheManager {

    private JedisPool jedisPool;

    @PostConstruct
    public void init() {
        jedisPool = new JedisPool(new JedisPoolConfig(), "localhost");
        System.out.println("✅ Redis 캐시 연결 성공");
    }

    @PreDestroy
    public void destroy() {
        if (jedisPool != null) {
            jedisPool.close();
            System.out.println("🚀 Redis 캐시 연결 해제 완료");
        }
    }
}

🎯 마무리: Bean 생명주기를 활용한 초기화 및 종료 로직 정리

🔥 Spring Boot에서 Bean 생명주기를 활용하면 안정적인 애플리케이션 운영 가능!
@PostConstruct, @PreDestroy를 활용하여 Bean 초기화 및 정리 작업 수행
InitializingBean, DisposableBean을 활용한 인터페이스 기반 생명주기 관리 가능
BeanPostProcessor를 활용하여 모든 Bean의 초기화 과정을 가로채어 확장 가능
실전에서는 Connection Pool, 캐시 초기화, 리소스 정리 등에 활용!

🚀 이제 프로젝트에서 Bean 생명주기를 활용하여 안정적인 운영을 해보자!

반응형