Spring boot와 thymeleaf를 사용하여 질문게시판 토이 프로젝트를 진행하다가, Get /question/new 요청시 다음과 같은 예외가 발생했다.
예외가 발생하기 전 코드는 아래와 같다.
<QuestionController.java>
@GetMapping("/question/new")
public String createForm(Model model) {
return "question_form";
}
@PostMapping("/question/new")
public String createQuestion(@Validated @ModelAttribute QuestionForm questionForm, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "question_form";
}
service.save(questionForm.getTitle(), questionForm.getContent());
return "redirect:/qbp/question";
}
<question_form.html>
<html layout:decorate="~{layout}">
<div layout:fragment="content" class="container">
<h5 class="my-3 border-bottom pb-2">질문등록</h5>
<form th:action="@{/qbp/question/new}" th:object="${questionForm}" method="post">
<div class="mb-3">
<label for="title" class="form-label">제목</label>
<input type="text" th:field="*{title}" th:errorclass="field-error" name="title" class="form-control">
<div th:if="${#fields.hasErrors('title')}" th:errorclass="field-error" th:errors="*{title}">
제목 오류
</div>
</div>
<div class="mb-3">
<label for="content" class="form-label">내용</label>
<textarea name="content" th:field="*{content}" th:errorclass="field-error" class="form-control" rows="10">
</textarea>
<div th:if="${#fields.hasErrors('content')}" th:errorclass="field-error" th:errors="*{content}">
본문 오류
</div>
</div>
<input type="submit" value="저장하기" class="float-end btn btn-info btn-sm my-2">
</form>
</div>
</html>
단순히 th:object="${questionForm}" 문법을 통해 폼의 입력값을 컨트롤러에게 넘겨만 주면 된다고 생각을 해서 입력폼 페이지를 조회하는 아래의 함수를 수정하지 않았다.
@GetMapping("/question/new")
public String createForm(Model model) {
return "question_form";
}
Neither BindingResult nor plain target object for bean name 'questionForm' available as request attribute
예외 자체도 BindingResult라고 쓰여져 있어, thyemleaf 코드에 error 와 관련된 문법(th:errors나 th:errorclass)에 오타나 잘못된 문법이 있거나 @BindingResult을 잘못 사용한 것이라 생각을 해서 이리 저리 수정해보았지만 해당 예외를 해결하지 못했다.
구글링 결과,
결국 예외가 발생한 이유는 입력폼 페이지 조회시(/question/new Get 요청), 템플릿에서 th:object="${questionForm}에서 questionForm에 대한 정보를 전달받지 못해 발생한 것이었다. 따라서 아래와 같이 model에 questionForm에 대한 객체 정보를 저장하여 템플릿에게 전달해야 한다.
이 때, 처음 입력 폼 페이지를 조회할 때 입력 폼은 모두 비어져있어야 하기 때문에 빈 객체(new QuestionForm())을 전달해야 한다.
@GetMapping("/question/new")
public String createForm(Model model) {
model.addAttribute("questionForm", new QuestionForm());
return "question_form";
}