Spring Web MVC에서 요청 마다 Thread가 생성되어 Controller를 통해 요청을 수행할텐데, 어떻게 1개의 Controller만 생성될 수 있을까요?
Backend-Interview-Question
답변
생성한 Controller 클래스에 대한 정보가 JVM 메모리 영역 중 Method Area(메서드 영역)에 올라가기 때문입니다.
Controller 객체는 Heap(힙)에 생성 되지만, 해당 클래스의 정보(메소드 처리 로직, 명령들)는 Method Area(메서드 영역)에 생성 됩니다.
따라서 결국 모든 Thread가 객체의 메서드를 공유할 수 있기 때문에 Controller는 1개만 생성됩니다.
Controller 1개는 어떻게 여러 개의 요청을 처리하지?
Request 별로 Thread가 따로 생성되고, 이에 따라 각각의 ServletContext를 갖는데 어떻게 Controller가 1개만 생성되는 것일까 ??
▶️ Singleton인 Controller
- 각각의 Thread는 singleton으로 생성된 Bean( ⇒ Controller 포함 ) 들을 참고하여 일을 한다.
- Bean들은 기본적으로 Singleton으로 생성되고 관리된다.
- 사실상 이 Thread들은 그 1개의 Singleton Controller 객체를 공유하기에 최종적으로 1개의 Controller만 사용하는 것이다.
- 즉, 하나의 Singleton Controller가 수많은 request를 처리한다기 보다는, 각각의 Thread가 singleton으로 생성된 Controller를 참고하여 실행한다고 보면 된다.
▶️ Controller가 저장되는 곳
- 우선 Controller 객체 하나를 생성하면 객체 자체는 Heap에 생성되지만, 해당 Class의 정보는 Method Area(메서드 영역)에 저장된다.
( 자바의 메모리 구조 - 참고 )
- 메소드 영역으로는 모든 Thread가 접근 가능하기 때문에 객체의 Binary Code 정보를 공유할 수 있다.
▶️ 공유된다 해서 동기화 될 필요가 없다.
- 공유되는 정보를 사용하기 위하여 굳이 Controller 객체를 사용하고 있는 Thread나 Controller 객체 자체가 동기화 될 필요가 없다.
- 원래 동기화를 해주는 이유는 프로세스(Thread)들간 알고있는 정보(상태)를 일치하기 위해서인데, Controller가 내부적으로 상태를 갖는 것이 없으니, 그냥 메소드 호출만 하면 된다. → 공유하는 데이터 즉, 클래스변수, 전역변수를 컨트롤러에서 사용하지 않기 때문에 상태를 갖는 것이 없음
- 그로 인해 굳이 동기화할 이유도 없고 → 그저 처리 로직만 ‘공유되어’ 사용되는 것이다.
- 따라서 스레드는 Controller의 메소드를 공유하고 제각각 호출할 수 있기 때문에 → 들어오는 요청이 1만 개의 요청이든 10만 개의 요청이든 상관없게 된다.
▶️ 만약 상태 정보를 갖게 된다면?
- 결론적으로 싱글톤으로 관리되는 Bean의 경우 상태 정보를 갖지 않기 때문에 요청의 수와 상관없이 싱글턴 객체의 장점을 이용할 수 있었던 것이다.
- 만약 Bean이 상태 정보를 갖게된다면 스레드들간의 동기화가 필요하고 그렇게 된다면 오버헤드가 발생하게 된다. → Controller 객체를 하나만 만들고 컨테이너에서 단순히 꺼내쓸 수 있었던 장점을 잃게 된다.
참고 자료