본문 바로가기
공부/springboot

SpringMVC(1) : 웹 어플리케이션 서버(WAS) 의 이해

by 샤샤샤샤 2023. 12. 6.

웹 서버(Web Server)와 웹 어플리케이션 서버(Web Application Server)

이 둘의 경계는 모호하나 굳이 구분하면 정적인 웹 서버와 동적인 웹 어플리케이션 서버로 나눌수 있다.

정적인 서버는 오직 정적 리소스만 제공하며, 따라서 html, css, js 파일, 이미지 등을 클라이언트에게 전송해주나, DB에 저장된 데이터 등을 이용해 그에 맞는 화면을 클라이언트에게 전송해주는 것은 불가능하다.

반대로 was는 프로그램 코드를 실행하여, 애플리케이션 로직을 수행 그에 맞는 화면을 보여주거나 행동을 하는 것이 가능하다. 웹 어플리케이션 서버가 웹 서버의 개념까지 포함하여 더 많은 기능을 제공한다고 생각하면 편하다.

 

일반적으로 웹 시스템은 웹 서버 => 웹 어플리케이션 서버 => DB 로 이뤄진다.

출처: 인프런 김영한님

중간에 웹 서버를 두지 않고, was에서 모든 처리가 가능하기도 하나, 이 경우 과부하의 위험이 존재하고, 정적 리소스를 처리하느라 어플리케이션 로직을 수행에 문제가 생길수도 있기에 이 둘을 분리하곤 한다.

이런 식으로 설계하면 서버 증설도 효율적으로 가능하다.

 

 

서블릿(Servlet)

현 시대에 모든 서버와 클라이언트간의 통신은 HTTP로 이뤄진다. 그러나 HTTP 는 요청을 받을때는 통신 내용을 해석하는 과정을, 보낼때는 새롭게 통신을 만들어야 하는 복잡한 과정이 필요하다. 이 정형화된 과정을 대신 처리해주는 java 기술이 존재하는데, 이것이 바로 서블릿(Servlet)이다.

출처: 인프런 김영한님

 

서블릿을 지원하는 was를 사용하면 자바 서블릿을 사용할수 있어 의미있는 비지니스 로직 개발에 집중할수 있다.

서블릿에는 HTTP요청을 쉽게 처리하는 HttpServletRequest 와 응답을 쉽게 만드는 HttpServletResponse 클래스가 존재한다.

 

서블릿 컨테이너

천명의 사람이 이용하는 웹사이트가 존재한다고 가정해보자. 만약 모든 이용자가 동시에 같은 요청을 서버로 보내면, 서버는 같은 요청을 처리하는 servlet 천개를 새롭게 만들고 없앨 것이다. 이는 시스템 자원 측면에서도으로도 엄청난 부담일 뿐더러, 처리 시간 측면에서도 새롭게 객체를 만들어야 하다보니 시간이 오래 걸린다. 이를 해결하기 위해 나온 것이 바로 서블릿 컨테이너다.

@WebServlet(name = "helloServlet", urlPatterns = "/hello") 
public class HelloServlet extends HttpServlet { 
 @Override 
 protected void service(HttpServletRequest request, HttpServletResponse response){ 
 //애플리케이션 로직
 }

위와 같은 코드를 통해 "helloServlet" 라는 이름을 가진 서블릿은 서블릿 컨테이너에 저장된다. 이후 /hello url로 요청이 들어오면, HTTP요청 내용을 기반으로 만들어진  HttpServletRequest 객체(request)와, 아직 아무런 내용도 없는  HttpServletResponse 객체(response)가 미리 생성되어 서블릿 컨테이너에 보관되어있는 "helloServlet" 서블릿을 실행한다. 그리고 "helloServlet"가 종료될때 개발자가 작성한 내용을 기반으로 request 의 내용을 채워 클라이언트에게 전송한다.

 

순서

  1. 웹서버가 HTTP 요청을 받는다
  2. 웹서버는 요청을 서블릿 컨테이너로 전달한다
  3. 서블릿이 컨테이너에 없다면, 서블릿을 동적으로 검색하여 컨테이너의 주소 공간에 로드한다
  4. 컨테이너가 서블릿의 init() 메소드를 호출하면, 서블릿이 초기화된다
    : 서블릿이 처음 로드됬을 때 한번만 호출
  5. 컨테이너가 서블릿의 service() 메소드를 호출하여 HTTP 요청을 처리한다.
    (요청의 데이터를 읽어 request를 만들고, 종료될때 response을 만들어낸다)
    서블릿은 컨테이너 주소에 남아있고, 다른 HTTP 요청들을 처리할 수 있습니다.
  6. 웹서버는 생성된 응답을 클라이언트에게 전송한다.

출처: 인프런 김영한님

 

서블릿 컨테이너는 자동적으로 서블릿을 관리하며, 서버가 시작될때 생성, 요청이 들어올때 호출, 생명주기 관리를 통한 삭제를 사용자 대신해서 처리해준다.

 

정리

서블릿 - HTTP통신을 쉽게 처리하게 해주는 java 기능. 서버가 지원해줘야 사용 가능.

            - 동시 요청을 위한 멀티 쓰레드 지원.

서블릿 컨테이너 - 서블릿을 관리해주는 was 기능. 생성, 초기화, 호출, 생명주기 관리를 담당.

                           - 서블릿은 싱글톤으로 관리되며 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용된다.

                           - 따라서 모든 사용자는 동일한 객체 인스턴스에 접근하게 된다.

 

동시 요청 - 멀티 쓰레드

동시에 다수의 사용자로부터 요청이 들어올때, 요청 순서대로 처리하는 것이 아닌 한번에 여러개의 요청을 처리하는 기능을 말한다. 이를 사용하면 컴퓨터 자원이 허용하는 한(CPU, 메모리 등) 다수의 요청을 한번에 처리할수 있어 지연시간이 없는 장점이 존재하나, 반대로 컴퓨터 자원을 넘어서는 요청을 처리하다 컨텍스트 스위칭이 일어나거나 서버가 다운될 위험이 존재한다.

*컨텍스트 스위칭 : cpu가 처리해야하는 1번 업무와 2번 업무가 존재할때, 1번 업무 처리 도중 2번 업무로 넘어가는 현상을 말한다. 일반적으로 실제 cpu 동작 시간보다 컨텍스트 스위칭 시간이 더 길기에 최대한 발생하지 않는 것이 좋다.

 

쓰레드 풀 - 멀티 쓰레드의 보완

요청이 들어올때마다 새롭게 쓰레드를 생성하느라 발생하는 지연 시간과, 너무 많은 쓰레드를 생성하다 서버가 다운될 위험을 피하기 위해 쓰레드 풀이라는 개념이 도입되었다. 쓰레드 풀은 미리 설정된 숫자만큼의 쓰레드를 생성해둔 뒤, 요청이 들어올때마다 해당 쓰레드에 요청을 넘기는 식으로 동작하기에 새롭게 쓰레드를 생성-종료하 않아 되는 장점이 존재한다. 또한 쓰레드 숫자를 넘어서는 요청이 들어오면, 해당 요청들은 대기시키거나 거절하는 방식으로 서버의 안정성을 보장해준다.

멀티 쓰레드를 생성, 관리하는 부분은 was에서 처리해주기에 사용자는 복잡한 쓰레드 관련 코드를 신경쓰지 않아도 된다.

출처: 인프런 김영한님

자바 웹 기술의 역사

과거에는 jsp를 주로 사용했으며, 스프링 mvc 의 기능도 다양하지 않아 다양한 MVC 프레임워크가 존재했다. 또한 배포 역시 서버에 직접 was를 설치한 뒤, 코드 소스를 war 파일로 만들어 was에 배포하는 복잡한 방식으로 이뤄졌다.

하지만 시간이 흐르고 어노테이션 기반으로 간단하게 MVC 패턴을 만들수 있도록 스프링 MVC가 발전하고, 이와 강력하게 기능이 통합되면서도 jpa보다 더 빠르고 기능이 다양한 타임리프와 was를 내장하고 있는 스프링 부트가 나오면서 빌드 결과가 was 서버에 포함됨에 따라 개발의 편의성이 올라갔다.