새로운 상품 관리 예제 시작!
상품을 관리할 수 있는 서비스를 만들어보자. 요구사항은 다음과 같다.
: 상품 ID / 상품명 / 가격 / 수량
: 상품 목록 / 상품 상세 / 상품 등록 / 상품 수정
요구사항이 정리되고 디자이너, 웹 퍼블리셔, 백엔드 개발자가 업무를 나누어 진행한다.
💡 상품 도메인 모델
: 상품 ID / 상품명 / 가격 / 수량
테스트까지 확인 완료!
HTML
HTML 개발을 편리하게 하기 위해서 부트스트랩을 사용해보자!😃
부트스트랩에서 Compiled CSS and JS
항목을 다운받은 뒤 bootstrap.min.css
파일을 resources/static/css
폴더에 추가해주자!
⚠ 주의
가끔 IntelliJ에 파일 그대로 옮기면 안될 때도 있어서,
http://localhost:8080/css/bootstrap.min.css
에 접속했을 때 이렇게 잘 나오는지 확인하기!
HTML
만들기이제 페이지를 만들어보자!
items.html
item.html
addForm.html
editForm.html
상품 목록 컨트롤러와 뷰 템플릿을 개발해보자!
BasicItemController
package hello.itemservice.web.basic;
import hello.itemservice.domain.item.Item;
import hello.itemservice.domain.item.ItemRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.PostConstruct;
import java.util.List;
@Controller
@RequestMapping("/basic/items")
@RequiredArgsConstructor
public class BasicItemController {
private final ItemRepository itemRepository;
@GetMapping
public String items(Model model) {
List<Item> items = itemRepository.findAll();
model.addAttribute("items", items);
return "basic/items";
}
@PostConstruct
public void init() {
itemRepository.save(new Item("testA", 1000, 10));
itemRepository.save(new Item("testB", 2000, 20));
}
}
itemRepository
에서 모든 상품 조회 → 모델에 저장 → 뷰 템플릿 호출@RequiredArgsContructor
: final
이 붙은 멤버 변수만 사용해 생성자를 자동 생성@PostConstructor
init()
을 수행해 2개의 아이템 미리 추가!items.html
위에서 작성했던 items.html
을 뷰 템플릿 영역으로 복사해주자.
🔗 코드 확인하기
Thymeleaf
) 간단히 알아보기<html xmlns:th="http://www.thymeleaf.org">
타임리프를 사용하려면 html 파일에 이렇게 적어야 한다.
th:href
th:href="@{/css/bootstrap.min.css}"
href
를 th:href
로 변경해준다.th:xxx
로 변경한다. 만약 값이 없다면 새로 생성한다.href
속성이 사용되고, 뷰 템플릿을 거치면 th:href
의 값이 href
로 대체되면서 동적으로 변경할 수 있다.th:xxx
부분은 서버사이드에서 렌더링되고, 기존 속성을 대체한다. 만약 th:xxx
이 없으면 기존 html의 xxx
속성이 그대로 사용된다.th:xxx
속성을 웹 브라우저에서는 읽지 못하기 때문에 무시한다.URL링크 표현식 - @{...}
@{...}
를 사용하는데, 이를 URL링크 표현식이라 한다.|...|
th:onclick="|location.href='@{/basic/items/add}'|"
1. +
+ escape
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
2. |...|
(리터럴 대체 문법)
<span th:text="|Welcome to our application, ${user.name}!|">
+
연산자와 escape
기호를 사용해 하나하나 작성해야 했지만, 리터럴 대체 문법을 사용하면 편리하게 사용할 수 있다!th:each
<tr th:each="item : ${items}">
th:each
를 사용한다. <tr>..</tr>
이 하위 태그를 포함해서 생성된다.${...}
<td th:text="${item.price}">10000</td>
item.getPrice()
)th:text
<td th:text="${item.price}">10000</td>
th:text
의 값으로 변경한다.10000
을 ${item.price}
의 값으로 변경한다.URL 링크 표현식2
- @{...}
th:href="@{/basic/items/{itemId}(itemId=${item.id})}"
{itemId}
)뿐만 아니라 쿼리 파라미터도 생성할 수 있다.th:href="@{|/basic/items/${item.id}|}"
📌 네츄럴 템플릿 (
natural templates
)타임리프는 순수 HTML 파일을 웹 브라우저에서 열어도 내용을 확인할 수 있고, 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다.
이렇게 순수 HTML을 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿이라고 한다!