CustomException

codakcodak·2023년 12월 3일
0

wannago

목록 보기
2/5
post-thumbnail

문제점

  • 프론트 입장에서는 status code를 받았을 때 대략적인 상태만 인식하지만 상세사항은 알지 못하여 의사소통의 어려움이 있다.
    ex)401코드를 받았을 때 권한문제인 것을 인지는 하지만 이것이 token이 없어서인지,token이 만료되어서 인지,토큰의 형식이 옳바르지 않아서인지는 정확히 알지 못함

  • 기존의 try-catch와 throw new Exception에 메세지와 코드를 인자로 전해 던져주면 추후 수정에 있어서 유연하지 못함

해결 방안

  • 에러 설명과 상태 코드를 함께 저장하는 상수형 클래스 ErrorCode 선언
  • Exception을 상속받고 CustomException인터페이스를 구현한 구현체 생성

구현

1.ErrorCode

import lombok.Getter;

@Getter
public enum ConceptErrorCode {
	UserIdNotMatchConceptUserId(401,"컨셉의 소유주가 일치하지 않습니다."),
	ConceptNotFound(404,"해당컨셉은 존재하지 않습니다.");
	private int code;
    private String description;
    
    private ConceptErrorCode(int code, String description) {
        this.code = code;
        this.description = description;
    }
}
  • 단순히 상태코드와 메세지를 함께 저장하기 때문에 상수형으로 저장
  • enum을 통해 가독성을 향상시키고 싱글톤으로 작동하게 설정

2. CustomException

// ExceptionHandler에서 자신의 code와 msg를 항상 사용할 수 있어야 하기 때문에 메서드로 선언
public interface CustomException {
	public int getCode();
	public String getMsg();
}
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class ConceptException extends Exception implements CustomException{
	private final int code;
	private final String msg;
	
	@Override
	public int getCode() {
		return this.code;
		
	}
	@Override
	public String getMsg() {
		return this.msg;
	}
}

3.service의 throw CustomException

	@Override
	public ConceptDetailResponseDto getConcept(String userId, int conceptNo) throws Exception {
		log.info("class:=================getConcept====================");
		ConceptDto concept=conceptMapper.selectByConceptNo(conceptNo);
		if(concept==null) {
			throw new ConceptException(ConceptErrorCode.ConceptNotFound.getCode(), ConceptErrorCode.ConceptNotFound.getDescription());
		}
		if(!concept.getUserId().equals(userId)) {
			throw new ConceptException(ConceptErrorCode.UserIdNotMatchConceptUserId.getCode(), ConceptErrorCode.UserIdNotMatchConceptUserId.getDescription());
		}
		ConceptDetailResponseDto conceptDetailRespons=new ConceptDetailResponseDto(concept);
		setConceptMetaData(conceptDetailRespons);
		
		
		
		return conceptDetailRespons;
	}

4.ExceptionHandler

ExceptionControllerAdvice.java

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestControllerAdvice
public class ExceptionControllerAdvice {	
	@ExceptionHandler(Exception.class)
	public ResponseEntity<Exception> handleException(Exception e, Model model) {
		e.printStackTrace();
		log.debug("Exception: 내부 에러");
		
		return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e);
	}
	
    //자신의 던진 CustomException의 타입에 따라 알맞은 에러 로그를 출력 및 처리
	@ExceptionHandler(ConceptException.class)
	public ResponseEntity<CustomException> handleConceptException(CustomException e, Model model) {
		log.debug("Exception type:"+e.getClass());
		log.error("Exception 발생 : {}",e.getCode());
		log.error("Exception 발생 : {}",e.getMsg());
		
		return ResponseEntity.status(e.getCode()).body(e);
	}
}
profile
숲을 보는 코더

0개의 댓글