스프링 부트는 src/main/resources/templates
경로에서 템플릿을 찾는다. 하지만 만약에 모든 템플릿이 예를 들어 new-templates
폴더 안에 들어가도록 변경해야하는 요구사항이 들어왔다고 하자. 그러면 어떻게 해야할까? 아래와 같이 spring.thymeleaf.prefix를 변경해주면 된다. 기본적으로 suffix는 .html
로 되어 있다.
spring.thymeleaf.prefix=classpath:/new-templates/
spring.thymeleaf.suffix=.html
하지만 나는 프로젝트 진행 중 아래와 같은 에러 메세지를 만나게 되었다.
Exception processing template "/login/loginPage":
Error resolving template [/login/loginPage],
template might not exist or might not be accessible
by any of the configured Template Resolvers
왜 일까? 더욱이 문제의 갈피를 잘 못 찾았던 것은, Local에서는 잘 실행이 되었는데, 호스팅을 했을 때 문제가 생긴 까닭이었다. 무엇이 원인이었을까? 그것은 내가 Spring MVC에서 view 를 반환할 때 그 경로를 /login/loginPage
이렇게 해두었기 때문. 인텔리제이 IDE에서는 중복 슬래시(//)도 알아서 처리를 해주지만 jar 파일로 배포를 할 때는 그러한 처리 과정이 없기 때문에 오류가 난 것이었다. 모든 view에서 앞에 있는 /(slash)를 제거해준 뒤 문제를 해결할 수 있었다.
<form th:action="@{/posts/{postId}/delete(postId=${postAndComments.id})}"
th:object="${postAndComments}" th:method="delete">
Thymeleaf 에서는 Delete, Put 방식의 경우 post 방식으로 처리되지만, <input type="hidden" name="_method" value="delete">
or <input type="hidden" name="_method" value="put">
이 추가되어서 Spring MVC에 의해 적절히 처리된다. 그래서 delete 방식의 경우 th:method=”delete”
로 하고, Controller 단에서는 @PostMapping
으로 처리해야 한다.
// 게시글 삭제
@PostMapping("/posts/{postId}/delete")
public String deletePost(@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long postId) {
boardService.deletePost(postId, userDetails.getUsername());
return "redirect:/posts";
}
form에서 submit을 할 때, form의 데이터가 th:object에 설정한 객체로 받아진다.
각 필드를 매핑해주는 역할을 한다. 설정해 준 값으로, th:object의 객체내부 값과 매칭해준다.
아래는 로그인 페이지 예시이다.
<form th:object="${loginForm}" th:action="@{login}" method="post">
<div>
<label for="username" th:text="#{member.loginId}">아이디</label>
<input th:type="text" id="username" th:field="*{username}" name="username">
</div>
<div>
<label for="password" th:text="#{member.password}">비밀번호</label>
<input th:type="password" id="password" th:field="*{password}" name="password">
</div>
<div class="checkbox">
<label><input class="checkbox" type="checkbox" id="remember" name="remember-me">Remember me</label>
</div>
<div>
<div class="form-check">
<input type="checkbox" id="open" th:field="*{open}">
<label for="open">자동 로그인</label>
</div>
</div>
<button type="submit">로그인</button>
</form>
https://www.baeldung.com/spring-thymeleaf-template-directory