๊ด€๋ฆฌ ๋ฉ”๋‰ด

๐‘†๐‘ข๐‘›๐‘ โ„Ž๐‘–๐‘›๐‘’ ๐‘Ž๐‘“๐‘ก๐‘’๐‘Ÿ ๐‘Ÿ๐‘Ž๐‘–๐‘›โœง

[Spring] ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ณธ๋ฌธ

์˜ˆ์™ธ(Exception) 

 

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

 

์—๋Ÿฌ(Error)

 

  • ์ฃผ๋กœ ์ž๋ฐ”์˜ ๊ฐ€์ƒ๋จธ์‹ ์—์„œ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์˜ˆ์™ธ์™€ ๋‹ฌ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ๊ฑฐ์˜ ์—†๋‹ค.
  • ex) ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ(OutOfMemory), ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ(StackOverFlow)
  • ๋ฐœ์ƒ ์‹œ์ ์— ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ฏธ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ์˜ˆ๋ฐฉํ•ด์„œ ์ฐจ๋‹จํ•ด์•ผํ•œ๋‹ค.

 

 

์˜ˆ์™ธ ํด๋ž˜์Šค

 

  • ๋ชจ๋“  ์˜ˆ์™ธ ํด๋ž˜์Šค๋Š” Throwable ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š”๋‹ค.
  • Exceptionํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•œ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.
    • Checked Exception
      • ์ปดํŒŒ์ผ ๋‹จ๊ณ„์—์„œ ํ™•์ธ ๊ฐ€๋Šฅํ•œ ์˜ˆ์™ธ ์ƒํ™ฉ
      • IDE์—์„œ ์บ์น˜ํ•ด์„œ ๋ฐ˜๋“œ์‹œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ‘œ์‹œํ•ด์ค€๋‹ค.
      • ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์™ธ ํด๋ž˜์Šค
        • IOException
        • SQLException
    • Unchecked Exception
      • ๋Ÿฐํƒ€์ž„ ๋‹จ๊ณ„์—์„œ ํ™•์ธ๋˜๋Š” ์˜ˆ์™ธ ์ƒํ™ฉ
      • ๋ฌธ๋ฒ•์ƒ ๋ฌธ์ œ๋Š” ์—†์ง€๋งŒ ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ž‘ํ•˜๋Š” ๋„์ค‘ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
      • ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์™ธ ํด๋ž˜์Šค
        • RuntimeException
        • NullPointerException
        • IllegalArgumentException
        • IndexOutOfBoundException
        • SystemException

 

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

 

  • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„๋•Œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•
    • ์˜ˆ์™ธ ๋ณต๊ตฌ
      • ์˜ˆ์™ธ ์ƒํ™ฉ์„ ํŒŒ์•…ํ•ด์„œ ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ์‹
      • ๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•
        • try/catch
    • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํšŒํ”ผ
      • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ์‹œ์ ์—์„œ ๋ฐ”๋กœ ์ฒ˜๋ฆฌํ•˜๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ ๊ณณ์—์„œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ „๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹
      • ๋Œ€ํ‘œ์ ์ธ ๋ฐฉ๋ฒ•
        • throw
    • ์˜ˆ์™ธ ์ „ํ™˜
      • ์•ž์˜ ๋‘ ๋ฐฉ์‹์„ ์ ์ ˆํ•˜๊ฒŒ ์„ž์€ ๋ฐฉ์‹(try/catch + throw)
      • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์–ด๋–ค ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”๋ƒ์— ๋”ฐ๋ผ ํ˜ธ์ถœ๋ถ€๋กœ ์˜ˆ์™ธ ๋‚ด์šฉ์„ ์ „๋‹ฌํ•˜๋ฉด์„œ ์ข€ ๋” ์ ํ•ฉํ•œ ์˜ˆ์™ธ ํƒ€์ž…์œผ๋กœ ์ „๋‹ฌ ํ•  ํ•„์š”๊ฐ€ ์žˆ์„๋•Œ ํ™œ์šฉ.

 

 

์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹

 

  • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„๋•Œ ํด๋ผ์ด์–ธํŠธ์— ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜๋ ค๋ฉด ๊ฐ ๋ ˆ์ด์–ด์—์„œ ๋ฐœ์ƒํ•œ ์˜ˆ์™ธ๋ฅผ ์—”๋“œํฌ์ธํŠธ ๋ ˆ๋ฒจ์ธ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ์ „๋‹ฌ๋ฐ›์€ ์˜ˆ์™ธ๋ฅผ ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.
    • @(Rest)ControllerAdvice์™€ @ExceptionHandler๋ฅผ ํ†ตํ•ด ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์˜ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌ
    • @ControllerAdvice ๋Œ€์‹  @RestControllerAdvice๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ณผ๊ฐ’์„ JSON ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • @ExceptionHandler ๋ฅผ ํ†ตํ•ด ํŠน์ • ์ปจํŠธ๋กค๋Ÿฌ์˜ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌ
    • ๋งŒ์•ฝ ์ปจํŠธ๋กค๋Ÿฌ ๋˜๋Š” @controllerAdvice ํด๋ž˜์Šค๋‚ด์—์„œ ๋™์ผํ•œ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์„ ์–ธ๋œ ์ƒํƒœ์—์„œ @ExceptionHandler(Exception.class) ์™€@ExceptionHandler(NullPointerException.class)๊ฐ€ ์‹คํ–‰๋œ ๊ฒฝ์šฐ ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค๊ฐ€ ์ง€์ •๋œ ์ชฝ(NullPointerException)์ด ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ–๊ฒŒ๋œ๋‹ค. 
    • ๋˜ํ•œ @ControllerAdvice์˜ ๊ธ€๋กœ๋ฒŒ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์™€ @Controller ๋‚ด์˜ ์ปจํŠธ๋กค๋Ÿฌ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ์— ๋™์ผํ•œ ํƒ€์ž…์˜ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ๋ฒ”์œ„๊ฐ€ ์ข์€ ์ปจํŠธ๋กค๋Ÿฌ์˜ ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๊ฐ€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ–๊ฒŒ๋œ๋‹ค.

 

 

์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ(์ปค์Šคํ…€ ์˜ˆ์™ธ)

 

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

 

 

์ปค์Šคํ…€ ์—์™ธ ํด๋ž˜์Šค ์ƒ์„ฑํ•˜๊ธฐ

 

  • ์ปค์Šคํ…€ ์˜ˆ์™ธ๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์— ํ•ด๋‹นํ•˜๋Š” ์ƒ์œ„ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š”๋‹ค.
  • ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋‚ด์šฉ
    • ์—๋Ÿฌ ํƒ€์ž…(Error Type) : HttpStatus์˜ reasonPhrase
    • ์—๋Ÿฌ ์ฝ”๋“œ(Error Code) : HttpStatus์˜ value
    • ๋ฉ”์‹œ์ง€(Message) : ์ƒํ™ฉ๋ณ„ ์ƒ์„ธ ๋ฉ”์‹œ์ง€

 

์˜ˆ์ œ ์ฝ”๋“œ

 

๋จผ์ € ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜ ์ƒํ™ฉ๋ณ„ ErrorCode๋ฅผ ์ •์˜ํ•œ Enum ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

๊ทธ ๋‹ค์Œ, ์˜ˆ์™ธ ํด๋ž˜์Šค์ž„์„ ์•Œ๋ ค์ฃผ๋Š” Exception ๋˜๋Š” RuntimeException ์„ ์ƒ์†๋ฐ›์•„ AppException ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค. ์˜ˆ์™ธ๋ฅผ ๊ฐ•์ œ ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ Exception,  ๋Š์Šจํ•˜๊ฒŒ ์ •๋ณด๋งŒ ์ œ๊ณตํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ RuntimeException์„ ์ƒ์†ํ•œ๋‹ค.

 

@AllArgsConstructor
@Getter
public enum ErrorCode {
    USERMAIL_DUPLICATED(HttpStatus.CONFLICT, ""),
    USERMAIL_NOT_FOUND(HttpStatus.NOT_FOUND, ""),
    INVALID_PASSWORD(HttpStatus.UNAUTHORIZED, ""),
    CART_NOT_FOUND(HttpStatus.NOT_FOUND, ""),
    PRODUCT_NOT_FOUND(HttpStatus.NOT_FOUND, ""),
    PAGE_INDEX_ZERO(HttpStatus.BAD_REQUEST, ""),
    ORDER_NOT_FOUND(HttpStatus.NOT_FOUND, "");


    private HttpStatus httpStatus;
    private String message;
}

HttpStatus๋ฅผ ์ปค์Šคํ…€ ์˜ˆ์™ธ ํด๋ž˜์Šค์— ํฌํ•จ์‹œํ‚ค๋ฉด ํ•ธ๋“ค๋Ÿฌ ์•ˆ์—์„œ ์„ ์–ธํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์˜ˆ์™ธ ํด๋ž˜์Šค๋งŒ ์ „๋‹ฌ๋ฐ›์œผ๋ฉด ๊ทธ ์•ˆ์— ๋‚ด์šฉ์ด ํฌํ•จ๋ผ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. 

@AllArgsConstructor
@Getter
public class AppException extends RuntimeException{
    private ErrorCode errorCode;
    private String message;
}
package com.example.creditmarket.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class ExceptionManager {

    @ExceptionHandler(AppException.class)
    public ResponseEntity<?> appExceptionHandler(AppException e){
        return ResponseEntity.status(e.getErrorCode().getHttpStatus())
                .body(e.getErrorCode().name() + " " + e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<?> runtimeExceptionHandler(RuntimeException e){
        return ResponseEntity.status(HttpStatus.CONFLICT)
                .body(e.getMessage());
    }
}

 

  •  @RestControllerAdvice
    • @Controller๋‚˜ @RestController์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ธฐ๋Šฅ ์ˆ˜ํ–‰
    • basePackagesClasses, basePackages๋ฅผ ๋ณ„๋„๋กœ ์„ค์ •ํ•˜์—ฌ ์˜ˆ์™ธ๋ฅผ ๊ด€์ œํ•˜๋Š” ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ๋„ ์žˆ๋‹ค.
      • basePackageClasses: ์ ์šฉ ํด๋ž˜์Šค์—๋งŒ ์ ์šฉ
      • basePackages:  ํ•˜์œ„ ํด๋ž˜์Šค์— ๋ชจ๋‘ ์ ์šฉ
      • @RestControllerAdvice(basePackageClasses =  ProductController.class) // ํ•ด๋‹น ํด๋ž˜์Šค
      • @RestControllerAdvice(basePackages = "com.example") // ์ง€์ • ํŒจํ‚ค์ง€๋‚ด์— ๋ชจ๋‘ ์ ์šฉ 
  • @ExceptionHandler
    • @Controller๋‚˜ @RestController๊ฐ€ ์ ์šฉ๋œ ๋นˆ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ์žก์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
    • ์–ด๋–ค ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์ฒ˜๋ฆฌํ• ์ง€๋Š” value ์†์„ฑ์œผ๋กœ ๋“ฑ๋กํ•˜๋ฉฐ ์—ฌ๋Ÿฌ ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ๋“ฑ๋ก ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

 

 

 

์ฐธ๊ณ 

์Šคํ”„๋ง ๋ถ€ํŠธ ํ•ต์‹ฌ๊ฐ€์ด๋“œ - ์žฅ์ •์šฐ