๐ ํด๊ฒฐํ๊ณ ์ ํ๋ ์ํฉ
์ง๋ฌธ ํผ์ ์์ฑํ์ฌ POST request ๋ฅผ ๋ ๋ฆฌ๋ฉด Controller ์์ ์ ํจ์ฑ์ ํ์ธ ํ ๋ฌธ์ ๊ฐ ์์ผ๋ฉด Service ๋ก ๋๊ฒจ ์ ์ฅ, ๋ฌธ์ ๊ฐ ์์ผ๋ฉด ๋ฌธ์ ๋ฅผ ์ง๋ฌธํผ View ๋ก ๋๊ฒจ์ ์ฌ์ฉ์์๊ฒ ์๋ฆผ
๐ ํด๊ฒฐ ๋ฐฉ๋ฒ
โ ์ผ๋จ View ๋ก ๋ถํฐ ๋๊ฒจ๋ฐ์ ๊ฐ์ if null ์กฐ๊ฑด๋ฌธ์ ํตํด ํ์ธ, ๋ฌธ์ ๊ฐ ์์ผ๋ฉด Model ์ ํด๋น ๋ฌธ์ ์ ๋ฉ์ธ์ง๋ฅผ ์ ์ด ์ ์ฅ ํ View ๋ก ๋๊น โก๏ธ ๋๊ฒจ๋ฐ์ ๋ชจ๋ ํ๋ผ๋ฏธํฐ๋ค์ ๋ํด if ๋ฌธ์ ์์ฑํด์ผํจ์ผ๋ก ์ฝ๋๊ฐ ๊ธธ์ด์ง, ๋ ํ๋ผ๋ฏธํฐ๊ฐ ์ถ๊ฐ๋๋ฉด ๊ทธ ๋งํผ ์๋ก ์์ฑํด์ผํจ.
โก Spring ์ @Valid ํ์ฉ โก๏ธ if ๋ฌธ์ ๋งค๋ฒ ์์ฑํ ํ์๊ฐ ์๊ณ , ํ๋ผ๋ฏธํฐ๊ฐ ์ถ๊ฐ๋์ด๋ Controller ๋จ์์๋ ์๋ก ์์ฑํด์ผ ํ ๋ด์ฉ์ด ์์
์ด ์ธ์๋ ๋ค์ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ ์ ์๊ฒ ์ง๋ง ์ง๊ธ์ @Valid ์ ํจ์ฑ ํ์ธ ๋ฐฉ์์ ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค.
๐ ํด๊ฒฐ ๊ณผ์
โ Valid ํ์ฉ์ ์ํ ์์กด์ฑ ์ฃผ์
implementation 'org.springframework.boot:spring-boot-starter-validation'
โก ์ ํจ์ฑ ํ์ธ์ ์ํ ์ ์ฝ ์กฐ๊ฑด ์ถ๊ฐ
@Getter
@Setter
public static class RequestQuestionForm {
@NotEmpty (message = "์ ๋ชฉ์ ํ์ ์ฌํญ ์
๋๋ค.") // ์ ์ฝ ์กฐ๊ฑด (1)
@Size(max = 100, message = "์ ๋ชฉ์ 100์ ์ดํ๋ก ์
๋ ฅํด์ฃผ์ธ์") // ์ ์ฝ ์กฐ๊ฑด (2)
private String subject;
@NotEmpty (message = "๋ด์ฉ์ ํ์ ์ฌํญ ์
๋๋ค.") // ์ ์ฝ ์กฐ๊ฑด (3)
private String content;
}
โข Contoller ์์ ์ ํจ์ฑ ํ์ธ
โก๏ธ ํ์ธ์ ํด์ผํ ๊ฐ์ @Valid ๋ฅผ ๋ถ์ฌ์ฃผ์ด์ผํ๊ณ , ์ ํจ์ฑ ํ์ธ ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ธฐ์ํ BindingResult ๊ฐ์ฒด๋ฅผ ์์ ์์ฑํด์ฃผ์ด์ผํจ
@Controller
@RequestMapping("/question")
@RequiredArgsConstructor
public class QuestionController {
// (์๋ต)
// ์ง๋ฌธ ๋ฑ๋ก (POST)
@PostMapping("/create")
public String createQuestion(@Valid QuestionDto.RequestQuestionForm requestQuestionForm, BindingResult bindingResult) {
if(bindingResult.hasErrors()) { // ์ ํจ์ฑ ํ์ธ
return "question_form";
}
questionService.createQuestion(requestQuestionForm.getSubject(), requestQuestionForm.getContent());
return "redirect:/question/list";
}
}

โฃ View ์์ ํด๋น ์๋ฌ ๋ณด์ผ ์ ์๋๋ก
<div layout:fragment="content" class="container my-3">
<form method="POST" th:action="@{/question/create}" th:object="${requestQuestionForm}" class="my-3">
<!-- (์ถ๊ฐ ์์) -->
<div class="alert alert-danger" role="alert" th:if="${#fields.hasAnyErrors()}">
<div th:each="err : ${#fields.allErrors()}" th:text="${err}" />
</div>
<!-- (์ถ๊ฐ ๋) -->
<!-- (์๋ต) -->
</form>
</div>
- ์ถ๊ฐ (1) : form ์๋ฆฌ๋จผํธ ์์ th:object
- ์ถ๊ฐ (2) : div ํ๊ทธ ๋ด์ฉ
๐ฑ ๋ฌธ์ ๋ฐ์
๋ด์ฉ๋ง ์ ๋ ฅํ๋ฉด ์ ๋ชฉ์ ์ ๋ ฅํ๋ผ๋ ์๋ด ๋ฌธ๊ตฌ๊ฐ ๋จ์ง๋ง, ์ ๋ชฉ๋ง ์ ๋ ฅํ๋ฉด ์๋ด ๋ฌธ๊ตฌ ์์ด ์ง๋ฌธ์ด ์ ์ฅ๋จ.
html ํ์ผ์์ content ์ ํด๋นํ๋ textarea ์๋ฆฌ๋จผํธ๋ฅผ input ์ผ๋ก ๋ฐ๊พธ๋ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๊ฐ ๋์์. textarea ์ผ ๋๋ ๋ญ๊ฐ ๋ค๋ฅธ๊ฐ..?
โก๏ธ (์์ธ ํ์ ) ์ด์ ๋ ์ ์ ์์ง๋ง, textarea ์ ๊ฒฝ์ฐ ํ์นธ์ ๋์ด์ฐ๊ธฐ๊ฐ ์๋์ผ๋ก ๋ค์ด๊ฐ์ @NotEmpty ์ ์ฝ ์กฐ๊ฑด์ ๊ฑธ๋ฆฌ์ง ์์. ํ์ง๋ง ์๊ณ ๋ณด๋ label ์๋ฆฌ๋จผํธ๋ฅผ ์ํ for & id Mapping ๊ณผ์ ์์ ์๊ธฐ๋ ๋์ด์ฐ๊ธฐ ์๋ค๋...! ๊ทธ๋ฅ id & for ์์ ์ค.
โก๏ธ (์ถ๊ฐ ๋ด์ฉ ์ ๋ฆฌ : 2022.10.26) : ํผ์ด๋ฆฌ๋ทฐ๋ฅผ ํ๋ ์ค @NotEmpty ๋ฅผ ๋์ฒดํ @NotBlank ๋ฅผ ์๊ฒ๋์๋ค. ํด๋น ์ด๋ ธํ ์ด์ ์ ์ผ๋ฐ ๊ณต๋ฐฑ (" ") ๋ ํ์ฉํ์ง ์์ผ๋ฏ๋ก textarea ๋ฅผ ์ฐ๋ฉด์๋ ์์ธ๋ฅผ ํ์ธ ํ ์ ์๋ค!
๐ ๊ฒฐ๊ณผ
