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

KUKJIN LEE's profile picture

KUKJIN LEE1개월 전 작성

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`에 주입하여 사용하게 합니다.

New Tech Posts