상세 컨텐츠

본문 제목

3. 웹 서버와 서블릿

Tech - 웹 개론

by Nested World 2021. 10. 21. 00:05

본문

WAS

당연하게도, 이런 번거로운 작업을 매번 할 이유가 없다. 웹 표준은 말 그대로 표준이며, 따라서 웹 서버가 해야 하는 일은 모두 완벽하게 동일하다. 소켓을 통해 패킷으로 들어온 HTTP 메시지를 수신하고, 이를 파싱해서 적절한 컨텐츠를 찾아서 다시 HTTP메시지에 담아 응답하는 것이다.

이 과정은 모든 서버에서 완벽하게 동일하지만, 직접 만들려면 상당한 작업을 필요로 한다. 패킷을 수신하는것 부터가 그리 간단한 일은 아니다. 일단 스레드풀을 만들고, 커넥션이 들어오면 스레드 풀을 할당하고......... 하지만 다행히도, 당연히 누군가 이런 기능들을 모두 구현 해 놓았다.

Tomcat과 nginx같은 말을 들어본 적이 있을 것이다. 바로 이들이 위의 과정을 이미 개발해놓은 웹 서버이다. 보다 정확히는 Web Application Server, WAS라고 한다. 만약 여러분이 nginx를 사용하기로 결정했다고 하자. 그러면 웹 서비스를 제공하기 위해 여러분이 할 일은 그저 nginx를 설치해서 구동하고, nginx 설정파일에 명시된 경로에 웹 문서들을 올려두는것 뿐이다.

예를 들어 nginx를 사용한다면, 여러분이 할 일은 서버 역할을 할 PC에 nginx를 설치하고, conf/nginx.conf파일에서 root로 명시된 경로에다가 여러분이 서비스하고자 하는 html파일을 집어넣는것 뿐이다. 디렉토리를 통해 구조화도 할 수 있다. 만약 아래의 예시에서 html폴더 하위에 test폴더를 만들고 test.html을 추가하면, 브라우저에서 localhost/test/test.html을 통해 접근 가능하다.

 

Javascript

하지만, 아직 심심하다. CERN에서 논문 공유 용도로 사용할 때야, 그저 문서만 공유되면 충분했다. 웹 문서는 HTML표준을 따르고, 여기서는 하이퍼 링크를 지원하므로 다른 문서로 클릭하면 이동되는 좋은 기능이 포함돼 있기도 하니까 말이다.

하지만 당신이 고객들에게 보여주고 싶은것은 회사의 상품들이지, 논문이 아니다. 그냥 움직이지 않는 단순 문서만 보여주기에는 너무 심심하지 않은가?

따라서 웹 문서에 포함시켜서 같이 내려보내면 브라우저들이 동적으로 실행할 수 있는 어떤 소스코드같은것이 등장했고, 이것이 javascript이다.

*웹 문서의 형식인 HTML이 지원하는 하이퍼 링크는 javascript와는 관계가 없다. 하이퍼 링크는 HTML문서에 <a href="주소"> 이런식의 태그가 포함되어있으면, 브라우저가 이를 '클릭 가능하도록' 그려준다는 약속이다. 그리고 클릭하면 브라우저가 자동으로 해당 태그에 포함되어있는 href 값을 주소창에 입력하고 엔터를 친다. 즉, 동적으로 보이지만 사실 브라우저가 제공하는 기능이고 javascript와는 아무 관계가 없다.

 

서블릿

이제 당신은 단순히 고정된 문서를 선보이는 것을 넘어, 다양하게 움직이고 상호작용도 가능한 문서를 고객들에게 보여줄 수 있게 되었다. 하지만, 여전히 한계는 존재한다.

예를 들어서, 고객이 당신의 서버가 내려보낸 상품 카달로그를 보다가 그 상품을 구매하고 싶어졌다고 가정하자. 당신은 고객에게 내려보낸 웹 문서에 구매버튼을 넣어두었고, 이 버튼을 누르면 구매 요청에 해당하는 HTTP메시지가 서버로 날아온다.

그런데, 이것은 말 그대로 구매 요청이지 무슨 문서를 내려달라는 것이 아니다. nginx는 이러한 메시지를 받으면 어떻게 대응을 할까? 사실, 할 수 있는 것이 없다. 물론 설정에 따라서 적절한 응답메시지를 보낼 수는 있겠지만, 응답이 무슨 소용이 있겠는가? 여러분의 고객은 여러분에게 요청을 했는데, 여러분은 그 요청에 대해 알지 못한다. nginx는 이러한 요청이 왔다고 여러분의 DB에 저장해 주지 않기 떄문이다. (어떻게 알고 저장해 주겠는가?) 그렇다고 nginx의 로그를 매일 뒤져가면서 고객의 주문을 파악하겠는가?

따라서, 여러분은 이제 WAS로만 만족할 수가 없다. 여러분은 고객의 요청을 자체개발한 로직으로 처리해서 DB에 넣을 수 있도록, 웹 서버를 직접 개발해야 한다. 하지만, 앞서 말했던 과정을 다 개발할 필요는 없다. 이미 수신되어 파싱까지 완료된 HTTP메시지를 전달받을 수 있는 인터페이스가 언어별로 존재한다. 여기서는 웹개발의 표준처럼 쓰이고 있는 Java 언어에서 제공하는 서블릿을 다룰 것이다.

서블릿은 하나의 인터페이스다. 서블릿을 사용해서 직접 요청을 처리하는 로직을 구현하려면, 아래의 메소드를 구현하면 된다.

@WebServlet(name = "myServlet", urlPatterns = "/hello")
public class MyServlet extends HttpServlet {
	@Override
    protected void service(HttpServletRequest request, HttpServletResponse response){
    	//to do
    }
}

물론 실제로 패킷을 수신하고 메시지를 파싱할 WAS가 필요한데, Java의 Spring 프레임워크를 사용하면 이미 안에 Tomcat을 내장하고 있으므로 위의 메소드만 구현해주면 바로 요청 처리가 가능하니 테스트 해보고싶다면 그렇게 하자. Spring을 사용하지 않으려면 우선 Tomcat을 설치하고, 설정파일에서 명시한 경로에 서블릿을 컴파일한 jar파일을 올려두어야 한다. 몹시 번잡하고 피곤하므로 그냥 Spring을 사용하자.

HTTP요청 메시지가 오면, Tomcat(WAS)는 이것을 소켓으로부터 패킷 형태로 받아서 파싱한다음 객체로 만들어서 위의 service메소드에 인자 request로 넘겨준다. 물론 응답 메시지를 받을 response참조도 제공하므로, 여러분은 응답의 내용을 그냥 response에 넣으면 된다. 그러면 Tomcat이 이를 HTTP응답 메시지로 만들어서 사용자에게 제공할 것이다. 

*짧게 언급한 Spring프레임워크는 사실 서블릿 위에서 동작하는, 서블릿을 대체하는 강력한 프레임워크이다. 따라서 Spring을 사용할거라면 서블릿을 직접 사용할 이유는 없다. 다만 여기서는 서블릿을 설명하기 위해 tomcat이 필요한데, Spring이 편리하게 tomcat을 사용할 수 있게 해주기 때문에 사용했을 뿐이다. Spring은 매우 강력한 프레임워크로 거의 모든 웹개발은 이 프레임워크 위에서 이뤄진다. 이에 대해서는 추후에 설명할 것이다.

관련글 더보기