일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 임베디드 타입
- 스프링
- JPA
- 로그인
- 컬렉션 조회 최적화
- 검증 애노테이션
- 페이징
- 스프링 mvc
- 불변 객체
- 스프링MVC
- 일론머스크
- 스프링 데이터 JPA
- 김영한
- 프로젝트 환경설정
- 값 타입 컬렉션
- Spring Data JPA
- Bean Validation
- 타임리프 문법
- 벌크 연산
- API 개발 고급
- jpa 활용
- 기본문법
- QueryDSL
- JPA 활용 2
- 타임리프
- 트위터
- 실무활용
- 예제 도메인 모델
- JPA 활용2
- JPQL
- Today
- Total
RE-Heat 개발자 일지
스프링 MVC 2편 - [1] 타임리프 - 기본기능(하편) 본문
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/dashboard
인프런 김영한님의 스프링 MVC 2편 강의를 토대로 정리한 내용입니다.
[10] 속성 값 설정
th:* 속성을 지정하면 타임리프는 기존 속성을 th:*로 지정한 속성으로 대체한다. 기존 속성이 없으면 새로 만든다.
예시) <input type="text" name="mock" th:name="userA" />
→ 타임리프 렌더링 후 <input type="text" name="userA" />
실행결과·코드·attribute.html
■ 속성추가
th:attrappend : 속성값 뒤에 값을 추가한다.
예시) th:attrappend="class=' large'" → class="text large"
th:attrprepend : 속성값 앞에 값을 추가한다.
예시) th:attrprepend="class='large '" → class="large text"
th:classappend : class 속성에 자연스럽게 추가한다.
예시) th:classappend="large" → class="text large"
=> classappend는 띄어쓰기를 신경 쓸 필요 없어 편리함.
■ checked 처리
HTML에선 check속성이 있으면 checked가 true인지 false인지 관계없이 checked처리가 되어버린다.
그래서 타임리프는 개발자의 편의성을 위해 th:checked값이 false이면 checked 속성 자체를 제거한다.
<input type="checkbox" name="active" th:checked="false" />
→ 타임리프 렌더링 후: <input type="checkbox" name="active" />
[11] 반복
■ 반복기능
<tr th:each="user : ${users}">
타임리프에서 반복은 th:each를 사용하며 List 외에도 배열, java.util.Iterable , java.util.Enumeration, Map 등에서도 사용할 수 있다.
■ 반복상태 유지 기능
<tr th:each="user, userStat : ${users}">
반복의 두 번째 파라미터를 설정해 반복의 상태를 확인할 수 있다.
두 번째 파라미터(userStat)을 생략하면 생략한 지정한 변수명(user) + Stat이 된다.
반복상태유지기능
- index : 0부터 시작하는값
- count : 1부터 시작하는값
- size : 전체사이즈
- even , odd : 홀수, 짝수여부( boolean )
- first , last :처음, 마지막여부( boolean )
- current : 현재객체
[12] 조건부 평가
타임리프의 조건식은 Java와 굉장히 흡사하다.
① if문
② unless문(if문 반대)
③ switch~case문
BasicController : condition + addUsers()
@GetMapping("/condition")
public String condition(Model model){
addUsers(model);
return "basic/condition";
}
private void addUsers(Model model){
List<User> list = new ArrayList<>();
list.add(new User("UserA", 10));
list.add(new User("UserB", 20));
list.add(new User("UserC", 30));
model.addAttribute("users", list);
}
userA의 age는 10, UserB의 age는 20, UserC의 age는 30으로 세팅
■ if·unless
타임리프는 해당 조건이 맞지 않으면 태그 자체를 렌더링 되지 않는다.
브라우저에서 소스를 열어보면 미성년자 조건을 충족하지 않은 20, 30에선 <span>태그 자체가 사라진 것을 확인할 수 있다.
■ switch
[13] 주석
■ 타임리프 주석
1. 표준 HTML 주석 <!-- -->
타임리프가 렌더링하지 않고 그대로 남겨둔다.
2. 타임리프 파서 주석 <!--/* */-->
타임리프의 진짜 주석으로, 렌더링하면 주석 부분을 제거한다.
3. 타임리프 프로토타입 주석 <!--/*/ /*/-->
HTML 파일을 열어보면 주석처리가 되고, 타임리프를 렌더링하면 보이는 기능
렌더링 후 브라우저 소스보기 - comments.html
브라우저에서 직접 열기
타임리프 파서 주석은 렌더링되면 사라지나, 브라우저에서 직접 열면 보인다.
반면 타임리프 프로토타입 주석은 렌더링되면 보이나 브라우저에서 직접 열면 보이지 않는다는 것을 알 수 있다.
[14] 블록
<th:block>은 HTML 태그가 아닌 타임리프의 유일한 자체 태그다.
block.html
<th:block th:each="user : ${users}">
<div>
사용자 이름1 <span th:text="${user.username}"></span>
사용자 나이1 <span th:text="${user.age}"></span>
</div>
<div>
요약 <span th:text="${user.username} + ' / ' + ${user.age}"></span>
</div>
</th:block>
반복문을 쓸 때 <div> 한 개는 th:each만 써도 되나, 두 개를 출력하려면 th:block을 써주어야 한다.
실행화면
① th:block은 렌더링시 제거되는 특징이 있다.
② html 태그 안에 넣을 곳이 애매할 때 사용된다.
[15] 자바스크립트 인라인
타임리프는 자바스크립트에서 타임리프를 편리하게 사용할 수 있는 자바스크립트 인라인 기능을 제공한다.
자바스크립트 인라인 기능 기본형 : <script th:inline="javascript">
javascript.html & 브라우저 소스 보기
■ 텍스트 렌더링
① var username
th:inline="javascript" 적용 전
var username = [[${user.username}]] -> var username = userA;가 돼 "[[${user.username}]]" 큰따옴표를 붙여줘야 함
th:inline="javascript"적용 후
var username = "userA"; 쌍따옴표를 붙이지 않아도 타입에 맞게 알아서 출력해 준다.
② var age
숫자는 큰따옴표를 붙이지 않아도 돼 둘 다 정상적으로 동작한다.
추가] 자바스크립트에서 문제가 될 문자(\)가 포함돼 있으면 이스케이스 처리를 해준다.
BasicController : javascript
@GetMapping("/javascript")
public String javascript(Model model){
model.addAttribute("user", new User("user\"A\"", 10));
addUsers(model);
return "basic/javascript";
}
inline을 사용하면 백슬래쉬(\)가 Escape된 것을 확인할 수 있다. 여기선 백슬래시 대신 원화기호가 출력.
■ 자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
- 인라인사용 전 → var username2 = /*userA*/ "test username";
- 인라인사용 후 → var username2 = "userA";
인라인 사용 전엔 순수하게 해석해 내추럴 템플릿 기능이 동작하지 않는다. 렌더링 내용은 주석처리까지 된다.
반면 인라인 사용 후엔 결과를 보면 /**/주석 부분이 제거되고 "userA"가 정확하게 적용된다.
■ 객체
타임리프 자바스크립트 인라인 기능을 쓰면 객체를 JSON으로 자동 반환한다.
var user = [[${user}]];
- 인라인 사용 전 var user = BasicController.User(username=userA, age=10);
- 인라인 사용 후 var user = {"username":"userA","age":10};
인라인 사용 전엔 toString() 값이 호출되나, 사용 후엔 객체를 JSON으로 변환해 줌.
■ 자바스크립트 인라인 each
자바스크립 인라인은 th:each를 제공한다. 단, [#...]로 시작되고 [/]로 끝나야 한다.
자세한 내용은 아래 링크의 13 Textual template modes 부분을 확인하면 된다.
https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#javascript-inlining
[16] 템플릿 조각
웹 페이지를 개발할 땐 상단영역·하단 영역·좌측 카테고리 등 여러 페이지에서 함께 사용하는 영역이 있다. 이런 부분을 일일이 코드를 복사해 사용하면 비효율적이므로 타임리프는 1. 템플릿 조각과 2. 레이아웃 기능을 지원해 보다 효율적으로 관리할 수 있도록 해준다.
fragmentMain.html & footer.html
■ 부분 포함 insert
<div th:insert="~{template/fragment/footer :: copy}"></div>
를 쓰면 footer.html의 th:fragment="copy"라는 부분을 템플릿 조각으로 가져와 사용한다.
insert는 기존 태그인 <div>를 남겨놓은 상태에서 <footer>를 내부에 추가한다는 게 특징이다.
■ 부분 포함 replace
<div th:replace="~{template/fragment/footer :: copy}"></div>
를 쓰면 마찬가지로 footer.html의 th:fragment="copy"라는 부분을 템플릿 조각으로 가져와 사용한다.
단, replace는 insert와는 달리 기존 태그 <div>를 대체한다.
■ 부분 포함 단순 표현식
<div th:replace="template/fragment/footer :: copy"></div>
~{template/fragment/footer :: copy}처럼 ~{...}를 사용하는 게 원칙이나 템플릿 조각을 쓰는 코드가 단순하면 생략할 수 있다.
■ 파라미터 사용
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
footer.html의 ${param1} , ${param2} 부분을 '데이터1' '데이터2'식으로 입력해 출력할 수 있다.
[17] 템플릿 레이아웃 1
웹페이지에서 공통으로 사용할 레이아웃 페이지를 구성하고 가져올 수 있다. 추가로 타임리프엔 각 페이지마다 필요한 정보를 더 추가해 사용하는 방법도 있다.
layoutMain.html & base.html & 실행화면
① logoutMain.html
common_header(~{::title},~{::link}) 매개변수로 모든 title태그(<title>메인타이틀</title>)와
모든 link태그<link ... bootstrap> <link jquery-ui.css>를 전달
② base.html
<title th:replace="${title}">은 logoutMain.htlm에서 넘어온 <title>메인 타이틀<title>로 대체됨.<th:block th:replace=${links}/> th:block을 사용하고 ${links}가 있으면 <link>태그 개수만큼 추가됨.실행화면을 보면 <link>태그가 두 개가 넘어온 것을 확인할 수 있다.
레이아웃 개념(base.html)을 두고 필요한 코드 조각(title, link)을 전달해 완성하는 것으로 이해하면 된다.
[18] 템플릿 레이아웃 2
앞선 개념을 <head>에 국한되지 않고 <html> 전체에 적용할 수 있다.
layoutExtendMain.html & layoutFile.html & 실행화면
① layoutExtendMain.html
<html th:replace="~{template/layoutExtend/layoutFile :: layout(~{::title}, ~{::section})}" xmlns:th="http://www.thymeleaf.org">
title과 section을 layoutFile.html로 넘김
② layoutFile.html
head에 th:fragment가 붙어있던 base.html과는 달리 html태그에 th:fragement 속성이 정의돼 있는 것을 확인할 수 있다.
타이틀은 layoutExtendMain에서 가져온 <title>메인 페이지 타이틀</title>로 대체되며
레이아웃 컨텐츠 부분도 역시 <section></section>으로 교체된 것을 확인할 수 있다.
'백엔드 > 스프링' 카테고리의 다른 글
스프링 MVC 2편 - [3] 메시지·국제화 (0) | 2023.07.13 |
---|---|
스프링 MVC 2편 - [2] 스프링 통합과 폼 (0) | 2023.07.12 |
스프링 MVC 2편 - [1] 타임리프 - 기본기능(상편) (0) | 2023.07.08 |
스프링 MVC 1편 - [7] 웹 페이지 만들기 [하편] (0) | 2023.07.06 |
스프링 MVC 1편 - [7] 웹 페이지 만들기 [상편] (0) | 2023.07.05 |