앞선 포스팅에서 클라이언트가 싱글톤으로 관리되는 서블릿을 동시에 요청했을 때, 멀티쓰레드를 사용하여 이를 지원한다고 했었다. 멀티쓰레드가 뭔지, 어떻게 동시 요청을 처리하는지 간단히 알아보자.
멀티쓰레드
멀티쓰레드 이전에 쓰레드의 개념부터 살펴보자.
쓰레드란?
- 쓰레드란 프로그램(프로세스)실행의 단위이며 하나의 프로세스는 여러 개의 쓰레드로 구성이 가능하다
- 하나의 프로세스를 구성하는 쓰레드들은 프로세스에 할당된 메모리, 자원 등을 공유한다
- 프로세스와 같이 실행, 준비, 대기 등의 실행 상태를 가지며 실행 상태가 변할 때마다 문맥교환(Context Switching)을 수행한다
즉, 쓰레드는 프로그램 실행의 단위라고 생각하면 된다.
위 그림에서 서블릿 객체를 호출하는 것을 프로그램의 실행 단위인 쓰레드가 하는 것이다.
멀티쓰레드란?
- 하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상시키는 것을 멀티쓰레딩 이라고 한다
- 즉, 하나의 프로그램에 동시에 여러 개의 일을 수행할 수 있도록 해주는 것이다.
따라서 우리는 동시 처리가 필요하다면 쓰레드를 추가로 생성하여 사용하면 되는 것이다.
WAS에서 클라이언트의 요청에 대해 어떻게 처리하는 지 하나씩 살펴보자
동시 요청 처리
단일 요청의 경우 쓰레드가 하나만 있어도 정상적으로 작동한다.
문제는 다중 요청의 경우이다.
다중 요청의 경우 만약 하나의 쓰레드만 사용하게 된다면, 먼저 온 요청1을 처리하는 동안 요청2는 대기 상태이다.
하지만 요청1을 처리가 지연되면, 요청1과 요청2 모두 처리하지 못하게 되므로 서비스에 장애가 일어나게 된다.
이런 경우에 멀티쓰레드를 사용하면 된다.
멀티쓰레드를 클라이언트의 요청 마다 쓰레드를 생성하여 처리하는 방법과, 쓰레드 풀을 이용하여 처리하는 방법으로 나누어서 살펴보자.
요청 마다 쓰레드를 생성하여 처리하면 요청1의 처리가 지연되더라도 요청2는 문제없이 처리할 수 있다는 장점이 있지만, 쓰레드의 생성 비용은 매우 비싸기 때문에 고객의 요청이 올 때마다 쓰레드를 생성하면, 응답 속도가 늦어진다는 단점이 있다. 또 문맥 교환 비용이 발생하며, 가장 큰 단점은 쓰레드 생성에 제한이 없다는 것이다.
쓰레드 생성에 제한이 없기 때문에 처리하지 못할 만큼의 요청이 들어오게 되면, 그 만큼의 쓰레드를 생성하려다 CPU, 메모리 임계점을 넘어 서버가 죽게될 수 있기 때문이다.
따라서 요청 마다 쓰레드를 생성하는 것은 비효율적이라고 볼 수 있다.
쓰레드 풀을 사용하게 되면 요청 마다 쓰레드를 생성하는 방법의 단점을 보완할 수 있다.
쓰레드를 요청 마다 생성하고 요청이 끝나면 종료시키는 것이 아니라,
미리 쓰레드를 생성해놓고, 이를 가져다 사용하며, 사용이 끝나면 종료시키는 것이 아닌 쓰레드 풀에 다시 반납한다.
이런식으로 멀티쓰레드를 사용하게 되면 쓰레드를 생성하고 종료하는 비용(CPU)가 절약될 뿐만 아니라 가장 큰 문제였던 안정성이 해결된다. 생성 가능한 쓰레드의 최대치가 정해져 있기 때문에 처리하지 못할 만큼의 요청이 들어오더라도 처리할 수 있는 만큼의 쓰레드만을 사용하여 처리하게 되는 것이다.
즉, 쓰레드 풀을 이용하면 동시 처리를 안정적이고 효율적으로 처리할 수 있게 된다.
WAS가 이런 멀티쓰레드와 관련된 부분을 처리해주기 때문에 우리는 스프링이 동시 처리를 어떤 방식으로 하는 지 정도만 이해하면 될 것 같다. 추가로 쓰레드 풀이 200개로 디폴트 설정이 되어 있는데 이를 어떤 식으로 늘리고 관리해야 되는 지에 대해서도 생각해보면 좋을 것 같다.