국비

[ 56일차 18~21 ] 수업 정리 - Spring boot

코딩하는냥이 2025. 7. 7. 16:52
반응형

오늘은 Spring Boot 유효성 검사(Validation) 기능을 도입하여 질문과 답변 작성 시 빈값 입력 방지를 처리하였고, 오류 메시지를 사용자에게 보여주는 방식까지 완성했습니다. 또한, 네비게이션 바와 공통 템플릿도 정비하며 전체적인 UI의 일관성을 향상시켰습니다.


📌 주요 학습 내용


1. 📦 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-validation'
  • @Valid 및 @NotEmpty, @Size 등 검증 기능을 활성화하기 위한 의존성

2. 📄 DTO 클래스에 유효성 검증 어노테이션 적용

📝 AnswerForm.java

@NotEmpty(message = "내용을 입력해주세요.")
private String content;

📝 QuestionForm.java

@NotEmpty(message = "제목을 입력해주세요.")
@Size(max = 200)
private String subject;

@NotEmpty(message = "내용이 비어있습니다.")
private String content;
  • 빈값 제출 방지
  • 메시지를 사용자에게 명확히 전달 가능

3. ✅ 컨트롤러에서 유효성 검사 처리

📂 AnswerController.java

@PostMapping("/create/{id}")
public String createAnswer(..., @Valid AnswerForm answerForm, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        model.addAttribute("question", question);
        return "question_detail";
    }
    ...
}

📂 QuestionController.java

@PostMapping("/create")
public String questionCreate(@Valid QuestionForm questionForm, BindingResult bindingResult) {
    if (bindingResult.hasErrors())
        return "question_form";
    ...
}
  • @Valid와 BindingResult를 함께 사용하여 폼 유효성 검사 수행
  • 유효성 오류 발생 시 해당 폼으로 다시 이동

4. 🧩 Thymeleaf에서 오류 메시지 출력 처리

✅ 개별 폼에 직접 처리

<div class="alert alert-danger" th:if="${#fields.hasAnyErrors()}">
    <div th:each="err : ${#fields.allErrors()}" th:text="${err}"></div>
</div>

✅ 공통 Fragment화 (form_errors.html)

<!-- templates/form_errors.html -->
<div th:fragment="formErrorsFragment" ...>
    <div th:each="err : ${#fields.allErrors()}" th:text="${err}"></div>
</div>
  • 오류 메시지 UI 일관성 유지
  • 중복 제거

5. ✍ 질문 등록 폼 (question_form.html)

<form th:action="@{/question/create}" th:object="${questionForm}" method="post">
    <div th:replace="~{form_errors :: formErrorsFragment}"></div>
    <input type="text" th:field="*{subject}" class="form-control">
    <textarea th:field="*{content}" class="form-control"></textarea>
</form>
  • th:object로 바인딩하고 th:field로 폼 필드를 매핑
  • 오류 메시지는 Fragment로 출력

6. 💬 답변 등록 UI (question_detail.html)

<form th:action="@{|/answer/create/${question.id}|}" th:object="${answerForm}" method="post">
    <div th:replace="~{form_errors :: formErrorsFragment}"></div>
    <textarea class="form-control" th:field="*{content}"></textarea>
    <input class="btn btn-primary" type="submit" value="등록">
</form>
  • 유효성 실패 시에도 질문 상세 화면을 그대로 유지하며 오류 표시

7. 🌐 기본 템플릿 구성

📁 layout.html

  • Bootstrap, CSS 링크, layout:fragment 사용
  • nav를 fragment로 분리해 재사용

📁 navbar.html

<nav th:fragment="navbarFrgment" class="navbar ...">
    <a class="navbar-brand" href="/">게시판</a>
</nav>

📄 layout.html에서 nav 호출

<nav th:replace="navbar :: navbarFrgment"></nav>

💡 포인트 정리

  • @Valid, @NotEmpty, @Size를 통해 입력값 검증
  • BindingResult로 에러를 확인하고 사용자에게 피드백
  • 오류 메시지 출력을 공통 fragment로 만들어 재사용성 향상
  • Bootstrap을 활용한 UI 구성으로 사용자 편의성 개선
  • nav 바를 fragment로 관리하여 코드 중복 최소화

📌 정리하자면, 55일차에는 질문 및 답변 작성 시 사용자 입력을 서버 측에서 검증하고, 검증 실패 시 오류 메시지를 자연스럽게 출력하는 구조를 구현했습니다. 이를 통해 보다 안정적이고 사용자 친화적인 웹 폼을 완성하게 되었습니다.