6 min read

<Spring> 스프링 배우기 전 알아두면 좋은 개념

Web Application Server vs Web Server

  • Web Server : 단순한 정적인 리소스들 화면에 뿌려줄 수 있습니다.대표적인 예로 Apache,Nginx 등이 존재합니다.
  • WAS : 단순히 정적인 리소스들을 화면에 뿌리는 것은 물론 동적으로 사용자에게 맞춰서 데이터를 뿌려 줄 수 있습니다.즉,프로그래밍이 가능해집니다.자바 진영에서는 서블릿 컨테이너를 가지게 된다면 WAS의 기능을 수행할 수 있습니다.
  • 실제로는 둘의 경계가 모호하도록 서비스를 개발할 수 있지만,차이점은 알고 있는게 좋습니다.

서블릿

스프링을 배우기 전, 자바로 웹 어플리케이션을 처음 만들면 무조건 듣게되고 한번쯤은 사용해보게 되는 서블릿입니다.우선 서블릿이 하는일을 알기전에 대략적인 웹 통신(HTTP)에 대한 지식이 존재해야합니다.

저희가 사용하는 HTTP의 경우 L5 응용계층에서 사용하는 프로토콜입니다.즉 L4 수송계층(transport layer)에서 오는 TCP/IP 소켓에 대한 연결에 대한 처리를 해줘야합니다.(패킷을 받는경우 unpack하고,패킷을 보내는 경우 pack을 해준다고 간단하게 이해합시다)또한 소켓연결을 마치면,HTTP 요청 메세지를 파싱하고 헤더와 바디로 나누어 각각의 데이터가 어떤 행위를 포함하고 어떤 데이터를 보내려는지를 parsing해야합니다.

이후 들어온 요청에 의해 비지니스 로직을 마치면 응답메세지를 헤더와 바디로 나눠 작성하고 다시 TCP/IP 소켓에 대한 연결을 진행해서 L4계층으로 보내는 일까지 진행해줍니다.위와 같은 일련의 과정이 HTTP 통신을 하는데 필요한데 서블릿은 비지니스 로직을 실행하는 일을 제외한 수고로운 일들을 모두 처리해주는 역할을 수행한다고 이해하시면 됩니다.

그림을 통해 서블릿이 하는 일을 알아봅시다.

우선 WAS로 클라이언트가 HTTP 요청을 보냅니다.그러면 WAS는 해당 HTTP 요청을 파싱해서 request 객체와 response 객체를 생성합니다.그리고 생성된 객체들을 기반으로 서블릿 객체를 호출하여 비지니스 로직을 수행합니다.그리고 서블릿 호출이 종료될 경우 생성된 response 객체를 기반으로 HTTP 요청 응답을 생성하고 클라이언트에게 반환해줍니다.

좀 더 이해를 돕기위해 코드를 통해 해당 동작을 알아봅시다.

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

helloServlet이라는 서블릿 객체는 localhost:8080/hello라는 요청이 들어올 경우 생성됩니다.그러면 위에 설명한것 처럼 servlet 객체가 생성되기전에 이미response와 request 객체가 생성되어 있기에 service라는 메서드의 파라미터로 req,res를 사용할수 있습니다.(참고로 들어오는 요청마다 response와 request 객체는 모두 다릅니다)

service 메서드는 개발자가 비지니스 로직을 넣어두거나 response 객체에 원하는 응답 데이터를 직접 넣을 수도 있습니다.

결론적으로 res,req를 통해 편리하게 HTTP 스펙을 사용할 수 있게 해줍니다.

Multi Thread

우선적으로 Thread(쓰레드)에 대한 간단한 설명을 드리겠습니다.저희가 어플리케이션(프로그램)을 하나 실행시키는 단위를 process라고 합니다.그리고 이러한 process내에서 프로그램을 실행시키기 위해 존재하는 일꾼들을 thread라고 비유할 수 있습니다.쓰레드는 한번에 하나의 코드만을 실행시킬수 있기 때문에 동시에 어떠한 작업들을 진행해주기 위해서는 쓰레드를 여러개 생성해서 사용해야합니다.

당장은 자바 쓰레드 프로그래밍에 대한 포스트가 아니니 간략히 알려드리고 넘어가겠습니다.

그러면 서블릿에서 이러한 쓰레드를 어떻게 활용하는지 알아봅시다.서블릿의 경우 당연히 Multi Thread 방식을 취하고 있습니다.그러면 동시에 요청이 들어올경우 각기 다른 쓰레드를 생성해서 동일한 코드작업을 진행해줄수 있습니다.즉,요청이 들어올 경우마다 쓰레드를 생성하여 요청을 처리하는 것이죠.하지만 이러한 방식은 Context-Switching이라는 큰 단점이 발생합니다.이는 OS의 스케쥴러에서 나오는 개념인데 쉽게 말하면 CPU가 하나의 작업에 대한 연산을 진행하는 중 다른 작업의 연산으로 변경할때 드는 비용을 말합니다.즉,쓰레드를 생성할때마다 비용이 너무 많이 들어가게 되는 것입니다.이러한 단점을 보완하기 위해 아래와 같은 구조를 서블릿은 취합니다.

위 그림의 경우 Thread-Pool이라는 곳에 지정된 수만큼의 쓰레드를 미리 만들어 놓고 요청이 오면 해당 풀에서 쓰레드를 꺼내 사용하도록 하는 방식입니다.당연히 해당 쓰레드를 사용하는 작업이 종료되면 해당 쓰레드는 풀로 반납됩니다.이러한 방식은 앞서 말한 쓰레드의 생성비용이 줄어들고, 한번에 너무 많은 트래픽이 발생할 경우에도 유연하게 대처 가능합니다.

Ref: 김영한 - 스프링 MVC 1편