스프링 통합과 폼

zookeeper·2022년 2월 22일
0

타임리프는 스프링과 통합을 위한 다양한 기능을 편리하게 제공한다.
이번 글에서는 타임리프를 스프링에서 200% 활용할 수 있는 방법을 알아보자.

먼저 스프링 부트에서 타임리프를 사용하기 위해 build.gradle에 다음과 같이 등록해준다.

build.gradle
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf

편리한 폼 관리

기능

  • th:object : 폼에서 컨트롤러에서 전달받은 특정 객체를 사용하겠다고 지정한다.
  • *{...} : th:object에서 선택한 객체에 접근한다.
  • th:field : html태그의 id, name, value 속성을 자동으로 등록한다.

이러한 기능을 통해 어떻게 폼을 편리하게 관리할 수 있는지 알아보자.
예를 들어 다음과 같이 Person이라는 클래스가 존재한다.
Person.java

public class Person(){
	String name;
    int age;
}

controller에서 뷰에 Person객체를 전달한다.

@GetMapping('/add')
public String addForm(Model model){
	model.addAttribute("person",new Person());
    return "form/addFrom";
}

addForm.html에서는 폼에서 Person객체를 사용하겠다고 지정할 수 있다.

<form action="person.html" th:action th:object="${person}" method="post">
 <div>
 <label for="personName">이름</label>
 <input type="text" id="personName" th:field="*{personName}" class="form-control" placeholder="이름을 입력하세요">
 </div>
 <div>
 <label for="age">나이</label>
 <input type="text" id="age" th:field="*{age}" class="form-control"
placeholder="나이을 입력하세요">
 </div>

장점

  • th:object로 사용할 객체를 지정해두면 해당 객체의 속성이 아닐 경우 오류를 표시해주기 때문에 사소한 오류를 방지할 수 있다.
  • th:field는 지정한 변수명으로 자동으로 id와 name속성을 만들고, 변수의 값으로 value속성을 만든다. 훨씬 코드를 간소화하고 오류를 방지할 수 있다.

폼 컴포넌트 기능

단일 체크박스

<div>판매 여부</div>
<div>
 <div class="form-check">
 <input type="checkbox" id="open" name="open" class="form-check-input">
 <label for="open" class="form-check-label">판매 오픈</label>
 </div>
</div>

위와 같이 판매 여부 체크 박스가 있을 때 체크박스를 체크할 경우 open=on이라는 값이 넘어간다. 스프링은 on을 true로 변환해준다.
만약 체크를 하지 않고 전송할 경우 open이라는 필드가 아예 서버로 전송되지 않는다.
이럴 경우 사용자가 체크되어 있던 값을 체크 해재해서 수정 저장시에도 서버에 아무 값이 넘어가지 않기 때문에 값을 변경하지 못한다.
이 문제를 해결하기 위해 _기존체크박스명 이라는 이름을 가지는 히든 필드를 만들어 기존 체크박스명이 전송되지 않고, _가 붙은 필드가 전송되면 스프링은 체크를 해제했다고 판단한다.

체크박스에서 th:field를 사용하게 되면 타임리프는 이러한 히든필드를 자동으로 생성해준다.
또한 체크박스의 값이 true인 경우 자동으로 checked속성을 추가해준다.

멀티 체크박스

멀티 체크박스 활용법

<div>
 <div>등록 지역</div>
 <div th:each="region : ${regions}" class="form-check form-check-inline">
 <input type="checkbox" th:field="*{regions}" th:value="${region.key}"
class="form-check-input">
 <label th:for="${#ids.prev('regions')}"
 th:text="${region.value}" class="form-check-label">서울</label>
 </div>
</div>

타임리프는 체크박스를 each루프 안에서 만들 때 임의로 필드명에 숫자를 붙여줌으로써 각 체크박스의 id를 고유하게 한다.
체크한 value들을 스프링이 배열로 받을 수 있다.

라디오

itemType

package hello.itemservice.domain.item;
public enum ItemType {
 BOOK("도서"), FOOD("식품"), ETC("기타");
 private final String description;
 ItemType(String description) {
 this.description = description;
 }
 public String getDescription() {
 return description;
 }
}

위의 itemType을 선택할 수 있는 폼을 만들어보자.
Controller

@ModelAttribute("itemTypes")
public ItemType[] itemTypes() {
 return ItemType.values();
}

html

<div>
 <div>상품 종류</div>
 <div th:each="type : ${itemTypes}" class="form-check form-check-inline">
 <input type="radio" th:field="*{itemType}" th:value="${type.name()}"
class="form-check-input">
 <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
class="form-check-label">
 BOOK
 </label>
 </div>
</div>

셀렉트 박스

controller에서 셀렉트 박스에 출력할 값 전달
controller

@ModelAttribute("deliveryCodes")
public List<DeliveryCode> deliveryCodes() {
 List<DeliveryCode> deliveryCodes = new ArrayList<>();
 deliveryCodes.add(new DeliveryCode("FAST", "빠른 배송"));
 deliveryCodes.add(new DeliveryCode("NORMAL", "일반 배송"));
 deliveryCodes.add(new DeliveryCode("SLOW", "느린 배송"));
 return deliveryCodes;
}

html

<div>
 <div>배송 방식</div>
 <select th:field="*{deliveryCode}" class="form-select">
 <option value="">==배송 방식 선택==</option>
 <option th:each="deliveryCode : ${deliveryCodes}" th:value="$
{deliveryCode.code}"
 th:text="${deliveryCode.displayName}">FAST</option>
 </select>
</div>

form 생성시 이러한 타임리프 기능을 최대한 사용하도록 노력하여 더욱 간결하고 오류가 없는 프로그램을 개발하는 것이 좋을 것 같다.

※김영한님의 스프링 MVC2 강의를 듣고 정리한 내용입니다.

0개의 댓글