API 서버의 경우 JSON 또는 XML 형태의 데이터를 클라이언트에 제공하는 반면, 웹 애플리케이션은 직접 화면 UI까지 만들어 클라이언트인 브라우저에 제공합니다. 이러한 차이점을 바탕으로 RESTful API 서버와 웹 애플리케이션 서버를 그림으로 비교하면 다음과 같습니다.
그렇다면 스프링 부트에서는 웹 애플리케이션을 어떻게 개발할까요? 스프링 부트는 모델-뷰-컨트롤러(MVC)라는 프로그래밍 패턴을 지원합니다. MVC 패턴을 사용하면 빠르고 쉽게 애플리케이션을 개발할 수 있을 뿐만 아니라 웹 디자이너와 백엔드 개발자 간에 이루어지는 협업도 용이하게 할 수 있습니다.
자바로 웹 서비스를 개발하기 위해 많이 사용되던 기술 중 하나는 JSPJava Server Page입니다. 최근에는 타임리프와 같은 템플릿 엔진을 많이 사용하지만, 예전에는 자바로 웹 서비스를 개발한다고 하면 대부분 JSP를 사용했을 정도입니다. 물론 현재도 JSP로 구축된 서비스를 유지보수하기 위해 JSP를 공부하는 사람들이 많습니다.
다음 JSP 예시를 살펴보면, JSP를 잘 모르더라도 자바 언어에 익숙한 경우 JSP로 만든 웹 페이지에는 HTML과 자바 코드가 섞여 있다는 점을 금방 눈치챘을 것입니다. 클라이언트의 요청에 따라 변경되어야 하는 부분은 <% %>로 감싼 자바 코드에 의해 처리됩니다. 예시 속 웹 페이지에서는 자바의 랜덤 함수를 사용해 호출할 때마다 매번 다른 오늘의 운세가 표시됩니다. 이렇게 하나의 웹 페이지에 UI를 담당하는 HTML과 동적인 컨트롤을 담당하는 자바 코드가 섞여 있는 방식을 ‘Java in HTML’ 또는 ‘모델 1 아키텍처’라고 합니다.
fortune.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<html>
<body>
<%
String[] fortunes = {
"오늘은 운이 아주 좋습니다!",
"무난한 하루가 될 거예요.",
"조심해야 할 일이 있을 수 있어요.",
"행운이 따를 거예요!",
"뜻밖의 기회가 찾아올 거예요."
};
int index = (int)(Math.random() * fortunes.length);
String fortune = fortunes[index];
%>
<h2>오늘의 운세</h2>
<p><%= fortune %></p>
</body>
</html>
모델 1 아키텍처에서는 웹 디자이너의 관심사인 HTML 영역과 백엔드 개발자의 관심사인 자바 코드 영역이 하나의 모듈에 혼재되어 있습니다. 따라서 복잡할 뿐만 아니라 서로의 협업을 힘들게 하고, 유지보수 또한 어려워집니다. RESTful API 서버는 데이터를 만들어 제공하는 역할을 하고, 모바일 앱에서는 API 서버가 제공한 데이터를 사용해 화면을 구성하는 역할로 분명하게 구분되어 있습니다.
마찬가지로, 웹 애플리케이션 서버도 중간에 데이터를 매개로 하여 HTML 영역과 자바 프로그래밍 영역으로 나눌 수는 없을까요? 이를 실현하는 개념이 바로 ‘모델 2 아키텍처’ 또는 ‘모델-뷰-컨트롤러’라고 하는 MVC 패턴입니다.
MVC 패턴이란 웹 애플리케이션을 개발할 때 세 가지 요소, 즉 데이터를 담당하는 모델Model, 화면을 담당하는 뷰View, 전체적인 흐름과 비즈니스 로직을 담당하는 컨트롤러Controller를 분리해 구성하는 방식을 말하며, ‘모델 2 아키텍처’라고도 합니다. 따라서 웹 디자이너의 관심사인 뷰 영역과 백엔드 개발자의 관심사인 컨트롤러 영역 사이를 데이터에 해당하는 모델을 매개로 해서 분리하게 됩니다.
다음과 같이 스프링 부트는 브라우저의 요청을 컨트롤러에게 전달하고 그 처리 결과로 모델을 전달받아 뷰에 전달합니다. 뷰는 모델에 포함된 데이터를 사용해 HTML을 구성하고 그 결과를 스프링 부트를 통해 다시 브라우저에게 전달합니다. 다음 그림의 화살표를 따라 흐름이 진행되며, 스프링 부트를 중심으로 컨트롤러와 뷰 사이에 모델이 흘러가는 모습을 볼 수 있습니다.
이렇게 세 가지로 분리된 JSP 웹 페이지를 예제로 살펴보겠습니다. 백엔드 개발자는 컨트롤러에서 필요한 정보를 데이터베이스에서 가져오는 코드를 작성합니다. RESTful API 서버의 경우 데이터를 JSON 또는 XML 형태로 클라이언트에 전달합니다. 하지만 MVC 패턴의 웹 애플리케이션에서는 데이터를 모델(데이터를 보관할 수 있는 객체)에 넣은 다음, 이를 HTML 문서로 만들어 주는 뷰 이름을 반환하게 됩니다.
controller/MemberController.java
@GetMapping("/member/list")
public String getMembers(Model model) {
model.addAttribute("members", members);
return "member-list";
}
컨트롤러에서 전달받은 모델 데이터를 사용해 HTML을 구성하는 JSP 화면은 다음과 같습니다. 복잡한 자바 코드 대신에 단순히 모델 안에 들어 있는 데이터만 사용하는 것을 볼 수 있습니다. 모델을 매개로 해서 컨트롤러와 뷰를 분리하면, 각각의 영역이 단순화되어 개발과 유지보수를 더 쉽고 빠르게 할 수 있습니다.
member-list.jsp
<table>
<c:forEach var="member" items="${members}">
<tr>
<td>${member.id}</td>
<td>${member.name}</td>
<td>${member.email}</td>
<td>${member.age}</td>
</tr>
</c:forEach>
</table>
지금까지 MVC 패턴의 기본 개념과 동작 원리를 살펴봤습니다. 복잡했던 JSP 코드가 컨트롤러, 모델, 뷰로 깔끔하게 분리되는 것을 확인할 수 있었죠. 이것이 바로 현대 웹 개발에서 MVC 패턴이 널리 사용되는 이유입니다.
위 콘텐츠는 『이것이 스프링 부트다 with 자바』의 내용을 재구성하여 작성되었습니다.
댓글