[Spring Boot] 13. 홈페이지 만들기 ④ 에러 페이지 처리

shr·2022년 2월 24일
0

Spring

목록 보기
12/23
post-thumbnail

에러 페이지 처리


📝 MVC와 REST 분리

에러 페이지 처리를 위해서 Advice(부가 기능을 담은 객체)를 사용하려고 한다. 이때 예외에 응답하는 컨트롤러를 지정해 주어야 하는데, MVC 방식과 REST 방식은 응답 방식이 다르다. 따라서 MVC와 REST를 분리하여 작업하려고 한다.
위와 같이 분리해 놓았다.

📝 에러 페이지 - e403과 error

e403
Spring Security에서 발생한 403 상태 코드에 대한 처리 페이지이다.

error
ControllerAdvice를 거쳐, 다양한 상황에서 RedirectAttibutes나 HttpSession에 담긴 에러들을 처리하는 페이지이다.


  1. src/main/resources - templates - system - e403.html, error.html 생성
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8" xmlns:th="http://www.thymeleaf.org">
    <title>잘못된 접근</title>
    </head>
    <body>
        <p>잘못된 접근입니다.</p>
        <a href="/">첫 페이지로 이동</a>
    </body>
    </html>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8" xmlns:th="http://www.thymeleaf.org">
    <title>Insert title here</title>
    </head>
    <body>
        <p th:text="${msg}"></p>
        <a href="/">첫 페이지로 이동</a>
    </body>
    </html>

지난 시간에 SecurityConfig - accessDeniedPage("/system/e403"); 해 준 부분의 화면을 만든다.


  1. 기존의 MemberController에 있던 REST 방식의 메소드들을 src/main/java - com.example.demo.controller.rest - MemberRestController로 이동 후 수정

    package com.example.demo.controller.rest;
    
    import java.security.Principal;
    
    import javax.validation.constraints.NotEmpty;
    
    import org.springframework.http.*;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import com.example.demo.service.MemberService;
    
    import lombok.AllArgsConstructor;
    
    // @RestController로 작동하는 메소드의 집합, @Controller는 REST + MVC
    @Validated
    @AllArgsConstructor
    @RestController
    public class MemberRestController {
        private MemberService service;
    
        // javax.validation을 이용한 사용자 입력 값 검증
        @GetMapping("/member/id_check")
        public ResponseEntity<String> idCheck(@NotEmpty(message="아이디는 필수 입력입니다.") String username, Principal principal) {
            if (principal != null)
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body("잘못된 접근입니다.");
            if (service.idCheck(username)==false)
                return ResponseEntity.status(HttpStatus.CONFLICT).body("사용 중인 아이디입니다.");
            return ResponseEntity.status(HttpStatus.OK).body("사용 가능한 아이디입니다.");
        }
    
        @ResponseBody
        @GetMapping("/member/find/id")
        public ResponseEntity<String> findId(@NotEmpty(message="아이디는 필수 입력입니다.") String email, Principal principal) {
            if (principal != null)
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body("잘못된 접근입니다.");
            String username = service.findId(email);
            if (username == null)
                return ResponseEntity.status(HttpStatus.CONFLICT).body("아이디를 찾지 못했습니다.");
            return ResponseEntity.ok(username);
        }
    }

  1. src/main/java - com.example.demo.controller.mvc - SystemController 생성

    package com.example.demo.controller.mvc;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class SystemController {
        @GetMapping("/system/e403")
        public void e403() {
    
        }
    
        @GetMapping("/system/error")
        public void error() {
    
        }
    }

  1. src/main/java - com.example.demo.controller.advice - ProjectAdvice, ProjectRestAdvice 생성

    package com.example.demo.controller.advice;
    
    import javax.validation.*;
    
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.servlet.mvc.support.*;
    
    @ControllerAdvice(basePackages = "com.example.demo.controller.mvc")
    public class ProjectAdvice {
        @ExceptionHandler(ConstraintViolationException.class)
        public String constraintViolationException(ConstraintViolationException e, RedirectAttributes ra) {
            ra.addFlashAttribute("msg", e.getMessage());
            return "redirect:/system/error";
        }
    }
    package com.example.demo.controller.advice;
    
    import javax.validation.*;
    
    import org.springframework.http.*;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.servlet.mvc.support.*;
    
    @ControllerAdvice(basePackages = "com.example.demo.controller.rest")
    public class ProjectRestAdvice {
        @ExceptionHandler(ConstraintViolationException.class)
        public ResponseEntity<String> constraintVoilationException(ConstraintViolationException e, RedirectAttributes ra) {
            return ResponseEntity.status(HttpStatus.CONFLICT).body(e.getMessage());
        }
    }

    💡 ConstraintViolationException

    메소드의 파라미터나 리턴 값에 문제가 있을 때 발생하는 오류이다. 500 상태 코드를 반환한다. 본문은 @ControllerAdvice를 이용해 그에 대한 변경 처리를 해 준 것이다.

    예외에 응답하는 컨트롤러 역할을 한다.

profile
못하다 보면 잘하게 되는 거야 ・ᴗ・̥̥̥

0개의 댓글