[Web] 웹 애플리케이션의 발전 - CGI, Servlet
정적인 컨텐츠만을 제공하던 시기(CGI 도입 전)
CGI라는 기술이 사용되기 전에는 정적인 컨텐츠만을 웹에서 제공했다. 고정된 내용의 html만 보여준다고 이해하면 된다.
(CGI에 대한 자세한 설명은 다음 항목에서 할것이니 지금은 몰라도 괜찮다.)
따라서 사용자는 항상 같은 내용의 정보만 봐야한다. 즉, 아무리 유익한 정보를 공개해도 그 내용이 매번 같으면 사용자는 흥미를 잃는다. 매번 같은 컨텐츠니 사용자의 흥미는 더 빨리 떨어지고 결국 사용자가 감소하게 된다.
기업이 웹을 통해 제품이나 정보를 공개하거나 광고를 할 경우, 효과를 최대화하려면 조금이라도 더 많은 사람이 웹 컨텐츠를 열람하도록 유도해야한다. (개인이 만든 웹 컨텐츠도 더 많은 사용자가 봐줬으면 한다.)
사용자 역시 재밌는 컨텐츠를 보고싶은 욕구가 있는데 동적인 컨텐츠만 있다보니 만족하지 못한다.
이런 욕구를 만족하기 위해서는 동적인 컨텐츠, 즉 항상 새로운 컨텐츠를 제공해야 한다. 하지만 컨텐츠의 갱신을 사람이 매번 직접하는 것은 힘들것이다. (html을 매번 바꿔서 등록?!)
미리 준비된 컨텐츠만 보여주는 웹 서버(Web Server)에게는 자동으로 컨텐츠가 갱신되는 일은 힘든 일이다.
CGI(Common Gateway Interface)의 탄생
동적 컨텐츠를 생성해 웹 클라이언트에 보내기 위해 웹 서버와 컨텐츠를 생성하는 프로그램의 연동이 필요하다. 거기서 고안된 것이 CGI(Common Gateway Interface)라는 구조다.
컴퓨터를 이용해 컨텐츠에 변화를 주는 방법이 있다. 아래와 같이 실시간 동적 컨텐츠를 보여주면 사용자의 흥미가 생기지 않겠는가?
- 웹 페이지에 접속자 수가 표시, 그 페이지가 얼마나 인기 있는지 알 수 있다.
- 접속한 시간에 맞춰 아침에는 "좋은 아침이네요, OO님", 점심에는 "점심은 드셨나요? OO님", 저녁에는 "즐거운 저녁이에요, OO님"같은 식으로 인사에 변화를 준다.
- 실시간으로 상품의 재고를 사용자에게 알려준다.
- 사용자가 올리는 게시글을 실시간으로 다른 사용자에게도 보여준다.
더 많은 정보, 더 편리하고, 좋은 경험을 사용자에게 제공할 수 있다.
이를 구현하려면 어떤 기능이 있어야 할까?
웹 서버에서 작동하는 프로그램을 만들어 그 프로그램이 사람 대신 컨텐츠를 생성하면 될 것이다.
즉, html을 예로들면 프로그램이 html을 동적으로 생성하도록 하는 것이다. 이렇게 동적으로 생성한 html등의 컨텐츠를 동적 컨텐츠라고 한다. (미리 준비된 컨텐츠는 정적 컨텐츠다.)
CGI에서는 다음 흐름을 가진다.
- 웹 서버가 클라이언트로부터 받은 요청을 웹 서버상에서 작동하는 프로그램에 보낸다.
- 프로그램은 요청을 참조해 HTML을 생성, 웹서버에 돌려보낸다.
- 웹 서버는 프로그램으로부터 받은 HTML을 클라이언트에 보낸다.
이때 웹 서버상에서 동적 컨텐츠를 생성할 목적으로 주로 이용되던 것이 펄(Perl)이라는 프로그래밍 언어였다. 또 규모가 거대하거나 빠른 속도가 요구될 때는 C언어로 작성한 프로그램이 활약했다.
CGI는 어디까지나 '웹 서버와 프로그램 사이에서 요청과 응답을 주고받기 위한 규약' 이었으므로 응용 범위를 넓히기 쉬웠다.
CGI로 인해 웹 서비스가 폭발적으로 성장했다.
서블릿(Servlet)의 등장
CGI를 이용한 웹 애플리케이션이 보급됨에 따라 새로운 문제도 발생했다.
- 개발 언어 문제
- 웹 애플리케이션에 요구되는 기능의 규모가 커지고 복잡해짐에 따라 주로 사용하는 언어인 펄(Perl)로 프로그램을 제작하기가 어려웠다. (펄은 텍스트 처리에 강점이 있는 언어, 대규모 애플리케이션에 사용하기에는 적잡하지 않았다.)
- 성능 문제
- 웹 브라우저 요청이 도착할 때마다 CGI를 통해 프로세스를 기동했다. (1요청 1프로세스)
- 이는 조금 시간이 걸리는데, 접속 수가 적을 때는 전혀 문제가 없지만 하루 접속수가 수만, 수십만에 이르면 프로세스가 많이 만들어져 처리 속도가 요청을 따라잡지 못한다.
- 결국 인기가 많은 웹 서비스의 사용자는 웹 사이트에 접속해도 흰 화면만 보는 상황이 생긴다.
자바/서블릿의 탄생으로 이런 문제를 해결했다.
웹 애플리케이션 개발이 위의 문제로 고통받고 있을 때 자바가 등장했다.
자바는 객체지향 기능을 완벽히 지원하고, 대규모 시스템을 개발하기 용이했다. 당시 널리 사용되던 C 언어와 문법도 비슷하여 개발자들이 쉽게 받아들일 수 있었다. 멀티 스레드와 보안, 네트워크 통신 등 당시 중요성이 높아지던 기술을 표준화된 방식으로 지원했다는 점도 매력적이었다. (자바 보안에 대한 Oracle Guide 문서)
자바 자체는 웹 애플리케이션을 위해 개발된 언어가 아니다. 그러나 웹 애플리케이션은 당시 기업의 시스템 개발에서도 주류가 되고 있었다.
그래서 JavaEE의 일부로서 서블릿(Servlet)이라는 웹 애플리케이션 개발을 지원하기 위한 기능을 제공했다.
서블릿은 자바로 만들어진, HTML 등의 웹 컨텐츠를 생성하기 위한 프로그램이다.
CGI를 경유해 기동하는 펄이나 C언어 프로그램의 자바 버전이다.
서블릿은 아래와 같은 특징이 있다.
- 기본적으로 CGI와 같은 개념
- 컨텐츠를 생성하는 언어가 자바이며 객체지향을 지원함으로써 대규모 애플리케이션 개발에 적합하다.
- 웹 서버와 같은 프로세스 속에서 컨텐츠를 생성하는 프로그램이 작동하기 때문에 CGI처럼 새로운 프로세스를 매번 기동할 필요가 없고 요청에 따라 스레드가 생성해서 비교적 고속으로 작동한다. (1요청 1스레드 생성)
서블릿 컨테이너(또는 웹 컨테이너)
서블릿 컨테이너란?
서블릿을 위한 컨테이너로, 서블릿의 생명주기(Lifecycle)를 관리하고, URL과 특정 서블릿을 맵핑하며, URL 요청이 올바른 접근 권한을 갖도록 보장한다. 서블릿의 표준은 인터페이스로 제공되며, 구현체는 서블릿 컨테이너인 Tomcat, Jetty, Undertow가 제공한다.
- 통신 지원
- 웹서버와 서블릿이 통신 할 수 있도록 API를 제공한다.
- 개발자는 서블릿에 비즈니스 로직만 구현하면 된다.
- 생명주기(Life Cycle) 관리, 서블릿의 생명주기 메서드 init(), service(), destroy() 세 가지를 활용한다.
- 서블릿 초기화 메서드 호출 (init)
- HTTP 요청에 해당되는 적절한 서블릿 메서드를 호출한다.(service)
- 서블릿 종료 메서드 호출 (destroy)
- 멀티스레딩 지원
- 새로운 HTTP 요청이 들어오면 스레드를 부여한다.
- 1요청 1스레드
서블릿 컨테이너가 서블릿에 어떻게 관여하는가? - 참고자료
1. 사용자가 브라우저를 통해 HTTP 요청을 보낸다.
2. 요청을 받은 서블릿 컨테이너는 HttpServletRequest, HttpServletResponse 두 객체를 만든다.
3. 서블릿 컨테이너는 요청을 처리할 수 있는 서블릿을 찾아서 스레드를 할당하고, HttpServletRequest, HttpServletResponse 두 객체를 전달한다.
4. 서블릿 컨테이너는 service 메서드를 호출한다. HttpMethod에 따라 doGet() 또는 doPost()를 호출한다.
5. 1번 그림을 보면 GET 메서드의 요청이므로 doGet() 메서드를 호출하고, 컨테이너에게 응답 객체를 전달한다.
서블릿 컨테이너는 1요청당 1스레드를 할당한다. 서블릿 컨테이너는 각 서블릿마다 객체를 하나씩만 만든다. 따라서 스레드 안전하기 위해서는 서블릿은 스레드끼리 공유했을 때 위험한 상태를 가지면 안된다. request나 response 또한 마찬가지다. (request나 response 객체의 경우 서블릿 컨테이너가 요청마다 새로 만들기 때문에 스레드 안전하다고 볼 수 있다.)
핵심은 1요청 1스레드다.
서블릿 필터
서블릿 필터(Filter)는 서블릿으로 요청이 전송되기 전에 추가적인 처리를 적용하고 싶을 때 사용한다.
- 예를 들면 모든 서블릿의 요청의 로그를 쌓을 수 있다.
- 서블릿 시작, 종료 시간을 로그로 기록해 호출 지연되는 부분을 찾기도 한다.
마무리
CGI와 서블릿에 대해 알아봤다.
이후에 Spring MVC 에서 활용하는 Front Controller Pattern도 알아보면 좋겠지만, 이 글에서는 여기까지만 정리하고 기회가 되면 다른 글에서 자세히 정리해보고싶다. (대신 이 아티클을 참고하는 것으로 참아주시길!)
프로그래밍의 역사를 공부하다보면 문제가 생기고 이를 해결하는 과정의 반복으로 이뤄지는걸 느낀다.
항상 완성된 프로그램이라는 건 없는 느낌이고, 계속해서 문제점을 찾아내고 이를 해결하는 방법을 찾아내는것이 개발자의 평생 숙제라 생각한다!
참고자료
- 프로가 되기위한 웹기술(위키북스) - 고모리 유스케 지음/김정환 옮김
- https://www.oreilly.com/library/view/head-first-servlets/9780596516680/ch02s04.html