브라우저에 www.sample.com을 입력하면 어떤 일이 발생하나요?
면접 단골 질문이자 인터넷에서 많은 내용을 찾을 수 있는 질문입니다. 하지만 대부분 클라이언트 측면에서 발생하는 내용을 담고 있고 web server(이하 WS), web application server(이하 WAS), Spring, servlet 등의 관계를 정확히 이해하지 못하는 분들이 있어 해당 글을 통해 알아보고자 합니다.
본 글을 웹 프레임워크를 사용해 본 독자를 대상으로 합니다. WS, HTTP 등에 대한 사전 학습이 필요합니다.
WAS, MVC, Spring에 대한 깊이 있는 설명보다는 그들의 연결에 중점을 맞추고 있습니다.
태초의 웹 서비스로 돌아가 봅시다. HTTP 요청을 받으면 미리 저장된 데이터를 return 해주었습니다. 사용자가 데이터에 개입할 여지는 없었죠.(체험하기) 하지만 요즘 웹 서비스는 어떤가요? 가장 쉬운 예시로 로그인을 생각해 봅시다. 사용자가 어떤 정보를 서버에 보내면 서버는 로그인 실패 혹은 로그인이라는 응답을 보내줍니다. 즉 사용자와 서버가 상호작용하며 동적으로 데이터를 만들고 있습니다. 동적으로 데이터를 만들어 낸다는 것은 어떠한 가공 처리가 이루어졌다는 이야기입니다. 이렇게 동적으로 데이터를 처리하면 스크롤에 따른 새로운 피드, 사용자 맞춤 광고 등이 가능하며 보다 나은 서비스를 제공해 줄 수 있습니다.
간단히 사진으로 보면 아래와 같습니다.
“가공 처리”는 결국 어떠한 코드를 실행했다는 의미겠죠? 결국 어떻게 코드를 실행할 것인가 이 질문이 오늘 주제의 핵심입니다. 그 발자취를 따라가 봅시다.
CGI는 HTTP 서버와 web content를 생성하는 프로그램과의 Common Gateway Interface를 의미합니다. CGI 규약만 지킨다면 Python, C++, C, Java 등 어떠한 프로그래밍 언어로 작성해도 상관없습니다.
하지만 CGI 프로그램은 요청마다 새로운 프로세스를 생성합니다. 모두 독립적이기에 무겁고 느리고 중복된 코드가 많이 발생할 수밖에 없습니다!
왜 Interface가 필요한지를 한번 생각해 보시면 Servlet의 존재 의의도 이해하실 수 있습니다. 웹 통신이 HTTP 프로토콜을 사용한다는 점을 한 번 떠올려 보세요.
우선 Servlet은 HTTP 요청에 대한 파싱 그리고 그에 대한 응답을 만들어 주는 Java 클래스라고 생각하시면 됩니다. CGI의 주요 단점은 개별 프로세스를 요청마다 생성하고 종료시켜야 하는 것이었습니다. Servlet은 WAS을 Servlet Container에 등록하면 WAS가 이를 관리하고 스레드 단위로 요청이 실행됩니다. 조금 복잡하죠? 사진을 통해 조금 더 자세히 알아봅시다.
가공이 필요한 요청이 WS로 들어온 경우를 생각해 보면, WAS로 가공을 부탁합니다. WAS는 해당 요청에 맞는 Servlet을 찾아 실행한 후 결과를 WS로 보내줍니다. 그림을 보면 알 수 있듯, Servlet은 생명 주기를 가집니다.
생명 주기는 아래와 같습니다.
WAS의 한 종류인 Tomcat은 한 번 생성된 Servlet 객체를 메모리에 두어서 init() 메서드가 한 번만 실행하도록 관리를 합니다. 또 종료되기 전이나 reload 전에 destroy()를 호출하여 매번 객체가 생성되는 것을 방지합니다.
하지만 이러한 방식은 아래 그림처럼 어떤 공통 로직을 처리해야 한다면 코드가 반복되는 문제점을 가지고 있습니다. 만약 어떤 서블릿에서 공통 로직을 잊어버렸다면 상당히 곤란하겠죠?
(Servlet을 가지고 코딩을 해보셨다면 구체적인 코드가 떠오르시지 않을까 합니다.)
그럼 아래와 같은 구성을 하면 좋지 않을까요? 입구를 하나로 만들어서 공통 로직을 모두 처리하고 요청에 맞는 컨트롤러를 찾아서 호출하도록 하는 것이죠.
그렇다면 다른 컨트롤러는 굳이 Servlet이 아니어도 괜찮겠죠? 그럼 Servlet을 WAS에 하나만 등록하고 나머지 컨트롤러는 Servlet 객체 상속을 안 받아도 되니 구현도 훨씬 단순해지겠죠!
Spring 프레임워크는 Front Controller를 제공해주고 이를 Dispather Servlet 이라 부릅니다. 그렇다면 최종 모습은 아래와 같겠죠.
전체적인 구조 이해를 위해 Tomcat에 어떻게 Servlet을 등록하는지, MVC, Front Controller 등에 대한 내용과 코드를 모두 생략했습니다. 이는 다음에 다루어 보도록 하겠습니다. 개인적으로 Tomcat에서 어노테이션을 통해 Servlet을 등록하는 것을 보고 Spring과 상당히 유사하다고 느꼈습니다. 아마 Spring이 이를 참고하지 않았을까 합니다. (Bean 관리도 그렇고요) MVC도 왜 HTML, CSS, JS로 파일을 나눈 이유와 유사한 부분을 많이 느꼈습니다.
참고 링크