이 글은 김영한님의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의를 요약한 것이며 강의 자료 및 출처는 가장 아래에서 확인할 수 있습니다.
웹 서버(Web Server),웹 애플리케이션(WAS - Web Application Server)
웹 서버와 웹 애플리케이션 서버는 모두 HTTP 기반으로 동작한다.
웹 서버는 정적 리소스(HTML, CSS, JS, image ...)만 제공하는 반면 웹 애플리케이션 서버는 애플리케이션 로직이 들어간다. (사실 둘의 용어와 경계가 모호하다고 하다.)
보통 자바는 서블릿 컨테이너 기능을 제공하면 WAS라고 부른다. (서블릿 컨테이너는 아래에서 설명한다.)
웹 서버는 NGINX,APACHE등이 있고, 웹 애플리케이션 서버는 Tomcat,Undertow등이 있다.
웹 시스템을 구성하는 방법
위에서 웹 서버는 정적 리소스, 웹 애플리케이션 서버는 로직이라고 구분했는데 웹 애플리케이션 서버는 정적 리소스까지 모두 포함하여 제공 가능하다. 따라서 웹 시스템은 WAS, DB만으로 시스템 구성이 가능하다.
그러나 WAS가 너무 많은 역할을 담당하면 서버에 과부하가 올것이다. 로직이 정적 리소스때문에 수행이 어려울수있다.
WAS에서 모든것을 보여주기 때문에 만약 장애시 오류 화면도 노출할 수 없다.
따라서 웹 시스템을 WEB, WAS, DB로 구성하면?
정적 리소스는 웹 서버가 , 로직이 필요한 동적 처리는 WAS가 처리해줄 수 있다.
정적 리소스가 많이 사용되면 Web 서버를 증설하고 애플리케이션 리소스가 많이 사용되면 WAS를 증설하면 된다.
만약 WAS,DB장애 발생시 WAS,DB로만 이루어진 구성과는 달리 웹 서버가 오류 화면을 띄워줄 수 있다.
이런식으로 효율적인 리소스 관리가 가능하다.
서블릿
위에서 언급했듯이 모든 서버는 HTTP를 기반으로 동작한다.
만약 HTML Form 데이터 형식으로 username과 age를 클라이언트에서 서버로 전송받는 경우를 생각해보자. 아래와 같은 HTTP 메시지가 서버로 날아올것이다.
만약 서블릿이 없다면 서버에서는 아래의 모든 일을 수행해야한다.
그저 username과 age를 받아와 저장만할뿐인데 위의 모든 번거로운 과정을 거쳐야 한다.
사실상 의미가있는 로직은 초록색테두리로 쳐진 일부일뿐이다.
따라서 서블릿을 지원하는 WAS를 사용하면 테두리를 제외한 모든일들을 대신 처리해준다.
특징
서블릿의 형태는 아래와 같다.
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response){
//애플리케이션 로직
}
}
urlPatterns에 있는 URL이 호출되면 서블릿 코드가 실행되며 HttpServlet을 상속하여 service 메서드를 override한후 메서드 내부에 애플리케이션 로직을 작성하면 된다. 대충 흐름은 아래와 같다.
HTTP 요청이오면 WAS는 Request,Response 객체를 만들어 서블릿 객체를 호출한다.
개발자는 편하게 Request객체에서 HTTP 요청을 꺼내서 사용하고, Response객체에 HTTP 응답 정보를 입력하면 된다.
이후 WAS는 Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성한다.
그런데 정작 중요한 서블릿 컨테이너가 뭘까?
서블릿 컨테이너
톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 한다.
서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리한다.
서블릿 객체는 싱글톤으로 관리된다.
모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근하고, JSP를 사용하는 경우도 서블릿으로 변환 되어 사용된다.
제일 중요한점은 동시 요청을 위한 멀티 쓰레드 처리를 지원한다
쓰레드가 뭔지 아래에서 살펴보자
쓰레드
위에서 요청이올때 WAS에 접근해서 servlet을 호출을 하는것은 누가 할까?
그것이 바로 쓰레드이다.
쓰레드는 애플리케이션 코드를 하나하나 순차적으로 실행하는 것을 의미한다. 쓰레드는 하나의 코드 라인만 수행한다.
예를들어 메인 메서드를 처음 실행하면 main이라는 이름의 쓰레드가 실행된다.
쓰레드가 없으면 자바 애플리케이션 실행이 불가능하다.
동시 처리가 필요하면 쓰레드를 추가로 생성한다.
위는 쓰레드를 하나사용하는 예시이다.
요청1이 첫번째 쓰레드에 접근해서 연결이 된후 처리중이라면 두번째 요청2는 위와 같이 대기상태에 들어갈 것이다.
쓰레드는 제한이없기때문에 무한대로 생성할 수 있다는 특성이있다.
그렇다면 요청 마다 쓰레드를 생성하면 되지않을까?
요청 마다 쓰레드를 생성하면 동시 요청을 처리할수있고, 리소스가 허용할 때 까지 처리가능하지만
쓰레드의 생성 비용이 매우 비싸고 컨텍스트 스위칭 비용이 발생한다.
따라서 쓰레드의 갯수를 서비스에 따라 제한해두고, 아래와 같이 사용한다.
쓰레드 풀
쓰레드풀은 말그대로 쓰레드를 보관하고 관리하는 공간을 의미한다.
요청1이오면 쓰레드풀에 있는 200개의 쓰레드중 하나를 할당하여 servlet과 연결하고 요청2가오면 남아있는 199개의 쓰레드중 하나를 할당하여 servlet과 연결할 것이다.
위에서 언급한것과 같이 쓰레드는 생성비용이 비싸므로 쓰레드풀을 미리 생성해두면 생성종료 비용(CPU)이 절약되고, 응답 시간이 빨라진다.
만약 최대 쓰레드가 모두 사용중이여서 쓰레드 풀에 쓰레드가 없다면 기다리는 요청은 거절하거나 특정 숫자만큼 대기하도록 설정할 수 있다.
실무에선?
WAS의 주요 튜닝 포인트는 최대 쓰레드수이다.
이 값을 너무 낮게 설정할때 동시 요청이 많으면 서버 리소스는 여유롭지만 클라이언트는 금방 응답 지연할것이고,
이 값을 너무 높게 설정할땐 동시 요청이 많을때 CPU,메모리 리소스 임계점 초과로 서버가 다운될 것이다.
따라서 상황과 여건에 따라 이 쓰레드수를 조정해야하며
만약 장애가 발생할경우 클라우드를 사용중이라면 일단 서버부터 늘리고 이후에 쓰레드를 튜닝하고,
클라우드가 아니라면 열심히 쓰레드를 튜닝한다.
* WAS는 멀티 쓰레드를 지원한다
다시 돌아가서 핵심은 WAS는 멀티 쓰레드를 지원하는 것이며 개발자는 멀티 쓰레드 관련 코드를 작성하지 않아도 되고, 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스 코드를 개발하면 된다.
멀티 쓰레드 환경이므로 싱글톤 객체(서블릿,스프링 빈)는 주의해서 사용하도록 한다.
자바 백엔드 웹 기술 역사
요약하자면 리소스를 담당하는 부분과 로직을 담당하는 부분을 나누는 춘추 전국 시대가 열렸고 결국 애노테이션 기반의 MVC의 등장으로 이 시대가 마무리된다.
애노테이션 기반의 스프링 MVC는 @Controller를 의미하며 이후 스프링 부트가 등장하게 된다.
과거에는 서버에 WAS를 직접 설치하고 소스는 War 파일을 만들어서 설치한 WAS에 배포했다. 그러나 스프링부트는 간략하게 빌드 결과(Jar)에 WAS 서버를 포함하고있다. 즉, 빌드 배포가 단순화되었다.
강의 자료
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
'Spring' 카테고리의 다른 글
Spring MVC 정리 3) 검증 (0) | 2023.11.06 |
---|---|
Spring MVC 정리 2)단계별로 구현하며 알아보는 스프링의 핵심 기술 (0) | 2023.10.25 |
빈의 생명주기와 스코프 , DL(의존성 검색) (0) | 2023.09.22 |
의존성 주입으로 살펴보는 컴포넌트와 자동 주입 (0) | 2023.09.15 |
의존성 주입으로 살펴보는 스프링 컨테이너와 싱글톤 컨테이너 (0) | 2023.09.12 |