๊ฐœ๋ฐœ์ž HOON
๐Ÿ› HOON DEVLog
๊ฐœ๋ฐœ์ž HOON
์ „์ฒด ๋ฐฉ๋ฌธ์ž
์˜ค๋Š˜
์–ด์ œ
  • ๐Ÿ˜Ž ์ „์ฒด ์นดํ…Œ๊ณ ๋ฆฌ (137)
    • ๐Ÿ“ ์‹ ์ž… ์ธํ„ฐ๋ทฐ ์ค€๋น„ (7)
    • ๐Ÿฆ” ์ทจ์—…์ค€๋น„ ๊ธฐ๋ก (7)
    • โ˜• ์ž๋ฐ” : JAVA (5)
    • ๐Ÿ ์ฝ”๋”ฉํ…Œ์ŠคํŠธ ๋Œ€๋น„ : PS (80)
    • ๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend (13)
    • ๐Ÿงช ์ปดํ“จํ„ฐ๊ณผํ•™ : CS (11)
    • ๐Ÿ—‚ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค : DB (1)
    • ๐Ÿƒ‍โ™‚๏ธ DEVLOG (8)
    • โš™๏ธ Trouble Shooting (5)

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • GitHub
  • Resume

๊ณต์ง€์‚ฌํ•ญ

์ธ๊ธฐ ๊ธ€

์ตœ๊ทผ ๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

hELLO ยท Designed By ์ •์ƒ์šฐ.
๊ฐœ๋ฐœ์ž HOON

๐Ÿ› HOON DEVLog

๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend

[Spring] @ControllerAdvice์™€ @ExceptionHandler

2023. 3. 18. 17:06

 

๐Ÿค” 0. ๊ธฐ์กด์˜ Exception์„ ํ•ธ๋“ค๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ•

 

 Java Application์„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ, ๋งŽ์€ Exception์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ Exception์„ ๋‹ค๋ฃจ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ๋Œ€๋ถ€๋ถ„ ์•„์‹œ๋‹ค์‹œํ”ผ try-catch ๋ฌธ์ด ์žˆ์Šต๋‹ˆ๋‹ค. try ๊ตฌ๋ฌธ ๋‚ด๋ถ€์—์„œ Exception์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๋ฌธ์žฅ์„ ์‹คํ–‰ํ•˜๊ณ , ํ•ด๋‹น try๋ฌธ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ Exception์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ๊ฐœ์˜ catch ๋ฌธ์„ ๋ถ™์—ฌ ํ•ธ๋“ค๋ง ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

๋ฌผ๋ก , Exception์„ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, SpringBoot์—์„œ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ๋ช‡ ๊ฐ€์ง€ ๋ถˆํŽธํ•œ ์ ์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์—†๊ณ , ํ•ญ์ƒ try-catch ๋ธ”๋ก์œผ๋กœ ๋ฌถ์–ด์„œ ๊ฐœ๋ฐœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ •ํ™•ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ํŒŒ์•…ํ•˜๋ ค๋ฉด, ์ด๋Ÿฌํ•œ ์˜ˆ์™ธ ์ƒํ™ฉ์— ๋Œ€ํ•œ ๋กœ์ง์€ ๋”ฐ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์–ด์•ผ ์ข€ ๋” ๊ฐœ์„ ๋  ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ try-catch ๋ธ”๋ก์„ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ€๋…์„ฑ์˜ ๋ฌธ์ œ๋„ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ . ๋˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์˜ ๋กœ์ง์ด ๋ณ€๊ฒฝ๋˜๋Š” ์ƒํ™ฉ์—๋„, ํ•ด๋‹น ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง์ด ๋”ฐ๋กœ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์ง€ ์•Š์•„, ๋ชจ๋“  ๋ฉ”์„œ๋“œ์˜ try-catch๋ฌธ์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•ด์•ผ ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ, Spring์—์„œ๋Š” @ExceptionHandler์™€ @ControllerAdvice๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

 

๐Ÿค” 1. @ExceptionHandler

 

@ExceptionHandler ์–ด๋…ธํ…Œ์ด์…˜์€ ์ด๋ฆ„์—์„œ๋„ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ ค์žˆ๋Š” ๋ถ€๋ถ„์— ๋Œ€ํ•ด Exception์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด, ํ•ธ๋“ค๋ง์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ @ExceptionHandler๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฒ”์œ„๋Š” @Controller์™€ @RestController๊ฐ€ ๋‹ฌ๋ ค์žˆ๋Š” ๋นˆ ๊ฐ์ฒด์— ํ•œํ•ด์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, @Service๋‚˜ @Repository๊ฐ€ ์ ์šฉ๋œ ๋นˆ ์œ„์—์„œ๋Š” ์ž‘๋™ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

์ปจํŠธ๋กค๋Ÿฌ์— ํŠน์ • Exception์— ๋Œ€ํ•ด ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ , ์ด ์œ„์— @ExceptionHandler๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

@Controller
public class Controller {

    // ...

    @ExceptionHandler(value = RuntimeException.class)
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}

 

์ด๋Ÿฐ ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด, Controller ๋ ˆ๋ฒจ์—์„œ ๋ฐœ์ƒํ•œ RuntimeException์— ๋Œ€ํ•ด ํ•ด๋‹น ExceptionHandler ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด์žˆ๋Š” ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•ด๋‹น Exception์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๋ฌผ๋ก , ๋‹จ์ผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ์•„๋‹ˆ๋ผ, ์—ฌ๋Ÿฌ๊ฐ€์ง€ Exception์„ ํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹ค๋ฃจ๋„๋ก ์ง€์‹œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@Controller
public class Controller {

    // ...

    @ExceptionHandler(value = {IOException.class, NullPointerException.class})
    public ResponseEntity<String> handle(Exception ex) {
        // ...
    }
}

 

์œ„์™€ ๊ฐ™์€ ์ฝ”๋“œ๋กœ ์ž‘์„ฑ์„ ํ•˜๊ฒŒ ๋˜๋ฉด, Controller ํด๋ž˜์Šค์—์„œ ๋ฐœ์ƒํ•œ IOException๊ณผ NullPointerException์— ๋Œ€ํ•ด ํ•ด๋‹น handle ํ•จ์ˆ˜๊ฐ€ catchํ•ด์„œ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

๊ณตํ†ต์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋Š” Exception์— ๋Œ€ํ•ด์„œ Exception ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด, ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๊ฐ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ํ•œ ํ•ธ๋“ค๋ง ๋ฉ”์„œ๋“œ์—์„œ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ƒ์‚ฐ์„ฑ์ด ๋”์šฑ ๋Š˜์–ด๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

๐Ÿค” 2. @ControllerAdvice

 

์ข€ ๋” ํ™•์žฅํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์•„๋‹Œ, ์ „์—ญ์ ์œผ๋กœ ์—ฌ๋Ÿฌ ์ปจํŠธ๋กค๋Ÿฌ์— ๋Œ€ํ•ด์„œ Exception์„ ๋‹ค๋ฃจ๊ณ  ์‹ถ๋‹ค๋ฉด @ControllerAdvice๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

๋ชจ๋“  Controller์— ๋Œ€ํ•ด์„œ ํŠน์ • Exception์„ ํ•œ ๋ฒˆ์— ์ œ์–ดํ•˜๋ ค๋ฉด, ์ƒˆ๋กœ์šด ๊ด€๋ฆฌ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  @ControllerAdvice ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์ค๋‹ˆ๋‹ค.

 

@ControllerAdvice
public class ControllerAdvice{
	// ..
}

 

์ด๋Ÿฐ์‹์œผ๋กœ ์ƒˆ๋กœ์šด ControllerAdvice ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™ํ˜€์ค€๋‹ค๋ฉด, ๋ชจ๋“  Controller์—์„œ ๋ฐœ์ƒํ•˜๋Š” Exception์— ๋Œ€ํ•ด ์ „์—ญ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ด ControllerAdvice๊นŒ์ง€ Exception์ด ์ „๋‹ฌ๋˜์—ˆ๋‹ค๋ฉด, ์ด ์ „๋‹ฌ๋œ Exception์— ๋Œ€ํ•ด ํ•ธ๋“ค๋ง ํ•  ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌํ•œ ๋ฉ”์†Œ๋“œ๋Š”, ์œ„์—์„œ ์„ค๋ช…ํ•œ @ExceptionHandler๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

@RestContollerAdvice
public class ControllerAdvice{
	
    @ExceptionHandler(value = NullPointerException.class)
    public ResponseEntity<String> handle(Exception ex){
		// ...
	}
}

 

์œ„์™€ ๊ฐ™์€ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑํ•˜๋ฉด ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์— ๋Œ€ํ•ด์„œ NullPointerException์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค์˜ handle ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๊ณ , ํ•ด๋‹น handle ๋ฉ”์†Œ๋“œ์˜ ๋กœ์ง์— ๋”ฐ๋ผ์„œ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

@ContollerAdvice์™ธ์—๋„ @RestControllerAdvice๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๊ฒƒ์€ @Controller์™€ @RestController์˜ ์ฐจ์ด์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@RestControllerAdvice์—๋Š” @ResponseBody ์–ด๋…ธํ…Œ์ด์…˜์ด ํฌํ•จ๋˜์–ด ์ž๋ฐ”๊ฐ์ฒด๋ฅผ HTTP ์š”์ฒญ์˜ ๋ฐ”๋””๋‚ด์šฉ์œผ๋กœ ๋งคํ•‘ํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†กํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice {
	// ...
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
	// ...
}

 

์ €์ž‘์žํ‘œ์‹œ ๋น„์˜๋ฆฌ ๋™์ผ์กฐ๊ฑด (์ƒˆ์ฐฝ์—ด๋ฆผ)

'๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Spring] API ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Swagger ๋„์ž…ํ•˜๊ธฐ (gradle ๊ธฐ์ค€)  (0) 2023.03.24
[Spring] @Transactional๊ณผ DB Lock์— DeepDive - (1) DB ํŠธ๋žœ์žญ์…˜, ์‚ฌ์šฉ๋ฐฉ๋ฒ•, ๊ฒฉ๋ฆฌ์ˆ˜์ค€, ์ „ํŒŒ ๋‹จ๊ณ„ ํ›‘์–ด๋ณด๊ธฐ  (0) 2023.03.21
[Spring WebFlux] 1. Mono์™€ Flux์— ๋Œ€ํ•œ ์ดํ•ด(2) : ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” operator (method)  (0) 2023.01.06
[Spring WebFlux] 1. Mono์™€ Flux์— ๋Œ€ํ•œ ์ดํ•ด(1) : ์ž‘๋™ ๋ฐฉ์‹๊ณผ ์ดํ•ด  (0) 2023.01.06
[Spring WebFlux] 0. ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์†Œ๊ฐœ  (1) 2023.01.01
    '๐ŸŒฑ ๋ฐฑ์—”๋“œ : Backend' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • [Spring] API ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Swagger ๋„์ž…ํ•˜๊ธฐ (gradle ๊ธฐ์ค€)
    • [Spring] @Transactional๊ณผ DB Lock์— DeepDive - (1) DB ํŠธ๋žœ์žญ์…˜, ์‚ฌ์šฉ๋ฐฉ๋ฒ•, ๊ฒฉ๋ฆฌ์ˆ˜์ค€, ์ „ํŒŒ ๋‹จ๊ณ„ ํ›‘์–ด๋ณด๊ธฐ
    • [Spring WebFlux] 1. Mono์™€ Flux์— ๋Œ€ํ•œ ์ดํ•ด(2) : ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” operator (method)
    • [Spring WebFlux] 1. Mono์™€ Flux์— ๋Œ€ํ•œ ์ดํ•ด(1) : ์ž‘๋™ ๋ฐฉ์‹๊ณผ ์ดํ•ด
    ๊ฐœ๋ฐœ์ž HOON
    ๊ฐœ๋ฐœ์ž HOON
    ์ข‹์€ ๋ฐฑ์—”๋“œ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๋˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ก์„ ๋ชจ์•˜์Šต๋‹ˆ๋‹ค. # ์ฃผ๋‹ˆ์–ด # ๋ฐฑ์—”๋“œ # ๊ฐœ๋ฐœ์ž

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”