반응형

RESTful API 에러 처리 팁

2018. 2. 1. 17:29

 개발 중에 에러 스택을 제공하면 생산성 및 디버그에 좋다는 아이디어를 얻어서 저번 프로젝트에 적용해 보았습니다. 대략 컨테이너를 시작할 때 show-error-stack이라는 프로필을 넘기면 오류가 발생시 스택 트레이스를 함께 넘겨주는 형태입니다. 

...... 일반적인 서비스 구조에서는 에러 스택정보를 API 에러 메세지에 포함 시키지 않는 것이 바람직 하다. 그렇지만, 내부 개발중이거나 디버깅 시에는 매우 유용한데, API 서비스를 개발시, 서버의 모드를 production과 dev 모드로 분리해서, 옵션에 따라 dev 모드등으로 기동시, REST API의 에러 응답 메세지에 에러 스택 정보를 포함해서 리턴하도록 하면, 디버깅에 매우 유용하게 사용할 수 있다.......
// 클라이언트에게 넘어가는 JSON 표현 예시 { "errorMessage" : "토큰이 만료되었습니다.", "errorStack" : "service.sp.spring.auth.exception.TokenExpiredException: JWT expired at 2018-01-31T18:14:50Z. Current time: 2018-02-05T18:37:51Z, a difference of 433261020 milliseconds. Allowed clock skew: 120000 milliseconds. at service.sp.spring.auth.JWTPayloadExtractor.extract(JWTPayloadExtractor.java:33) at service.sp.spring.auth.JWTInterceptor.preHandle(JWTInterceptor.java:36) at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:133) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:962) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)....." }
class ApiError{ String errorMessage; String errorStack; } interface ApiErrorBuilder{ ApiError build(Throwable e); } // 개발모드 @Profile("show-error-stack") @Component static class ApiErrorBuilderDev implements ApiErrorBuilder{ public ApiError build(Throwable e) return new ApiError(e.getMessage(), ExceptionUtils.getStackTrace(e)); } // 운영모드 @Profile("!show-error-stack") @Component static class ApiErrorBuilderProd implements ApiErrorBuilder{ public ApiError build(Throwable e) return new ApiError(e.getMessage(), null);// 운영모드에서는 스택에 null }

예제에서는 간단하게 스택 트레이스 정도이지만, exceptionType/customErrorCode/errorData 등을 부가적으로 전송할 수도 있습니다. 또 스택 트레이스는 너무 길으므로 대략 1500자 정도 잘라서 주는 것도 괜찮습니다.

... String simpleStackTrace = ExceptionUtils.getStackTrace(e).substring(0, 1500) + "....... (See log for detail.)"; return new ApiError(e.getMessage, simpleStackTrace); }

마지막으로 아래와 같은 형식도 괜찮은 것 같습니다.

// Json 표현 예시 { "errorMessage" : "유저가 없습니다.", "errorType" : "UserNotFoundException", "developerMessage" : "아이디가 발견되지 않았습니다. 정합성을 체크해주세요.", "customerMessage" : "잠시 후 다시 시도해주세요." }


반응형

+ Recent posts