본문 바로가기
Spring

Spring Tiles (스프링 타일즈)

by SuldenLion 2023. 7. 25.
반응형

스프링 타일즈(Tiles)란?

- 스프링 프레임워크를 기반으로 한 웹 애플리케이션에서 레이아웃과 템플릿 기능을 제공하는 뷰 템플릿 엔진.

- 스프링 타일즈를 사용하면 웹 페이지의 일부분을 재사용 가능한 타일(템플릿)로 정의하고, 이를 조합하여 다양한 웹 페이지를 생성할 수 있음.

- 페이지들을 일괄 관리 할 수 있고, 공통으로 사용하는 부분들을 매번 따로 등록해주지 않아도 된다. (디자인과 구조를 간편하게 관리, 코드의 재사용성과 유지보수성 향상)

 

 

▷ 스프링 타일즈의 특징과 장점

Tile(Template) 기반의 레이아웃 

- Spring Tiles를 사용하면 웹 페이지의 레이아웃을 타일로 분리하여 정의할 수 있음. 이렇게 정의한 타일을 여러 웹 페이지에서 재사용할 수 있으며, 레이아웃의 변경이 필요할 때 전체 웹 페이지를 수정하는 것이 아니라 타일만 수정하여 변경사항이 적용됨.

Tile 간의 상속과 확장

- Spring Tiles에서는 타일들 간에 상속과 확장이 가능함. 즉, 부모 타일에 공통적인 레이아웃을 정의하고 자식 타일들은 해당 레이아웃을 확장하여 개별적인 내용을 추가하거나 변경할 수 있음.

자체 템플릿 언어

- Spring Tiles는 JSP, Thymeleaf 등과 같은 다른 뷰 템플릿 엔진과 비교해 자체적인 템플릿 언어를 제공함. 이 언어를 사용하여 타일 정의와 속성 설정 등을 간편하게 처리할 수 있음

유연성과 확장성

- Spring Tiles는 Spring Framework와 통합되어 동작하므로, 스프링의 기능과 확장성을 그대로 사용할 수 있음. 또한 타일즈 설정 파일을 통해 다양한 기능과 동작을 커스터마이징 할 수 있음.

 

 

▷ 타일즈의 동작 방식

웹 애플리케이션에서 사용할 타일들을 정의하고, 각 타일의 레이아웃과 구성 요소를 정의하는 타일 정의 파일을 작성함.

② 웹 페이지에서는 타일 정의 파일에 정의된 타일들을 사용하여 웹 페이지의 레이아웃을 구성한다. 이때, 각 웹 페이지에서는 타일을 삽입하는 방식으로 웹 페이지의 내용을 정의함.

③ 컨트롤러에서 뷰를 처리할 때, Spring Tiles View Resolver가 타일 정의 파일에 따라 웹 페이지를 조합하여 최종 HTML 문서를 생성하고 클라이언트에게 반환함.

 

 

Tiles 방식을 사용하여 다음과 같은 웹 페이지를 띄워보도록 하겠다.

 

먼저, pom.xml 파일에 dependency를 추가해준다.

tiles-jsp와 tiles-core, tiles-servlet 세가지 의존성을 추가시켜준다.

 

 

다음은 servlet-context.xml의 View Resolver를 변경시켜준다.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<!--<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>  -->
	<beans:bean id="tilesConfigurer" 
            class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
            <beans:property name="definitions">
                <beans:list>
                    <beans:value>classpath:tiles/*.xml</beans:value>
                </beans:list>
            </beans:property>
            <beans:property name="preparerFactoryClass" 
                    value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory"></beans:property>
	</beans:bean>
	<beans:bean id="viewResolver"
                    class="org.springframework.web.servlet.view.UrlBasedViewResolver">
                    <beans:property name="viewClass" 
                    value="org.springframework.web.servlet.view.tiles2.TilesView"></beans:property>
	</beans:bean>
	<context:component-scan base-package="bitedu.bipa.tiles" />
    
</beans:beans>

 

Controller에서 반환된 뷰 이름을 실제 뷰로 변환시켜주는 역할을 담당하는 View Resolver이다. (컨트롤러에서 뷰 이름을 반환하면 뷰 리졸버가 해당 뷰 이름을 사용하여 최종적으로 뷰를 결정하고 랜더링함)

기존의 View Resolver 설정 방식은 InternalResourceViewResolver를 사용하여 설정했었다.

InternalResourceViewResolver는 내부 리소스를 뷰로 사용하는 기본적인 뷰 리졸버로 class="org..." 클래스를 생성하여 뷰 리졸버를 생성하고, 뷰 이름앞에 붙일 접두사(prefix)를 설정했다. (이 설정으로 뷰 이름을 반환할 때, '/WEB-INF/views/'와 함께 사용되어 최종적인 JSP 파일의 경로를 결정함)

그리고 뷰 이름 뒤에 붙일 접미사(suffix)를 설정했다. (이 설정은 뷰 이름을 반환할 때, '.jsp'와 함께 사용되어 최종적인 JSP파일의 경로를 결정함)

 

↳ Controller에서 return "hello"; 와 같이 뷰 이름을 반환하면, 뷰 리졸버는 '/WEB-INF/views/hello.jsp' 파일을 찾아서 해당 JSP 파일을 랜더링하여 클라이언트에게 응답하는 방식.

 

 

기존 방식 대신 Tiles 방식을 사용하기 위한 설정을 하겠다.

- tilesConfigurer는 타일즈 뷰 템플릿 엔진을 설정하는 TilesConfigurer 빈을 생성한다.

- definition property에는 타일즈의 정의 파일들 위치를 설정한다. tiles 폴더 밑의 경로에 있는 '*.xml' 파일들을 사용하도록 설정.

- preparerFactoryClass는 타일즈 뷰 템플릿에서 사용할 preparer 팩토리 클래스를 지정한다. 스프링 빈 기반의 SpringBeanPreparerFactory 클래스를 사용하도록 설정.

- viewResolver에는 뷰 리졸버를 생성하는 빈을 생성한다. viewClass라는 프로퍼티는 뷰 리졸버가 타일즈 뷰(TilesView)를 사용하도록 설정한다. 

 

위의 설정을 통해 스프링은 Tiles view 템플릿 엔진을 사용하여 웹 페이지의 레이아웃을 조각으로 나누고, 각 조각들을 재사용하여 웹페이지를 구성하게 된다. (타일즈를 사용하면 웹 페이지의 구성 요소들을 독립적인 타일로 분리하여 개발 및 유지보수를 편리하게 할 수 있으며, 웹 애플리케이션의 일관된 레이아웃을 유지하기에 용이함)

 

 

그럼 resources 아래에 tiles 폴더와 필요한 xml 파일을 만들어 줄 것이다.

 

세 개의 파일은 형태가 비슷하다. 이중 tiles_member.xml을 보겠다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
   <definition name="baseLayout"  template="/WEB-INF/views/common/layout.jsp">
      <put-attribute name="title" value="" />
      <put-attribute name="header" value="/WEB-INF/views/common/header.jsp" />
      <put-attribute name="side" value="/WEB-INF/views/common/side.jsp" />
      <put-attribute name="body" value="" />
      <put-attribute name="footer" value="/WEB-INF/views/common/footer.jsp" />
   </definition>

   <definition name="main" extends="baseLayout">
      <put-attribute name="title" value="메인페이지" />
      <put-attribute name="body" value="/WEB-INF/views/main.jsp" />
   </definition>

   <definition name="/member/loginForm" extends="baseLayout">
      <put-attribute name="title" value="Book List" />
      <put-attribute name="body" value="/WEB-INF/views/member/loginForm.jsp" />
   </definition>

</tiles-definitions>

tiles-definition 태그를 쓰고 그 안에 definition 들을 둔다. baseLayout은 '/WEB-INF/views/common/layout.jsp'의 파일이 될 것이다.

 

layout.jsp를 보면

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"  isELIgnored="false"
 %>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <style>
      #container {
        width: 100%;
        margin: 0px auto;
        text-align:left;
        border: 0px solid #bcbcbc;
      }
      #header {
        padding: 5px;
        margin-bottom: 5px;
        border: 0px solid #bcbcbc;
         background-color: lightgreen;
      }
      #sidebar-left {
        width: 15%;
        height:700px;
        padding: 5px;
        margin-right: 5px;
        margin-bottom: 5px;
        float: left;
         background-color: yellow;
        border: 0px solid #bcbcbc;
        font-size:10px;
      }
      #content {
        width: 75%;
        padding: 5px;
        margin-right: 5px;
        float: left;
        border: 0px solid #bcbcbc;
      }
      #footer {
        clear: both;
        padding: 5px;
        border: 0px solid #bcbcbc;
         background-color: lightblue;
      }
      
    </style>
    <title><tiles:insertAttribute name="title" /></title>
  </head>
    <body>
    <div id="container">
      <div id="header">
         <tiles:insertAttribute name="header"/>
      </div>
      <div id="sidebar-left">
          <tiles:insertAttribute name="side"/> 
      </div>
      <div id="content">
          <tiles:insertAttribute name="body"/>
      </div>
      <div id="footer">
          <tiles:insertAttribute name="footer"/>
      </div>
    </div>
  </body>
</html>

전체적인 layout에 대한 스타일과 구조를 만들어 준다.

header와 sidebar, body, footer에 대한 부분들을 div 태그로 나누어서 'tiles:insertAttribute' 해준다. (xml의 name 값에 맞게 매칭해주는듯. 또한 xml에서 value 값을 통해 분리해둔 원하는 파일을 가리키게 하여 연결해주는듯)

 

 

title과 body는 각각 "메인페이지"와 "Book List"로 값을 설정하고 "main" 타일즈와 "loginForm" 타일즈에서 "baseLayout"의 "title"속성을 오버라이딩하여 페이지의 제목을 설정한다.

그리고 body는 해당 경로의 타일즈에서 body 속성을 오버라이딩하여 페이지의 내용을 설정한다.

 

다음은 각각 main, header, side, loginForm, footer에 해당하는 파일이다.

 

 

> main.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"   isELIgnored="false"  %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"  %>


<%
  request.setCharacterEncoding("UTF-8");
%>    

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>메인 페이지</title>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
   <h1>메인 페이지입니다!!</h1>
</body>
</html>

 

> header.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
  request.setCharacterEncoding("UTF-8");
%> 
<c:set var="contextPath"  value="${pageContext.request.contextPath}"  />

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
<title>헤더</title>
</head>
<body>
<table border=0  width="100%">
  <tr>
     <td>
		<a href="${contextPath}/main.do">
			<img src="${contextPath}/resources/image/duke_swing.gif"  />
		</a>
     </td>
     <td>
       <h1><font size=30>스프링실습 홈페이지!!</font></h1>
     </td>
     
     <td>
       <!-- <a href="#"><h3>로그인</h3></a> -->
       <c:choose>
          <c:when test="${user != null}">
            <h3>환영합니다. ${user.userId }님!</h3>
            <a href="${contextPath}/member/logout.do"><h3>로그아웃</h3></a>
          </c:when>
          <c:otherwise>
	        <a href="${contextPath}/member/viewLogin.do"><h3>로그인</h3></a>
	        <a href="${contextPath}/member/viewRegist.do"><h3>회원가입</h3></a>
	      </c:otherwise>
	   </c:choose>     
     </td>
  </tr>
</table>

</body>
</html>

 

> side.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    isELIgnored="false" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>    
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
  request.setCharacterEncoding("UTF-8");
%> 
<c:set var="contextPath"  value="${pageContext.request.contextPath}"  />
<!DOCTYPE html>

<html>
<head>
 <style>
   .no-underline{
      text-decoration:none;
   }
 </style>
  <meta charset="UTF-8">
  <title>사이드 메뉴</title>
</head>
<body>
	<h1>사이드 메뉴</h1>
	<%--<h1>
		<a href="#"  class="no-underline">회원관리</a><br>
	    <a href="#"  class="no-underline">게시판관리</a><br>
	    <a href="#"  class="no-underline">상품관리</a><br>
    </h1>
	 --%>
	<h1>
		<a href="${contextPath}/member/list.do"  class="no-underline">회원관리</a><br>
		<a href="${contextPath}/book/list.do"  class="no-underline">도서관리</a><br>
		<a href="${contextPath}/guestbook/list.do"  class="no-underline">방명록</a><br>
	</h1>
	 
</body>
</html>

 

> loginForm.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>LoginForm</title>
</head>
<body>
<form action="login.do" method="post">
	<input type="text" name="id">
	<input type="password" name="pass">
	<input type="submit" name="" value="Login">
</form>
</body>
</html>

 

> footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"   isELIgnored="false"
 %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>하단 부분</title>
  <style>
    p {
     font-size:20px;
      text-align:center;
    }
  </style>
</head>
<body>
<p> e-mail:admin@test.com</p> 
<p> 회사주소:서울시 강동구</p>
<p>찾아오는 길:<a href="#">약도</a></p>

</body>
</html>

 

Spring Tiles를 알아봤다. (추가할 내용?)

반응형

댓글