[TIL] #2. 타임리프 - 스프링 통합과 폼

kiteB·2021년 9월 21일
0

TIL-Spring4

목록 보기
4/17
post-thumbnail

프로젝트 설정

스프링 MVC 1편에서 만들었던 상품 관리 프로젝트를 다듬어서 스프링 MVC를 깊이있게 알아보자!

🔗 코드 확인하기


타임리프 스프링 통합

타임리프 매뉴얼

타임리프는 크게 2가지 매뉴얼을 제공한다.

타임리프는 스프링 없이도 동작하지만,
스프링과 통합을 위한 다양한 기능을 편리하게 제공한다!

✔ 스프링 통합으로 추가되는 기능들

  • 스프링의 SpringEL 문법 통합
  • ${@myBean.doSomething()}처럼 스프링 빈 호출 지원
  • 편리한 폼 관리를 위한 추가 속성
    • th:object (기능 강화, 폼 커맨드 객체 선택)
    • th:field, th:errors, th:errorclass
  • 폼 컴포넌트 기능
    • checkbox, radio button, List 등을 편리하게 사용할 수 있는 기능 지원
  • 스프링의 메세지 국제화 기능의 편리한 통합
  • 스프링의 검증, 오류 처리 통합
  • 스프링의 변환 서비스 통합(ConversionService)

✔ 타임리프 설정 방법

build.gradle에 다음 코드 추가해주기

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

입력 폼 처리

타임리프가 제공하는 입력 폼 기능을 이용하여 기존 프로젝트의 폼 코드를 효율적으로 개선할 수 있다!

  • th:object: 커맨드 객체를 지정한다.
  • *{...}: 선택 변수 식. th:object 에서 선택한 객체에 접근한다.
  • th:field: HTML 태그의 id, name, value 속성을 자동으로 처리해준다.

✔ 렌더링 전

<input type="text" th:field="*{itemName}" />

✔ 렌더링 후

<input type="text" id="itemName" name="itemName" th:value="*{itemName}" />

코드로 확인하기

🔗 전체 코드 확인하기

th:object, th:field를 이용하여 폼 개발이 조금 편리해졌다!

사실 이 기능들의 위력은 뒤에 배울 검증(Validation)에서 나타난다!


요구사항 추가

타임리프를 사용해서 폼에서 체크박스, 라디오 버튼, 셀렉트 박스를 편리하게 사용하는 방법에 대해 알아보자!

요구사항 추가

기존 상품 서비스에 다음 요구사항이 추가되었다.

  • 판매 여부
    • 판매 오픈 여부
    • 체크 박스로 선택할 수 있다.
  • 등록 지역
    • 서울, 부산, 제주
    • 체크 박스다중 선택할 수 있다.
  • 상품 종류
    • 도서, 식품, 기타
    • 라디오 버튼으로 하나만 선택할 수 있다.
  • 배송 방식
    • 빠른 배송 / 일반 배송 / 느린 배송
    • 셀렉트 박스하나만 선택할 수 있다.

예시 이미지


코드로 확인하기

🔗 전체 코드 확인하기

ItemType - 상품 종류

상품 종류는 ENUM을 사용한다.

DeliveryCode - 배송 방식

배송 방식은 DeliveryCode라는 클래스 사용!

  • codeFAST 같은 시스템에서 전달하는 값이고,
  • displayName은 빠른 배송 같은 고객에게 보여지는 값이다.

Item - 상품

ENUM, 클래스, String 같은 다양한 상황을 준비했다.
각각의 상황에 어떻게 폼의 데이터를 받을 수 있는지 하나씩 알아보자.


체크박스 - 단일 1

단순 HTML 체크 박스 주의점

HTML에서 체크 박스를 선택❌ 폼 전송 → open 필드 자체가 서버로 전송되지 않는다!
이것은 우리가 원하는 결과가 아니다! 선택하지 않았을 때 false가 출력되기를 원한다.


히든 필드를 이용해서 해결

위의 문제를 해결하기 위해 스프링 MVC는 히든 필드를 하나 만든다!

_open처럼 "_ + 기존 체크박스 이름 "으로 만든 히든 필드를 전송하여 체크를 해제했음을 인식하도록 한다.

이것은 히든 필드는 항상 전송된다는 특징을 이용한 방법으로,
체크를 해제한 경우 여기에서 open은 전송되지 않고 _open만 전송되어,
스프링 MVC는 체크를 해제했다고 판단할 수 있게 된다!

🔗 전체 코드 확인하기

📌 정리

1. 체크박스 체크 - open=on&_open=on

: 체크박스를 체크하면 스프링 MVC가 open에 값이 있는 것을 확인하고 사용한다. 이때 _open은 무시한다.

2. 체크박스 미체크 - _open=on

: 체크박스를 체크하지 않으면 스프링 MVC가 _open만 있는 것을 확인하고, open의 값이 체크되지 않았다고 인식한다.
위의 실행화면에서 볼 수 있듯이, 서버에서 Boolean 타입을 찍어보면 open의 값이 null이 아닌 false로 나온다!


체크박스 - 단일 2

하지만 매번 사용할 때마다 히든 필드를 추가하는 것은 매~~우 번거로운 일이다.

타임리프가 제공하는 폼 기능을 사용하면 이런 부분을 자동으로 처리할 수 있다!

타임리프 - 체크박스 코드 추가

<!-- single checkbox -->
<div>판매 여부</div>
<div>
    <div class="form-check">
    <input type="checkbox" id="open" th:field="*{open}" class="form-check-input">
    <label for="open" class="form-check-label">판매 오픈</label>
    </div>
</div>

체크박스의 기존 코드를 제거하고 타임리프가 제공하는 체크박스 코드로 변경하자

실행 결과

타임리프를 사용하면 히든 필드 부분이 자동으로 생성된다!

🔗 전체 코드 확인하기


체크박스 - 멀티

이번에는 체크박스를 멀티로 사용해서, 하나 이상을 체크할 수 있도록 해보자!

✔ 등록 지역

  • 서울, 부산, 제주
  • 체크 박스로 다중 선택할 수 있다.

코드로 확인하기

🔗 전체 코드 확인하기

@ModelAttribute의 특별한 사용법

등록 폼, 상세화면, 수정 폼에서 모두 서울, 부산, 제주라는 체크 박스를 반복해서 보여줘야 한다.

이렇게 하려면 각각의 컨트롤러에서 model.addAttribute() 을 사용해서 체크 박스를 구성하는 데이터를 반복해서 넣어주어야 한다.

@ModelAttribute는 이렇게 컨트롤러에 있는 별도의 메서드에 적용할 수 있다.

@ModelAttribute("regions")
public Map<String, String> regions() {
    Map<String, String> regions = new LinkedHashMap<>();
    regions.put("SEOUL", "서울");
    regions.put("BUSAN", "부산");
    regions.put("JEJU", "제주");
   return regions;
}

해당 컨트롤러를 요청할 때 regions에서 반환한 값이 자동으로 모델(model)에 담기게 된다.

물론 이렇게 사용하지 않고, 각각의 컨트롤러 메서드에서 모델에 직접 데이터를 담아서 처리해도 된다!

addForm.html

th:for="${#ids.prev('regions')}"

멀티 체크박스는 같은 이름의 여러 체크박스를 만들 수 있다.

그런데 이렇게 반복해서 HTML 태그를 생성할 때,
생성된 HTML 태그 속성에서 name은 같아도 되지만, id 는 모두 달라야 한다.

이를 위해 타임리프는 체크박스를 each 루프 안에서 반복해서 만들 때,
임의로 1, 2, 3 숫자를 뒤에 붙여준다.


실행 결과


라디오 버튼

라디오 버튼은 여러 선택지 중에 하나를 선택할 때 사용할 수 있다.

✔ 상품 종류

  • 도서, 식품, 기타
  • 라디오 버튼으로 하나만 선택할 수 있다.

코드로 확인하기

🔗 전체 코드 확인하기

FormItemController

@ModelAttribute("itemTypes")
public ItemType[] itemTypes() {
    return ItemType.values();
}
  • itemTypes를 등록 폼, 조회, 수정 폼에서 모두 사용하므로 @ModelAttribute의 특별한 사용법을 적용!
  • ItemType.values()를 사용하면 해당 ENUM의 모든 정보를 배열로 반환한다.
    • Ex) [BOOK, FOOD, ETC]

실행 결과

⭐ 라디오 버튼

  • 라디오 버튼은 아무것도 선택하지 않을 경우, 아무 값도 넘어가지 않아 null이 된다.
  • 라디오 버튼은 이미 선택이 되어 있다면, 수정시에도 항상 하나를 선택하도록 되어있기 때문에 별도의 히든필드를 사용할 필요가 없다!

셀렉트 박스

셀렉트 박스는 여러 선택지 중에 하나를 선택할 때 사용할 수 있다.

✔ 배송 방식

  • 빠른 배송 / 일반 배송 / 느린 배송
  • 셀렉트 박스로 하나만 선택할 수 있다.

코드로 확인하기

🔗 전체 코드 확인하기

FormItemController

@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;
}

DeliveryCode를 등록 폼, 조회, 수정 폼에서 모두 사용하므로 마찬가지로 @ModelAttribute의 특별한 사용법을 적용한다.

실행 결과

profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글