Servlet은 무엇이며 어떻게 동작하는가?
웹서버 구축을 위해서 Java를 사용한다면 알아야하는 Servlet이라는 클래스에 대해 알아보자.
서블릿의 사용법보다 서블릿이 무엇이며 웹에서 어떤 환경 활용되고 있는지, 어떤 원리로 동작하고 있는지에 대해 중점적으로 알아보려 한다. 자바 서블릿이 웹 페이지를 동적으로 생성하게 해주는 클래스라고 하는데 어떻게 도와주는 것일까?
이것을 이해하기 위해선 웹이 어떻게 통신하는지부터 이해해야 한다.
HTTP
웹은 HTTP라는 비연결성 프로토콜을 이용해 통신을 한다. 메세지 방식에는 request와 response가 있는데, 서버측에 요청(request)을 하면 서버는 요청에 맞는 데이터를 응답(response)한다. 보통 요청을 보내고 응답을 받는 쪽을 클라이언트라 말하고, 요청을 받고 응답을 보내는 쪽을 서버라고 한다.
클라이언트는 브라우저의 주소창에 사이트 주소를 입력하는 사용자라고 생각하면 된다.
주소를 입력에 서버에 요청을 보내면, 서버는 해당 요청을 받아서 알맞은 데이터를 응답해야 한다고 했다. 이때 사용되는 것이 서블릿이다.
WAS : Web Application Server
Servlet을 알아보기 전에 알아야 하는 것이 하나 더 있는데 바로 WAS이다. WAS는 정적인 리소스 뿐 아니라 동적인 서버 컨텐츠를 구현할 수 있게 지원해주는 서버라고 할 수 있다. 자바 계열의 WAS는 Tomcat, Jetty 등이 유명하고, 이 글에서는 Tomcat을 사용한다.
Servlet
자바 서블릿은 위키에서 다음과 같이 정의하고 있다.
자바 서블릿(Java Servlet)은 자바를 사용하여 웹페이지를 동적으로 생성하는 서버측 프로그램 혹은 그 사양을 말하며, 흔히 "서블릿"이라 불린다. 자바 서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종이다. 서블릿은 JSP와 비슷한 점이 있지만, JSP가 HTML 문서 안에 Java 코드를 포함하고 있는 반면, 서블릿은 자바 코드 안에 HTML을 포함하고 있다는 차이점이 있다.
서블릿은 웹페이지를 동적으로 생성하는 서버측 프로그램이며 자바 클래스의 일종이라고 설명하고 있다. 하지만 서블릿 클래스 자체만으로는 웹페이지를 작성할 수 없다. 위에서 WAS를 설명한 이유는 WAS와 함께 서블릿이 동작하기 때문이다. 당연한 얘기지만 서블릿은 클래스, 즉 단순 자바코드이기 때문에 값을 전달하고 실행시켜줄 무언가가 필요하다. 이 일을 WAS가 담당한다고 생각하면 된다.
톰캣으로 작동하는 작동순서를 나열하면 아래와 같다.
- 개발자가 HttpServlet을 상속하고 클래스를 작성해 빌드하면 war확장자로 빌드된 파일이 생성된다.
- war 파일을 톰캣에 배포한다. → 서블릿 컨테이너에 등록한다고도 말할 수 있다.
- 톰캣 서버를 구동한다.
- URL 주소로 톰캣에 요청이 온다.
- URL의 PATH에 맞는 서블릿을 톰캣이 찾아 접근해 실행한다.
- 실행된 결과를 응답한다.
이렇게만 알아보면 얕은 것 같으니, 작동순서에서 조금 더 자세하게 들어가보자.
[1] HttpServlet 생성 → war 빌드
Tomcat 설치
WAS로는 톰캣을 사용하는데, 버전은 Tomcat 10 버전을 사용할 것이다. 홈페이지에서 Download의 Tomcat10으로 들어가서 다운받으면 된다.
Mac OS를 사용하기 때문에 tar.gz로 된 파일을 받았고, 압축을 풀어주었다.
압축을 풀어주고 bin폴더의 startup.sh를 실행하고 http://localhost:8080으로 접속해보면 다음과 같이 페이지가 잘 나온다.
잘 동작하는 것을 확인했다면 shutdwon.sh를 통해 서버를 종료한다.
💡
Java EE는 8버전을 이후로 더 이상 릴리즈되지 않고 있다. 이클립스 재단으로 프로젝트가 이관되었지만, 새로운 이름으로 개발되고 릴리즈 되고 있다. 앞으로 Java EE의 운명이 어떻게 될 진 모르겠으나 계속해서 발전하고 릴리즈 있는 Jakarta EE를 사용하는 것이 좋아보인다.
Tomcat 홈페이지에 보면 “Jakarta EE 플랫폼은 Java EE 플랫폼의 진화입니다.”라는 문구가 있다. 이렇게까지 말하고 있으니 앞으로는 Jakarta를 사용하도록 하자.
Java EE와 Jakarta EE에 대한 자세한 내용을 확인하고 싶다면 다음 링크를 통해 확인하도록 하자.
→ https://www.samsungsds.com/kr/insights/java_jakarta.html
프로젝트 생성
IDE는 Intellij를 사용할 것이고 스펙은 다음과 같이 설정했다.
Tomcat은 다운받은 폴더를 Application server로 연결해주면 된다. 그리고 Next를 누르고 Jakarta를 선택하고 프로젝트를 생성하자.
프로젝트를 생성하면 다음과 같이 기본적으로 servlet이 작성되어 있는 것을 볼 수 있다.
war 빌드
오른쪽의 아이콘을 클릭하면 Maven의 명령어가 보일 것이다. Lifecycle의 install을 통해 빌드를 해보면 프로젝트 폴더 내부에 target폴더가 생성이 되고, 안에 war파일이 생성된 것을 볼 수 있다.
[2, 3] 톰캣에 배포, 톰캣 실행
톰캣에 배포하고 실행하는 것은 IDE에서 간단하게 버튼 한번으로 가능하지만 동작과정을 직접 느끼기 위해 수동으로 배포해보도록 한다.
배포
- 빌드한 war파일을 ROOT로 이름을 변경한다.
- 변경한 ROOT.war 파일을 다운받은 톰캣 폴더 내부의 webapps폴더로 복사한다.
- 기존에 있던 ROOT 폴더는 삭제해버리자.
서버 실행
- 위에서 서버를 실행했던 것처럼 ./startup.sh 를 통해 실행해보도록 하자
💡 이름을 ROOT로 변경하는 이유
파일 이름이 ROOT.war이라면 다른 설정의 변경 없이 톰캣이 압축을 풀고 실행시켜주기 때문이다.
[4, 5, 6] URL 주소로 요청 및 응답
실행되고 있는 톰캣 서버에 다시 http://localhost:8080 으로 접속해보면 servlet을 실행하고 처리된 데이터를 보내주는 것을 알 수 있다. 조금 더 자세하게 알아보면 아래와 같은 동작을 가진다.
- 톰캣은 클라이언트로부터 요청이 오면 HTTP 요청을 서블릿 컨테이너로 넘기게되고, 서블릿 컨테이너는 HttpServletRequest, HttpServletResponse 객체를 생성한다.
- 요청에 알맞는 서블릿을 찾는다.
- 서블릿을 찾았다면 메모리에 서블릿이 존재하는지 확인한다.
- 메모리에 해당 서블릿이 존재한다면 해당 서블릿으로 로직을 실행한다.
- 메모리에 서블릿이 존재하지 않는다면 인스턴스를 생성하고 로직을 실행한다.
- 로직이 실행되었다면 처리한 데이터를 응답한다.
정리
정리를 해보자면 Java로 웹앱을 제작한다는 것은 보통 Java EE 또는 Jakarta EE에서 제공하는 API를 사용해 구현하는 것이라고 볼 수 있다. 그리고 해당 EE에서 제공하는 API중 Servlet도 포함이 되는 것이고, EE 표준을 어느정도 구현한 WAS(Tomcat)를 통해 Servlet을 작성, 배포하는 것이다.
서블릿 자체의 사용법을 아는 것도 중요하지만 이런 원리와 환경을 이해하지 못하고 사용하면 보이지 않는 바다에서 헤엄치고 있는 느낌이 들 수 있다. (본인이 그랬음..)
부족한 글이지만 공부하시는 분들에게 미약하게나마 도움이 되길 바라며 글을 줄인다.