ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링 : BindingResult 를 통한 에러 처리해보기
    백엔드 : 서버공부/Spring 2024. 2. 19. 15:39
    728x90

    웹사이트에서 사용할 회원가입기능을 구현한다고 생각해봅시다.

    여기서 설계를 할때 이름은 필수로 입력받도록 처리했다는 가정을 해보겠습니다.

    코드로 서의 구현은 다음과 같습니다.

    @Getter @Setter
    public class MemberForm {
    
        /**
         *  이 어노테이션을통해 값이 비어있으면 오류가  발생하게 해줍니다
         * */
        @NotEmpty(message = "회원 이름은 필수 입니다")
        private String name;
    
        private String email;
        private String age;
    }

    @NotEmpty 어노테이션을 통해 name 필드에 어떠한 값도 넘어오지않으면, 유효성 검사 오류를 터뜨리도록 하였습니다.

    그런데 이렇게 처리하면 문제가 있습니다. 클라이언트 측에서 이름을 누락하고 값을입력하면 Spring MVC는 기본적으로 whitelabel 오류 페이지를 표시하기때문에 다음과 같이 whitelabel 페이지가 나타나서, 웹페이지의 사용성을 떨어뜨립니다.

    Spring MVC에서 제공하는 Whitelabel 오류페이지

    오류페이지로 넘어가는거 대신 오류 발생시에 해당 페이지내에서 오류를 클라이언트측에서 알수있게 구현해보겠습니다.

    이때 사용되는 것이 BindingResult입니다. BindingResult는 오류가 있는 입력값들을 처리하게 해주는 스프링에서 제공하는 객체입니다. BindingResult는 컨트롤러단에서 폼 입력값의 유효성 검사를 수행한 후 그 결과를 담는 역할을 합니다. 오류가 발견되면 오류들을 감지해서, 서버측에서 이 오류에대한 적절한 피드백을 사용자에게 직접 제공할 수 있습니다.

    BindingResult는 javax의 validation과 함께쓰여 좀더 자연스러운(?) api를 구현할 수 있게해줍니다. 조합은 폼 입력값에 대한 복잡한 유효성 검사 규칙을 선언적으로 정의할 수 있게 하며, 오류 발생 시 이를 효과적으로 처리할 수 있는 자연스러운 API를 구현할 수 있도록 지원합니다.

    BindingResult를 사용해서 회원가입 매서드를 구현해보겠습니다.

    @PostMapping("/members/new")
        public String create(@Valid MemberForm form, BindingResult result) {
    
            if (result.hasErrors()) {
                return "members/createMemberForm";
            }
    
            Member member = new Member();
            member.setName(form.getName());
            member.setAge(form.getAge());
            member.setEmail(form.getEmail());
            
            memberService.join(member);
            return "redirect:/"; // 뭔가 저장 후에 재로딩하면 안좋기때문에 리다이렉팅 시킴
        }

    create 매서드의 파라미터도 MemberForm 뒤에 BindingResult를 추가해줍니다. 그 후에 아래의 조건문을 통해 오류가 발생했을때 회원가입페이지로 이동하도록 해줍니다.

    if (result.hasErrors()) {
                return "members/createMemberForm";
            }

    이렇게 회원가입 api를 구현하면 프론트단에서 입력창에서 오류를 뽑아 처리해줄 수 있습니다.

    <label th:for="name">이름</label>
    
                <input type="text" th:field="*{name}" class="form-control" placeholder="이름을 입력하세요"
                       th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'">
                <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p>

    이렇게 구성을 완료하면 클라이언트 측에서 입력을 누락했을때 다음과 같은 화면을 볼 수 있습니다.

    여기서 다른 입력값들이 유지되는 이유는, 폼 제출 시 MemberForm 객체에 사용자의 입력값들이 저장되고, 이 객체가 BindingResult와 함께 처리되기 때문입니다. BindingResult는 유효성 검사 과정에서 발생한 오류들을 관리하지만, 사용자의 입력값 자체는 MemberForm 객체 내에 유지됩니다. 이렇게 함으로써, 유효성 검사에 실패할 경우 사용자의 입력값을 폼에 다시 표시하고, 오류 메시지를 제공하여 사용자가 어떤 부분을 수정해야 하는지 쉽게 알 수 있도록 합니다.

     

    BindingResult는 많은 기능을 갖고 있고, 더 다양한 부분에서 활용되고 있습니다. 앞으로 공부를 진행하면서 더 깊게 공부해야할 부분중 하나인것 같습니다.

Designed by Tistory.