Spring Boot에서 빈(bean)이 기본적으로 싱글톤(Singleton)으로 등록되는 이유는 의존성 주입(DI: Dependency Injection)과 애플리케이션 성능을 고려한 설계 원칙 때문
1. 싱글톤 빈(Singleton Bean)의 정의
- 싱글톤 빈이란 애플리케이션 구동 시 딱 한 번만 생성되고, 애플리케이션이 종료될 때까지 동일한 객체 인스턴스가 사용되는 빈을 말함.
- Spring에서는 빈을 만들 때 기본적으로 싱글톤 스코프를 적용하여, 해당 빈에 대해 하나의 인스턴스만 생성하도록 보장.
2. 싱글톤으로 등록되는 이유
A. 메모리 및 성능 최적화
- 싱글톤 스코프를 사용하면 메모리를 절약할 수 있음.
- 각 빈마다 새로운 인스턴스를 생성하는 대신, 한 번 생성된 인스턴스를 계속해서 재사용하기 때문에 메모리 사용량이 줄어듬.
- 또한, 빈을 재사용할 수 있기 때문에 객체를 매번 생성하는 오버헤드를 줄일 수 있어 애플리케이션 성능이 향상.
B. 의존성 주입 간결성
- 의존성 주입(DI)을 통해 Spring은 여러 컴포넌트 간의 복잡한 객체 의존성을 관리하는데, 빈이 싱글톤으로 관리되면 이 과정이 단순해짐.
- 각 빈의 인스턴스를 한 번만 생성하고 이를 재사용하기 때문에 트랜잭션 관리, 캐시, 세션 관리와 같은 부분에서 일관성을 유지할 수 있음.
* 다른 스코프
- Spring에서는 싱글톤 외에도 다양한 스코프를 제공
- Prototype: 요청할 때마다 새로운 인스턴스를 생성
- Request: 웹 요청 하나당 하나의 빈 인스턴스를 생성
- Session: 웹 세션 하나당 하나의 빈 인스턴스를 생성
- Application: 웹 애플리케이션당 하나의 빈을 생성
4. 싱글톤 스코프의 단점
- 만약 상태를 가지는 빈을 싱글톤으로 사용할 경우, 다른 요청이나 스레드에서 빈의 상태가 공유되어 예상치 못한 동작을 유발할 수 있음.
- 이러한 상태가 있는 빈은
prototype
스코프로 관리하거나, 상태를 별도로 관리하는 것이 중요합니다.
5. 상태를 가진다?
- "상태를 가진다"는 말은 객체가 인스턴스 변수(필드)에 값을 저장하여 그 값이 시간에 따라 변할 수 있는 것을 의미.
- 이러한 상태는 객체가 특정 시점에서 어떠한 값을 유지하고 있다는 뜻. 시간이 지남에 따라 변할 수 있다는 뜻.
- 상태를 가진 객체는 여러 요청이나 스레드에서 동시에 사용될 때, 그 상태가 공유되므로 예기치 않은 동작을 초래할 수 있음.
상태를 가진 빈의 예
- 이 빈은 사용자마다 로그인한 사용자 이름을 저장하고 그 값을 반환하는 기능을 제공
- 이 빈이 싱글톤으로 등록되어 있을 경우, 여러 사용자 요청이 들어오면 서로 다른 사용자들이 같은 상태를 공유하게 되어 데이터 충돌이 발생.
@Service
public class LoginService {
private String loggedInUser;
public void login(String username) {
this.loggedInUser = username;
}
public String getLoggedInUser() {
return this.loggedInUser;
}
}
동작 시나리오
- 사용자 A가 로그인하고
login("UserA")
메서드를 호출.
loggedInUser
필드에 "UserA"가 저장.
- 사용자 B가 로그인하고
login("UserB")
메서드를 호출.
loggedInUser
필드 값이 "UserB"로 갱신.
- 이제 사용자 A가
getLoggedInUser()
메서드를 호출하면, "UserA"가 아니라 "UserB"가 반환.
이처럼 상태를 가진 객체는 싱글톤으로 사용할 때, 여러 사용자가 동시에 접근할 경우 상태가 공유되면서 데이터 충돌이 발생할 수 있음.
무상태 객체의 예
- 무상태 객체는 필드에 상태를 저장하지 않고, 필요한 데이터를 메서드 파라미터로 처리
- 이 경우 객체는 요청마다 새로운 데이터를 처리할 뿐, 내부적으로 상태를 유지하지 않음.
@Service
public class CalculationService {
public int add(int a, int b) {
return a + b;
}
}
동작 시나리오
- 사용자 A가
add(5, 3)
을 호출하면, 결과로 8
이 반환.
- 사용자 B가
add(10, 2)
을 호출하면, 결과로 12
가 반환.
- 이 객체는 내부에 상태를 저장하지 않기 때문에, 사용자 A와 B의 요청이 서로 영향을 미치지 않음.
어떠한 사용자 요청에도 상태가 공유되지 않고 독립적으로 처리.
정리
- Spring Boot에서 빈이 기본적으로 싱글톤으로 등록되는 이유는 메모리 효율성, 성능 향상, 그리고 의존성 주입의 단순화를 위한 것.
- 싱글톤 스코프는 대부분의 서비스나 리포지토리와 같은 무상태 빈에 적합하며, Spring은 이를 통해 애플리케이션을 효율적으로 관리
- 상태를 가진 빈이 필요한 경우 프로토타입 스코프를 사용하거나, 상태를 외부에서 관리하는 방식으로 변경하는 것이 좋음.