개발

REST API Convention

사무엘 얼터 2023. 5. 12. 13:11

Json Style Guide


공식적으로 REST API Guide는 이렇게 존재합니다.

Summary

  • 문자열 유형의 속성값을 큰 따옴표로 묶을 것.
{
  "name": "Taeeun Kim"
}
  • 편의를 위해 데이터를 임의로 그룹화 하지 말것.
    데이터 요소는 JSON 표현에서 평면화 되어야합니다. 편의를 위해 데이터를 임의로 그룹화해서는 안됩니다.
    단일 구조를 나타내는 속성 모음과 같은 일부 경우에는 구조화 된 계층을 유지하는 것이 합리적 일 수 있습니다. 
    이러한 경우는 신중하게 고려되어야하며 의미론적 의미가 있는 경우에만 사용해야 합니다. 예를 들어 주소는 두 가지 방식으로 표현 될 수 있지만 구조화 된 방식이 개발자에게 더 적합할 수 있습니다.
// 평면화된 구조
{
  "company": "Google", 
  "website": "https://www.google.com/", 
  "addressLine1": "111 8th Ave", 
  "addressLine2": "4 층", 
  "state": "NY", 
  "city ":"New York", 
  "zip ":"10011"
}

// 구조화된 구조
{ 
  "company": "Google", 
  "website": "https://www.google.com/", 
  "address": { 
    "line1": "111 8th Ave", 
    "line2": "4 층", 
    "state": "NY", 
    "city": "New York", 
    "zip": "10011" 
  } 
}
  • 속성의 이름은 의미있는 이름으로 지정할 것.
    • 속성 이름은 의미가 정의 된 의미있는 이름이어야합니다.
    • 속성 이름은 lowerCamelCase의 ASCII 문자열이어야합니다.
    • 첫 번째 문자는 문자, 밑줄 (_) 또는 달러 기호 ($) 여야합니다.
    • 후속 문자는 문자, 숫자, 밑줄 또는 달러 기호가 될 수 있습니다.
    • 예약 된 JavaScript 키워드는 피해야합니다.
  • 속성 이름에 lowerCamelCase를 사용할 것. 하지만 object를 맵으로 사용할 경우엔 제외.
  • 지도의 키는 속성 이름에 대한 명명 지침을 따를 필요가 없습니다. 맵 키에는 모든 유니 코드 문자가 포함될 수 있습니다. 클라이언트는 맵에 대괄호 표기법(Ex : result.thumbnails["72"])을 사용하여 이러한 속성에 액세스 할 수 있습니다.  
{
  "address": { 
    "addressLine1": "123 Anystreet", 
    "city": "Anytown", 
    "state": "XX", 
    "zip": "00000" 
  },
  "thumbnails": { 
    "72": "http : //url.to.72px.thumbnail", 
    "144": "http : //url.to.144px.thumbnail" 
  } 
}
  • 배열 유형의 속성 이름은 복수형 이름이어야하고 다른 속성 이름은 모두 단수형 이름일 것.
{ 
  // 단수 
  "author": "lisa", 
  // 형제 배열, 복수형 
  "siblings": [ "bart", "maggie"], 
  // "totalItem"은 올바르게 보이지 않음
  "totalItems": 10, 
  // 하지만 "itemCount"가 더 나음
  "itemCount": 10, 
}
  • 속성값의 타입은 null, boolean, number, string, object, array 일 것.
// Good
{ 
  "canPigsFly": null, // null 
  "areWeThereYet": false, // 부울 
  "answerToLife": 42, // 숫자 
  "name": "Bart", // 문자열 
  "moreData": {}, // object 
  " things ": [] // 배열 
}

// Bad
{ 
  "aVariableName": aVariableName, // Bad-JavaScript 식별자 
  "functionFoo": function () {return 1; } // 나쁨-자바 스크립트 함수 
}

가이드를 보면 대부분 같은 내용이고 그 중 Google에서 만든 Json Style Guide가 가장 내용이 많고 사용하는 사람이 많기 때문에 이를 따라 가도록 하겠습니다.

JSON 구조 & 예약된 속성명들

API 간에 일관된 인터페이스를 유지하기 위해 JSON 오브젝트는 아래에 설명된 구조를 따라야 합니다. 이 구조는 JSON을 사용한 요청과 응답 모두에 적용됩니다. 이 구조에는 특정 용도로 예약된 특정 속성 이름이 있습니다. 다음은 JSON 구조의 스키마 입니다.

object {
  string apiVersion?;
  string context?;
  string id?;
  string method?;
  object {
    string id?
  }* params?;
  object {
    string kind?;
    string fields?;
    string etag?;
    string id?;
    string lang?;
    string updated?; # date formatted RFC 3339
    boolean deleted?;
    integer currentItemCount?;
    integer itemsPerPage?;
    integer startIndex?;
    integer totalItems?;
    integer pageIndex?;
    integer totalPages?;
    string pageLinkTemplate /^https?:/ ?;
    object {}* next?;
    string nextLink?;
    object {}* previous?;
    string previousLink?;
    object {}* self?;
    string selfLink?;
    object {}* edit?;
    string editLink?;
    array [
      object {}*;
    ] items?;
  }* data?;
  object {
    integer code?;
    string message?;
    array [
      object {
        string domain?;
        string reason?;
        string message?;
        string location?;
        string locationType?;
        string extendedHelp?;
        string sendReport?;
      }*;
    ] errors?;
  }* error?;
}*;

JSON 개체에는 몇 가지 최상위 속성이 있으며, 그 중에는 data 개체 또는 error 개체가 있습니다. 이러한 각 속성에 대한 설명은 아래에서 찾을 수 있습니다.

최상위 레벨에 예약된 속성명

nametypeParent

apiVersion string -
context string -
id string -
method string -
params string -
data object -
error object -

data object에 예약된 속성명

nametypeParent

kind string data
fields string data
etag string data
id string data
lang string data (or any child element)
updated string data
deleted boolean data (or any child element)
items array data

Paging을 위해 예약된 속성명

nametypeParent

currentItemCount integer data
itemsPerPage integer data
startIndex integer data
totalItems integer data
pagingLinkTemplate string data
pageIndex integer data
totalPages integer data

Links를 위한 예약된 속성명

nametypeParent

self / selfLink object, string data
edit / editLink object, string data
next / nextLink object, string data
previous / previousLink object, string data

error object에 예약된 속성명

nametypeParent

code integer error
message string error
errors array error
domain string error.errors
message string error.errors
location string error.errors
locationType string error.errors
extendedHelp string error.errors
sendReport string error.errors

Then, What we do?


따라서 우리는 이런 식으로 Response를 구성할 수 있습니다.

{
  "apiVersion": "2.0",
  "data": {
    "updated": "2010-02-04T19:29:54.001Z",
    "totalItems": 6741,
    "startIndex": 1,
    "itemsPerPage": 1,
    "items": [
      {
        "id": "BGODurRfVv4",
        "uploaded": "2009-11-17T20:10:06.000Z",
        "updated": "2010-02-04T06:25:57.000Z",
        "uploader": "docchat",
        "category": "Animals",
        "title": "From service dog to SURFice dog",
        "description": "Surf dog Ricochets inspirational video ...",
        "tags": [
          "Surf dog",
          "dog surfing",
          "dog",
          "golden retriever",
        ],
        "thumbnail": {
          "default": "https://i.ytimg.com/vi/BGODurRfVv4/default.jpg",
          "hqDefault": "https://i.ytimg.com/vi/BGODurRfVv4/hqdefault.jpg"
        },
        "player": {
          "default": "https://www.youtube.com/watch?v=BGODurRfVv4&feature=youtube_gdata",
          "mobile": "https://m.youtube.com/details?v=BGODurRfVv4"
        },
        "content": {
          "1": "rtsp://v5.cache6.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
          "5": "https://www.youtube.com/v/BGODurRfVv4?f=videos&app=youtube_gdata",
          "6": "rtsp://v7.cache7.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp"
        },
        "duration": 315,
        "rating": 4.96,
        "ratingCount": 2043,
        "viewCount": 1781691,
        "favoriteCount": 3363,
        "commentCount": 1007,
        "commentsAllowed": true
      }
    ]
  }
}

만약 페이징이 필요하다면 이렇게 만들 수 있습니다.

{
  "apiVersion": "2.1",
  "id": "1",
  "data": {
    "query": "chicago style pizza",
    "time": "0.1",
    "currentItemCount": 10,
    "itemsPerPage": 10,
    "startIndex": 11,
    "totalItems": 2700000,
    "nextLink": "https://www.google.com/search?hl=en&q=chicago+style+pizza&start=20&sa=N"
    "previousLink": "https://www.google.com/search?hl=en&q=chicago+style+pizza&start=0&sa=N",
    "pagingLinkTemplate": "https://www.google.com/search/hl=en&q=chicago+style+pizza&start={index}&sa=N",
    "items": [
      {
        "title": "Pizz'a Chicago Home Page"
        // More fields for the search results
      }
      // More search results
    ]
  }
}

'개발' 카테고리의 다른 글

[k8s] EFK 스택 구성하기 with helm charts  (0) 2023.09.27
[NestJS] 슬랙 알람 데코레이터 리팩토링  (0) 2023.05.12
Select marker with drag in Google map  (0) 2023.05.12
Naming Convention  (0) 2023.05.12