서블릿은 Http 메세지를 개발자가 쉽게 처리할 수 있게 돕는 Java 프레임워크다. 원래는 Http메시지를 직접 개발자가 파싱해서 처리해야겠지만, 서블릿을 통해 이러한 반복작업을 줄일 수 있다.
서블릿은 수신된 Http 메시지를 파싱해서 HttpServletRequest 객체로 만들고, 개발자가 응답메시지를 보낼 때 사용할 수 있는 HttpSevletResponse 객체 또한 제공한다. 이들은 Sevlet을 상속받아서 service 메소드를 오버라이드하여 사용할 수 있다. 당연히 각각의 객체는 한번의 Http 요청과 응답이 수행되는 동안만 유지된다.
*당연히, Http 메시지 자체를 수신하는데 필요한 TCP소켓 관련 로직이나 멀티스레드 관련 처리 등, 모든 기반 서버 로직역시 서블릿에 포함되어 있다. (이를 Web Application Server - WAS라고 한다) 따라서 서블릿으로 개발하면 개발자는 비즈니스 로직에만 신경을 쓰며, 마치 싱글스레드 프로그램처럼 개발할 수 있다.
*이러한 서블릿을 지원하는 서버 패키지들이 많이 있다. 톰캣같은 것들이 이에 포함되며, 이들은 내부에 WAS와 서블릿 컨테이너를 가지고있다. 프로그래머가 개발한 서블릿 클래스들(서블릿을 상속받아 service메소드를 구현한 클래스)은 톰캣에 의해 컨테이너 안에 생성되어 관리되며, 톰캣은 WAS로 요청이 들어오면 이를 적절한 서블릿 인스턴스에 전달해 처리하고 응답을 내보낸다.
즉, 서블릿은 Http 메시지를 받아서 원하는 처리를 수행하고, 필요한 응답을 보내는 과정에서 불필요한 반복적인 개발(메시지 파싱이나 응답 메시지에 들어갈 헤더 작성 등)을 줄여주는 역할을 한다. 따라서 Http 메시지를 이해하지 못하면 서블릿을 이해할 수 없다. 결국 서블릿을 이해하기 위해서는 Http 자체를 이해해야 한다.
여기서 Http의 자세한 스펙을 논하지는 않겠지만 Http도 결국은 통신 프로토콜의 일종이고, 'Http 메시지'를 통해 상호간에 통신한다. 우리가 흔히 사용하는 웹 브라우저 역시 이 프로토콜에 특화되어 있는데, 웹 브라우저는 아주 능숙하게 Http 메시지를 처리해서 그 안에 있는 내용을 우리에게 보여준다. 실제로 Http 메시지에는 메시지의 내용(Body)뿐 아니라 다양한 헤더가 포함되어있다. 이들에 대한 자세한 내용은 공식 스펙문서를 통해 확인할 수 있다.
한편, Http 메시지 안의 내용은 다양한 것이 될 수 있다는 점에 주의해야 한다. 절대로 HTML과 HTTP를 혼동해서는 안되며, 둘은 직접적으로 아무런 상관이 없다. Http 메시지에 들어가는 대표적인 것이 HTML 문서이지만, 꼭 HTML문서만 Http 메시지에 포함되는 것은 아니다. Http 메시지의 내용은 단순한 문자열(혹은 개발자가 단독으로 정의한 어떠한 프로토콜을 따르는 문자열)일 수도 있고, json이나 HTML 문서 등 모든것이 될 수 있다.
*애초에 구글 검색창에 뭔가를 검색했을 때 구글서버로 날아가는것도 Http 메시지이다. 여기에 당연히 HTML은 들어있지 않다. 다만 구글 서버가 이 요청을 받아서 우리가 원하는 페이지(HTML)을 보여주기 위해 응답을 할 때, 그 응답 메시지에는 당연히 HTML이 들어있다. 요점은 Http와 Html은 아무 관계가 없다는 것이다.
Http 메시지는 어떠한 요청/응답을 위해 날아다니는 메시지이다. 먼저 요청을 살펴보자면, 요청에는 당연히 '요청의 내용'과 '파라미터'가 포함되어야 한다. 실제로 Http 요청 메시지에는 이러한 내용이 포함된다. 요청의 내용은 메시지의 url에 들어있지만, 파라미터를 포함시키는 방식은 하나가 아니라 크게 3가지 정도로 나뉘어 있다. 하나는 url 자체에 파라미터를 포함시키는 방식, 다른 하나는 body에 파라미터를 넣는 방식, 마지막 하나는 로우 텍스트(보통은 json)를 통해 필요한 파라미터를 전달하는 방식이다.
*웹 브라우저에서 ? 뒤에 파라미터들을 넣고 &로 서로 연결하는 것으로 쉽게 첫번째 방법을 테스트할 수 있다. 두번째 방식은 <form>태그를 통해 작성된 문서를 통해 흔히 볼 수 있다. 전자의 경우는 URL 자체에 파라미터를 전달하는 방식이므로, Http메시지의 Body는 비어있다. 후자의 경우 Http메시지의 Body에 파라미터가 들어간다. 하지만 어쨌든 서블릿에서는 동일한 방식(getParameter)을 통해 이들을 사용할 수 있다.
어떤 방식으로 요청이 들어오든, 서블릿은 그 요청을 파싱해서 Request 객체로 만들어 개발자에게 제공한다. 또한 개발자가 Response객체를 채워서 리턴하면, 이 내용을 응답 메시지에 담아서 송신한다.
이 때, 당연히 응답 메시지의 방식도 여러개가 있을 수 있다. 그냥 로우 텍스트(보통 json)를 응답하는 경우도 있지만, HTML문서로 응답을 하는 경우도 있다. 예를 들어 웹 브라우저에서 구글을 치면, 구글 서버는 우리가 알고있는 그 구글 웹 페이지(HTML문서)를 응답해 줘야 한다.
여기에 문제가 있다. 서블릿은 자바 코드이고, 따라서 HTML로 응답을 해야 하는 경우 HTML문서를 Java 스트링으로 코딩해야 한다. 웹 페이지가 .java 소스파일에 하드코딩 되어야 한다는 뜻이다. 이것은 난이도가 어려운것이 문제가 아니라 절대로 해서는 안되는 짓이다.
서블릿으로 웹 서버를 작성해보면, 불필요하게 반복되는 코드가 지나치게 많다.
문제점 1을 해결하기 위해, 템플릿 엔진을 사용한다. 서블릿을 통해 HTML 문서를 응답할때는 자바 코드에 HTML이 포함되는 방식이었다면, 템플릿 엔진은 응답이 될 HTML문서에 자바 코드를 포함시키는 방식으로 개발을 돕는다. 대표적인 탬플릿 엔진에는 JSP, Thymeleaf 등이 있다.
*서버에서 HTML을 만들어서 응답하고 클라이언트(웹 브라우저)는 이를 그대로 표시할 뿐이기 때문에, 이런 방식을 '서버사이드 랜더링'(SSR)이라고 부른다.
Spring MVC가 문제점 2를 해결한다. 스프링 MVC도 근본은 서블릿에서 시작하지만, 다양한 아이디어를 통해 많은 불편함을 개선하여 개발자가 꼭 필요한 작업만 해도 서버가 원하는대로 동작하도록 돕는다.
짤막 팁 (0) | 2021.05.25 |
---|---|
서블릿에서 스프링 MVC까지 - 2 (0) | 2021.05.21 |
[Spring 해석] 2장. Spring MVC - 1절. 뷰와 컨트롤러의 상호작용 (0) | 2020.09.17 |
[Spring 해석] 1장. Spring이 시스템을 구성하는 방법 - 2절. 빈을 실체화 시키고 사용하기 (0) | 2020.09.16 |
[Spring 해석] 1장. Spring이 시스템을 구성하는 방법 - 1절. 빈을 등록하고 연결하기 (0) | 2020.09.14 |