스프링 빈은 싱글톤, Tomcat 쓰레드와의 연결
Spring Bean은 Singleton인데, 이게 요청 10만 개도 다 처리한다는 말인가?
Tomcat 쓰레드와 Spring Bean은 어떻게 연결되는가?
BeanFactory가 Singleton이라는 말이 Bean이 Singleton이라는 뜻인가?
내가 싱글톤, 프로토타입, 스레드 세이프 개념을 혼동하고 있었던 건 아닐까?
Spring Bean은 Singleton -> 하나만 만들어진다.
Component, Service, Repository, Controller 등은 모두 기본 스코프가 싱글톤이다.
즉, ApplicationContext 가 시작될 때 한 번만 생성되고, 이후에 요청이 들어오든 말든 그 인스턴스 하나가 계속 사용된다.
Tomcat의 Thread 100개가 동시에 같은 빈을 써도 되나?
단, Bean이 무상태(Stateless)하게 설계되어 있어야 한다.
같은 UserService 객체를 Thread-1, Thread-2, Thread-99가 동시에 호출하더라도
내부에 상태(state)를 저장하지 않고, 메서드의 지역 변수만 사용한다면
동시 접근에도 문제 없다 -> 이게 바로 Thread-safe
3️⃣ BeanFactory vs ApplicationContext vs Singleton vs Prototype
BeanFactory
Spring의 최상위 DI 컨테이너 인터페이스 (기본 기능 제공)
ApplicationContext
BeanFactory의 확장 (AOP, 메시지, 이벤트 등 추가)
Singleton Scope
Spring이 1개의 인스턴스만 생성하고 공유
Prototype Scope
요청마다 새로운 인스턴스 생성
BeanFactory가 Singleton이다?
❌ BeanFactory는 "객체 공장"일 뿐이고, 빈의 스코프는 Bean 정의에 따름
→ BeanFactory 자체가 Singleton이다
는 건 틀린 말.
정확히는 Bean의 스코프가 Singleton이면, BeanFactory는 같은 인스턴스를 계속 반환한다.
🔍 정확히 말하자면:
1. Spring Bean = 실행 주체(Thread)가 아님
@Service
,@Controller
,@Repository
같은 빈은 Thread처럼 실행되는 객체가 아닙니다이들은 정적인 로직을 담고 있는 구성 요소에 불과합니다
즉, 5개를 만들어도 동시에 실행되거나 병렬 처리되는 게 아닙니다
plaintext복사편집Thread 실행 = Tomcat이 담당
빈 로직 실행 = Thread가 빈의 메서드를 호출
2. Thread는 Tomcat이 요청마다 생성/할당
Spring은 Thread를 직접 만들지 않습니다
요청이 들어오면 Tomcat (or Jetty 등)이 Thread Pool에서 Thread를 꺼내서 DispatcherServlet을 실행
이 Thread는 싱글톤 빈이든 프로토타입 빈이든 상관없이 안전하게 재사용 가능 (stateless 조건 하에)
3. 빈을 여러 개 생성한다고 해서 병렬성이 향상되지 않는 이유
예를 들어 이런 구조를 생각해봅시다:
@Service
public class TaskService {
public void run() { ... }
}
이걸 5개 만든다고 해도…
@Bean
public TaskService taskService1() { return new TaskService(); }
@Bean
public TaskService taskService2() { return new TaskService(); }
// ...
Tomcat Thread가 어떤 TaskService를 쓸지 알아서 골라서 실행해주지 않습니다. → 우리가 직접 라운드로빈하거나, ThreadLocal로 고르게 선택해줘야 함 → 결국 불필요한 복잡성과 메모리 낭비만 생깁니다.
🧠 그러면 왜 싱글톤 설계가 굳이 선택되었나?
🔹 1. 빈은 무거운 객체가 아니다
Thread처럼 계속 돌아가는 게 아니고, 내부에 상태도 없음
싱글톤으로 하나만 만들어도 10만 요청 처리 가능 → 가볍고 효율적
🔹 2. 트랜잭션, AOP, DI를 프레임워크가 쉽게 관리할 수 있음
싱글톤이면 프록시 객체 생성, 부가 기능 삽입, DI 흐름이 단순해짐
다수 빈은 AOP 구성/프록시 캐시/DI 복잡도 증가
🔹 3. 병렬성은 ThreadPool로 제어하는 게 더 효율적
병렬성은
@Async
,CompletableFuture
,Executor
,WebFlux
같은 비동기/논블로킹 처리 도구가 더 적절함
📌 비유로 쉽게 말하면
빈은 요리법 레시피고, Thread는 그걸 들고 요리하는 셰프입니다.
레시피를 5개 복사해둔다고 셰프가 5배 빨라지진 않죠. 셰프(Thread)를 잘 늘리고 관리하는 게 병렬성 향상의 포인트입니다.
✅ 정리
빈을 여러 개 만들면 병렬 처리에 더 유리한가?
❌ 그렇지 않음. 병렬 처리는 Thread가 담당
그럼 왜 싱글톤만 쓰는가?
효율적이고, 프레임워크 관리가 쉬우며, thread-safe하게 설계 가능
병렬 처리는 어디서 제어하는가?
Tomcat ThreadPool, 비동기 Executor, WebFlux 같은 구조에서 담당
빈을 코어 수만큼 만들면 성능이 좋아지나?
❌ 실제 실행 주체는 코어가 아닌 Thread → 빈 개수는 무관
Last updated