Written by
Sunwoo Han
on
on
스프링 MVC 기본 기능 - 웹 페이지 만들기
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술을 공부하고 정리하는 포스트입니다.
Thymeleaf(타임리프)
설명
개념
- 스프링에서 권장하는 템플릿 엔진
- TML파일을 가져와서 파싱하고 분석한 후, 정해진 위치에 데이터를 치환해서 웹 페이지를 생성
JSP vs Thymeleaf
- JSP
- 템플릿 엔진이 X –> HTML내에 Java코드를 삽입해서 동적 페이지를 생성하는 서버사이드 스크립트 언어
- Java Servlet으로 변환되어 실행 O
- 배포를 위해 WAR(Web Application Archive) 타입이 사용 (JAR에 비해 무거움)
- HTML파일 미리보기시 코드와 함께 존재하므로 정상 결과 X
- Thymeleaf
- 템플릿 엔진 O
- Java Servlet으로 변환되어 실행 X
- 배포를 위해 JAR(Java Archive) 타입 사용
- HTML파일 미리보기 시 정상 결과 O
추가
- 템플릿 엔진??
- HTML과 데이터를 결합해서 결과물을 만들어 주는 도구 ex) Thymeleaf / Velocity / Mustach 등
- SpringBoot 경로
- 정적 파일 :
/resources/static
- 동적 파일(템플릿 엔진 등) :
/resources/templates
- 정적 파일 :
- WAR vs JAR
- WAR(Web application ARchive)
- Servlet / JSP 컨테이너에 배치할 수 있는 웹 어플리케이션(Web Application) 압축 파일 포맷
- Servlet 해석과 관련된 모든 패키지들을 포함해서 무거운 구조를 가짐
- 단독으로 실행 불가하며 WEB / WAS가 함께 수행되어야 함
- JAR(Java ARchive)
- 쉽게 Java 어플리케이션이 동작할 수 있도록 Java 프로젝트를 압축한 파일
- JDK(Java Development Kit)에 있는 JRE(Java Runtime Environment)만 있으면 실행 가능
- Java만 설치되면 실행 가능
문법
- 핵심
th:xxx
가 붙은 부분은 서버 사이드에서 렌더링 되고, 기존 속성을 대체 하는 원리- 서버에서 동적으로 데이터를 변경할 때
th:xxx
로 속성을 대체하는 것 - HTML파일을 직접 열었을 때, 브라우저는 th: 속성을 모르니까 무시하고 출력됨
- 선언
<html xmlns:th="http://www.thymeleaf.org">
- URL 링크 표현식
- 타임리프에서 URL링크를 사용하는 경우 @{…}를 사용
- Path Variable 뿐만 아니라 Query Parameter도 생성해서 사용할 수 있음
/* 기본 사용 */
<a th:href="@{/css/bootstrap.min.css}"/>
/* Path Variable / Query Parameter */
<a th:href="@{/basic/items/{itemId}(itemId=${item.id}, query='test')}" />
실제 생성 링크 예시 --> http://localhost:8080/basic/items/1?query=test
- 속성 변경
- 타임리프의 핵심이 바로 기존 속성을 동적으로 대체할 수 있게 속성을 변경하는 것
- 아래 예시는 onclick시 특정 경로로 이동하게 동적으로 처리
<button
onclick="location.href='addForm.html'"
th:onclick="|location.href='@{/basic/items/add}'|"
/>
- 리터럴 대체
- 타임리프에서 문자와 표현식 등은 분리되어 있기 때문에, 더해서 사용해야 함.
- 하지만, 가독성과 사용성이 떨어지므로
|...|
를 통해 리터럴을 대체할 수 있음.
/* 기존 방법 */
<button
onclick="location.href='addForm.html'"
th:onclick="location.href=' + '/'' + @{/basic/items/add} + '\'"
/>
/* 리터럴 대체 사용 */
<button
onclick="location.href='addForm.html'"
th:onclick="|location.href='@{/basic/items/add}'|"
/>
- 반복 출력
th:each
를 사용해서 model에 포함된 값을 반복적으로 순회하며 수행할 수 있다
<tr th:each="item : ${items}">
<td><a href="item.html" th:href="@{/basic/items/{itemId}(itemId=${item.id})}">회원id</a></td>
<td><a href="item.html" th:href="@{|/basic/items/${item.id}|}"th:text="${item.itemName}">상품명</a></td>
</tr>
- 내용 변경
- text 속성 값을 특정 값으로 대체
/* 정적인 경우의 10000을 가지지만, 값이 넘어오면 item.price로 대체 */
<td th:text=${item.price}">10000</td>
PRG(Post-Redirect-Get) 패턴
개요
- PRG 패턴
- PRG 패턴은 웹 개발시 자주 사용되는 디자인 패턴
- POST 요청에 대한 응답이 또 다른 URL로의 GET 요청을 위한 리다이렉트(응답 코드가 3XX)여야 한다는 것
- 만약 POST요청에 대한 응답이 리다이렉트가 아닌 단순 페이지 이동이면 문제가 발생함
- 문제점(POST 응답이 단순 페이지 이동인경우)
- 브라우저 새로고침을 할 때 마다 POST요청이 수행된다 –> 중복 수행
- 따라서 반드시 PRG 패턴을 적용해야 함
패턴 적용
- Redirect를 이용해서 GET을 호출하도록 설계
- 이제 브라우저 새로고침이 있어도 해당되는 GET만 다시 요청됨
- Post 요청 후 redirect 수행시 주의사항
- 특정 값을 추가해서 redirect할 때, 해당 값은 인코딩 과정이 수행되지 않는다 -> 한글인 경우 모두 깨지게 됨 -> 이것을 해결하기 위해 RedirectAttributes를 사용할 수 있음
@PostMapping("/add")
public String addItemV5(Item item) {
itemRepository.save(item);
/* Path Variable로 추가되는 item의 id와 같은 변수를 추가적으로 인코딩 되지 않음 */
return "redirect:/basic/items/" + item.getId();
}
RedirectAttributes
개념
- Redirect를 할 때 URL 인코딩, Path Variable / Query Parameter를 처리해주는 도구
- 특정 View에서 Redirect의 여부를 확인하기 위해 변수를 전달하기 위해 사용하기도 함
적용
@PostMapping("/add")
public String addItemV6(Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemRepository.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/basic/items/{itemId}";
}
- RedirectAttributes 객체 사용
.addAttribute
로 값을 추가할 수 있음- url 경로에 변수가 존재하면 넣어주며, 없으면 자동으로 Query Parameter로 처리됨
- 실제 요청 예시 :
http://localhost:8080/basic/items/3?status=true
Comments
SPRING 의 다른 글
-
스프링 타입 컨터버 24 Jun 2022
-
API 예외 처리 17 Jun 2022
-
예외 처리와 오류 페이지 12 Jun 2022
-
로그인 처리 - 인터셉터 08 Jun 2022
-
로그인 처리 - 필터 06 Jun 2022
-
로그인 처리 - 쿠키, 세션 31 May 2022
-
Bean Validation 22 May 2022
-
검증 22 May 2022
-
메시지, 국제화 21 May 2022
-
타임리프 - 스프링 통합과 폼 19 May 2022
-
타임리프 - 기본 기능 10 May 2022
-
스프링 MVC 기본 기능 - 웹 페이지 만들기 02 May 2022
-
스프링 MVC 기본 기능 - HTTP 응답 30 Apr 2022
-
스프링 MVC 기본 기능 - HTTP 요청 24 Apr 2022
-
스프링 MVC 기본 기능 - 요청 매핑 19 Apr 2022
-
스프링 MVC 기본 기능 19 Apr 2022
-
스프링 MVC 구조 이해 14 Apr 2022
-
MVC 프레임워크 만들기 - V4, V5 12 Apr 2022
-
MVC 프레임워크 만들기 - V1, V2, V3 09 Apr 2022
-
서블릿, JSP, MVC 패턴 05 Apr 2022
-
서블릿 29 Mar 2022
-
웹 애플리케이션 이해 24 Mar 2022
-
스프링 웹 계층이란? 05 Nov 2021
-
스프링 시큐리티 공식문서 번역 27 Sep 2021
-
스프링 AOP 총정리 : 개념, 프록시 기반 AOP, @AOP 27 Apr 2021
-
SpEL (스프링 Expression Language) 25 Apr 2021
-
데이터 바인딩 추상화 : Converter와 Formatter 21 Apr 2021
-
데이터 바인딩 추상화 : PropertyEditor 12 Apr 2021
-
Validation 추상화 10 Apr 2021
-
Resource 추상화 08 Apr 2021
-
IoC 컨테이너 9부 07 Apr 2021
-
IoC 컨테이너 8부 06 Apr 2021
-
IoC 컨테이너 7부 02 Apr 2021
-
IoC 컨테이너 6부 29 Mar 2021
-
IoC 컨테이너 5부 27 Mar 2021
-
IoC 컨테이너 4부 23 Mar 2021
-
IoC 컨테이너 3부 20 Mar 2021
-
IoC 컨테이너 2부 18 Mar 2021
-
IoC 컨테이너 1부 12 Mar 2021
-
스프링 PSA 07 Jan 2021
-
스프링 @AOP 실습 07 Jan 2021
-
프록시 패턴 06 Jan 2021
-
스프링 AOP 04 Jan 2021
-
의존성 주입(Dependency Injection) 04 Jan 2021
-
스프링 빈(Bean) 02 Jan 2021
-
스프링 IoC 컨테이너 01 Jan 2021
-
스프링 IoC 01 Jan 2021