1. 개요
이번 게시물에서는 서블릿과 이를 담고 있는 서블릿 컨테이너에 대해 알아볼 것이다.
2. 서블릿
1) 서블릿이 그래서 뭐하는 건데?
HTTP 요청과 응답을 처리하기 위해서, 서버에서는 왼쪽에 적힌 모든 처리를 해주어야 한다. 하지만, 저 중에서 의미있는 비즈니스 로직에 해당되는 것은 초록색 네모 만의 부분 뿐이다. 따라서 서블릿은 초록색 네모를 제외한 나머지를 개발자 대신 해줌으로서, 개발자로 하여금 비즈니스 로직에 집중할 수 있도록 해준다.
2) 실제 코드
- urlPatterns(/hello)의 URL이 호출되면, 해당 서블릿 코드가 실행된다.
- 파라미터를 보면, HTTP 요청을 관리하는 HttpServletRequest와 HTTP 응답을 관리하는 HttpServletResponse가 있다.
- 이 서블릿을 활용함으로서, 매우 편리하게 개발할 수 있다.
3) HTTP 요청, 응답 흐름
- HTTP 요청시, WAS는 Request, Response 객체를 만든 후 서블릿 객체를 호출한다.
- 개발자는 Request 객체에서 HTTP 요청 정보를 꺼내서 사용한 후, HTTP 응답 정보를 Response 객체에 담는다.
- WAS는 Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성한다.
- 그런데 이 흐름대로라면 서블릿이 필요한지 의문이 든다.. 아래 내용에서 확인해보자.
3. 서블릿 컨테이너
- 서블릿을 지원하는 WAS안에 서플릿 컨테이너가 존재한다.
- 서블릿 컨테이너는 서블릿 객체를 생성하며, 생명주기를 관리한다.
- 서블릿 객체들은 싱글톤으로 관리된다.
-> 요청이 올때마다 객체를 생성하는 것을 비효율적이기 때문에, 최초 로딩 시점에 서블릿 객체를 미리 만들어 논다.
-> 따라서 공유 변수 사용에 주의해야 하며, 서블릿 컨테이너 종료 시 서블릿도 함께 종료된다.
- JSP도 서블릿으로 변환 되어서 사용된다.
4. 쓰레드
- 그래서 요청이 들어왔을 때, 서블릿 객체를 누가 호출할까?
-> 애플리케이션 코드를 하나하나 순차적으로 실행하는 것은 쓰레드이다!
- 쓰레드는 한번에 하나의 코드 라인만 수행하며, 동시 처리가 필요하면 쓰레드를 추가로 생성해야 한다.
1) 쓰레드 하나만 생성
쓰레드를 하나만 사용할 경우, 단일 요청은 대응하기 쉽다. 요청을 받을 경우 쓰레드가 해당 서블릿을 호출하고, 서블릿이응답하여 다시 HTTP 응답을 내리면 된다. 하지만 여러 요청이 동시에 들어온다면?
쓰레드가 요청 1에 대해서 처리를 하는 중에 요청 2가 들어오면, 요청 2는 대기하고 있을 수 밖에 없다. 또한 만일에 요청 1에 대한 처리가 지연된다면? 요청 1, 2 모두 멈춰버리게 된다. 따라서 동시다발적인 요청에 대해서 취약해진다.
2) 요청마다 쓰레드 생성
이를 해결하기위해 새로운 요청이 들어올 경우, 신규 쓰레드를 생성하였다. 이 경우 요청 1을 첫 번째 쓰레드가 처리하고 있어도, 신규 쓰레드가 요청 2를 처리함으로서 해결 가능하다.
- 장점
- 동시 요청을 처리할 수 있다.
- 리소스가 허용할 때 까지 처리가능하다.
- 하나의 쓰레드가 지연되더라도, 나머지 쓰레드는 정상 동작한다.
- 단점
- 쓰레드는 생성 비용이 매우 비싸기 때문에, 고객의 요청이 올때마다 생성 시 응답 속도가 늦어진다.
- 쓰레드는 컨텍스트 스위칭 비용(실행되는 프로세스의 변경 시 발생)이 발생한다.
- 쓰레드 생성 제한이 없다.
-> 좋아보이지만, 고객 요청이 너무 많이 올 경우 CPU, 메모리 임계점이 넘어 서버가 죽을 수 있다.
다중 요청을 사용하러면 여러개의 쓰레드가 필요해보이는데, 비용 문제로 인하여 서버의 위험성이 너무 커보인다. 이를 해결하기 위해 쓰레드 풀이라는 개념이 도입된다.
5. 쓰레드 풀
미리 숫자를 지정하여 쓰레드 풀에 쓰레드를 만들어 놓는다. 그 후, 요청이 오면 쓰레드 풀에 쓰레드를 요청한다. 즉, 쓰레드 풀에서 쓰레드를 꺼내 쓰는 모양이라고 생각하면 된다. 사용을 종료하면 쓰레드 풀에 해당 쓰레드를 반납한다.
ex) 톰캣을 최대 200개가 기본 설정이며, 이는 변경 가능하다.
만일에 쓰레드 풀에 모든 쓰레드를 사용하고 있을 경우, 서버 설정에 따라 쓰레드 대기 혹은 거절을 한다.
- 장점
- 쓰레드가 미리 생성되어 있어, 쓰레드를 생성하고 종료하는 비용이 절약되고 응답 시간이 빠르다.
- 쓰레드의 최대치가 정해져 있어, 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.
(비록 응답 지연이 발생하더도, 적어도 서버가 터지지는 않는다.)
- 결국 최대 쓰레드를 너무 낮게 설정하면, 클라이언트는 금방 응답 지연이 될 것이다.
- 최대 쓰레드를 너무 높게 설정하면, 동시 요청이 많을 시 서버가 다운될 수 있다.
-> 따라서 적정 숫자를 잘 지정하는 것이 좋다!
-> 아파치 ab, 제이미터, nGrinder 등의 툴로 성능 테스트를 해보자.
6. 멀티 쓰레드 관리는 WAS에서!
- 위에서 설명한 이런 멀티 쓰레드 관리는 WAS에서 모두 처리해준다!
-> 따라서 개발자가 멀티 쓰레드 관련 코드를 신경쓸 필요가 없다.
-> 싱글 쓰레드 프로그래밍을 하듯이 개발하면 된다.
-> 싱글톤 객체만 주의해서 사용하기
위 내용은 김영한 님의 인프런 강의 "스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술"의 내용과 강의자료를 토대로 작성된 게시글입니다.
강의 링크:
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
'Web > spring study' 카테고리의 다른 글
[Spring] SLF4J 로깅 간단한 정리 (0) | 2023.05.24 |
---|---|
[Spring] 서블릿, HttpServletRequest, HttpServletResponse (0) | 2023.01.17 |
웹 서버, 웹 어플리케이션(WAS), 그리고 사용법 (0) | 2023.01.15 |
[Spring] 빈 스코프 (@Scope) (0) | 2023.01.10 |
[Spring] 스프링 빈 생명주기 (0) | 2023.01.10 |
댓글