🌱 Spring MVC (13) 였λ₯˜ νŽ˜μ΄μ§€처리 (μ˜ˆμ™Έ 처리)

Kim Dae HyunΒ·2021λ…„ 7μ›” 19일
1

Spring-MVC

λͺ©λ‘ 보기
11/13
post-thumbnail

Github μ†ŒμŠ€μ½”λ“œ

πŸ”Ž Spring MVCμ—μ„œ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” 방법

μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” 두 가지 λ°©λ²•μž…λ‹ˆλ‹€.

  • 첫 λ²ˆμ§ΈλŠ” throwλ₯Ό μ΄μš©ν•΄ 직접 μ˜ˆμ™Έ 클래슀λ₯Ό λ™μž‘μ‹œν‚€λŠ” λ°©λ²•μž…λ‹ˆλ‹€.
    • throw new RuntimeException("μ—λŸ¬ μ—λŸ¬");
  • 두 λ²ˆμ§ΈλŠ” HttpServletResponse의 sendError λ©”μ„œλ“œλ₯Ό μ΄μš©ν•΄ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚€λŠ” 것 λ°©λ²•μž…λ‹ˆλ‹€.
    • response.sendError(404, "404μ—λŸ¬ λ°œμƒ λ©”μ‹œμ§€");

ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ μœ„ 두 가지 방법을 μ΄μš©ν•΄ μ—¬λŸ¬ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œμΌ°μŠ΅λ‹ˆλ‹€.
λ§Œμ•½ μ•„λ¬΄λŸ° 처리λ₯Ό ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ Springμ—μ„œ 기본으둜 μ œκ³΅ν•˜λŠ” White Lable μ—λŸ¬κ°€ λ°œμƒν•  것 μž…λ‹ˆλ‹€.

@Slf4j
@Controller(value = "/error-page")
public class ExceptionController {

    @RequestMapping("/error-boom")
    public String errorRuntime() {
        throw new RuntimeException("μ—λŸ¬ μ—λŸ¬");
    }

    @RequestMapping("/error-404")
    public void error404(HttpServletResponse response) throws IOException {
        response.sendError(404, "404 μ—λŸ¬ λ°œμƒ λ©”μ‹œμ§€");
    }

    @RequestMapping("/error-400")
    public void error400(HttpServletResponse response) throws IOException {
        response.sendError(400, "400 μ—λŸ¬ λ°œμƒ λ©”μ‹œμ§€");
    }

    @RequestMapping("/error-403")
    public void error403(HttpServletResponse response) throws IOException {
        response.sendError(403, "403 μ—λŸ¬ λ°œμƒ λ©”μ‹œμ§€");
    }

    @RequestMapping("/error-500")
    public void error500(HttpServletResponse response) throws IOException {
        response.sendError(500, "500 μ—λŸ¬ λ°œμƒ λ©”μ‹œμ§€");
    }
}

πŸ”Ž Springμ—μ„œ μ˜ˆμ™Έμ˜ 흐름

μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ μ˜ˆμ™Έκ°€ λ°œμƒν•œ λ©”μ„œλ“œ ν˜Ήμ€ ν΄λž˜μŠ€μ—μ„œ try-catch λ“±μœΌλ‘œ μ˜ˆμ™Έλ₯Ό μž‘μ•„μ£Όμ§€ μ•ŠλŠ”λ‹€λ©΄ μžμ‹ μ„ ν˜ΈμΆœν•œ λ©”μ„œλ“œ ν˜Ήμ€ 클래슀둜 μ˜ˆμ™Έλ₯Ό λ˜μ§€κ²Œ λ©λ‹ˆλ‹€.

μ˜ˆμ™Έλ₯Ό μ „ν˜€ μž‘μ§€ μ•Šμ€ μ‹œλ‚˜λ¦¬μ˜€λ₯Ό ν•œ 번 μ‚΄νŽ΄λ³Όκ»˜μš”.
1. μ»¨νŠΈλ‘€λŸ¬μ—μ„œ RuntimeException λ°œμƒ
2. μ»¨νŠΈλ‘€λŸ¬λŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ μΈν„°μ…‰ν„°λ‘œ μ˜ˆμ™Έλ₯Ό 던짐
3. μΈν„°μ…‰ν„°λŠ” μžμ‹ μ„ ν˜ΈμΆœν•œ μ„œλΈ”λ¦Ώ μ»¨ν…Œμ΄λ„ˆμ— μ˜ˆμ™Έλ₯Ό 던짐(Dispatcher servlet)
4. μ„œλΈ”λ¦Ώ μ»¨ν…Œμ΄λ„ˆλŠ” ν•„ν„°λ‘œ μ˜ˆμ™Έλ₯Ό 던짐
5. ν•„ν„°λŠ” WAS둜 μ˜ˆμ™Έλ₯Ό 던짐

μ—¬κΈ°μ„œ μ€‘μš”ν•œ 것은 μ˜ˆμ™Έκ°€ WASκΉŒμ§€ μ „νŒŒλœλ‹€λŠ” 것 μž…λ‹ˆλ‹€.
WASλŠ” μ „νŒŒλ°›μ€ μ˜ˆμ™Έλ₯Ό 더 이상 λ˜μ§€μ§€ μ•Šκ³  μžκΈ°κ°€ μ²˜λ¦¬ν•©λ‹ˆλ‹€.
처리 방식이 μ€‘μš”ν•œλ° μ „νŒŒλœ WASλŠ” μ—λŸ¬μ½”λ“œλ₯Ό 보고 였λ₯˜ νŽ˜μ΄μ§€ 좜λ ₯을 μœ„ν•΄ μ–΄λ–€ URL을 λ§Œλ“€μ–΄μ„œ λ‹€μ‹œ νŠΉμ • μ»¨νŠΈλ‘€λŸ¬μ— μš”μ²­ν•©λ‹ˆλ‹€.

μ–΄λ–€ URLμΌκΉŒμš”?

SpringBootλ₯Ό μ‚¬μš©ν•˜λŠ” 경우 WASκΉŒμ§€ λ„λ‹¬ν•˜λŠ” μ˜ˆμ™Έμ— λŒ€ν•΄μ„œ WASλŠ” /error에 μ˜ˆμ™Έμ •λ³΄λ₯Ό λ‹΄μ•„ μš”μ²­ν•©λ‹ˆλ‹€. SpringBootλŠ” 기본적으둜 BasicErrorControllerμ—μ„œ /error에 λŒ€ν•œ 처리λ₯Ό ν•©λ‹ˆλ‹€.

BasicErrorControllerλŠ” μžμ‹ μ—κ²Œ 온 μš”μ²­μ„ μ²˜λ¦¬ν•©λ‹ˆλ‹€.
특히 μ—λŸ¬ νŽ˜μ΄μ§€λ₯Ό λžœλ”λ§ν•΄μ£ΌλŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

500μ—λŸ¬κ°€ λ°œμƒν–ˆλ‹€κ³  ν•΄λ³Όκ»˜μš”.
BasicErrorController κ°€ μ—λŸ¬νŽ˜μ΄μ§€λ₯Ό λžœλ”λ§ν•˜λŠ” 정책이 μ •ν•΄μ ΈμžˆμŠ΅λ‹ˆλ‹€.

    1. templates/error/500.html 을 μ°Ύμ•„ λžœλ”λ§
    1. templates/error/5xx.html을 μ°Ύμ•„ λžœλ”λ§
    1. static/error/500.html을 μ°Ύμ•„ λžœλ”λ§
    1. static/error/5xx.html을 μ°Ύμ•„ λžœλ”λ§

μŠ€ν”„λ§μ€ μ–Έμ œλ‚˜ ꡬ체적인 것이 μš°μ„ μˆœμœ„λ₯Ό κ°–μŠ΅λ‹ˆλ‹€. 5xxλ³΄λ‹€λŠ” 500이 ꡬ체적이기 λ•Œλ¬Έμ— μš°μ„ μˆœμœ„λ₯Ό κ°–λŠ” 것 μž…λ‹ˆλ‹€.

μš°λ¦¬λŠ” μ΄λ ‡κ²Œ κ°„λ‹¨ν•˜κ²Œ νŠΉμ • κ²½λ‘œμ— 정책에 λ§žλŠ” html을 λ§Œλ“€μ–΄μ£ΌκΈ°λ§Œ ν•˜λ©΄ μ„œλΈ”λ¦Ώ λ°–μœΌλ‘œ λ‚ λΌκ°€λŠ” μ—λŸ¬μ— λŒ€ν•΄ μ ν•©ν•œ μ—λŸ¬ νŽ˜μ΄μ§€λ₯Ό 보여쀄 수 μžˆμŠ΅λ‹ˆλ‹€.


πŸ”Ž WASμ—μ„œ μ˜ˆμ™Έμ²˜λ¦¬μ‹œ ν•„ν„°, 인터셉터가 쀑볡 ν˜ΈμΆœλ˜λŠ” 문제

μœ„ 그림을 λ‹€μ‹œ λ³Όκ»˜μš”.
λ°œμƒν•œ μ˜ˆμ™Έλ₯Ό μ„œλΈ”λ¦Ώ μ΄μ „μ—μ„œ μ²˜λ¦¬ν•˜μ§€ λͺ»ν•˜κ³  WASκΉŒμ§€ λ„˜μ–΄κ°„ 경우 WASλŠ” λ‹€μ‹œ 였λ₯˜ νŽ˜μ΄μ§€λ₯Ό μš”μ²­ν•˜λŠ” κ΅¬μ‘°μž…λ‹ˆλ‹€.

λ‹€μ‹œ 였λ₯˜ νŽ˜μ΄μ§€λ₯Ό μš”μ²­ν•˜λŠ” κ΅¬μ‘°μ—μ„œ μ˜λ―Έμ—†λŠ” ν•„ν„°, 인터셉터 등이 호좜될 수 μžˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œ μ˜λ―Έκ°€ μ—†λ‹€λŠ” 것은 둜그인 검증 ν•„ν„° 등이 ν•΄λ‹Ήν•©λ‹ˆλ‹€. 이미 검증을 마친 μ‚¬μš©μžμ˜ μš”μ²­μ„ μˆ˜ν–‰ν•˜κ³  μžˆλŠ”λ° λ°œμƒν•œ μ˜ˆμ™Έμ΄κ³  μ„œλ²„ λ‚΄λΆ€μ μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 것 뿐인데 λ‹€μ‹œ 검증 ν•„ν„° ν˜Ήμ€ μΈν„°μ…‰ν„°μ˜ 검증을 받을 ν•„μš”κ°€ μžˆμ„κΉŒμš”?

λ°˜λŒ€μ˜ 상황도 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.
WASμ—μ„œ 였λ₯˜ μ²˜λ¦¬μ— μ˜ν•œ 호좜인 κ²½μš°μ—λ§Œ λ™μž‘μ‹œν‚¬ ν•„ν„°, 인터셉터 등이 μžˆμ„ μˆ˜λ„ μžˆλŠ” 것이죠.

μ–΄λ–»κ²Œ μ˜ˆμ™Έμ²˜λ¦¬λ‘œ μΈν•œ μ—λŸ¬ νŽ˜μ΄μ§€ μš”μ²­μΈμ§€, 정상적인 μ‚¬μš©μžμ˜ μš”μ²­μΈμ§€ ꡬ뢄할 수 μžˆμ„κΉŒμš” ?

WAS의 μš”μ²­μ—λŠ” DispatcherTypeμ΄λΌλŠ” 좔가정보가 μ œκ³΅λ©λ‹ˆλ‹€.

DispatcherType νƒ€μž… μ’…λ₯˜
1. REQUEST: ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­
2. ERROR: μ—λŸ¬ νŽ˜μ΄μ§€ μš”μ²­
INCLUDE, FORWARD 등이 더 μžˆμ§€λ§Œ μ‚¬μš©ν•˜κ³ μž ν•˜λŠ” κ²ƒλ§Œ μ•Œμ•„λ‘˜κ»˜μš”.


πŸ”Ž Filterμ—μ„œ Dispatcher νƒ€μž… ꡬ뢄

FilterλŠ” λ“±λ‘μ‹œ Dispatcher Type을 ꡬ뢄할 수 μžˆμŠ΅λ‹ˆλ‹€.
μ œκ³΅λ˜λŠ” setDispatcherTypes λ©”μ„œλ“œλ‘œ ν•„ν„°λ₯Ό μ μš©μ‹œν‚¬ Dispatcher Type을 μ •μ˜ν•©λ‹ˆλ‹€.

μ•„λž˜ μ½”λ“œλŠ” μ •μ˜ν•œ Filterλ₯Ό 빈으둜 λ“±λ‘ν•˜λŠ” μž‘μ—…μ„ ν•©λ‹ˆλ‹€.
setDispatcherTypes 뢀뢄을 보면 DispatcherType.REQUEST, DispatcherType.ERROR을 μ„€μ •ν•΄μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.
μ‚¬μš©μžμ˜ μš”μ²­, μ—λŸ¬νŽ˜μ΄μ§€ μš”μ²­μ— λͺ¨λ‘μ— λ“±λ‘ν•˜λŠ” ν•„ν„°λ₯Ό μ μš©μ‹œν‚€κ² λ‹€λŠ” κ²ƒμ΄μ§€μš”.

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Bean
    FilterRegistrationBean<Filter> getLogFilter() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(new LogFilter());
        filterRegistrationBean.setOrder(1);
        filterRegistrationBean.addUrlPatterns("/*");
       
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ERROR);

        return filterRegistrationBean;
    }
}

λ§Œμ•½ μ‚¬μš©μžμ˜ μš”μ²­μ— λŒ€ν•΄μ„œλ§Œ ν•„ν„°λ₯Ό μ μš©μ‹œν‚€κ³  μ‹Άλ‹€λ©΄ μ•„λž˜μ™€ 같이 DispatcherType.ERRORλ₯Ό λΉΌμ£Όλ©΄ λ©λ‹ˆλ‹€.

filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);

πŸ”Ž Interceptorμ—μ„œ Dispatcher νƒ€μž… ꡬ뢄

이전 인터셉터λ₯Ό 닀룬 ν¬μŠ€νŠΈμ—μ„œ μ‚¬μš©ν–ˆλ˜ excludePathPatternsλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

WASλŠ” μ˜ˆμ™Έ νŽ˜μ΄μ§€ μš”μ²­μ„ μœ„ν•΄ BasicErrorController에 λ§€ν•‘λ˜μ–΄ μžˆλŠ” /error둜 μš”μ²­μ„ 보낸닀고 ν–ˆμŠ΅λ‹ˆλ‹€.

/error μš”μ²­ 자체λ₯Ό excludePathPatterns둜 μ„€μ •ν•˜κ³ μž ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ WAS의 μ—λŸ¬ νŽ˜μ΄μ§€ μš”μ²­μ— 인터셉터λ₯Ό λ™μž‘μ‹œν‚€κ±°λ‚˜ λ™μž‘μ‹œν‚€μ§€ μ•Šκ±°λ‚˜ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new LogInterceptor())
            .order(1)
            .addPathPatterns("/**")
            .excludePathPatterns("/css/**", "/error"); 
    }

μΈν”„λŸ° κΉ€μ˜ν•œλ‹˜μ˜ μŠ€ν”„λ§ MVC 2편 을 μˆ˜κ°•ν•˜κ³  μ •λ¦¬ν•œ λ‚΄μš©μž…λ‹ˆλ‹€.

profile
μ’€ 더 천천히 까먹기 μœ„ν•΄ κΈ°λ‘ν•©λ‹ˆλ‹€. 🧐

1개의 λŒ“κΈ€

comment-user-thumbnail
2021λ…„ 7μ›” 19일

μƒˆλ‘œμš΄ 지식을 μ•Œκ²Œ λ˜μ—ˆλ„€μš”!!

λ‹΅κΈ€ 달기