[Spring] 빈과 빈 생명주기 개념과 실무 예시
KUKJIN LEE • 2개월 전 작성
1. Spring 빈이란?
빈은 Java 객체이지만, 스프링 컨테이너에 의해 생성되고, 관리되며, 라이프사이클을 가집니다. (의존성 주입을 통해 서로 상호작용하며, 애플리케이션의 컴포넌트 간 결합도를 낮추는 역할을 합니다)
-
빈의 생성 및 제거는 스프링 컨테이너에 의해 자동으로 처리됩니다.
2. Spring 빈 생명주기란?
빈의 생명주기는 빈이 생성되고 소멸되기까지의 여러 단계를 포함합니다.
(쉽게 설명하자면, 필요한 기능이 있으면 생성하고, 기능이 종료 될 때 소멸된다~ 이해하시면 됩니다.)
주요 생명주기 단계
-
빈 생성: 빈이 생성됩니다.
-
의존성 주입: 빈에 필요한 의존성이 주입됩니다.
-
초기화(Initialization): 빈이 사용 준비가 되는 단계입니다.
@PostConstruct
또는InitializingBean
의afterPropertiesSet
메서드를 사용할 수 있습니다. -
사용: 빈이 애플리케이션에서 사용됩니다.
-
소멸(Destruction): 빈이 더 이상 필요하지 않을 때 소멸됩니다.
@PreDestroy
또는DisposableBean
의destroy
메서드를 사용할 수 있습니다.
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`에 주입하여 사용하게 합니다.