1. ๋ฌธ์ ์ํฉ
๊ธฐ์กด ์ฝ๋ ํ๋ฆ
@Getter
public enum ErrorCode {
DUPLICATED_LONGIND("0101", ์ด๋ฏธ ์ฌ์ฉ์ค์ธ ์์ด๋(ํ๋ฒ) ์
๋๋ค.)"),
...
public DuplicatedLoginIdException extends RuntimeException {
public DuplicatedLoginIdException() {
}
}
# SignupService
public void signup(LoginReq req) {
...
throw new DuplicatedLoginIdException();
}
@RestControllerAdvice
public class ControllerAdvice {
@ResponseStatus(HttpsStatus.CONFLICT)
@ExceptionHandler(DuplicatedLoginIdException.class)
public ErrorResponse duplicatedLoginIdEXHandler(DuplicatedLoginIdException e){
return new ErrorResponse(ErrorCode.DUPLICATED_ID);
}
}
์์ ๊ฐ์ด ์์ธ๋ฅผ ๊ฐ๊ฐ์ ์๋ฌ์ํฉ์ ๊ฑฐ์ 1๋ 1๋ก Custom Exception class๋ฅผ ๋ง๋ค๊ณ ์๋ฌ์ ๋ํ ์๋ต HttpStatus๋ ErrorCode๋ Member์ ControllerAdvice์์ ์์ธ ํธ๋ค๋ฌ๋ฅผ ๋ ์์ธ๋ง๋ค ํ๋์ฉ ๋ฑ๋กํ๋ ๋ฐฉ์์ ์ฌ์ฉํ์๋ค.
์ด๋ฐ ๊ตฌ์กฐ๋ก ํ๋ค๋ณด๋ ์ฝ๋๋ฅผ ๋ค ์์ฑํ๊ณ ๋ณด๋ ์๋์ ๊ฐ์ด Member Aggregate์ ๊ด๋ จํ ์์ธ๋ง 12๊ฐ๊ฐ ์์ฑ๋์๊ณ ๋ค๋ฅธ ๋๋ฉ์ธ์์ ๋ฐ์ํ ์์ธ๋ฅผ ํฉ์น๋ฉด 40๊ฐ๊ฐ ๋๋ CustomException๊ณผ ์ด ์์ธ๋ฅผ ๋ค๋ฃฐ ExceptionHandler ๋ํ 40๊ฐ๊ฐ ์์ฑ๋๊ฒ ๋์๋ค.
์ฝ๋๋ฅผ ์ง๋ฉด์ ๊ณ์ ์ด๋ ๊ฒ ํ๋ฉด ๊ด๋ฆฌ๊ฐ ๋๋ฌด ์ด๋ ค์ธ ๊ฒ ๊ฐ์๋ฐ๋ผ๋ ์๊ฐ์ ๊ณ์ํ์ง๋ง ๊ณ์ ์๋ง์ธ ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋ง์๋ค.
Effective Java ์ฑ
์ด๋ ๋ค๋ฅธ๊ณณ์์๋ ํ์ค ์์ธ๋ฅผ ์ฌ์ฉํ๊ณ ๋ฉ์์ง๋ฅผ ์ด์ฉํด์ ์ํฉ์ ์ดํดํ๊ฒ๋ ํด๋ ๊ฐ๋
์ฑ๊ณผ ๊ด๋ฆฌ๊ฐ ์ฉ์ดํ๋ค๊ณ ํ์ง๋ง Spring์ด๋ Jwt ๊ด๋ จ ์์ธ๋ค๋ง ๋ด๋ ์ด๋ฏธ Custom Exception์ ์์ฑํด์ ์ฌ์ฉํ๊ณ ์๊ณ
๋ด ์๊ฐ์๋ ์ปค์คํ
์์ธ๋ฅผ ์ฌ์ฉํ๋๊ฒ์ด ํจ์ฌ ๊ฐ๋
์ฑ์ด ์ข๋ค๊ณ ์๊ฐํ๊ธฐ์ ์ปค์คํ
์์ธ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ ์ ์งํ๊ณ ๋ฆฌํฉํ ๋ง์ ํตํด ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ํ๊ธฐ๋ก ํ์๋ค.
์ด๋ฒ์ ์ด Custom Exception, Exception Handler, ErrorCode๋ฅผ ํจ๊ป ๋ฆฌํฉํ ๋ง ์๋ํ์๊ณ ๋ง์กฑํ ๋งํ ๊ฒฐ๊ณผ๊ฐ ๋์จ ๊ฒ ๊ฐ์ ์ ๋ฆฌํ๋ค.
2. ๋ฌธ์ ํด๊ฒฐ
์ ์ง์ ์ผ๋ก ๋ฆฌํฉํ ๋งํ์์ต๋๋ค.
โ๏ธ 1์ฐจ ์๋ - ๋ถ๋ถ ์ฑ๊ณต
1. ErrorCode์์ HttpStatus๊น์ง ๊ด๋ฆฌํ๋๋ก ๋ณ๊ฒฝ.
@Getter
public enum ErrorCode {
DUPLICATED_LOGINID(CONFLICT, "0101", "์ด๋ฏธ ์ฌ์ฉ์ค์ธ ์์ด๋(ํ๋ฒ) ์
๋๋ค.)"),
....
private final HttpStatus httpStatus;
private final String code;
private final String message;
ErrorCode(final HttpStatus httpStatus, final String code, final String message) {
this.httpStatus = httpStatus;
this.code = code;
this.message = message;
}
}
2. ์ปค์คํ ์์ธ๋ค์ ์ถ์ ์ํผ ํด๋์ค๋ฅผ ์์ฑ
@Getter
public abstract class AbstractErrorException extends RuntimeException{
private final ErrorCode errorCode;
public AbstractErrorException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.errorCode = errorCode;
}
}
public abstract class AbstractBusinessLogicException extends AbstractErrorException{
public AbstractBusinessLogicException(ErrorCode errorCode) {
super(errorCode);
}
}
public class DuplicatedLoginIdException extends BusinessLogicException {
public DuplicatedLoginIdException() {
super(ErrorCode.DUPLICATED_LOGINID);
}
}
3. ์ ์ญ์ ์ผ๋ก ์ถ์ ์ปค์คํ ์์ธ์ ๋ํ ํ๋์ Exception Handler ๋ฑ๋ก
@RestControllerAdvice
public class GlobalExceptionHandler {
....
@ExceptionHandler(AbstractBusinessLogicException.class)
public ResponseEntity<ErrorResponse> handleBusinessLogicException(AbstractBusinessLogicException e){
ErrorCode errorCode = e.getErrorCode();
ErrorResponse response = new ErrorResponse(errorCode.getCode(), e.getMessage());
return new ResponseEntity<>(response, errorCode.getHttpStatus());
}
...
}
์์ ๊ฐ์ด ErrorCode๋ฅผ ์ปค์คํ ์์ธ ๋ด๋ถ์ ์จ๊ฒจ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง์์๋ ์์ธ์ ์ด๋ฆ์ ํตํด ๊ตฌ์ฒด์ ์ธ ์์ธ ์ํฉ์ ๊ฐ๋ ์ฑ ์ข๊ฒ ํ์ธ ๊ฐ๋ฅํ๊ณ ์๋ฌ์ฝ๋์์ ์์กด์ฑ์ ๋์ด์ ๊ด์ฐฎ๋ค๊ณ ์๊ฐํ๋ค.
๋ํ ์ถ์ ์ํผ ์์ธ ํด๋์ค๋ฅผ ๋ง๋ ์ด์ ๋ GlobalControllerAdvice๋ฅผ ํตํด ์ ์ญ์ ์ผ๋ก ํ๋์ ControllerAdvice๋ฅผ ๊ฐ์ง๊ณ ์ปค์คํ ์์ธ์ ๋ถ๋ชจ ํด๋์ค์ ๋ํด์ ExceptionHandler๋ฅผ ๋ฑ๋กํ๋ฉด ํ๋์ ์์ธ ํธ๋ค๋ฌ๋ก ๋ชจ๋ ์ปค์คํ ์์ธ์ ๋ํด์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๋ฏ๋ก ์ค๋ณต ์ฝ๋๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
ํ์คํ ์์ธ ํธ๋ค๋ฌ๋ ๊ณตํต์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ณ ์ข์ ์๋์๋ค๊ณ ์๊ฐํ๋ค.
ํ์ง๋ง ๊ฒฐ๋ก ์ ์ผ๋ก Custom Exception์ ๊ฐ์๋ ์ค์ด๋ค์ง ์์๋ค. ๊ณ์ ๊ฐ์ ํด ๋๊ฐ ๋ณด์!
โ๏ธ 2์ฐจ ์๋ - ์ฑ๊ณต!
1์ฐจ ์๋์์ ํ๋ ์ถ์ ์ํผ ์์ธ ํด๋์ค ๋ฐฉ์๊ณผ Global Exception Handler ๋ฐฉ์๋ ์ ์งํ๊ณ
Custom Exception์ ๊ฐ์๋ฅผ ์ค์ฌ ์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ์๊ฐํด ๋ดค๋ค.
์์ธ ์ด๋ฆ๋ค์ ๋ณด๋ DuplicatedXXException, NotFoundXXException ๋ฑ ์ํฉ์ด ๋น์ทํ ๊ฒ๋ค์ด ๊ฝค ๋ง์๋ค.
๊ทธ๋์ ์ํฉ์ ๋ง๋ ์์ธ์ ๊ฐ๋
์ฑ์ ์ง์ผ์ฃผ๋๋ผ๋ ๋น์ทํ ๊ฒ๋ค๋ผ๋ฆฌ ๋ ์ํผ ํด๋์ค๋ฅผ ์์ฑํ๊ณ ErrorCode๋ฅผ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋ ์ชฝ์์ ์์ธ๋ฅผ ๋ฐ์์ํฌ ๋ ์์ธ์ ๋ฃ์ด์ฃผ๋ ๋ฐฉ์์ผ๋ก ์งํํด ๋ณด์๋ค.
์ค๋ณต์ ๋ํ ์์ธ๊ฐ ์์ด๋ ๊ฒ์ฆ, ์ด๋ฉ์ผ ๊ฒ์ฆ, ์์ฝ ์ ๋ฑ๋ฑ ์ฌ๋ฌ ๊ณณ์์ ์ฌ์ฉํ๊ณ ์์๋ค.
๋ฐ๋ผ์ DuplicationException์ผ๋ก ์ฌ์ฌ์ฉ์ฑ์ ๋์๋ค.
public class DuplicationException extends AbstractBusinessLogicException {
public DuplicationException(ErrorCode errorCode) {
super(errorCode);
}
}
# SignupService
public void signup(LoginReq req) {
...
throw new DuplicationException(ErrorCode.DUPLICATED_LOGINID);
}
์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ค๋ฅธ ์์ธ๋ ๊ณตํตํํ์๋ค.
๋ ์ค์ผ ์๋ ์์ง๋ง ์ต๋ํ ์์ธ๋ฅผ ์ฝ๋๋ฐ ๊ฐ๋ ์ฑ์ ํค์น์ง ์์ ์ ๋๋ก ์ถ์ํํ์๊ณ ์ด 12๊ฐ์ ๊ตฌ์ฒด ์ปค์คํ ์์ธ๋ก ์ค์ด๋ค๊ฒ ๋์๋ค.
40๊ฐ -> 12๊ฐ๋ ํฐ ๋ณํ์๊ณ ์ข์ ๋ฆฌํฉํ ๋ง ๊ณผ์ ์ ๊ฒฝํํ๋ค๊ณ ์๊ฐํ๋ค.