서블릿
서블릿이란 자바 기반의 웹 프로그램 개발을 위해 만들어진 기술이다. 따라서 자바로 작성된 프로그램을 실행할 수 있는 서버 소프트웨어(예 : 톰캣)를 통해 관리된다. 즉 서블릿을 실행하기 위해서는 톰캣과 같은 서블릿 컨테이너(Servlet Container)가 필요하며 이러한 서버 소프트웨어는 일반적으로 WAS(Web Application Server)로 불리기도 한다.
데스크톱이나 스마트폰에서 실행되는 일반적인 애플리케이션과 달리 웹 프로그램은 서버에 접속해야만 화면을 볼 수 있고, 로그인이나 기타 기능은 모두 서버에서 실행된 이후 결과만 클라이언트(웹 브라우저)에 보이는 구조다.
기본적인 웹의 요청과 응답 과정
- 클라이언트(웹 브라우저)가 서버에 페이지(index.html)를 요청한다.
- 서버는 클라이언트에 요청받은 파일(html)을 응답한다.
- 클러이언트는 수신받은 파일(html)의 내용(CSS, 자바스크립트 포함)을 해석하여 화면에 표시한다.
이때 HTML은 정적인 파일이므로 실시간으로 변하는 뉴스 기사, 날씨 정보, 쇼핑몰의 상품 정보 등을 가지고 있을 수 없다. 이러한 정보는 데이터베이스에 저장되어 있기 때문에 사용자의 웹 요청을 받으면 별도의 프로그램을 통해 데이터베이스에서 가지고 온 정보를 HTML로 재구성하여 클라이언트에 다시 전달해야 한다.
HTML은 내용을 직접 수정하기 전까지 변하지 않으므로 정적인 파일이다.
이 외에도 사용자 로그인 처리를 위해서는 입력한 아이디, 비밀번호를 데이터베이스에서 저장된 내용과 비교하고, 게시판에 글을 올리기 위해서는 데이터베이스에 저장하는 과정이 필요하다. 서블릿은 바로 이러한 기능을 수행할 수 있도록 설계된 특수한 목적의 자바 프로그램이다.
서블릿의 동작 구조
- 클라이언트(웹 브라우저)가 서버에 페이지(url)를 요청한다.
- 서버는 요청 url에 매핑되는 서블릿을 호출하면서 파라미터를 전달한다.
- 서블릿이 실행되고 파라미터로 전달된 값을 처리하거나 데이터베이스와 연동한다.
- HTML과 데이터를 조합하여 재구성한 다음 클라이언트에 전달한다.
- 웹 브라우저는 수신받은 HTML 내용(CSS, 자바스크립트 포함)을 해석해서 화면에 표시한다.
그런데 서블릿은 HTML과 데이터를 조합하는 방식에 어려움이 있다.
다음 코드(서블릿 코드)를 본다.
out.println("<h2>"+username+"</h2>");
- out은 서블릿에서 클라이언트에 데이터를 전송하기 위한 출력 스트림이다.
- HTML 코드와 자바 코드를 문자열 결합으로 처리한다.
물론 문자열을 결합하는 코드는 여러 방법으로 개선할 수 있다. 하지만 한 화면에 수천 라인이 될 수도 있는 HTML 코드 구성을 위와 같이 자바 언어로 작성해야 한다는 것은 매우 비효율적이다. JSP는 바로 이러한 문제를 해결하기 위해 등장하게 되었다.
JSP
JSP(Java Server Pages)는 서블릿에서 HTML과 데이터 결합을 손쉽게 처리하기 위해 만들어졌다. 자바 중심의 서블릿과 달리 JSP는 HTML을 중심으로 데이터를 처리하는 특징을 가지는데, 쉽게 말해 HTML에서 자바 코드를 사용할 수 있는 구조다. 따라서 JSP는 HTML에 자바 코드를 더한 형태로 구성되며, 컨테이너에 의해 서블릿 형태의 자바 코드로 변환 후 컴파일 되어 컨테이너에 적재되는 구조가 된다.
위의 서블릿 코드는 JSP를 사용하면 다음과 같이 작성할 수 있다.
<html>
...
<h2><%= username %></h2>
...
</html>
- JSP 문법 자체는 page 지시어 선언 부분을 제외하면 HTML 파일 구조와 동일하다.
- CSS, 자바스크립트 사용 형식 또한 동일하다.
- <%= %>란 JSP 출력문으로 사칙연산, 간단한 변수의 출력 등에 사용된다.
서블릿과 비교했을 때 JSP를 사용하는 것이 편리하다는 것을 직관적으로 알 수 있으며 이러한 편리성 덕분에 오랫동안 JSP는 웹 개발의 기본이 되어왔다.
그러나 JSP를 이용한 개발에도 몇 가지 문제가 있다. 예를 들어 게시판이나 상품 목록과 같이 데이터를 반복해서 출력하거나 조건을 체크해야 하는 경우 단순한 HTML 문법만으로는 처리할 수 없기 때문에 자바 코드를 중간중간 사용해야 한다.
<table>
<% for(Member m : mlist) { %>
<tr>
<td><%=m.name %></td>
<td><%=m.email %></td>
</tr>
<% } %>
</table>
- <% ... %>는 스크립트릿으로 해당 블록 안에서 자바 코드를 자유롭게 사용할 수 있다.
- HTML 부분은 서블릿 컨테이너(톰캣)에 의해 out.println()을 사용하는 형태로 변환한된다. 따라서 JSP는 HTML이 아니라 궁극적으로 서블릿 형태의 프로그램으로 변환되는 것이다.
for 문 안에서 HTML과 데이터를 조합하려면 서블릿과 마찬가지로 'out.println()' 구문을 사용해야 한다. 이러한 문제를 피하려면 중간에 스크립트를 닫고 HTML에서 출력문을 사용하는 형태가 되기 때문에 코드가 복잡하고 가독성이 떨어진다.
JSTL/EL
위 JSP의 구조적 문제를 해결하기 위해 커스텀 태그를 기반으로 하는 JSTL(JSP Standard Tag Library) 및 EL(Expression Language)이 도입되었다. 위의 JSP 코드는 다음과 같이 개선될 수 있다.
<table>
<c:forEach var="m" items="${mlist}">
<tr>
<td>${m.name}</td>
<td>${m.email}</td>
</tr>
</c:forEach>
</table>
- <c:forEach>는 반복문을 제공하는 JSTL 커스텀 태그다.
- ${m.name}의 형태는 표현 언어로 자바 객체의 멤버 출력이 가능하다.
JSP보다 훨씬 구조적이고 가독성도 높아진 것을 알 수 있다. 이와 같은 프로그램 구조는 MVC 패턴과 함께 서블릿과 결합되어 오랫동안 자바 웹 개발의 정석으로 자리 잡아왔다.
물론 이 구조 역시 단점은 있다. 화면 구조를 서버에서 빌드(SSR)하는 구조이기 때문에 모든 실행이 톰캣과 같은 서블릿 컨테이너를 통해야 한다는 점이다. 예를 들어 <c:forEach> 태그나 ${m.name}, <%@ page.. %>와 같은 JSP 구문은 클라이언트(웹 브라우저)에서 해석할 수 없다. 즉 사소한 디자인 변경도 서버를 통해 실행해야 하며, 이는 개발 생산성과 디자이너와의 협업 등에서 큰 문제가 된다.
커스텀 태그란?
표준 HTML 태그 이외에 사용자 정의 태그를 자바 프로그램 형태로 구현하고 JSP를 서블릿 형태로 변환할 때 함께 처리될 수 있도록 하는 서블릿 규격 중 하나를 의미한다.
JSP 대체 솔루션
템플릿 엔진이라고 하는 JSP 대체 솔루션의 등장으로 여러 문제가 개선되기는 했지만, 2010년 이후 모바일 프로그래밍의 주류화, 자바스크립트 기술의 발전으로 인해 프론트엔드 개발이 새로운 트렌드가 되었다. 이후 전통적인 JSP 기반의 개발은 다소 성장세를 잃어가고 있다.
JSP의 주된 대체 솔루션인 스프링 프레임워크와 Vue.js에서 사용하는 형식을 간단하게 짚고 넘어간다.
스프링 프레임워크의 기본 템플릿 엔진인 타임리프를 사용하는 경우에는 다음과 같다. JSP와 EL 부분은 동일하지만 JSTL 대신 HTML 태그에 data-*- 속성을 사용하는 형태라 서버 실행 없이도 디자인 확인이 가능한 구조다.
<table>
<tr data-th-each="m : ${mlist}">
<td data-th-text="${m.name}">Hong</td>
<td data-th-text="${m.email}">test@text.com</td>
</tr>
</table>
- JSTL 대신 data-th-each와 같은 속성의 형태로 로직을 구현한다.
- 변수로 출력되는 데이터 이외 기본값 출력이 가능하다.
만일 Vue.js를 이용해 프론트엔드 개발 방식으로 클라이언트 사이드 렌더링(Client Side Rendering. CSR)을 사용한다면 다음과 같다. 물론 서버로부터 데이터를 가지고 오는 자바스크립트 코드는 생략된 상태다. 타임리프와 유사하게 v-* 형태의 속성을 사용하고 있으며 프론트엔드 방식이기 때문에 해당 속성은 자바스크립트로 동작하는 Vue.js에서 처리하게 된다.
<table>
<tr v-for="m in mlist">
<td>{{m.name}}</td>
<td>{{m.email}}</td>
</tr>
</table>
로직을 처리하기 위한 방법과 데이터를 핸들링하는 방법 등에서 차이가 있지만 HTML과 데이터 그리고 로직을 조함하는 방식이 모두 유사한 것을 알 수 있다.
'Programming > Web' 카테고리의 다른 글
[Web] 스프링 프레임워크 (0) | 2022.10.20 |
---|---|
[Web] REST API와 JAX-RS (0) | 2022.10.20 |
[Web] 웹 프로그래밍의 기초(JavaScript) (0) | 2022.10.19 |
[Web] 웹 프로그래밍의 기초(CSS) (0) | 2022.10.19 |
[Web] 웹 프로그래밍의 기초(HTML) (1) | 2022.10.18 |