싱글톤 객체의 다중 요청 처리 방법에 대한 의문점
뜬금없이 RestTemplate은 싱글톤 형식의 스프링 빈으로 등록하여 사용되는데 RestTemplate의 특성(blocking + 동기) 상 먼저 들어온 요청에 대한 응답이 늦게 와서 그동안 물려있다면 다음 요청은 먼저 들어온 요청이 완료되고 수행되는 것인가? 라는 의문이 들었습니다.
그러면 RestTemplate 뿐만 아니라 스프링 빈으로 등록되는 Controller, Service 등의 객체 역시 싱글톤으로 생성되는데, '(멀티스레드 환경에서) 싱글톤 객체에 대해 다중 요청이 처리되는 방식은 무엇일까?'가 궁금하여 찾아본 내용입니다.
싱글톤(Singleton) 패턴과 사용하는 이유
먼저 '싱글톤 패턴(Singleton pattern)'과 싱글톤 패턴을 사용하는 이유에 대해 간단하게 살펴보겠습니다.
싱글톤 패턴이란, 로직을 처리하는 과정에서 하나의 클래스에 대해 여러 개의 객체를 만들어서 처리하는 것이 아니라 오직 하나의 객체를 생성하고 해당 객체를 공유해서 사용하는 패턴을 말합니다.
예를 들어 웹 애플리케이션에서 동시에 다수의 클라이언트로부터 요청이 들어왔을 때, 매 요청마다 각각의 (동일한) Controller 인스턴스를 생성한다면 이는 메모리적으로도 낭비가 되는 부분이며, 객체를 생성하는 과정으로 인한 시간도 오래 걸리게 됩니다.
때문에 이러한 문제를 해결하기 위해 사용되는 것이 바로 '싱글톤 패턴'입니다.
***
싱글톤 객체에서 주의해야 할 점으로는 '공유되는 객체이기 때문에 무상태(stateless)를 유지해야 한다는 점'이 있습니다.
만약 객체 내부에서 공유되는 값을 가지고 있는 경우 이는 연산의 장애로 이어질 수 있습니다.
싱글톤 객체에 대해 다중 요청이 처리되는 방식
먼저 멀티스레드(Multi Thread) 환경으로 인해 동시에 여러 요청을 처리할 수는 있습니다.
하지만 결국 여러 개의 스레드가 동작하더라도 싱글톤 객체는 하나이기 때문에 요청에 따라 순차적으로 처리되어야 하는 게 아닌가? 하는 것이 주된 의문이었는데요.
Static Area (Method Area)
의문에 대한 답은 Java 메모리 영역 중 'Static Area(Method Area)'에서 찾을 수 있었습니다.
JVM 동작 과정에서 클래스 로더(Class Loader)는 클래스 파일의 바이트 코드(.class 파일)를 읽어 '런타임 데이터 영역(RunTime Data Area)'에 올리게 되는데요.
이 런타임 데이터 영역에는 'Static Area(Method Area)', 'Heap Area', 'Stack Area', 'PC Register', 'Native Method Stack' 이렇게 5가지 영역이 존재합니다.
그중 'Static Area(Method Area)'는 Static 영역 또는 Method 영역이라고 불리며, 클래스나 인터페이스의 메타 데이터(이름, 생성자, 필드, 메서드) 및 static으로 선언된 변수들이 해당 영역에 저장됩니다.
이 Static Area는 모든 스레드들이 공유하는 메모리 영역인데요.
***
결론적으로, 싱글톤 객체의 실제 인스턴스는 'Heap Area'에 단 하나만 존재하지만 'Static Area'에 있는 해당 빈의 메타 데이터(이름, 생성자, 필드, 메서드)를 모든 Thread들이 공유하기 때문에 객체 인스턴스의 개수와 관계없이 싱글톤 객체를 통한 다중 요청이 정상적으로 동작하는 것입니다.
여기까지가 궁금했던 '싱글톤 객체의 다중 요청 처리 방법'에 대해 찾아본 내용입니다.
아래 첫 번째 참고 자료를 통해 궁금했던 내용을 거의 다 해결할 수 있었으며, 해당 내용을 토대로 조금 더 찾아본 내용을 덧붙였습니다.
정리하면서도 과연 위 내용이 제대로 파악한 게 맞는지 조금 의문이 드는데요. 내용 중 잘못된 부분이나 궁금하신 부분은 댓글 남겨주시면 감사드리겠습니다.
< 참고 자료 >
https://jeong-pro.tistory.com/204
https://leezzangmin.tistory.com/41
'Programming > Spring' 카테고리의 다른 글
(eclipse) Spring MVC Project 수동 생성 과정 정리 (0) | 2024.02.23 |
---|---|
ThreadPoolTaskScheduler를 통해 스케줄러 동작 시간 동적으로 변경하기 (0) | 2024.01.24 |
(spring) web.xml, root-context.xml, servlet-context.xml 각각의 역할과 차이점 (0) | 2024.01.16 |
mysql mybatis 다중 insert 처리 방법 (1) | 2024.01.14 |
Spring Legacy @Transactional 동작하지 않는 문제 (tx:annotation-driven) (0) | 2024.01.11 |