스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 대시보드 - 인프런 | 강의 (inflearn.com)
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의
웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있
www.inflearn.com
텍스트 - text, utext
<li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
escape: HTML에서 사용하는 특수 문자를 HTML 엔티티로 변경. 타임리프는 기본적으로 escape를 제공함.
ex) "<": <
unescape
1. th:text -> th:utext
2. [[...]] -> [(...)]
변수 - SpringEL
- ${user.username} = userA
- ${user['username']} = userA
- ${user.getUsername()} = userA
- ${users[0].username} = userA
- ${users[0]['username']} = userA
- ${users[0].getUsername()} = userA
- ${userMap['userA'].username} = userA
- ${userMap['userA']['username']} = userA
- ${userMap['userA'].getUsername()} = userA
지역 변수 - (th:with)
1
2
3
|
<div th:with="first=${users[0]}">
<p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
</div>
|
cs |
기본 객체들
기본 객체
- ${#request}
- ${#response}
- ${#session}
- ${#servletContext}
- ${#locale}
편의 객체
HTTP 요청 파라미터 접근: param 예) ${param.paramData}
HTTP 세션 접근: session 예) ${session.sessionData}
스프링 빈 접근: @ 예) ${@helloBean.hello('Spring!')}
식 기본 객체 (Expression Basic Objects)
1
2
3
4
5
6
7
|
<ul>
<li>request = <span th:text="${#request}"></span></li>
<li>response = <span th:text="${#response}"></span></li>
<li>session = <span th:text="${#session}"></span></li>
<li>servletContext = <span th:text="${#servletContext}"></span></li>
<li>locale = <span th:text="${#locale}"></span></li>
</ul>
|
cs |
편의 객체
1
2
3
4
5
|
<ul>
<li>Request Parameter = <span th:text="${param.paramData}"></span></li>
<li>session = <span th:text="${session.sessionData}"></span></li>
<li>spring bean = <span th:text="${@helloBean.hello('Spring!')}"></span></li>
</ul>
|
cs |
유틸리티 객체와 날짜
1
2
3
4
|
<li>default = <span th:text="${localDateTime}"></span></li>
<li>yyyy-MM-dd HH:mm:ss = <span th:text="${#temporals.format(localDateTime,'yyyy-MM-dd HH:mm:ss')}"></span></li>
<li>${#temporals.day(localDateTime)} = <span th:text="${#temporals.day(localDateTime)}"></span></li>
<li>${#temporals.month(localDateTime)} = <span th:text="${#temporals.month(localDateTime)}"></span></li>
|
cs |
URL 링크
/hello
/hello?param1=data1¶m2=data2
/hello/{param1 }/{param2}
/hello/{param1}?param2=data2
1
2
3
4
|
<th:href="@{/hello}">
<th:href="@{/hello(param1=${param1}, param2=${param2})}">
<th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}">
<th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}">
|
cs |
리터럴: 소스 코드 상에 고정된 값
- String a = "hello" // 문자 리터럴
- int a = 10 * 20 // 숫자 리터럴
문자 리터럴은 항상 ' (작은 따옴표)로 감싸야 함
<span th:text="'hello'">
공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해서 다음과 같이 작은 따옴표를 생략할 수 있음.
룰: A-Z , a-z , 0-9 , [] , . , - , _
<span th:text="hello">
1
2
3
4
|
<li>'hello' + ' world!' = <span th:text="'hello' + ' world!'"></span></li>
<li>'hello world!' = <span th:text="'hello world!'"></span></li>
<li>'hello ' + ${data} = <span th:text="'hello ' + ${data}"></span></li>
<li>리터럴 대체 |hello ${data}| = <span th:text="|hello ${data}|"></span></li>
|
cs |
※ 공백 포함하는데 ' 없으면 오류!!
연산
Elvis 연산자: 조건식의 편의 버전
No-Operation: _ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<li>Elvis 연산자
<ul>
<li>${data}?: '데이터가 없습니다.' = <span th:text="${data}?: '데이터가 없습니다.'"></span></li>
<li>${nullData}?: '데이터가 없습니다.' = <span th:text="${nullData}?:'데이터가 없습니다.'"></span></li>
</ul>
</li>
<li>No-Operation
<ul>
<li>${data}?: _ = <span th:text="${data}?: _">데이터가 없습니다.</span></li>
<li>${nullData}?: _ = <span th:text="${nullData}?: _">데이터가 없습니다.</span></li>
</ul>
</li>
|
cs |
속성 값 설정
속성 설정
ht:* 속성 지정 -> 기존 속성을 th:*로 지정한 속성으로 대체
속성 추가
- th:attrappend = <input type="text" class="text" th:attrappend="class='large'" /><br/>
- th:attrprepend = <input type="text" class="text" th:attrprepend="class='large'" /><br/>
- th:classappend = <input type="text" class="text" th:classappend="large" /><br/>
checked 처리
HTML에서 checked 속성은 checked 속성의 값과 상관없이 checked 라는 속성만 있어도 체크가 된다.
타임리프의 th:checked 는 값이 false 인 경우 checked 속성 자체를 제거한다.
<input type="checkbox" name="active" th:checked="false" />
-> <input type="checkbox" name="active" />
th:checked="true" -> 체크 O
th:checked="false" -> 체크 X
checked="false" -> 체크 O
반복
반복 상태 유지
<tr th:each="user, userStat : ${users}">
반복의 두번째 파라미터를 설정해서 반복의 상태를 확인 할 수 있습니다.
두번째 파라미터는 생략 가능한데, 생략하면 지정한 변수명( user ) + Stat 가 됨
여기서는 user + Stat = userStat 이므로 생략 가능
반복 상태 유지 기능
- index : 0부터 시작하는 값
- count : 1부터 시작하는 값
- size : 전체 사이즈
- even , odd : 홀수, 짝수 여부( boolean )
- first , last :처음, 마지막 여부( boolean )
- current : 현재 객체
조건부 평가
조건 만족하지 않으면 태그 자체가 사라짐
<span th:text="'미성년자'" th:if="${user.age lt 20}"></span>
<span th:text="'미성년자'" th:unless="${user.age ge 20}"></span>
주석
1. 표준 HTML 주석: 그대로 표시, 렌더링 안함
<!-- ㅇㅁㄴㄻㄴㅇㄻ -->
2. 타임리프 파서 주석: 표시 안함
<!--/* ㄴㅁㅇㄻㄴㅇㄻ */-->
3. 타임리프 프로토타입 주석:
<!--/*/ ㅁㄴㅇㄻㄴㅇㄻㅇㄴㄹ /*/-->
타임리프 프로토타입 주석 (잘 안씀)
웹 브라우저에서 파일 직접 열 때는 안 보임
타임리프로 렌더링 된 경우에만 보여줌
블록 - <th:block>
HTML 태그가 아닌 타임리프의 유일한 자체 태그
<div>를 두 개씩 th:each 돌리기
1
2
3
4
5
6
7
8
9
|
<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>
|
cs |
자바스크립트 인라인
자바스크립트에서 타임리프를 편리하게 사용
<script th:inline="javascript">
1
2
3
4
5
6
7
8
9
10
|
<script th:inline="javascript">
var username = [[${user.username}]];
var age = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]];
</script>
|
cs |
인라인 X
var username = "UserA";
var age = 10;
var username2 = /*UserA*/ "test username";
var user = BasicController.User(username=UserA, age=10);
인라인 O
var username = "UserA";
var age = 10;
var username2 = "UserA";
var user = {"username":"UserA", "age":10};
자바스크립트 인라인 each
1
2
3
4
5
|
<script th:inline="javascript">
[# th:each="user, stat : ${users}"]
var user[[${stat.count}]] = [[${user}]];
[/]
</script>
|
cs |
결과
1
2
3
4
5
|
<script>
var user1 = {"username":"userA","age":10};
var user2 = {"username":"userB","age":20};
var user3 = {"username":"userC","age":30};
</script>
|
cs |
템플릿 조각
공통 영역 처리
fragmentMain.html에서 footer.html 불러서 사용
{template/fragment/footer}의 copy를 가져다가 씀
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<h1>부분 포함</h1>
<h2>부분 포함 insert</h2>
<div th:insert="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 replace</h2>
<div th:replace="~{template/fragment/footer :: copy}"></div>
<h2>부분 포함 단순 표현식</h2>
<div th:replace="template/fragment/footer :: copy"></div>
<h1>파라미터 사용</h1>
<div th:replace="~{template/fragment/footer :: copyParam ('데이터1', '데이터2')}"></div>
|
cs |
insert: <div> 살아있음
1
2
3
4
5
|
<div>
<footer>
footer 테스트
</footer>
</div>
|
cs |
replace: <div>를 교체함
1
2
3
|
<footer>
footer 테스트
</footer>
|
cs |
템플릿 레이아웃1
/template/layout/base에 있는 common_header를 불러옴 (title, link를 넘김)
1
2
3
4
5
|
<head th:replace="template/layout/base :: common_header(~{::title},~{::link})">
<title>메인 타이틀</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">
</head>
|
cs |
헤더를 이걸로 대체
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common_header(title,links)">
<title th:replace="${title}">레이아웃 타이틀</title>
<!-- 공통 -->
<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">
<link rel="shortcut icon" th:href="@{/images/favicon.ico}">
<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>
<!-- 추가 -->
<th:block th:replace="${links}" />
</head>
...
</html>
|
cs |
메인 타이틀이 전달한 부분으로 교체됨
공통 부분은 그대로 유지되고, 추가 부분에 전달한 <link>들이 포함됨
템플릿 레이아웃2
layoutExtendMain에서 title과 section을 넘기면 html 자체를 layoutFile로 교체함 (title과 section만 바꿔서).
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!DOCTYPE html>
<html th:replace="~{template/layoutExtend/layoutFile :: layout(~{::title},~{::section})}"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>메인 페이지 타이틀</title>
</head>
<body>
<section>
<p>메인 페이지 컨텐츠</p>
<div>메인 페이지 포함 내용</div>
</section>
</body>
</html>
|
cs |
'오늘 배운 것' 카테고리의 다른 글
[알고리즘] 다익스트라, 세그먼트 트리 (0) | 2021.07.13 |
---|---|
[알고리즘] 위상정렬, 프림, 크루스칼 (0) | 2021.07.12 |
[스프링 MVC 2] 타임리프 - 스프링 통합과 폼, 메시지, 국제화 (0) | 2021.07.02 |
[스프링 MVC 1, 2] 스프링 MVC - 기본 기능 (2), 타임리프 - 기본 기능 (0) | 2021.06.30 |
[스프링 MVC 1] 스프링 MVC - 기본 기능 (1) (0) | 2021.06.28 |