HTTP/네트워크 실습 Ch 1. REST API

HanSungUk·2022년 6월 10일
0

HTTP / 네트워크

목록 보기
4/9

HTTP/네트워크 실습 Ch 1. REST API

현재 코드스테이츠 강의를 통해 프론트엔드를 학습하고 있습니다.
본 포스트는 해당 강의에 대한 내용 정리를 목적으로 합니다.

학습목표

  • REST API에 대해 이해할 수 있다.
  • REST 성숙도 모델에 대해 이해할 수 있다.
  • REST API 문서를 읽을 수 있다.
  • REST API에 맞춰 디자인할 수 있다.
  • Open API와 API Key에 대해 이해할 수 있다.

웹 애플리케이션에서는 HTTP 메서드를 이용해 서버와 통신합니다. GET을 통해 웹 페이비나 데이터를 요청하고, POST로 새로운 글이나 데이터를 전송하고, DELETE로 저장된 글이나 데이터를 삭제할 수 있습니다. 이처럼 클라이언트과 서버가 HTTP 통신을 할 때는 어떤 요청을 보내고 받느냐에 따라 메서드의 사용이 달라집니다.
이와 같이 요청과 응답을 할때는 '제대로 보내고 받을 수 있는' 일종의 규약이 존재합니다.

REST API

1. REST API 디자인

REST API의 API는 "Representational State Transfer"의 약자로 REST API는 웹에서 사용되는 데이터나 자원(Resource)을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식 을 말합니다.
쉽게 말해서 자원(source)에 대한 주소를 정하는 방법. 디자인 원리/제약, 즉 규칙을 일컫습니다.

REST 성숙도 모델은 총 4단계(0 ~ 3단계)로 나누어집니다.
REST API에 대해서 처음 기술한 로이 필딩(Roy Fielding)은 위 모든 단계를 충족해야 REST API라고 부를 수 있다고 주장했습니다. 하지만 실제로 3단계까지 지키기 어렵기 때문에 2단계까지만 적용해도 좋은 API 디자인이라고 볼 수 있고, 이런 경우를 HTTP API라고도 부릅니다.

2. REST 성숙도 모델 - 0단계

0단계에서는 단순히 HTTP 프로토콜 을 사용하기만 해도 됩니다. 해당 API를 REST API라고 할수는 없습니다. 0단계는 REST API를 작성하기 위한 기본 단계입니다.


3. REST 성숙도 모델 - 1단계

1단계에서는 개별 리소스(Resource)와의 통신을 준수해야 합니다.
REST API는 웹에서 사용되는 모든 데이터나 자원(Resource)을 HTTP URI로 표현합니다. 따라서 모든 자원을 HTTP URI로 표현할때 개별 리소스에 맞는 엔드포인트(Endpoint)를 사용해야하며 요청하고 받는 자원에 대한 정보를 응답으로 전달해야 한다는 것이 1단계의 핵심입니다.
엔드포인트(Endpoint)의 기준은 개발자마다 다릅니다. 주로 port전까지를 일컫습니다.

위 0단계에서는 요청에서의 엔드포인트는 모두 /appointment를 사용했습니다. 하지만 1단계에서는 개별 리소스에 따라 각기 다른 엔드포인트로 구분하여 사용합니다.

위의 예시에서 예약 가능한 시간 확인이라는 요청의 응답으로 받게 되는 개별 리소스(Resource)는 허준이라는 의사의 예약 가능한 시간대입니다.
따라서, 요청 시 /doctors/허준 이라는 엔드포인트를 사용했습니다.
또한 특정 시간에 예약하게 되면, 실제 slots라는 리소스의 123이라는 id를 가진 리소스가 변경되기 때문에, 하단의 특정 시간에 예약이라는 요청에서는 /slots/123으로 실제 변경되는 리소스를 엔드포인트로 사용했습니다.

위 예시와 같이 어떤 리소스를 변화시키는지 혹은 어떤 응답이 제공되는지에 따라 각기 다른 엔드포인트를 사용하기 때문에 적절한 엔드포인트 작성이 중요 합니다.

엔드포인트(Endpoint) 작성 시에는 동사, HTTP 메서드, 혹은 어떤 행위에 대한 단어의 사용은 지양하고, 개별 리소스에 집중해서 명사 형태의 단어로 작성하는 것이 바람직합니다.

더불어 요청에 따른 응답으로 리소스를 전달할 때에도 사용한 리소스에 대한 정보와 함께 리소스 사용에 대한 성공/실패 여부를 반환해야합니다.


4. REST 성숙도 모델 - 2단계

2단계에서는 CRUD(Create, Read, Update, Delete)에 맞게 적절한 HTTP 메서드를 사용하는 것에 중점을 둡니다. 앞서 0단계와 1단계 예시에서는 모든 요청을 CRUD(Create, Read, Update, Delete)와 상관없이 POST메서드를 사용하고 있습니다.

예를 들어 예약 가능한 시간을 확인한다는 것은 예약 가능한 시간을 조회(READ)하는 행위고 조회(READ)하기 위해서 GET메서드를 사용하여 요청을 보냅니다.
이때, GET메서드는 body를 가지지 않기 때문에 query parameter를 사용하여 필요한 리소스를 전달합니다.

또한 특정 시간에 예약을 한다는 것은 해당 특정 시간에 예약을 생성(CREATE)한다는 행위고 예약을 생성(CREATE)하기 위해서는 POST메서드를 사용하여 요청을 보내야 합니다.
이 경우 응답은 새롭게 생성된 리소스를 보내주기 때문에, 응답 코드는 201 Created로 명확하게 작성해야 하며, 관련 리소스를 클라이언트가 Location헤더에 작성된 URI를 통해 확인할 수 있도록 하면 완벽하게 2단계를 충족했다고 볼 수 있습니다.

HTTP 메서드 사용 규칙

  • GET메서드 같은 경우는 서버의 데이터를 변화시키지 않는 요청에 사용해야 합니다.
  • POST메서드는 요청마다 새로운 리소스를 생성하고 PUT메서드는 요청마다 같은 리소스를 반환합니다. 이렇게 매 요청마다 같은 리소스를 반환하는 특징을 멱등(idempotent)하다고 합니다. 그렇기 때문에 멱등성을 가지는 메서드 PUT과 그렇지 않은 메서드 POST를 구분하여 사용해야 합니다.
  • PUT은 교체, PATCH는 수정의 용도로 사용합니다.

5. REST 성숙도 모델 - 3단계

마지막 단계에는 HATEOAS(Hypertext As The Engine Of Application State)라는 약어로 표현되는 하이퍼미디어 컨트롤을 적용합니다. 3단계의 요청은 2단계와 동일하지만 응답에는 리소스의 URI를 포함한 링크 요소를 삽입해야합니다.

6. Open API와 API KEY

Open API 는 정부에서 제공하는 공공데이터처럼 누구에게나 열려있는 API입니다. 하지만 API마다 정해진 이용 수칙이 있고, 그 이용 수칙에 따라 제한 사항(가격, 정보의 제한 등)이 있을 수 있습니다.

API Key 는 API를 호출하는 앱이나 사이트를 식별합니다. API Key가 필요한 경우에는 로그인한 이용자에게 자원에 접근할 수 있는 권한을 API Key의 형태로 제공하고, 데이터를 요청할 때 API Key를 같이 전달해야 원하는 응답을 받을 수 있습니다.


7. 포스트맨 사용하기

HTTP로 소통하기 위해서는 API 서버의 endpoint가 URL로 주어져야 합니다.

1. GET 요청하기

다음과 같은 API 문서가 있다고 가정해보겠습니다.

URL
http://3.36.72.17:3000/

메시지 조회

Request
GET /kimcoding/messages
[요청]kimcoding이 작성한 모든 메시지를 조회합니다.

추가적인 파라미터를 사용할 수 있습니다.

parameter형식설명필수 포함 여부
roomname방 이름(문자열)특정roomname만 조회필수 아님

Response
응답은 다음과 같은 형식입니다.

[
  {
  	"id": 1,
    "username": "김코딩",
    "text": "안녕하세요",
    "roomname": "로비",
    "date": "2021-04-02 12:00:00"
  }
  // ... 여러개의 메시지
]

메시지에서 사용하는 속성은 다음과 같습니다.

parameter형식설명
id숫자고유한 아이디
username문자열사용자 이름
text문자열사용자 이름
roomname문자열방 이름
date문자열작성한 시간
  • Postman 화면 보기
    다음 그림을 보고 포스트맨의 화면 구성을 확인합니다.
  1. 새로운 탭 오픈
    • 요청/응답을 여러 개 확인할 수 있습니다.
  2. HTTP 메서드 선택
    • GET, POST, DELETE 등과 같은 메서드 중 하나를 선택합니다.
      • API 문서 상 GET메서드를 사용하므로, GET으로 선택합니다.
  3. URL 입력 창
    • URL과 Endpoint를 입력합니다.
      • API 문서에 따르면 http://3.36.72.17:3000/kimcoding/messages와 같이 입력하면 됩니다.
  4. HTTP 요청 버튼
    • 요청을 보냅니다.
  5. HTTP 요청 시 설정할 수 있는 각종 옵션
    • 추가적인 파라미터나, 요청 본문(body)을 추가할 수 있습니다.
      • API 문서에서 확인할 수 있듯이, roomname이라는 파라미터를 사용할 수 있습니다. 필수는 아니지만, 파라미터를 사용하려면 Params탭의 KEY, VALUE에 각각 roomname과 필요한 값을 입력합니다.
  6. HTTP 응답 화면
    • 요청을 보낸 후 응답을 확인하세요.

2. POST 요청하기

POST 요청은 GET요청과 다르게 본문(body) 을 포함하는 경우가 많습니다.
다음과 같은 API 문서가 있다고 가정해보겠습니다.

URL
http://3.36.72.17:3000/

메시지 추가

Request
POST /kimcoding/messages
[요청]kimcoding이 새로운 message를 작성합니다.

요청 본문(body)에는 다음의 내용을 반드시 포함해야 합니다.

  • 요청 형식: JSON
    parameter형식설명
    username문자열사용자 이름
    text문자열본문 내용
    roomname문자열방 이름

Response
응답은 다음과 같은 JSON 형식입니다.

{
	"id": 5
}

id는 숫자 형식이며, 새로 생성된 메시지의 고유한 ID값입니다.

다음 이미지를 참고하여 POST 요청에 본문을 함께 보냅니다.

  1. 본문의 형식 선택(1)
    • JSON형식으로 보낸 때에는, raw를 선택합니다.
  2. 본문의 형식 선택(2)
    • 보낼 형식에 맞게 정확한 타입을 선택합니다.
      • JSON 형식으로 보낼 때에는 JSON을 선택합니다.
      • 앞서 1번 및 2번 과정은 HTTP 요청 헤더 에 다음과 같이 작성하는 것과 동일합니다.
        Content-type: applicaion/json
  3. 본문 내용
    • 본문을 입력합니다. 앞서 JSON을 선택했으므로, 유효한 JSON을 적어주어야 합니다.
      • API문서에 따르면, username, text, roomname을 형식에 맞게 적어주어야 합니다.

모든 요청 본문 입력이 완료되었다면, 요청을 보냅니다. URL과 Endpoint, 그리고 HTTP 메서드를 정확하게 입력했는지 확인하세요.

  • Endpoint
    http://3.36.72.17:3000
    • root-endpoint(혹은 root-URL): API로 요청을 서버와 통신할 때, 서버가 요청을 수락하는 시작점을 뜻합니다.
      Github API의 root-endpoint는 http://api.github.com이고, 트위터 API의 root-endpoint는 http://api.twitter.com입니다. 일반적으로 root-endpoint는 도메인 주소의 루트(/)를 가리킵니다.
    • path : path(또는 usl-path)는 API를 통해 서버와 통신할 때, 서버와 통신할 수 있는 key역할을 합니다. 서버에 정의된 문자열에 따라 path가 달라집니다. 예를 들어, http://api.github.com/user에서는 user가 path 입니다.

마무리

Q. 영화 예매 사이트 개발 시 API를 작성하며 잔여 좌석을 확인하는 GET/inquiry라는 엔드포인트에서 준수하지 않은 REST원칙은 무엇인가?
A. 엔드포인트에 좌석에 대한 리소스를 지칭하지 않았다.

Q. 트위터 웹사이트를 기획 시 트윗 목록을 보여주기 위해 무한 스크롤을 이용해 추가적인 트윗을 불러오려고 합니다. 이때 추가적인 트윗을 불러오기 위한 엔드포인트(endpoint)는 무엇인가?
A. GET/tweets?offset=10&limit=10
HTTP 메서드는 GET이 적합하며, 엔드포인트는 응답을 통해 받게 되는 리소스가 무엇인지 알려주는 명확한 명사 형태로 작성하는 것이 적절합니다.
수십, 수백개의 트윗을 한꺼번에 응답으로 받기에는 상당한 양의 payload가 전달되므로, 페이지네이션(pagination)을 이용해 트윗 목록을 끊어주는 게 좋습니다. 예를 들어 총 120개의 트윗 중 인덱스가 10~20인 트윗, 즉 열 개의 트윗만 가져온다고 가정했을때 관습적으로 사용되는 Query Parameter는 offset, limit으로 이 경우 offset=10&limit=10으로 해당 트윗을 가져올 수 있습니다.

Q. 영화 예매를 위한 요청과 응답입니다. 응답을 REST 원칙에 맞게 수정하세요.

// 요청
POST /seats/g10 HTTP/1.1
[헤더 생략]
{ "user": "kimcoding" }


// 정상 응답
HTTP/1.1 200 OK
[헤더 생략]
{ "message": "예약이 성공적으로 진행되었습니다"}


오류 응답
HTTP/1.1 409 Conflict
[헤더 생략]
{ 
  "message": "예약에 실패했습니다",
  "seat" : "g10",
  "status": "다른 사용자에 의해 예약됨"
 }

A.
예약을 진행한다는 것은 "POST 요청에 의해 새로운 예약 정보가 생성되는 것"을 의미하므로, 정상 응답 코드는 201 Created가 적합합니다.
또한 MDN의 201 Created에 대한 내용에 따르면 정상적으로 생성된 리소스에 대한 내용을 응답 메시지의 본문(body)에 포함할 것을 안내하고 있습니다. 이는 REST원칙에도 부합하며, 어떤 리소스에 영향을 끼쳤는지를 보다 명시적으로 설명할 수 있게 됩니다.

// 정상응답
HTTP/1.1 201 Created
[헤더 생략]
{ "message": "예약이 성공적으로 진행되었습니다",
  "seat": "g10",
  "user": "kimcoding"
}

Q. 게시판에서 10번 게시물을 삭제하는 엔드포인트를 작성하세요.
A. DELETE/articles/10
삭제는 DELETE메서드를 사용하는 것이 적절합니다.

Q. query parameter와 path parameter의 차이는?
A. path paremeter는 GET/people은 정제되지 않은 데이터를 호출하는 반면에 query parameter는 GET/student?age=25처럼 필터링을 통해 정제된 데이터를 호출할 수 있습니다.

0개의 댓글