HTTP

[API] 1. RESTful API란?

foxlee 2020. 11. 1. 10:09

참고 링크

1. 깃헙 http-api-design

2. stackoverflow /login or /register -> /session

3. stackoverflow return status for empty data of users/9

4. Naming 

 

다음 글 - 2021.11.01 - [개발 고민들] - [API] 2. RESTFUL API - RESPONSE STATUS CODE 적용하기

HTTP

  • 무상태 프로토콜
    • 장점 : 단순함과 확장성이 높음(서버가 클라이언트상태 보전하지 않아 전송간에 서로 연관이 없어 확장성이 높음)
    • 단점 : 클라이언트에서 추가 데이터 전송 필요(데이터 전송마다 그전 전송에 대한 정보가 없음)
    • 실무에서는 무상태는 로그인이 필요없는 단순한페이지
    • 상태유지의 예로는 로그인으로 로그인 했다는 상태를 서버에서 유지(쿠기, 서버 세션 등으로)
  • 비연결성
    • 연결을 유지하지 않기 때문에 요청 수가 많아도 빠른 속도 응답이 가능하고 서버 자원을 효율적으로 사용 가능
    • 단점으로는 3 Way Handshake 으로 매번 연결을 새로 맺어야 해서 시간이 늘어남
    • 위의 단점을 개선하기 위해서 지속 연결을 통해 연결을 잠시 유지하는 방법이 있음

메서드 종류

  • GET: 리소스 조회
    • 데이터 조회로 주로 쿼리 파라미터를 통해 필터등의 조건 등을 추가하여 조회
    • 메세지 바디를 사용해 전달은 가능하지만 지원하지 않는 곳이 많아서 안 쓰는 게 나음
  • POST: 리소스 생성 또는 다른 곳에 해당하지 않는 데이터 처리
    • 메세지 바디를 통해 서버로 데이터 전달
    • 보통 리소스가 생성되면 생성된 위치를 응답으로 보내줌 -> 헤더에 Location: /members/2
    • 생성(유저)뿐만 아니라 각종 비지니스 로직, 정책을 통한 로직 등에 사용 
    • 다른 메서드를 사용하기 애매한 경우
  • PUT: 리소스 전체 대체, 없으면 생성
    • 클라이언트에서 리소스의 위치(userID 등)를 알고 있음
    • 그동안 아래의 PATCH를 PUT으로 사용했었음..(물론, 절대적인 건 없음, 상황에 맞게, 팀워들과 상의 후 결정)
  • PATCH: 리소스 일부 변경
  • DELETE : 리소스 삭제
  • HEAD: GET에서 메세지 바디 없이 상태줄, 헤더만 반환
  • 그 외 OPTIONS, CONNECT, TRACE 가 있음

HTTP 메서드의 속성

  • 안전
    • 아무리 많이 호출해도 같은 요청에는 같은 결과
    • 다른 건 신경쓰지 않으며 오로지 리소스가 변경이 되는 것에만 신경 씀(과부화로 인한 에러발생과는 관계 없음)
  • 멱등
    • 같은 API 호출을 여러번 해도 그 결과는 같다
    • GET - 여러번 조회해도 그 결과는 같음
    • PUT - 같은 요청을 여러번 해도 그 결과는 같음
    • DELETE - 결과를 삭제하고 결과적으로 삭제되므로 같음
    • POST - 두번 호출하번 요청이 두번 일어나 중복되는 결과가 생길 수 있음
    • 멱등 활용 > 에러/TIMEOUT 등으로 클라이언트가 같은 요청을 다시 해도 되는가?
  • 캐시가능
    • GET, HEAD 정도는 캐시 가능

URI 설계 개념

  • 문서(단일 개념, 객체 인스턴스, 데이터베이스 ROW) - /members/20, /images/logo.png
  • 컬렉션(서버에서 관리하는 리소스 디렉터리로 서버가 리소스의 URI를 생성하고 관리)
  • 스토어(클라이언트가 리소스의 URI를 알고 관리함 - 파일)
  • 컨트롤러, 컨트롤러 URI(위의 개념으로 해결하기 어려운 경우로 동사를 직접사용)
  • Naming 참고 

적절한 상태 코드 반환

  • 200 - GET, DELETE(동기), PATCH(동기)
  • 201 - POST(동기)
  • 202 - POST, DELETE, PATCH 비동기
  • 204 - No content : 삭제 후 반환할 데이터가 없는 경우
  • 300 -
  • 4xx - (클라이언트 에러)요청파라미터가 잘못된거나 리소스 자체가 없는 경우
    • 클라이언트에서 잘못 보냄,
    • 클라이언트에서 명세대로 요청하고 있다면 400 에러를 보내주면 안됨
    • 비지니스 로직에 대한 실패라면 200으로보내주고 이에 대한 정보를 메세지로 보내줘야함  { "Result": "Failed", "Reason": "Error ~"}
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not found
  • 5xx - 서버 에러
  • METHOD는 GET/POST/PUT/DELETE 등으로 어떤 목적을 취하는지 명확하게 보여주고 이와 같은 action이 url 에는 넣지 않는 것이 좋다.(어쩔수 없는 경우 넣거나, restful 한 api가 아닐뿐이지 잘못된건 아니다. 상황에 맞게 개발!)

리소스

  • 반환하는 리소스는 가능한 전체 리소스를 반환
  • 리소스 아이디 제공

경로 포맷은 일정하게

  • 리소스의 이름을 복수형으로, 
  • 리소스 아이디 제공

Dash(-)사용 

  • api/app-setups

Nested 데이터

  • { "name": "service-production", "owner": { "id": "5d8201b0..." } } (O)
  • { "name": "service-production", "owner_id": "5d8201b0..."  {X)

구조화된 에러 

  • 일정한 에러 메세지
    • { "id": "rate_limit", "message": "Account reached its API rate limit.", "url": "관련 url"}

Etags로 캐시 지원

  • 모든 응답의 헤더에 Etag 포함시킴, 반환되는 리소스의 특정한 버전을 확인, IF-None-Match 헤더의 값을 제공  

로그인/ 로그아웃 엔드포인트

  • RESTFUL API에 대해서 모르기 전에는 login, logout 을 엔드포인트에 적용했었는데, 사실상 로그인 로그아웃은 세션이 생성되고 폐기되는 것이다. 
    • Login -> POST /session (또는 username/session)
    • Logout -> DELETE /session (또는 username/session)

데이터가 없는 리소스에 대한 상태 값

  • 404 가 적절
  • 204 No content
    • 데이터가 없기에 상태 코드 값으로는 괜찮으나 HTTP 스펙에 의하면 브라우저는 뷰를 바꾸지 말라는 것으로 이해함
    • 요청에 대한 성공을 나타내고 반환할 데이터가 없는 경우에 적절함(DELETE)
    • GET users/9 에 대한 응답으로는 적절하지 않음
  • GET /users 200 [John, Peter]
  • GET /users/john 200 John                  - /users/[string:name]
  • GET /unknown-url-egaer 404 Not Found
  • GET /users/kyle 404 User Not found      - /users/[string:name]  - 바로 리소스에 접근하는 url로 존재하는 데이터가 없으므로,
  • GET /users?name=kyle` 200 []     - search 와 같은 기능으로
  • DELETE /users/john 204 No Content

리소스에 대한 기준.

  • phrsal verb 에서 영어 구동사들을 동사와 부사 또는 전치사가 같이 합쳐진다. 구동사들의 동사를 가져오는 데 처음에는 내가 저장한 구동사들을 리소스로 생각하고 필터 플래그를 주어 only_verb(동사만), only_particle(부사, 전치사만) 등 과 같은 플래그를 통해 동사 리스트, 전치사, 부사 리스트를 반환하도록 했으나  verbs, particle 다른 리소스로 변경예정
    • phrsalverbs/?only_verb=0&only_particle=0
    • -> verbs/ particles/ 로 변경