backend

[Spring] 빈과 빈 생명주기 개념과 실무 예시

KUKJIN LEE
KUKJIN LEE
2024년 10월 2일
119

1. Spring 빈이란?

빈은 Java 객체이지만, 스프링 컨테이너에 의해 생성되고, 관리되며, 라이프사이클을 가집니다. (의존성 주입을 통해 서로 상호작용하며, 애플리케이션의 컴포넌트 간 결합도를 낮추는 역할을 합니다)

  • 빈의 생성 및 제거는 스프링 컨테이너에 의해 자동으로 처리됩니다.

 

2. Spring 빈 생명주기란?

빈의 생명주기는 빈이 생성되고 소멸되기까지의 여러 단계를 포함합니다.

(쉽게 설명하자면, 필요한 기능이 있으면 생성하고, 기능이 종료 될 때 소멸된다~ 이해하시면 됩니다.)

 

주요 생명주기 단계

  1. 빈 생성: 빈이 생성됩니다.

  2. 의존성 주입: 빈에 필요한 의존성이 주입됩니다.

  3. 초기화(Initialization): 빈이 사용 준비가 되는 단계입니다. @PostConstruct 또는 InitializingBeanafterPropertiesSet 메서드를 사용할 수 있습니다.

  4. 사용: 빈이 애플리케이션에서 사용됩니다.

  5. 소멸(Destruction): 빈이 더 이상 필요하지 않을 때 소멸됩니다. @PreDestroy 또는 DisposableBeandestroy 메서드를 사용할 수 있습니다.

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class MyBean implements InitializingBean, DisposableBean {

    public MyBean() {
        System.out.println("빈 생성자 호출");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("빈 초기화: @PostConstruct");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("빈 초기화: afterPropertiesSet 호출");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("빈 소멸: @PreDestroy");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("빈 소멸: destroy 호출");
    }
}
  • @PostConstruct: 빈이 생성된 후 초기화 작업입니다.

  • afterPropertiesSet(): InitializingBean 인터페이스를 구현하여 의존성 주입 후 실행할 작업을 정의합니다.

  • @PreDestroy: 빈이 소멸되기 전 정리 작업입니다.

  • destroy(): DisposableBean 인터페이스를 통해 최수의 수행 작업입니다.

 

기타 팁

  • 빈의 생명주기는 자동으로 처리되지만, 복잡한 의존성을 관리하거나 자원 정리가 필요한 경우, 초기화 및 소멸 메서드를 구현해 안정적인 애플리케이션을 유지할 수 있습니다.

  • 빈이 싱글톤 스코프인지 프로토타입 스코프인지에 따라 생명주기의 동작 방식이 달라질 수 있으므로, 스코프에 맞는 설계를 고려해야 합니다.

 

좀 더 쉽게 설명하면?

빈은 여러 함수와 데이터 포함한 객체로 이해하면 됩니다.

프로그램이 시작되면 스프링이 필요한 객체(빈)을 만들어서 준비하고, 빈이 사용되면서 안에 있는 다양한 기능(함수)들이 실행됩니다. 프로그램이 종료될 때 빈도 더 이상 필요 없기 때문에 스프링이 빈을 자동으로 제거하고, 메모리를 정리합니다. (TFT라고 이해하면 쉽습니다.)

 

예시도 더 쉽게 만들어보자.

사용자 조회와 생성을 수행하는 예시로 설명드리겠습니다.

우선 사용자 Service class 예시입니다.

import org.springframework.stereotype.Service;

@Service // 이 클래스가 스프링의 빈으로 관리됨
public class UserService {

    // 사용자 조회 기능 (예: 사용자 정보를 데이터베이스에서 가져오는 기능)
    public String getUserById(Long id) {
        // 실제로는 데이터베이스에서 사용자 정보를 조회하겠지만, 예시로 간단하게 구현
        return "사용자 정보: ID = " + id;
    }

    // 사용자 생성 기능 (예: 새로운 사용자를 데이터베이스에 저장하는 기능)
    public String createUser(String name) {
        // 실제로는 사용자 정보를 데이터베이스에 저장하겠지만, 예시로 간단하게 구현
        return "새로운 사용자 생성: 이름 = " + name;
    }
}

@Service 어노테이션을 사용하면 스프링이 이 클래스를 빈으로 인식하고 관리하게 만듭니다. 이제 이 클래스는 애플리케이션 실행 시 스프링이 자동으로 빈을 생성하고 관리합니다.

 

사용자 Controller 예시입니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    // UserService 빈을 주입받음 (자동으로 스프링이 빈을 연결)
    @Autowired
    private UserService userService;

    // 사용자 조회 API 예시
    @GetMapping("/user")
    public String getUser(@RequestParam Long id) {
        return userService.getUserById(id); // 사용자 조회 메서드 호출
    }

    // 사용자 생성 API 예시
    @PostMapping("/user")
    public String createUser(@RequestParam String name) {
        return userService.createUser(name); // 사용자 생성 메서드 호출
    }
}

`UserController` 클래스에서는 `UserService` 빈을 주입받아 사용하고 있습니다. 스프링이 실행될 때 자동으로 `UserService` 빈을 생성하고, 그 빈을 `UserController`에 주입하여 사용하게 합니다.

#스프링 빈 사용 이유#스프린 빈 이란#스프린 빈 싱글톤#java bean이란#Spring Bean#spring bean 생명주기#@Bean 어노테이션