[개념 설명] RESTful API

혜빈·2024년 8월 10일

보충내용

목록 보기
12/38

RESTful API

  • API의 다양한 형식들 중 가장 널리 사용되는 것
  • API가 'A가 이렇게 요청하면 B는 이렇게 응답한다'라는 약속이라면,
    RESTful API는 'A가 어떤 방식으로 요청하고, B는 어떤 방식으로 응답할지' 지정해놓은 다양한 형식들 중 하나임

RESTful API 예시

  • 하는 일은 크게 Create, Read, Update, Delete 네 가지임

  • 도서관으로 예시를 들어서 생각해보자

  • Create : 정보를 생성해서 넣음
    - 새로운 책의 정보를 입력하는 것

  • Read : 정보를 조회
    - 책들의 목록 또는 특정 책의 정보를 받아와 읽는 것

  • Update : 정보를 변경
    - 현존하는 특정 책의 정보를 변경하는 것

  • Delete : 정보를 삭제
    - 어느 책의 정보를 삭제하는 것

  • 우리가 사용하는 대부분의 서비스들이 API를 통해 하는 일들이 4가지로 구성되어있음

RESTful한 요청으로 작성해보기

POST https://api.happybeenbooks.com/v1/books
-> 새 책의 정보 받아오기
GET https://api.happybeenbooks.com/v1/books
-> 책들의 목록 받아오기
GET https://api.happybeenbooks.com/v1/books/1
-> 색인정보가 1인 책의 정보 조회하기
PUT https://api.happybeenbooks.com/v1/books/20
-> 색인번호가 20인 책의 정보 수정
PATCH https://api.happybeenbooks.com/v1/books/7
-> 색인번호가 7인 책의 대여 상태 변경
DELETE https://api.happybeenbooks.com/v1/books/123
-> 색인번호가 123인 책을 삭제하는 요청

  • HTTP 프로토콜을 사용하여 이와 같은 URI로 요청을 보냄
  • HTTP는 RESTful API의 필수요소는 아니지만, RESTful API의 조건을 구현하기 용이하기 때문에 현업에서는 HTTP가 주로 사용됨

  • URI는 이 요청이 '어떤 자원'에 관한 것인지 표현해야 하고, 가능한 한 '그것만' 표현해야 함
  • 위의 경우 books라는 부분을 통해서 요청들이 도서관의 책들에 관한 것임을 알 수 있고
    특정 책에 대한 요청인 경우에는 다른 책들과 중복되지 않는 색인번호를 뒤에 붙여서 명시해줌
  • 'add', 'modify', 'delete'와 같은 그것으로 '무엇을 하는가'를 나타내는 동사는 URI에 가능한 한 포함되지 않음
  • 어떤 종류의 작업을 할지는 HTTP 메소드로 표현함(POST, GET, PUT, PATCH, DELETE 등)

HTTP 메소드

  • HTTP라는 우편서비스가 있다고 가정해보기
  • 우편 서비스를 통해 보낼 수 있는 우편물의 종류(메소드)에는 GET, DELETE, POST, PUT, PATCH 등이 있음
  • GET, DELETE는 편지봉투에 담겨 보내지고
  • POST, PUT, PATCH는 소포상자에 담겨 보내짐
    (GET, DELETE보다 더 많은 내용을 담을 수 있음)

  • 각 요청을 어떤 색의 편지봉투, 또는 소포상자에 담아보내는가를 통해 해당 자원에 대해 어떤 작업을 요청하는 것인지를 나타냄

Read 요청 예시 (GET)

  • 무언가를 보여달라는 요청이기 때문에 많은 정보를 실어 보낼 필요가 없음 -> 편지봉투인 GET 메소드에 실어보냄
GET    https://api.happybeenbooks.com/v1/books
  • 이렇게하면 JSON 데이터가 넘어옴
  • RESTful API의 요청과 응답에는 구조화된 데이터 표현이 가능하면서도 가벼운 JSON이 많이 사용됨
GET    https://api.happybeenbooks.com/v1/books/status=available
  • 특정 조건으로 필터링하려면 query parameter를 사용하면 됨

  • status가 avaiable인 대여가 가능한 상태의 책들만 가져옴

GET    https://api.happybeenbooks.com/v1/books/page=1&size=10
  • 실무에서는 이와 같이 페이징 정보를 붙임
  • 한 페이지에 10권씩, 첫 페이지의 데이터를 보내달라는 의미
  • 이렇게 해야 부하가 걸리지 않음
GET    https://api.happybeenbooks.com/v1/books/1
  • 특정 책의 정보를 받아오는 방법
  • 끝에 해당 항목의 고유 식별자를 붙여주면 됨
  • 반드시 데이터베이스를 구출할 때 각 항목마다 고유값이 만들어지도록 설계해야함
[
  {
  	"id": 1,
    "title" : "Good code",
    "author" : "hyebeen"
  }
]

HATEOAS 원칙

  • RESTful API에서 권장되는 또 다른 원칙

  • Hypermedia

  • As

  • The

  • Engine

  • Of

  • Application State

  • 각 요청의 응답에, 가용한 다른 요청들의 정보를 포함시키는 것

  • '이 리소스에 관해 이런 기능들도 이와 같이 요청할 수 있다'고 첨부하는 것임

[
  {
  	"id": 1,
    "title" : "Good code",
    "author" : "hyebeen",
    "links": [
      {"rel": "self", "href": "https://api.happybeen.com/v1/books/1"},
      {"rel": "update", "href": "https://api.happybeen.com/v1/books/1"},
      {"rel": "delete", "href": "https://api.happybeen.com/v1/books/1"}
    ]
  }
]
  • 위 코드에서 links부분에 해당됨

  • 식당에서 메인 메뉴 주문했을 때 디저트 메뉴판도 같이 주는 것과 같음

  • 위 링크 정보들을 통해서, 개발자들은 API 문서들을 보지 않아도 다음에 어떤 요청을 보낼 수 있는지 살펴볼 수 있음

  • 또한, 이 부분의 API의 세부사항이 변경되더라도 클라이언트에서 이 정보를 참조하게 만들면 클라이언트의 코드를 수정할 필요도 없어짐

  • 각 리소스는 그것의 상위 또는 하위 리소스를 가질 수 있음

  • 책의 경우, 각각에 대한 리뷰들이 달릴 수 있으니 리뷰를 하위 리소스로 갖는다고 할 수 있음

  • 그래서 색인번호가 1인 책에 해당하는 리뷰들ㅇ르 조회하려면 이와 같이 URI를 작성하면 됨

  • 이를 통해 각 요청이 응답으로 받고자 하는 정보들 뿐만 아니라, 리소스들이 서로 어떤 관계를 갖는지 URI를 통해 쉽게 파악할 수 있음


Create 요청 예시(POST)

  • HATEOAS 원칙 생략한 예시
  • 새 항목의 정보를 입력하려면 용량이 클 수도 있는 정보를 담아서 보내야 하니 소포 상자가 필요함 -> POST 요청 사용
  • 새 책의 등록은 해당 요청이 어느 리소스에 데이터를 추가하는 것인지만 명시하면 됨
  • POST, PUT, PATCH와 같은 소포상자에는 body라는 공간이 있어서
    이곳에 용량이 큰 데이터를 실어보낼 수가 있음
{
	"title": "Hello JS",
    "autor": "been",
    "published_date": "2024-08-10",
    "isbn": "1234567890"
}
  • 그곳에 새로 등록할 책의 정보를 실어보냄
  • 서버는 책이 성공적으로 등록되고 나면 이와 같이 새로 추가된 정보를 응답으로 돌려줌
{
  	"id": 4,
	"title": "Hello JS",
    "autor": "been",
    "published_date": "2024-08-10",
    "isbn": "1234567890",
    "status": "available"
}
  • 이처럼 항목이 추가되면서 자동으로 부여되는 색인 번호 등의 정보들도 받아와지는 것을 확인 할 수 있음
  • 이를 통해 클라이언트에서는 방금 등록한 책의 정보를 GET 메소드로 바로 살펴볼 수 있음

Update 요청 예시(PUT, PATCH)

  • PUT과 PATCH의 차이는 전체를 수정하는지, 부분적으로 수정하는지 여부임

  • 특정 항목의 정보를 전체적으로 대체 -> PUT 요청

  • 특정 항목의 정보를 부분적으로 대체 -> PATCH 요청

  • 소포상자의 크기는 같지만, 색으로 용도가 다르게 표시된 것임

  • 수정은 특정 항목에 관한 것이기 때문에 어떤 책인지 명시하는 식별자를 붙여줌

PUT 요청

PUT https://api.happybeenbooks.com/v1/books/1
  • PUT 요청은 특정 항목의 정보를 전체적으로 대체하기 때문에 그곳에 들어갈 모든 정보를 body에 실어 보냄
{
	"title": "Hello JS",
    "autor": "been",
    "published_date": "2024-08-10",
    "isbn": "1234567890",
    "status": "available"
}
  1. 결과로는 해당 요청의 실행 성공여부를 보내줄 수도 있고
{
	"message": "Book update successfully"
}
  1. 수정된 결과 전체를 보내줄 수도 있음
{
  	"id": 1,
	"title": "Hello JS",
    "autor": "been",
    "published_date": "2024-08-10",
    "isbn": "1234567890",
    "status": "available"
}

PATCH 요청

  • 부분적으로 수정하고 싶다면 PATCH 요청하기
{
	"status": "rented"
}
  • 응답으로는 실행 결과를 보내주면 됨
{
  	"id": 1,
	"title": "Hello JS",
    "autor": "been",
    "published_date": "2024-08-10",
    "isbn": "1234567890",
    "status": "rented"
}

{
	"status": "rented"
}
  • 만약 이 내용을 PUT으로 보내게 되면, 원칙상 여기에 포함되지 않는 값들은 모두 NULL이 됨

Delete 요청 예시(DELETE)

  • 삭제할 도서를 지목하기만 하면 되니 편지봉투면 충분함 -> DELETE 메소드 사용
  • URI에는 삭제할 책의 식별자를 적어 보내주면 됨
DELETE https://api.happybeenbooks.com/v1/books/1
  • 결과로는 실행 결과의 성공 여부를 보내주면 됨
{
	"message": "Book deleted successfuly"
}

RESTful API의 중요한 점

Status Codes (상태코드)

  • 우편물에 도장이 찍히거나 스티커가 붙어 오는 것처럼, 서버의 응답에는 요청을 처리한 결과를 알려주는 상태 코드가 담겨옴

  • 성공적인 요청(Success) : 2XX

  • 200번대 상태코드

  • 클라이언트 요청의 문제(Client Error): 4XX

  • 400번대 상태코드

  • URI가 잘못되었거나, 권한 외의 요청을 하는 경우

  • 서버측의 오류(Server Error): 5XX

  • 500번대 상태코드

  • 이와 같은 상태 코드들로 각 요청이 어떻게 처리되었는지를 명확하게 나타내주어야 함

Stateless (상태가 없는 통신)

  • 클라이언트의 상태 정보가 서버에 저장되지 않아야 한다는 것

  • 즉, 서버는 클라이언트에 대해 아무것도 기억하지 않아야 한다는 것임

  • 때문에 클라이언트의 요청이 몇 번째 반복되어도 필요한 모든 내용을 포함하고 있어야 함

  • Idempotent(멱등성)과도 연결됨

  • 클라이언트가 같은 요청을 몇 번을 보내도 언제나 같은 답이 돌아와야 함(실제 데이터가 바뀐 경우 제외)

  • 클라이언트와 서버는 서로에 대해서는 기억하지 않아야 하지만 자신이 어떤 응답을 보냈는지, 자신이 어떤 응답을 받았는지는 기억해 두는게 좋음

  • 이처럼 한 번 얻어낸 데이터를 또 쓸 수 있도록 저장해 두는 것을 Casheability(캐싱)이라고 함

  • 클라이언트에서 어떤 요청에 대한 응답을 캐싱해두면 같은 데이터가 필요할 때마다 요청을 보내지 않아도 되고,
    서버도 특정 요청에 대해 응답한 바를 기억해 두면
    다른 클라이언트가 같은 요청을 보냈을 때
    또 데이터 베이스에서 정보를 캐낼 필요 없이
    가지고 있는 것을 바로 보내면 됨

  • RESTful API에서는 각 요청이 나타내는 바가 뚜렷하니까 그것마다 캐싱을 해두기가 수월함

profile
최강 개발자를 꿈꾸는 병아리

0개의 댓글