Computer Engineering/Design

간단한 원칙으로 좋은 HTTP API 만들기

jordan.bae 2024. 2. 18. 18:00

개요

REST API라는 용어는 자주 사용하고, 면접 시에도 자주 질문을 받아서 면접 전에 해당 내용을 정리하고 가는 경우가 많습니다. 하지만, 막상 실무에서는 REST API의 복잡한 내용을 기억하기보다는 간결한 원칙들을 기억하고 지키는 것이 중요한 경우가 많습니다. 그래서 이 글에서 REST API를 간단히 훑어본 후 RESTful API는 아니지만 좋은 HTTP API를 만들기 위해 핵심적으로 기억해야 할 몇 가지를 정리하려고 합니다.

 

REST API란?

RESTful API는 아니더라도 REST API의 내용을 이해하고 필요한 부분을 이해하고 지키는 것은 중요하기 때문에 한 번 내용을 정리하고 가려고 합니다.

API는 하나의 Application이나 서비스가 다른 Application의 서비스 내의 리소스에 액세할 수 있게 해주는 인터페이스입니다.

REST (Representational State Transfer)는 웹 서비스를 구축하는 데 사용되는 아키텍처 스타일 중 하나로, 간결하면서도 확장 가능한 디자인을 지향합니다. RESTful API를 설계할 때 핵심적으로 기억해야 할 몇 가지 원칙과 요소에 대해 살펴보겠습니다.

  1. uniform interface: 요청이 어디에서 오는지와 무관하게, 동일한 리소스에 대한 모든 API 요청은 동일하게 보여야 합니다. 즉, 클라이언트에 상관없이 같은 리소스에 대한 요청은 같은 리소스의 URI를 사용하여 요청해야 합니다. 이 밖에도 리소스에 대한 충분한 정보를 제공해야 합니다.→ 지키기가 가장 어려운 스타일 요소
    1. 애플리케이션의 상태는 Hyperlink를 이용해 전이되야 합니다.(HATEOAS)
      ex. Twilio fetch a channel resource API
      
      # <https://www.twilio.com/docs/chat/rest/channel-resource#fetch-a-channel-resource>
      { 
        "sid": "CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        "friendly_name": "friendly_name",
        "unique_name": "unique_name",
        "attributes": {
          "foo": "bar"
        },
        "type": "public",
        "date_created": "2015-12-16T22:18:37Z",
        "date_updated": "2015-12-16T22:18:37Z",
        "created_by": "system",
        "members_count": 0,
        "messages_count": 0,
        "url": "<https://chat.twilio.com/v2/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Channels/CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX>",
        "links": {
          "members": "<https://chat.twilio.com/v2/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Channels/CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Members>",
          "messages": "<https://chat.twilio.com/v2/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Channels/CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Messages>",
          "invites": "<https://chat.twilio.com/v2/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Channels/CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Invites>",
          "webhooks": "<https://chat.twilio.com/v2/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Channels/CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Webhooks>",
          "last_message": null
        }
      }
    2. 메시지는 스스로 설명할 수 있어야 합니다. (Self-descriptive message)
  2. 클라이언트-서버 디커플링: 클라이언트 Application에서 통신을 위해 알아야 하는 유일한 정보는 리소스의 URI여야 하고, 이 밖의 것은 서로 간에 완전히 독립적 이어야 한다.
  3. Stateless: REST API는 stateless입니다. 이는 각 요청에서 이의 처리에 필요한 모든 정보를 포함해야 함을 의미합니다. 즉, REST API는 서버 측 세션을 필요로 하지 않습니다. 서버 애플리케이션은 클라이언트 요청과 관련된 데이터를 저장할 수 없습니다.
  4. 캐시 가능: 가능하면 리소스를 클라이언트 또는 서버 측에서 캐싱할 수 있어야 합니다. 또한 서버 응답에는 전달된 리소스에 대해 캐싱이 허용되는지 여부에 대한 정보도 포함되어야 합니다. 이의 목적은 서버 측의 확장성 증가와 함께 클라이언트 측의 성능 향상을 동시에 얻는 것입니다. → HTTP 프로토콜 표준에서 사용하는 Last-Modified태그나 E-Tag를 이용하면 캐싱 구현이 가능합니다.
  5. 계층 구조 아키텍처:REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 합니다.→ HTTP 프로토콜인 경우 따로 해줄 것이 없음.
  6. 코드 온디맨드(옵션): REST API는 일반적으로 정적 리소스를 전송하지만, 특정한 경우에는 응답에 실행 코드를 포함할 수도 있습니다. 이 경우에 코드는 요청 시에만 실행되어야 합니다.

HTTP만 잘 따라도 Client-Server, Stateless, Cache(사실 서버에서 Cache를 사용하기 때문에 잘 사용하지는 않는 듯), Layered System은 다 지킬 수 있는데 uniform interface는 Self-descriptive messages나 HATEOAS는 지키지 않는 경우가 더 많은 것 같다.

 

좋은 API를 만들기 위해 진짜 기억해야 할 Practice

위에는 스타일 가이드에 대한 이론이다. 실제는 어떤 Practice가 기억하고 적용하기가 좋다!

URI 설계

  • 리소스는 비즈니스의 entity이다. 단일 데이터에 종속되서는 안된다.
    • /users/1 (o)
    • /users/1, /profiles/1 (x)
  • 동사보다는 명사를 사용하자. Method가 이미 동사이기 때문에 동사를 사용하면 중복으로 표현을 상요하게 되는 경우가 많다. 동작은 method로!
    • GET /users (good)
    • GET /get-users (bad)
  • 명사는 복수형! 복수형을 사용하는 경우에 다양한 API에 대해서 더 적합하다.
    • GET users/:id
    • GET user/:id
  • 마지막에 ‘/ ‘를 포함하지 않는다. ‘/’는 리소스를 구분할 때 사용한다. 즉, 구분하지 않을때는 사용하지 않기 때문에 마지막에 ‘/’를 붙일 필요가 없다.

기타

  • 파일 포맷을 URI에 사용하지 않기.
  • 소문자 사용
  • _(언더바)가 아닌 -(대시) 사용 하기.

 

적절한 Status Code 사용

응답 코드는 너무 많은 코드를 사용하는 것보다는 아래의 코드 정도를 잘 구분해서 사용하는 것이 좋습니다.

  • 200: GET 요청에 대한 성공 응답
  • 201: POST 요청에 대한 성공 응답
  • 204: DELETE 요청에 대한 성공 응답
  • 400: 올바르지 못한 요청에 대한 실패 응답
  • 401: 인증되지 않은 유저의 요청에 대한 실패 응답.
  • 403: 인증된 사용자이지만 해당 요청에 대한 권한이 있지 않은 요청에 대한 실패응답.
  • 404: 존재하지 않은 URI에 대한 요청.
  • 422: 요청에 포함된 데이터의 처리 실패에 대한 요청.
  • 500: 프로그램 내부에서 처리되지 않은 에러가 발생하는 경우 실패 응답.

 

마무리

실무를 하다보면 이론을 하나하나 더 잘 아는 것보다는 기억하기 쉽고 적용하기 쉬운 형태로 정리되어야 잘 활용하게 되는 경우가 많은 것 같습니다. API를 만들 때(특히, URI) 한 번씩 위 내용을 기억하면 조금 더 유지 보수하기 좋고 보기 좋은 API가 되지 않을까 싶습니다.

반응형