배꼽파지 않도록 잘 개발해요

[코드잇] 웹 API 디자인 본문

코드잇 Codeit/CS / 기타

[코드잇] 웹 API 디자인

꼽파 2024. 7. 4. 00:10

 


◆ REST 살펴보기

문서화


◆ REST 살펴보기

API 디자인과 REST

  • Roy T.Fielding : WEB과 HTTP가 그 설계의 우수성에 비하여 제대로 사용되지 못하고 있다.
    웹과 HTTP의 장점을 최대한 활용할 수 있는 디자인원칙을 논문으로 발표함.

  • REST : Representational State Transfer
    표현된 자원의 상태를 주고 받는 방법을 정리한 아키텍처 스타일

  • REST API : REST 원칙을 준수하여 만든 API
  • RESTful API : REST 조건을 잘 만족하는 API
    - 클라이언트 서버, 무상태성, 캐시, 일관화된 인터페이스, 계층화된 시스템, 주문형 코드
    이 중 일관화된 인터페이스가 API 디자인에 가장 크게 영향을 주는 제약조건임.

  • 일관화된 인터페이스
    - 자원에 대한 식별 : 접근하고자 하는 자원을 명시하고, 그 자원을 식별(다른 자원과 구별)할 수 있어야 한다.
    - 표현을 통한 자원에 대한 조작 
    - 자기 서술적 메시지
    - 하이퍼미디어를 통한 애플리케이션 상태 표현

REST의 제약 조건

1 Client-Server
(클라이언트-서버)
· API를 통해 정보를 교환하는 주체는 클라이언트와 서버 구조를 가져야 한다.
· 클라이언트와 서버의 분리를 통해 서로 의존하지 않는 구조를 가져야 한다(관심사의 분리).
2 Stateless
(무상태성)
· 클라이언트는 상태를 저장하지 않는다.
· 클라이언트의 각 리퀘스트는 서버가 리퀘스트를 이해하는 데에 필요한 모든 정보를 포함해야 한다.
3 Cache
(캐시)
· 데이터 복사본을 임시 저장 위치에 저장하여 보다 빠르게 액세스 할 수 있도록 하는 프로세싱인 캐싱을 통해 네트워크 효율성을 높인다.
· 리퀘스트에 대한 리스폰스에 캐시 기능 및 불가능 여부가 들어 있어야 한다.
4 Uniform Interface
(일관된 인터페이스)
· 전체 시스템을 잘 파악할 수 있도록 일관된 인터페이스를 제공해야 한다.
· 이를 통해 구현체가 서비스와 별도로 독립적으로 진화할 가능성을 얻게 된다(낮은 결합도).
ex. 클라이언트가 업데이트 되어도 서버를 함께 업데이트할 필요가 없어진다.
5 Layered System
(계층화된 시스템)
· 클라이언트는 서버에 직접 연결되었는지, 중간 서버를 통해 연결되었는지 알 수 없어야 한다.
6 Code on Demand
(주문형 코드)
· 서버에서 보낸 코드를 클라이언트에서 실행할 수 있어야 한다 (JavaScript)
· 선택적 제약 조건이며 지키지 않아도 REST에는 문제가 없다.

 

HTTP의 특징이 만족시키는 REST의 제약 조건

• 리퀘스트(클라이언트)와 리스폰스(서버)의 구조 → Client-Server(클라이언트-서버) 만족
• stateless(무상태성)과 connectionless(비연결성) →  Stateless(무상태성) 만족
• 헤더의 Cache-Control를 통한 캐시 가능 여부 명시 →  Cache(캐시) 만족
리퀘스트와 리스폰스를 보내는 주체는 중간 계층을 신경쓰지 않아도 되는 구조 →  Layered System(계층화된 시스템) 만족
서버의 코드를 담을 수 있는 Body →  Code on Demand(주문형 코드) 만족

URI 작성 규칙

REST : 자원의 식별 제약 조선은 접근하고자 하는 자원을 명시하고, 그 자원을 식별할 수 있어야 한다.

  • 명사형 사용
  • 반환(응답)하는 자원의 종류에 따라 단수형/복수형 사용
  • 계층 표현을 위하여 슬래시(/) 사용
  • 마지막 슬래시(/, Trailing Slash) 붙이지 않기
  • 모두 소문자로 작성 & 띄어쓰기는 대시(-) 사용
    ex. /articles/top-voted
  • 파일 확장자 포함하지 않기 (확장자는 Content-Type 헤더)
  • 목록에 필터가 필요할 경우, 쿼리 문자열을 사용
  • URI에 동사 사용하지 않기

HTTP 메소드와 표현

  • 조작의 표현 : HTTP Method
  • 자원의 표현 : JSON

표현을 통한 자원의 조작

  • HTTP Method : 자원을 다루는 행동
  • GET, POST, PUT/PATCH, DELETE

GET : 자원 가져오기
· 가져오는 행동이므로 자원은 변화하지 않도록 해야한다.
· 여러 번 리퀘스트를 보내도 같은 리스폰스를 돌려준다.
· 안전한(Safe) 메소드

GET /members : 멤버 목록 가져오기

 

POST : 자원 조작하기
· 자원에 대해 무언가를 수행하였기에 자원의 변화가 있다.
· 자원 목록에 데이터를 전송하여, 새로운 자원의 생성을 요청한다.

POST /members : 멤버 목록에 자원 추가하기

 

PUT/PATCH : 자원 수정하기

· PUT : 교체(replace)

PUT /members/1 : 1번 멤버를 자원으로 수정하기
{
    "username": "mike"
}
200 OK

{
    "username": "mike",
    "age": null
}

 

 

·PATCH : 부분 수정(partial update)

PATCH /members/1
{
    "username": "mike"
}
200 OK

{
    "username": "mike",
    "age": 30
}


DELETE : 자원 삭제하기
· DELETE /members/1 : 1번 멤버를 삭제하기
· 204 No Content


상태코드

100번대
(정보 응답)
100 Continue
(계속)
· 요청의 첫 부분을 받아서 다음 요청을 기다리고 있다는 것을 알려줌.
· 이미 요청을 완료했다면 해당 응답을 무시할 수 있음.
200번대
(성공 응답)
200 OK
(성공)
· 클라이언트의 요청이 성공적으로 처리되었다는 것을 의미함.
· 주로 요청한 페이지를 서버가 제공했다는 것을 의미함.
201 Created
(생성됨)
· 요청이 성공적으로 처리되어 새로운 자원을 생성했다는 것을 의미함.
204 No Content
(콘텐츠 없음)
· 요청을 성공적으로 처리했으며, 콘텐츠(body)를 제공하지 않는다는 것을 의미함.
300번대
(리다이렉션 메시지)
301 Moved Permanently
(영구이동)
· 요청한 자원이 새로운 위치로 영구 이동했음을 나타냄.
· 클라이언트는 서버가 전달된 리스폰스의 Location 헤더에 작성된 주소로 이동함.
302 Found
(임시 이동)
· 요청한 자원이 일시적으로 이동했음을 나타냄.
· 클라이언트는 향후 다시 해당 자원을 요청했을 때도 동일한 주소로 해야 함.
304 Not Modified
(수정되지 않음)
· 마지막 요청 이후 요청한 자원은 수정되지 않았다는 것을 알려주며 서버가 콘텐츠를 전달하지 않음.
· 클라이언트는 이전에 전달받은 자원을 계속해서 사용할 수 있음. 
400
(클라이언트 
에러 응답)
400 Bad Request
(잘못된 요청)
· 클라이언트의 요청을 서버가 아해할 수 없음을 의미함.
401 Unauthorized
(권한 없음)
· 클라이언트가 해당 요청에 대한 응답을 받기 위해서는 추가적인 인증이 필요하다는 것을 의미함.
403 Forbidden
(금지됨)
· 클라이언트가 요청한 자원에 접근할 권한이 없음을 의미함.
· 401과는 달리 인증된 클라이언트이지만 인가되지 않았음을 의미함.
404 Not Found
(찾을 수 없음)
· 클라이언트가 요청한 자원을 서버가 찾을 수 없음을 의미함.
405 Method Not Allowed
(메소드 허용되지 않음)
· 클라이언트가 요청한 HTTP 메소드가 허용되지 않았음을 의미함.
500
(서버 에러 응답)
500 Internal Server Error
(내부 서버 오류)
· 서버에서 오류가 발생하여 요청한 작업을 수행할 수 없음을 의미함.
502 Bad Gateway
(잘못된 게이트웨이)
· 서버가 요청을 처리하는데 필요한 작업을 수행하던 중, 요청을 처리하는 중간 단계의 서버인 게이트웨이로부터 잘못된 응답을 받았음을 의미함.
503 Service Unavailable
(서비스 사용 불가)
· 서버가 해당 요청을 처리할 준비가 되지 않았음을 의미함.
· 일반적으로 유지보수를 위해 작동이 중단되거나 과부하가 걸렸을 때 나타나며, 일시적 상황에서 사용됨.
504 Gateway Timeout
(게이트웨이 시간 초과)
· 서버가 응답을 제한 시간 안에 줄 수 없는 상태임을 의미함.

미디어 타입과 링크 헤더

자기 서술적 메시지 : 메시지의 내용만 보고도 자체적인 해석이 가능해야 한다.
Content-Type : Media Type (미디어 타입, type/subtype)
- text/html, application/json
- IANA(Internet Assigned Numbers Authority)에서 관리
Link : Profile


HATEOAS

하이퍼미디어를 사용한 애플리케이션 상태 표현(HATEOAS) : 리스폰스에 자신을 어떻게 사용하면 되는지에 대한 정보를 담아서 클라이언트가 서버와 동적인 상호 작용이 가능해야 한다는 의미를 가진 제약 조건

1) 리스폰스 바디에 상태 변경을 위한 링크 포함 : HAL (Hypertext Application Language)


2) 링크 헤더 : 이전 상태 및 다음 상태 링크를 받게 됨.


캐싱

캐싱의 필요성

  • API는 수없이 많은 클라이언트로부터 수없이 많은 리퀘스트를 받게 됨.
  • 대부분의 리퀘스트는 무언가를 새로 가져오거나, 어떤 동작을 수행하도록 하는 요청임.
  • 이러한 리퀘스트 중 일부는 이미 한번 가져갔었던 자원을 또다시 요청하고 있을 수도 있음. 그런데 이미 한번 가져갔던 자원을 또 가져갈 필요가 없음.

  • 서버의 자원이 매우 자주 바뀌거나 새로운 자원이 빠르게 생겨나고 있다면 같은 자원에 대한 리퀘스트라고 하더라도 서로 다른 리스폰스가 되는 경우가 많기 때문에 자원을 또 가져가는 행위가 이상하지는 않음. 
  • 하지만 서버가 제공하는 자원에 변화가 없다면 같은 자원에 대한 리퀘스트는 항상 같은 리스폰스를 받게 됨. 클라이언트는 이미 받았던 자원인데 또 받는 것은 불필요함.
  • 그래서 클라이언트는 이전에 받았던 자원을 보관해두었다가 서버의 자원이 변하지 않았다면 한번더 사용하게 됨. 

캐시 : 재사용을 위해 데이터를 보관하는 장소
캐싱 : 캐시에 저장된 데이터로 불필요한 과정을 줄여 시간과 비용을 절약하는 방식 
헤더 : 
- 캐싱할 자원을 판단
- 헤더에 담긴 자원에 대한 정보를 통해 클라이언트와 서버의 자원이 일치하는지, 혹은 변경되었는지를 판단함.

  • Cache-Control : 캐싱 방식
  • Last-Modified : 날짜 
  • Last-Modified의 한계 : 
    - 날짜와 시간을 기바능로 하기에, 1초보다 작은 단위의 캐시 관리가 불가능함.
    - 실제 자원의 변경 없이 수정된 시간만 변경된 경우에도 다른 데이터로 인식

ETag(Entitiy Tag)

· 자원마다 고유하게 부여하는 식별자
· 자원이 변하면 ETag값도 변함.

  • 첫 리퀘스트를 전달하여 받은 리스폰스에 ETag 헤더가 있으면 클라이언트는 캐시에 리스폰스를 보관함. 
  • 이후 max-age의 60초가 지나 더 이상 캐시가 유효하지 않은 상황에서 서버로 리퀘스트를 보낼 때 캐시의 ETag 정보가 존재한다면 해당 정보를 If-None-Match에 포함하여 서버로 리퀘스트를 전달하게 됨. 
  • 리퀘스트를 받은 서버는 ETag가 변경되지 않았을 경우 304 Not Modified 상태코드와 함께 body없이 헤더만 리스폰스로 저장하게 됨.
  • 이후 캐시데이터의 헤더는 리스폰스로 받은 헤더 정보로 갱신되고, 클라이언트는 캐시에 보관된 데이터를 재사용하게 됨. 
  • Last-Modified : 날짜와 시간 기반
  • ETag : 문자열 기반


◆ 문서화

웹 API 문서화

  • Swagger (API 문서 샘플)
  • Redocly (API 문서 샘플)
  • Postman의 Documentation 기능
  • Express 웹 프레임워크: Swagger UI Express
  • Django 웹 프레임워크: Yet another Swagger generator
  • Spring 웹 프레임워크: Springfox

 

728x90