반응형 Framework & Library/Spring Boot164 [Spring Boot] : HandlerExceptionResolver 활용하기 HandlerExceptionResolver 활용하기 예외 발생 → WAS → 오류 페이지 찾는다 → 다시 /error 호출 이 과정은 복잡하다. ExceptionResolver를 통해 예외가 발생했을 때 깔끔하게 해결이 가능하다. if (id.equals("user-ex")) { throw new UserException("사용자 오류"); } ApiExceptionController에 user-ex에 대한 코드를 넣어주어 호출 시 UserException이 발생하도록 했다. try { if (ex instanceof UserException) { log.info("UserException resolver to 400"); String acceptHeader = request.getHeader("acc.. 2022. 3. 5. [Spring Boot] : HandlerExceptionResolver 시작하기 HandlerExceptionResolver 시작하기 IllegalArgumentException을 처리하지 못 해 컨트롤러 밖으로 넘어가는 일이 생길 때 HTTP 상태 코드를 400으로 처리하고 싶다고 가정하고 실습을 진행했다. if (id.equals("bad")) { throw new IllegalArgumentException("잘못된 입력 값"); } 먼저 ApiExceptionController를 수정해 주었다. HandlerExceptionResolver를 사용하면 컨트롤러 밖으로 던져진 예외를 해결하고 동작 방식을 변경할 수 있따. 줄여서 ExceptionResolver라고 부른다. @Slf4j public class MyHandlerExceptionResolver implements Ha.. 2022. 3. 4. [Spring Boot] : API 예외 처리 스프링 부트 기본 오류 처리 API 예외 처리도 스프링 부트가 제공하는 기본 오류 방식을 사용할 수 있다. @RequestMapping(produces = MediaType.TEXT_HTML_VALUE) public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { } @RequestMapping public ResponseEntity error(HttpServletRequest request) { } /error 동일 경로를 처리하는 메서드 두 개를 코딩해 주었다. errorHTML은 produces를 사용해 값을 주어 클라이언트 요청의 Accept 해더 값이 text/html인 경우 errorHtml()을 호출해 view를 제공하고.. 2022. 3. 3. [Spring Boot] : API 예외 처리 기본 체크하기 API 예외 처리 기본 체크 API 예외 처리에 대해 공부했는데 API 경우 일반적인 오류 페이지 말고도 생각할 게 많다. API는 오류 상황에 맞는 응답 스펙과 JSON으로 데이터를 내보내야 한다. 먼저 WAS에 예외가 전달되거나 response.sendError()가 호출되면 등록된 예외 페이지 경로를 호출하는 WebSErverCustomizer에 Component 주석을 풀어줬다. private String memberId; private String name; 간단하게 DTO를 만들고 @GetMapping("/api/members/{id}") public MemberDto getMember(@PathVariable("id") String id) { if (id.equals("ex")) { thro.. 2022. 3. 2. [Spring Boot] : BasicErrorController가 model에 담는 정보 BasicErrorController는 여러 정보를 model에 담아 뷰에 전달하는데 뷰 템플릿에서 출력해서 확인해 볼 수 있다. 이런 정보는 고객에게 굳이 보여 줄 필요도 없고 해커가 이런 라이브러리를 사용하구나? 이런 라이브러리의 취약점은 이거지! 하고 공격 할 수도 있어서 더욱 보여 줄 필요가 없다. server.error.include-exception=true server.error.include-message=on_param server.error.include-stacktrace=on_param server.error.include-binding-errors=on_param application.properties에서 이런 설정을 통해 보이고, 안 보이고, 조건에 따라 보이고 등을 설정할 수.. 2022. 3. 1. [Spring Boot] : BasicErrorController 오류 페이지 스프링 부트는 에러 페이지를 자동으로 등록하는데 /error이라는 경로로 기본 오류 페이지를 설정한다. 오류가 발생하면 오류페이지로 /error를 기본 요청하고 스프링 부트가 자동 등록한 BasicErrorController는 이 경로를 기본으로 받는다. BasicErrorController는 기본 로직이 개발되어 있어서 우리는 이것을 잘 사용하기만 하면 된다. 간단하게 뷰 템플릿 경로에 오류 페이지 파일을 만들어서 넣어두면 끝이다. 이 BasicErrorController의 뷰 선택 우선 순위도 강의에서 다뤄줬는데 먼저 뷰 템플릿 그 다음이 정적 리소스, 그 다음이 적용 대상이 없을 때 뷰의 이름이다. 각 경로 위치에 상태 코드 이름의 뷰 파일을 넣으면 된다. 추가로 더 자세한 파일명이 우선시 된다. .. 2022. 2. 28. [Spring Boot] : 인터셉터 예외 처리 인터셉터의 중복 호출을 제거한다. @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestURI = request.getRequestURI(); String uuid = UUID.randomUUID().toString(); request.setAttribute(LOG_ID, uuid); log.info("REQUEST [{}][{}][{}][{}]", uuid, request.getDispatcherType(), requestURI, handler); return true; } 필터는 DispatcherTyp.. 2022. 2. 25. [Spring Boot] : 서블릿 예외 처리 필터 강의 전에 사용했던 DispatcherType에 대해 조금 더 자세히 공부했다. 요청 중 오류가 발생하게 되면 오류 페이지 출력을 위해 WAS 내부에서 다시 한 번 호출이 일어난다. 이때 필터, 서블릿, 인터셉터 또한 모두 다시 호출된다. 이때, 클라이언트로부터 발생한 호출인지 오류 페이지를 출력하기 위해 발생한 내부 요청인지 구분이 필요한데 그런 문제를 해결하기 위해 DispatcherType라는 추가 정보를 제공한다. 필터는 dispatcherType라는 옵션을 제공하는데 디폴트 값은 dispatcherType=REQUEST이다. 이 외에 여러 옵션이 있는데 내용은 아래와 같다. REQUEST : 클라이언트 요청 ERROR : 오류 요청 FORWARD : 서블릿에서 다른 서블릿이나 JSP를 호출할 때.. 2022. 2. 25. [Spring Boot] : 서블릿 예외 처리 오류 페이지 작동 원리 강의에서 계속 반복적으로 말 하는데 서블릿은 예외가 발생해서 서블릿 밖으로 전달되거나 response.sendError()가 호출 되었을 때 설정된 오류 페이지를 찾는다. 이떄, 예외 발생과 오류 페이지 요청 흐름을 잘 이해해야 한다고 했다. 요청이 와서 컨트롤러까지 왔다가 컨트롤러에서 다시 인터셉터, 서블릿, 필터, WAS까지 오게되고 WAS에서 에러페이지를 다시 요청한다. 그럼 다시 필터, 서블릿, 인터셉터, 에러처리컨트롤러를 거쳐 뷰로 나가게 된다. 강의에서 중요하다고 말 하고 있는 부분은 클라이언트는 서버 내부에서 컨트롤러가 두 번 호출되었는지 알 수가 없다는 점이다. 서버 내부에서 오류 페이지를 찾기 위해 호출이 추가적으로 발생하게 되는 것이다. javax.servlet.error.excepti.. 2022. 2. 25. [Spring Boot] : 서블릿 예외 처리 오류 화면 제공 기능 구현하기 서블릿이 제공하는 오류 화면 기능을 구현해 봤다. 서블릿은 Exception이 발생해서 서블릿 밖으로 전달되거나 response.sendError()가 호출되었을 때 각각의 상황에 맞춘 오류 처리 기능을 제공한다. @Component public class WebServerCustomizer implements WebServerFactoryCustomizer { @Override public void customize(ConfigurableWebServerFactory factory) { ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error-page/404"); factory.addErrorPages(errorPage404); Comp.. 2022. 2. 25. [Spring Boot] : Servlet Exception, 서블릿 예외 처리 시작하기 서블릿 예외 처리 시작 강의는 항상 점진적으로 발전해온 루트를 따라가기 때문에 시작 부분에서 먼저 스프링이 아닌 순수 코드를 통해 공부를 했다. 서블릿은 Exception과 response.sendError(HTTP 상태 코드, 오류 메시지) 이 두 방식으로 예외 처리를 한다. 내부에서 오류가 발생하면 500으로 Exception을 사용하고 그게 아니라 직접 뭔가 담아서 처리하고 싶으면 response.sendError에 담아 처리하면 된다. @GetMapping("/error-ex") public void errorEx() { throw new RuntimeException("예외 발생!"); } @GetMapping("/error-404") public void error404(HttpServletR.. 2022. 2. 24. [Spring Boot] : ArgumentResolver 활용 @Login 어노테이션을 만들고 이게 있으면 직접 만든 ArgumentResolver가 동작해서 자동으로 세션에 있는 로그인 회원을 찾아주고 없다면 null을 반환하도록 개발하는 실습을 진행했다. @Target(ElementType.PARAMETER) //파라미터에만 사용 @Retention(RetentionPolicy.RUNTIME) //리플렉션 등 활용할 수 있게 런타임까지 어노테이션 정보가 남는다. public @interface Login { } @Login 어노테이션을 생성해 주었다. 주석을 참고하면 된다. @Slf4j public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { HandlerMethodAr.. 2022. 2. 23. [Spring Boot] : 스프링 인터셉터 - 인증 체크 스프링 인터셉터 - 인증 체크 전 강의에서 서블릿 필터로 개발한 부분을 스프링 인터셉터로 바꾸어 개발하는 실습을 진행했다. public class LoginCheckInterceptor implements HandlerInterceptor { HandlerInterceptor를 구현한다. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 여러 기능이 있지만 그 중에 preHandle만 사용하면 된다. String requestURI = request.getRequestURI(); log.info("인증 체크인터셉터 실행 {}", requestUR.. 2022. 2. 23. [Spring Boot] : 스프링 인터셉터 - 요청 로그 String uuid = UUID.randomUUID().toString(); 요청 로그를 구분하기 위해 uuid를 생성해 주었다. //@RequestMapping: HandlerMethod //정적 리소스 : ResourceHttpRequestHandler if (handler instanceof HandlerMethod) { HandlerMethod hm = (HandlerMethod) handler; //호출할 컨트롤러 메서드의 모든 정보가 포함되어있다. } HandlerMethod는 어떤 핸들러 매핑을 사용하는가에 따라 달라진다. @controller와 @RequestMapping을 통한 핸들러 매핑을 주로 사용하는데 이 경우 핸들러 정보로 HandlerMethod가 넘어온다. @Configura.. 2022. 2. 23. [Spring Boot] : 스프링 인터셉터 스프링 인터셉터 소개 스프링 인터셉터는 서플릿 필터와 같이 웹과 관련된 공통 관심 사항을 효과적으로 해결할 수 있는 기술이다. 서블릿 필터는 서블릿이 제공하고 스프링 인터셉터는 스프링 MVC가 제공하는 기술이다. 스프링 인터셉터는 디스패쳐 서블릿과 컴트롤러 사이에서 컨트롤러 호출 직전에 호출이 된다. HTTP 요청 → WAS → 필터 → 서블릿 → 스프링 인터셉터 → 컨트롤러 //로그인 사용자 HTTP 요청 → WAS → 필터 → 서블릿 → 스프링 인터셉터 → 적절하지 않은 요청이라 판단해서 컨트롤러 호출 X //비로그인 사용자 이렇게 동작하게 된다. 스프링 인터셉터도 서블릿 필터처럼 체인으로 구성할 수 있다. 뭔가 서블릿 필터와 비슷해 보이지만 사실 더 편하고 정교하고 다양한 기능을 제공한다고 하는데 .. 2022. 2. 23. [Spring Boot] : Servlet Filter 인증 체크하기 이번 강의에서 인증 체크 필터를 개발했다. 공모전을 진행할 때 Filter를 전혀 알지 못 하고 있었는데.. 역시 좋은 기술은 많다. private static final String[] whitelist = {"/", "/members/add", "/login", "/logout", "/css/*"}; 화이트 리스트라는 것을 우선 만들어 주었다. private boolean isLoginCheckPath(String requestURI) { return !PatternMatchUtils.simpleMatch(whitelist, requestURI); } 화이트 리스트는 이 로직을 통해 검증이 된다. 화이트 리스트일 경우 인증 체크를 하지 않도록 하여 로그인 페이지나 로그아웃 페이지 등 화이트 리스트에 .. 2022. 2. 22. [Spring Boot] : Servlet Filter 요청 로그 확인하기 필터가 정상 작동하는지 확인하기 위해 모든 요청을 남기는 필터를 개발했다. public class LogFilter implements Filter 먼저 필터는 Filter 인터페이스를 구현해야 한다. ublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HTTP 요청이 오면 doFilter가 호출된다. ServletRequest request는 HTTP 요청이 아닌 경우까지 고려한 인터페이스인데 HTTP를 사용하면 HttpServletRequest httpRequest = (HttpServletRequest) request; 이렇.. 2022. 2. 22. [Spring Boot] : Servlet Filter 컨트롤러에서 로그인 여부를 판단하려면 체크 로직을 일일이 전부 다 넣어줘야 했다. 실제로 내가 진행했던 팀 프로젝트에서 그런 식으로 로그인 체크 여부를 판단했는데 이렇게 했을 때 문제가 있다. 일단 바꿔줘야 하는 부분이 많으면 노가다성 작업이 필요하다는 것과 적용해야 하는 부분이 많으면 역시 노가다성 작업이 들어가야 하는 것...그리고 혹시 모를 놓치는 부분이나 코드가 바뀌는 경우가 생길 수 있다는 문제이다. 이렇게 전체적으로 적용해야 하는 부분을 공통 관심사라고 한다.(cross - cutting concern) 이런 공통 관심사는 스프링의 AOP로도 해결할 수 있지만 웹과 관련된 공통 관심사는 서블릿 필터나 스프링 인터셉터를 활용하는 것이 좋다고 한다. 서블릿 필터나 스프링 인터셉터는 HttpServ.. 2022. 2. 22. [Spring Boot] : Session TimeOut 설정하기 세션이 제공하는 정보들을 로그를 찍어 확인해 본다. log.info("sessionId={}", session.getId()); log.info("maxInactiveInterval={}", session.getMaxInactiveInterval()); log.info("creationTime={}", new Date(session.getCreationTime())); log.info("lastAccessedTime={}", new Date(session.getLastAccessedTime())); log.info("isNew={}", session.isNew()); 위에서 부터 세션 ID, JESSIONID의 값 세션의 유효 시간 , 1800초 (30분) 세션 생성 일시 세션과 연결된 사용자가 최근에 .. 2022. 2. 22. [Spring Boot] : 서블릿 HTTP 세션을 활용해 로그인 처리하기(2) @SessionAttribute를 통해 스프링에서 세션을 조금 더 편리하게 사용할 수도 있다. 이미 로그인 된 사용자를 찾을 때는 다음과 같이 사용하면 된다. @SessionAttribute = "loginMember", required=false) Member loginMember 이런 형식으로 사용하면 되는데 강의에서 활용한 것은 아래와 같다. public String homeLoginV3Spring( @SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model) { 전에 만들어둔 상수를 넣어준다. 세션에 회원 데이터가 없으면 home if (loginMember == null) .. 2022. 2. 22. [Spring Boot] : 서블릿 HTTP 세션을 활용해 로그인 처리하기(1) 세션은 대부분 웹 애플리케이션에 필요한 개념이다. 서블릿은 세션을 위해 HttpSession이라는 기능을 제공하고 우리가 직접 구현한 것 보다 더 잘 구현되어 있다. | HttpSession 소개 서블릿이 제공하는 HttpSession도 강의에서 만들어 본 SessionManager와 같은 방식으로 동작한다. 서블릿을 통해 HttpSession을 생성하면 쿠키의 이름이 JSESSIONID이고 값은 UUID와 같은 값을 생성하게 된다. public static final String LOGIN_MEMBER = "loginMember"; 데이터를 보관하고 조회할 때 중복 사용되므로 상수 하나를 정의했다. //세션이 있으면 있는 세션 반환, 없으면 신규 세션 생성 HttpSession session = req.. 2022. 2. 22. 이전 1 2 3 4 5 ··· 8 다음 반응형