Web API의 에러를 어떻게 표현해야 할까? (1)

조성철 (JoSworkS)·2020년 4월 16일
2

TIL(Today I Learned)

목록 보기
55/73

웹 개발에 있어서 클라이언트의 요청에 문제가 있을 때, 서버에서 클라이언트에게 어떤 에러 응답을 보여줄 것인지는 매우 중요한 부분이라고 생각한다.

그래서 에러처리와 관련하여 조사하던 중 발견한 qiita의 'WebAPIでエラーをどう表現すべき?15のサービスを調査してみた'을 개인적인 공부를 위해 번역하고자 한다.

이 게시글은 15개의 글로벌 웹 서비스의 에러 응답을 비교하는 것을 주 내용으로 하고 있으며, 웹 서비스들이 어떤 패턴으로 에러응답을 하고 있는지 가볍게 보면 좋을 듯하다.

원문: https://qiita.com/suin/items/f7ac4de914e9f3f35884

조사한 서비스

이번 Web API에 대하여 조사한 웹 서비스는 아래 15개의 서비스이다. 생각난 순서대로 조사했기 때문에 순서에는 의미가 없다.

  1. GitHub
  2. Facebook
  3. Heroku
  4. Toggl
  5. Yahoo!
  6. GREE
  7. Nike
  8. Twitter
  9. Google
  10. Twilio
  11. Foursquare
  12. Flickr
  13. Linkedin
  14. Philips Hue
  15. Qiita

그러면 각각의 서비스가 Web API에서 에러를 JSON으로 어떻게 표현하고 있는지 확인해 보자.

Github

{
   "message": "Validation Failed",
   "errors": [
     {
       "resource": "Issue",
       "field": "title",
       "code": "missing_field"
     }
   ]
 }
  • message: 에러 메세지
  • errors: 보내진 필드에 에러가 있는 경우에 추가된다.
    • resource: 대상의 리소스
    • field: 대상의 필드
    • code: 에러 코드

전형적인 에러는 message 뿐이기에 심플하지만, errors에서 복수의 에러가 보여지고, 상세 에러를 표현하는 것이 가능한 구조로 되어 있다.

Facebook

     {
       "error": {
         "message": "Message describing the error", 
         "type": "OAuthException", 
         "code": 190,
         "error_subcode": 460,
         "error_user_title": "A title",
         "error_user_msg": "A message"
       }
     }
  • message: 에러 메세지
  • type: 에러 타입
  • code: 에러 코드
  • error_subcode: 에러 서브코드
  • error_user_title: 유저에게 직접표시할 수 있는 메세지. 다이얼로그의 타이틀 등으로 표시하는 용도.
  • error_user_msg: 유저에게 직접표시할 수 있는 메세지.

Facebook의 특징은 엔드유저용의 메시지가 별도로 있는 것이다. 밖에도 요청하는 장소에 맞춰서 번역까지 해주기 떄문에 어플을 만드는 쪽에서 굉장히 편리하다.

Heroku

{
  "id": "rate_limit",
  "message": "Your account reached the API rate limit\nPlease wait a few minutes before making new requests",
  "url": "https://devcenter.heroku.com/articles/platform-api-reference#rate-limits"
}
  • id: 에러 코드
  • message: 에러 메세지
  • url: 에러의 상세가 기술된 페이지의 url

Heroku는 극단적으로 심플한 형식이지만, 에러에 대한 설명이 있는 페이지의 url이 같이 있는 것이 특징 중에 하나이다.

Toggl

  {
    "error": {
      "message":"We are sorry, this Error should never happen to you",
      "tip":"Please contact support@toggl.com with information on your request",
      "code":500
    }
  }
  • message: 에러 메세지
  • tip: 이 에러를 어떻게 처리하면 좋을지에 대한 설명
  • code: HTTP 상태 코드

Toggl의 특징은 에러를 어떻게 처리하면 좋을지 간단한 힌트가 있다는 점이다.

Yahoo!

{
  "Error" : {
    "Message" : "error message"
  }
}
  • Message: 에러 메세지

Yahoo!의 API는 에러 메세지만을 응답하는 것으로 되어 있다.

GREE

{
   "code":1001,
   "message":"Message API (batch type) to same user is called 
             several times by official user in a certain period of time. Service unavailable.",
   "ref_url":"http:\/\/docs.developer.gree.net\/error.html"
}
  • code: 에러 코드
  • message: 에러 메세지
  • ref_url: 에러의 상세가 기술된 페이지의 url

GREE의 에러 응답도 Heroku와 같이 심플한 형식이지만 에러에 대한 설명이 있는 페이지의 URL이 있다는 것이 특징 중 하나이다.

Nike

{
    "requestId": "-1712857370761229397",
    "errors": [
        {
            "code": 90,
            "message": "Invalid format: Start Date must follow format yyyy-mm-dd"
        },
        {
            "code": 100,
            "message": "Invalid format: End Date must follow format yyyy-mm-dd"
        },
        {
            "code": 110,
            "message": "Invalid Format: count must be greater than or equal to 1"
        }
    ]
}
  • requestId: 요청 ID
  • code: 에러 코드
  • message: 에러 메세지

Nike는 요청 ID가 있어 개발자가 API 프로바이더에 질문했을 때, 이용되는 것이라고 생각된다. 또한 복수의 에러를 응답할 수 있도록 되어 있다는 특징이 있다.

Twitter

{
  "errors": [
    {
      "message": "Sorry, that page does not exist",
      "code": 34
    }
  ]
}
  • message: 에러 메세지
  • code: 에러 코드

Twitter의 API의 에러 응답은 에러가 배열에 담겨 있어 복수의 에러를 응답할 수 있도록 설계되어 있는 점이 특징이다.

Google

{
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "appNotConfigured",
        "message": "The app with id {appId} does not exist or is not properly configured as a Google Drive app."
      }
    ],
    "code": 403,
    "message": "The app with id {appId} does not exist or is not properly configured as a Google Drive app."
  }
}
  • domain: 어느 영역의 에러인지를 특정하기 위해 용도인 듯 하다. 예를 들어 유튜브 영역 고유의 에러라고 하면 youtube.parameter와 같이 된다.
  • reason: 에러 코드
  • message: 에러 메세지
  • code: HTTP 상태 코드

Google의 특징은 다양한 서비스를 아우루는 통일된 형식의 JSON을 사용하고 있다는 점이다. 그래서 서비스를 보여주기 위해서 domain 필드가 설계되어 있다. 또한, 복수의 에러를 응답할 수 있도록 errors 필드가 배열로 되어 있다.

Twilio

{
    "status": 400,
    "message": "No to number is specified",
    "code": 21201,
    "more_info": "http:\/\/www.twilio.com\/docs\/errors\/21201"
}
  • status: HTTP 상태 코드
  • message: 에러 메세지
  • code: 에러 코드
  • more_info: 에러에 대한 상세가 적혀 있는 페이지의 링크

code와 more_info는 필드 자체가 없는 경우도 있다.

Foursquare

{
    "meta": {
        "code": 400,
        "errorDetail": "Missing access credentials. See https://developer.foursquare.com/docs/oauth.html for details.",
        "errorType": "invalid_auth"
    },
    "response": {}
}
  • code: HTTP 상태 코드
  • errorDetail: 에러 메세지
  • eorrorType: 에러 코드

Foursquare의 특징은 일반적인 응답과 에러 응답의 형식의 차이가 없고, 에러가 발생한 뒤에 응답의 meta 키에 에러가 들어가는 것이다.

Flickr

{
    "code": 96,
    "message": "Invalid signature",
    "stat": "fail"
}
  • code: 에러 코드
  • message: 에러 메세지
  • stat: 요청이 성공했는지 실패했는지의 여부

Flickr는 심플한 형식이지만 stat이 있는 점이 특징이다.

Linkedin

{
    "errorCode": 0,
    "message": "Unknown authentication scheme",
    "requestId": "PFB5T8NVLO",
    "status": 401,
    "timestamp": 1432283172233
}
  • errorCode: 에러 코드
  • message: 에러 메세지
  • requestId: 요청 ID
  • status: HTTP 상태 코드
  • timestamp: 요청한 타임 스탬프

Linkein의 에러 응답은 요청 ID와 요청한 타임 스탬프가 있다는 점이다. 만약 개발자로 부터 문의가 있는 경우에 커뮤니케이션 하기 쉬울 것 같다. 단지, 요청 ID 등은 헤더에 있는 편이 좋지 않을까 생각한다.

Philips Hue

[
  {
    "error": {
      "type": 2,
      "address": "/",
      "description": "body contains invalid json"
    }
  }
]
  • type: 에러 코드
  • address: 에러가 있는 URL
  • description: 에러 메세지

Qiita

{
  "message": "Not found",
  "type": "not_found"
}
  • message: 에러 메세지
  • type: 에러 코드

참고 자료

1개의 댓글

comment-user-thumbnail
2022년 9월 16일

궁금했던 것인데 잘 정리해주셔서 감사합니다

답글 달기