네이버나 카카오 Open API를 보면 Error Response 스펙에 서비스가 자체적으로 정의한 code를 사용한다.
API 레퍼런스
- kakao: https://developers.kakao.com/docs/latest/ko/reference/rest-api-reference#response
- naver: https://developers.naver.com/docs/common/openapiguide/errorcode.md
이는 REST API의 Error Response를 이해하기 위해서는 문서를 봐야한다는 치명적인 단점이 있다. 그럼에도 불구하고 직접 정의한 Error code를 사용하는 이유에 대해 알아보자.
개요
이번 주 회사에서 Mail API를 개발 중인 선배분께서 자리로 오셔서 이런 말씀을 하셨다.
Jerry님 저희도 Error 본문에 code를 정의해서 내려주게 수정할까요?
이유를 여쭤보니까 Mail Domain 기능을 개발하다가 이런 문제가 발생했다고 한다.
(Mail을 다루는 end-point는 HttpMethod /mailboxes/{mailboxId}/mail/{mailId} 이다.)
- Mailbox가 존재하지 않을 시 404 (NotFound)를 내려준다.
- Mail이 존재하지 않을 시 404 (NotFound)를 내려준다.
- Mail eml 파일이 존재하지 않을 시 404 (NotFound)를 내려준다.
클라이언트 단에서는 어떤 예외인지에 따라서 다르게 처리하는 로직이 필요하다. 그런데 해당 예외들이 전부 동일한 StatusCode를 제공하므로 클라이언트 단이 StatusCode와 더불어 추가로 Error Message를 참조해서 처리해야 하는 상황이 생긴 것이다.
Error Code
클라이언트 단에서 Message를 전달 받아서 예외를 처리하는 것은 클라이언트 단과 서버 단이 불필요하게 결속됨을 의미하고 추후 변경이 어려워진다.
따라서 서비스에서 정의한 Code가 필요하다. 가령 클라이언트 측이 로그인을 실패하는 경우 다음의 응답을 제공할 수 있다.
{
"error": "auth-0001",
"message": "Incorrect username and password",
"detail": "Ensure that the username and password included in the request are correct"
}
이때 error 필드는 HttpStatusCode와 일치하게 되면 혼란을 야기할 수 있다. 따라서 "auth-0001"과 같이 문자열 코드를 추가하거나 "wrong-user-pass"와 같은 문자열 코드만 제공하는 방식도 있다.
kakao에서는 이러한 HTTP StatusCode와 내부 Error code 간의 혼란을 피하기 위해 Error code를 음수로 사용하는 방식을 사용한다.
RFC 7807
오늘날 많은 REST API는 유사한 규칙을 따르지만 에러 메시지 등을 제각각으로 사용하여 라이브러리와 프레임워크에서 해당 부분을 다루기 어렵다.
그래서 REST API의 에러 메시지를 표준화하기 위해 IETF는 일반화된 오류 메시지 스키마를 생성하는 RFC 7808을 발표했다.
해당 스키마는 아래 다섯 부분으로 구성된다.
- type – 오류를 분류하는 URI 식별자
- title – 오류에 대한 간략하고 사람이 읽을 수 있는 메시지
- status – HTTP 응답 코드 (Optional)
- detail - 사람이 읽을 수 있는 오류 설명
- instance – 오류의 특정 발생을 식별하는 URI
이를 고려하면 다음과 같은 응답 본문을 내려줄 수 있다.
{
"type": "/errors/incorrect-user-pass",
"title": "Incorrect username or password.",
"status": 401,
"detail": "Authentication failed due to incorrect username or password.",
"instance": "/login/log/abc123"
}
클라이언트는 응답의 HATEOAS 링크를 사용하여 해당 오류에 대한 추가 정보를 찾을 수 있다.
RFC 7808은 균일성이 필요한 경우 유리하지만 반드시 따라야 하는 것은 아니다.
트위터 에러 메시지를 참조하기 위해 인증 데이터 없이 GET 요청을 보내보자.
curl -X GET https://api.twitter.com/1.1/statuses/update.json?include_entities=true
Twitter API는 다음 에러 메시지를 본문으로 응답한다.
{
"errors": [
{
"code":215,
"message":"Bad Authentication data."
}
]
}
HTTP Status code와 별개로 자체로 정의한 Error code를 사용함을 알 수 있다. 실제로 해당 요청은 인증 데이터 자체를 보내지 않았고, 그에 맞게 400 (Bad Request) 응답을 받았다.
Facebook도 인증 데이터 없이 GET 요청을 보내보자.
curl -X GET https://graph.facebook.com/oauth/access_token?client_id=foo&client_secret=bar&grant_type=baz
그 결과 다음 응답을 받을 수 있다.
{
"error": {
"message": "Missing redirect_uri parameter.",
"type": "OAuthException",
"code": 191,
"fbtrace_id": "AWswcVwbcqfgrSgjG80MtqJ"
}
}
Twitter와 마찬가지로 400번 응답을 받았고 자체적으로 정의한 Error Code를 추가로 제공한다. 그 결과 사용자는 구체적인 원인을 파악하고 적절한 처리를 실행 (핸들링) 할 수 있다.
Reference
'Server > Spring' 카테고리의 다른 글
Spring Security - SecurityFilterChain 사용하기! (+ WebSecurityConfigurerAdapter is Deprecated) (0) | 2022.07.18 |
---|---|
JPA - Fetch Join에 ON절 추가하는 방법! (쿼리 개선, 인덱싱) (0) | 2022.07.08 |
Spring - REST에서 예외를 처리하는 다양한 방법! (0) | 2022.07.03 |
Spring - JpaRepository와 Querydsl 연결하기! (사용자 정의 리포지토리) (2) | 2022.06.18 |
SpringBoot - 프로퍼티를 안전하게 가져오는 방법! (0) | 2022.06.14 |