스프링 부트에서는 JSP를 이용하여 view 페이지를 개발하는 방식에서 벗어나 템플릿 기반의 화면 처리를 지원한다.

FreeMarker, Mustache, Thymeleaf 를 이용하여 확장자가 thml인 페이지를 개발하는데,

기존의 JSP에서 사용하던 JSTL과 유사한 기능을 제공한다.

 

 - 코드를 변경하지 않기 때문에 디자인 팀과 개발 팀간의 협업에 도움이 된다.

 - JSP와 달리 서블릿 코드로 변환되지 않기 때문에 비즈니스 로직과 분리되어 View에 집중할 수 있다.

 - 서버 상에서 동작하지 않아도 된다. 때문에 서버 동작 없이 화면을 확인할 수 있어 디자인, 테스트에 용이하다.

 

https://abcdefgh123123.tistory.com/480

 

[Spring] JSP 대신 Thymeleaf를 사용하는 이유

클라이언트에게 동적인 웹페이지를 보여주기 위해 JSP, Thymeleaf 등 다양한 방식이 있습니다. 스프링에서는 Thymeleaf를 권장하고, 최근 개발자들 또한 jsp 대신 thymeleaf를 사용하는 추세입니다. 그렇

abcdefgh123123.tistory.com

 

 

 

스프링 부트 프로젝트 생성 시

라이브러리 목록에서 타임리프를 선택하면 사용 가능하다. (Spring Web도 함께 체크)

 

 

 

 

타임리프를 실습해보기 위한 예제 프로젝트 Thymeleaf 를 import 했다.

 

pom.xml 파일을 열어보면 타임리프 라이브러리가 설치되어 있다.

 

 

 

application.properties를 열어 서버포트를 80으로 설정한다.

jsp에서 뷰 페이지를 출력할 때는 이 문서에 prefix와 suffix를 설정해야 했지만,

타임리프에서는 그런 설정을 할 필요가 없다.

 

 

 

타임리프는 뷰 페이지를 jsp가 아닌 html로 생성하고,

기존의 src > main > webapp > WEB-INF > view 하위가 아닌

src > main > resources > templates 에 저장한다.

 

 

 

 

 

 

sample1 - th:text

 

 

index.jsp를 열어보면 많은 location 객체가 있다.

어떤 것을 주석 처리 하느냐에 따라 컨트롤러 요청 값이 달라지고,

브라우저 출력 페이지도 달라진다.

 

 

 

현재는 sample1 값을 요청하도록 되어 있기 때문에

컨트롤러 페이지에서 해당 값을 받는 어노테이션으로 찾아가본다.

 

별 다른 내용은 없고 메시지를 뷰 페이지로 리턴하도록 되어 있다.

sample1 이라는 페이지로 찾아간다.

이전에는 prefix에서 경로를 지정하고, suffix 에서 확장자를 jsp로 지정해서 찾아갔지만,

사전에 설정을 하지 않더라도 경로가 미리 지정되어 있기 때문에 파일명만 올바르게 적으면 잘 찾아간다.

 

 

 

 

 

JSTL을 사용할 때 상단에 코어 라이브러리를 불러왔던 것 처럼.

타임리프 페이지의 상단에는 타임리프를 불러오는 코드가 반드시 있어야 한다. (2번째 줄)

사용하고자 하는 내용에 따라 코어 라이브러리, 국제화 라이브러리 등 여러가지가 있었던 것 처럼

th 태그를 사용하기 위한 설정을 해 둔 상태이다.

 

문자열을 출력할 때에는 EL과 th:text 속성을 사용한다.

 

 

 

만약 text를 사용하지 않고 그냥 EL을 사용한다면?

제대로 동작하지 않는다.

 

 

 

 

 

 

 

sample2 - th:utext

 

 

index.jsp 의 주석을 수정했다.

 

 

 

DTO 객체에 값을 저장하여 model 객체를 이용하여 뷰 페이지로 전달한다.

 

 

상단에 th 속성 설정을 하고,

th:text와 EL로 DTO 객체를 출력했다. (10번째 줄) 브라우저에는 객체의 내용이 아닌 주소값이 출력됐다.

 

두번째로, <h3> 태그로 감싼 객체 member.no 값이

속성을 갖춰 출력되지 않고, 그대로 브라우저에 노출된 모습이다.

이는 th:text 속성을 사용했기 때문이다.

 

의도한 대로 출력을 한 모습이 아래쪽의 굵고 큰 '1' 이다.

태그를 사용할 때에는 th:utext 속성을 사용한다.

 

 

 

 

 

 

 

sample3 - th:each, #dates.format

 

index.jsp 의 주석을 수정하여 sample3를 활성화 했다.

 

 

인덱스 번호가 9까지 있는 리스트 객체를 생성하여 sample3 에 공유하는 내용이다.

 

 

기존 JSTL에서는 forEach 태그를 이용하여 루프를 돌렸는데,

타임리프에서는 th:each 를 사용하여 루프를 돌릴 수 있다.

값을 받는 변수는 member, ${list}는 model로 공유된 리스트 객체이다.

변수 member의 이름은 임의로 변경가능하다.

#dates.format로 사용자가 패턴을 지정해서 날짜/시간을 출력할 수 있다.

 

 

 

regdate 에 패턴을 지정하지 않고 그냥 출력해보았다.

 

 

 

 

 

sample4 - th:with, th:if ~ th:unless

sample4 요청을 찾아가면

DTO 객체로 구성된 리스트 객체를 생성하여 루프를 돌려 값을 주입하는 모습이 보인다.

이 리스트를 뷰 페이지 sample4로 공유한다.

 

 

 

 

뷰 페이지로 넘어가면 넘겨받은 리스트 객체의 값으로 만든 표가 3개 있는데

그 중 첫번째이다.

 

값을 받는 변수는 member, ${list}는 model로 공유된 리스트 객체이다.

변수 member의 이름은 임의로 변경가능하다.

 

 

 

 

두번째 표에서는 th:with 라는 속성을 사용하여 변수를 생성해본다.

 

th:with = " 변수명 = '값' "

 

u0001 이라는 id 에 대해 변수를 설정한다. ( target='u0001' )

첫번째 td태그를 보면 삼항 연산자를 사용해

member.id == target인 경우 'secret' 이라는 문자를 대신 출력 하도록 한다.

그러나 member.id != target 이라면 그대로 member.id를 출력한다.

 

정의 위치에 따라 적용되는 범위가 달라진다.

이 표에서는 table 태그 안에서 사용했기에 테이블 전체에 적용되지만,

만약 tr안에 사용했다면 해당 행 전체에 적용되고,

td 안에 사용했다면 칸 안에서만 적용된다.

 

 

 

 

세번째 표에서는 조건식 th:if ~ th:unless 를 사용한다.

다른 조건식들과 마찬가지로 참일 경우 th:if 내용이 적용되고,

그렇지 않을 경우 th:unless가 적용된다. (else if)

 

'u0001' ID에 target 변수를 적용했다.

컨트롤러에서 전달받은 리스트 객체를 member 변수에 전달, th:each를 이용하여 루프를 돌린다.

첫번째 td 태그에 th:if 태그를 사용하는데, 중첩으로 사용되고 있다.

만약 ${member.id} 값이 존재할 경우에서 다시 조건문을 사용,

${member.id} == target 이라면, "/modify" 링크가 걸린 Modify 라는 문자를 출력,

${member.id} != 라면 (th:unless) 아무런 링크도 속성도 적용되지 않은 View라는 단순한 문자를 출력한다. 

 

 

 

 

 

 

sample 5 - th:inline="javascript"

"SUCCESS" 문자열을 저장한 result 변수를 sample5 뷰 페이지에 공유한다.

 

 

자바스크립트 안에서 타임리프를 사용하기 위해서는

th:inline="javascript" 를 script 태그와 함께 사용한다.

<script th:inline="javascript">

 

이 th:inline은 "javascript" 뿐 아니라 다른 것으로도 사용할 수 있다.

 

th:inline="text"
th:inline="none"
ht:inline="javascript"

 

이것은 나중에 시간이 날 때 따로 공부해봐야겠다.

 

 

 

 

 

sample6 - #dates, #numbers, #strings

 

model 객체로 여러가지 값을 담은 변수를 sample6 뷰 페이지로 전달하고 있다.

값이 정해져 있을 경우 Arrays.asList를 사용하고 생성자에 값을 적으면 해당 내용으로 리스트가 생성된다.

 

th:text와 함께 사용할 수 있는 여러 속성을 사용하여

변수를 브라우저에 출력하고 있다.

이 속성들은 패턴을 지정하거나 함수를 함께 사용하여 다양한 형식으로 브라우저에 나타낼 수 있다.

 

날짜 : #dates.format

숫자 : #numbers.format

문자 : #strings.replace, #string.listSplit

 

price 객체에 담긴 123456789를 세자리씩 끊어서 구분자 기호를 삽입하는데,

'COMMA' 는 타임리프에서 제공하는 기본적인 구분자 중 하나이다.

타임리프 사용 튜토리얼을 찾아보니 사용할 수 있는 구분자는

POINT, COMMA, WHITESPACE, NONE, DEFAULT 가 있는 것 같다.

 

#strings와 replace 함수를 함께 사용했는데,

title 변수의 값 'This is a just sample' 중 's'문자열만 골라 볼드 효과를 적용한 's'로 치환했다.

태그를 적용시키기 위해 th:text가 아닌 th:utext를 사용했다.

 

 

 

th:each와 #string를 함께 사용했는데, 이 때 <li></li> 태그를 사용해 리스트화 시켰다.

title 변수에 들어 있는 문자열 'This is a just sample'을 공백으로 파싱한 것을 리스트로 출력했는데,

이 값을 왼쪽의 str로 전달했다.

그것을 [[${str}]] 로 출력했다.

 

 

 

 

sample 7 - th:href

 

아무런 값도 공유 하지 않고 바로 sample7 뷰 페이지로 이동한다.

 

 

 

 

th:href 로 링크를 걸고 값 전달을 하는 내용이 출력된다.

일반 앵커 태그처럼 <a href=" url " > </a> 이 아닌

<a th:href="@{ url }"> </a>  <- 다음과 같은 형식을 갖춰야 한다.

 

<a href="/sample1?p1=aaa&p2=bbb">
		=
<a th:href="@{/sample1(p1='aaa', p2='bbb')}"

 

 

 

 

 

listTest - 컨트롤러의 void 메소드

 

이 요청값은 sample~ 과는 달리 다른 컨트롤러 파일에 어노테이션이 작성되어 있다.

리스트 객체를 생성하여 19번까지 인덱스를 생성한 후

model로 Sample Data와 list를 공유하는 내용이 들어있다.

 

그런데 한 가지 특이한 점은 메소드의 자료형이 void 라서 return 구문이 없다.

이렇게 되면 요청 이름값과 동일한 뷰 페이지를 찾아가게 된다.

 

 

공유 받은 리스트 객체를 data 변수에 담아 루프를 돌리고, th:text로 data변수를 모두 출력한다.

'스프링 부트' 카테고리의 다른 글

Lombok (예제 boot02 프로젝트)  (0) 2022.10.17
예제 boot01 프로젝트  (0) 2022.10.17
스프링 부트 (demo 프로젝트)  (0) 2022.10.17

+ Recent posts