19. [HTTP/네트워크] 실습

문도연·2022년 6월 10일
1

Chapter1. REST API
1-1. REST API 디자인
1-2. REST 성숙도 모델 - 0단계
1-3. REST 성숙도 모델 - 1단계
1-4. REST 성숙도 모델 - 2단계
1-5. REST 성숙도 모델 - 3단계
1-6. Open API와 API Key
Chapter2. Postman
2-1. Postman 사용하는 방법
2-2. Postman으로 API 테스트하기
2-3. Postman으로 날씨 받아오기


Chapter1. REST API

클라이언트와 서버가 HTTP 통신을 할 때는 어떤 요청을 보내고 받느냐에 따라 HTTP 메서드의 사용이 달라짐
메서드 사용은 아무런 규칙 없이 이루어지는 것이 아님.
요청과 응답을 할 때, '제대로 보내고 받을 수 있는' 일종의 규약이 존재함

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

1-1. REST API 디자인

REST

“Representational State Transfer”의 약자
웹(http)의 장점을 최대한 활용할 수 있는 아키텍처로써 처음 소개됨

REST API

웹에서 사용되는 데이터나 자원(Resource)을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식

REST API 디자인 잘 짜야 하는 이유

  • 클라이언트는 식당에서 메뉴판을 보고 식사를 주문하듯 서버에 요청하고, 서버는 이에 대한 응답을 메뉴판에 있는 사진이나 음식에 대한 설명처럼 클라이언트에게 전송하게 됨

  • 즉, HTTP 프로토콜을 기반으로 요청과 응답에 따라 리소스를 원활하게 주고받기 위해서는 모두가 알아보기 쉽고 잘 작성된 메뉴판이 필요하고, 이 역할을 API가 수행 하므로 같이 일하는 개발자, 유저가 잘 알아볼 수 있도록 작성하는 것이 중요함

REST API를 디자인하는 방법 : REST 성숙도 모델(RMM)

  • 로이 필딩이 REST 방법론(REST API 작성시 지켜야 할 몇가지 규칙) 제시
    • 레오나르드 리차드슨이 이를 더 실용적으로 적용하기 위한 REST 성숙도 모델만듦
단계설명
3단계HATEOAS 원칙 준수
2단계HTTP 메소드 원칙 준수
1단계개별 리소스와의 통신 준수
0단계HTTP 사용
  • REST 성숙도 모델은 총 4단계(0~3단계)로 나뉨
    • 로이 필딩은 이 모델의 모든 단계를 충족해야 REST API라고 부를 수 있다고 주장
    • 그러나 실제로 3단계까지 지키기 어렵기 때문에 2단계까지만 적용해도 좋은 API 디자인이라고 볼 수 있고, 이런 경우를 HTTP API 라고도 부름

퀴즈

REST API는 웹에서 사용되는 데이터나 자원(Resource)을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식입니다.


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

  • 0단계는 REST API를 작성하기 위한 기본 단계
  • 0단계에서는 단순히 HTTP 프로토콜을 사용하기만 해도 되지만 이 경우, 해당 API를 REST API라고 할 수는 없음

0단계 예시 : 주치의 예약

요청내용요청응답
예약가능시간 확인POST/appointment HTTP/1.1
{
"date":"2022-06-10",
"doctor":"문도연"
}
HTTP/1.1 200 OK {
"slots":[ {"doctor:"문도연","start":"09:00", "end":"12:00"},
{"doctor:"문도연","strat":"14:00","end":"16:00"} ]
}
특정시간 예약POST/appointment HTTP/1.1
{
"doctor":"문도연",
"start":"14:00",
"end":"15:00",
"patient":"문하림"
}
HTTP/1.1 200 OK

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

1단계에서는 개별 리소스(Resource)와의 통신을 준수해야 함

REST API는 웹에서 사용되는 모든 데이터나 자원(Resource)을 HTTP URI로 표현함.

따라서 모든 자원은 개별 리소스에 맞는 엔드포인트(Endpoint)를 사용해야 하고 요청하고 받는 자원에 대한 정보를 응답으로 전달해야 하는 것이 1단계의 핵심

1단계 예시 : 주치의 예약(성공)

0단계에서는 요청에서의 엔드포인트로 모두 /appointment를 사용함
-> 하지만 1단계에서는 요청하는 리소스가 무엇인지에 따라 각기 다른 엔드포인트로 구분하여 사용

요청내용요청응답(따옴표 생략)
예약가능시간 확인POST /doctors/문도연 HTTP/1.1
{"date":"2022-06-10"}
HTTP/1.1 200 OK
{slots[{id:123, doctor:문도연 start:09:00, end:12:00},
{id:124, doctor:문도연, start:14:00, end:16:00}]}
특정 시간에 예약POST /slots/123 HTTP/1.1
{ "patient":"문하림" }
HTTP/1.1 200 OK
{appointment : {slot:{id:123,doctor:문도연,...], patient:문하림}
  • ' 예약 가능한 시간 확인' 요청 시 /doctors/허준이라는 엔드포인트를 사용
  • '특정 시간에 예약'이라는 요청에서는 /slots/123를 엔드포인트로 사용
    ->특정 시간에 예약하게 되면, 실제 slots라는 리소스의 123이라는 id를 가진 리소스가 변경되므로, 해당 요청에서는 실제 변경되는 리소스를 엔드포인트로 사용

이처럼 어떤 리소스를 변화시키는지 혹은 어떤 응답이 제공되는지에 따라 각기 다른 엔드포인트를 사용하기 때문에, 적절한 엔드포인트를 작성하는 것이 중요함

  • 엔드포인트 작성 시 동사, HTTP 메서드, 혹은 어떤 행위에 대한 단어 사용은 지양하고, 리소스에 집중해 명사 형태의 단어로 작성하는 게 좋음

응답으로서, 리소스를 전달할 때에도 사용한 리소스에 대한 정보와 함께 리소스 사용에 대한 성공/실패 여부를 반환해야 함

1단계 예시 : 주치의 예약(실패)

요청내용요청응답
예약가능시간 확인POST /doctors/문도연 HTTP/1.1
{"date":"2022-06-10"}
HTTP/1.1 200 OK
{"slots"[{id:123, doctor:문도연 start:09:00, end:12:00},
{id:124, doctor:문도연, start:14:00, end:16:00}]}
특정 시간에 예약POST /slots/123 HTTP/1.1
{ patient:문하림 }
HTTP/1.1 499 Conflict
{appointmentFailure :
{slot:{id:123,doctor:문도연,...], patient:문하림, reason:해당 시간은 이미 예약돼 있어요}

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

CRUD에 맞게 적절한 HTTP 메서드를 사용하는 것이 2단계의 핵심

  • 예약 가능한 시간을 확인한다는 것은 예약 가능한 시간을 조회(READ)하는 행위를 의미함
    • GET 메서드_ body를 갖지 않으므로 query parameter를 사용하여 필요한 리소스를 전달해야 함
  • 특정 시간에 예약한다는 것은 해당 특정 시간에 예약을 생성(CREATE)하는 것과 같음
    • POST 메서드_ POST 요청에 대한 응답이 어떻게 반환되는지가 중요함
      ->이 경우 응답은 새롭게 생성된 리소스를 보내주게 되므로, 응답 코드는 201 Created 로 명확하게 작성해야 함.
      -> 또한,클라이언트가 Location 헤더에 작성된 URI를 통해 관련 리소스를 확인할 수 있도록 해야 함
요청내용요청응답
예약가능시간 확인GET /doctors/문도연/slots?date=2022-06-10 HTTP/1.1HTTP/1.1 200 OK
{"slots"[{id:123, doctor:문도연 start:09:00, end:12:00},
{id:124, doctor:문도연, start:14:00, end:16:00}]}
특정 시간에 예약POST /slots/123 HTTP/1.1
{patient:문하림}
HTTP/1.1 201 Created
Location: slots/123/appointment

{appointment : {slot:{id:123,doctor:문도연,...], patient:문하림}

HTTP 메서드 사용 규칙

  • GET 메서드: 서버의 데이터를 변화시키지 않는 요청에 사용해야 함
  • POST 메서드는 요청마다 새로운 리소스를 생성
  • PUT 메서드는 요청마다 같은 리소스를 반환
    -매 요청마다 같은 리소스를 반환하는 특징을 멱등(idempotent)하다고 함. 멱등성을 가지는 메서드 PUT과 그렇지 않은 메서드 POST는 구분하여 사용해야 함
  • PUT 메서드와 PATCH 메서드도 구분하여 사용해야 함. PUT은 교체, PATCH는 수정의 용도로 사용
  • Location : 300 혹은 201 Created 응답일 때 어느 페이지로 이동할지 알려주는 헤더

    API를 작성할 때, REST 성숙도 모델의 2단계까지 적용하면 대체적으로 잘 작성된 API라고 함
    REST 성숙도 모델의 3단계까지 적용한 경우는 드뭄.
    -> 따라서 3단계까지 무조건적으로 모두 적용해야 하는 것은 아님

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

3단계는 HATEOAS(Hypertext As The Engine Of Application State)라는 약어로 표현되는 하이퍼미디어 컨트롤을 적용함

요청은 2단계와 동일하지만, 응답에는 리소스의 URI를 포함한 링크 요소를 삽입하여 작성해야 함
-> 이때 링크 요소는 응답을 받은 다음에 할 수 있는 다양한 액션들을 위해 많은 하이퍼미디어 컨트롤을 포함

3단계 예시

요청내용요청응답
예약가능시간 확인GET /doctors/문도연/slots?date=2022-06-10 HTTP/1.1HTTP/1.1 200 OK
{"slots":[{id:123, doctor:문도연 start:09:00, end:12:00},
{id:124, doctor:문도연, start:14:00, end:16:00}],
"links":{"appointment":
{"href":http://localhost:8080/slots/123,
"method":POST
}}
}
특정 시간에 예약POST /slots/123 HTTP/1.1
{patient:문하림}
HTTP/1.1 201 Created
Location: slots/123/appointment
{appointment :
{slot:{id:123,doctor:문도연,...], patient:문하림},
links:
{self:{href:http://localhost:8080/slots/123, method:GET},
cancel:
{href:http://localhost:8080/slots/1223, method:DELETE
}}
}
  • 이렇게 응답 내에 새로운 링크를 넣어 새로운 기능에 접근할 수 있도록 하는 것이 3단계의 핵심 포인트

1-6. Open API와 API Key

Open API

글자 그대로 누구에게나 열려있는 API
그러나 "무제한으로 이용할 수 있다"라는 의미는 아님.
API마다 정해진 이용 수칙이 있고, 그 이용 수칙에 따라 제한사항(가격, 정보의 제한 등)이 있을 수 있음.

ex) 정부는 Open API의 형태로 공공데이터를 제공하고 있음 _ 공공데이터 포털
ex) 날씨 API Open Weather Map

  • 제한적이나마 무료로 날씨 API를 사용할 수 있습니다.
    • 프리 플랜에서는 기본적으로 분당 60번, 달마다 1백 번 호출이 가능합니다.
  • 데이터를 JSON 형태로 응답합니다.

API Key

API를 이용하기 위해서는 API Key가 필요함
API key는 서버의 문을 여는 열쇠임
-> 서버를 운용하는 데에 비용이 발생하기 때문에 서버 입장에서 아무런 조건 없이 익명의 클라이언트에게 데이터를 제공할 의무는 없음 (가끔 API key가 필요하지 않은 경우도 있음)

->API Key가 필요한 경우에는 로그인한 이용자에게 자원에 접근할 수 있는 권한을 API Key의 형태로 제공함. 이용자는 데이터를 요청할 때 API key를 같이 전달해야 원하는 응답을 받을 수 있음


Chapter2. Postman

웹 개발에서 대표적인 클라이언트는 브라우저임
브라우저는 서버에 HTTP 요청을 보낼 수 있는 훌륭한 도구이지만, 주로 웹 페이지를 받아오는 GET 요청에 사용함

브라우저의 주소창에 URL을 입력하면, 해당 URL의 root-endpoint로 GET 요청을 보냅니다. 테스트를 위해 GET 요청이 아닌 다른 요청을 보내려면, 개발자 도구의 콘솔 창에서 Web API fetch를 사용해야 함

HTTP 요청을 테스트할 수 있는 다양한 API 테스트 도구들이 있음. 이러한 API 테스트 도구는 클라이언트 입장에서 서버 API를 테스트하거나, API를 만드는 과정에서 매우 유용함

  • Postman을 사용하는 방법에 대해 이해할 수 있다.
  • Postman으로 API를 테스트 할 수 있다.
  • Postman으로 날씨를 받아올 수 있다.

2-1. Postman 사용하는 방법

HTTP API 테스트 도구 (CLI)

  • curl (대부분의 리눅스 환경에 내장되어 있습니다.)
  • wuzz

HTTP API 테스트 도구 (GUI)

  • Postman
  • Insomnia

2-2. Postman으로 날씨 받아오기

api.openweathermap.org/data/2.5/weather?id=1835848&appid={your api key}


과제

  • Endpoint
    root-endpoint(혹은 root-URL): API로 요청을 서버와 통신할 때, 서버가 요청을 수락하는 시작점을 뜻합니다.

  • path
    path(또는 url-path)는 API를 통해 서버와 통신할 때, 서버와 통신할 수 있는 key 역할을 합니다. 서버에 정의된 문자열에 따라 path가 달라집니다.


종합퀴즈

☝🏻 영화 예매 사이트를 개발한다. API를 작성하며 잔여 좌석을 확인하는 GET /inquiry라는 엔드포인트가 REST 원칙을 준수하지 않았다는 지적을 받았다면, 이유는?

  • -> 엔드포인트에 좌석에 대한 리소스를 지칭하지 않았기 때문이다.
  • 잔여좌석을 확인하기 위한 요청의 HTTP 메서드는 GET을 사용하는 것이 적절합니다.
  • 엔드포인트에는 리소스를 지칭하는 명사 사용이 권장되며, 해당 엔드포인트 inquiry는 명사이긴 하나 행위에 대한 명사형이기 때문에 권장되지 않습니다.

☝🏻 요리 레시피를 제공하는 웹사이트, 냉장고에 있는 재료 목록을 조회해야 한다면, 올바른 엔드포인드?

  • GET /ingredient

☝🏻 트위틀러 웹사이트의 기획을 전달받았다. 데이터베이스에는 트윗이 너무 많으므로, 트윗 목록을 보여주기 위해 무한 스크롤을 이용해 추가적으로 트윗을 불러오려고 함. 추가적인 트윗을 불러오기 작성해야 할 엔드포인트?

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

☝🏻 위치 기반 맛집 탐색 앱의 기획을 전달받은 개발자
-> 특정 위치 기반의 모든 식당 목록을 조회하고, 그중 한식만 필터링하는 기능이 추가됨. 요청을 수행하기에 알맞은 엔드포인트(endpoint)?

  • GET /restaurants?coordinate=126.9178889,37.5561619&type=korean
    • 리소스 요구사항은 식당 목록이므로, 엔드포인트만 보고도 식당 목록이 응답으로 전달될 것을 예상할 수 있도록 이름을 짓는 것이 좋음
    • 추가적으로 필터링을 위해서 해당 리소스의 필터링 조건을 Query Parameter로 전달하는 것이 바람직함
      ->type=korean
    • 위치 기반의 식당이므로 특정 반경의 중심이 될 만한 좌표(coordinate)를 Query Parameter로 제공했으며, 이 역시도 필터링의 한 방법임

☝🏻 도서 검색 사이트에서 도서 제목을 바탕으로 검색 기능을 구현하고자 함. 요청이 REST 원칙에 적합하도록 하려면?

요청
GET /books
[헤더 생략]

{ "query": { "title": "code" } }


정상 응답
HTTP/1.1 200 OK
[헤더 생략]
{
	"books": [
		{ "isbn": "9780132350884", "title": "Clean Code", "author": "Robert C.Martin", "price": "$42.47" },
      { "isbn": "0735619670", "title": "Code Complete", "author": "Steve McConnell", "price": "$24.17" }
	]
}

도서 제목을 바탕으로 검색하는 기능을 구현한다는 것은 GET 요청을 사용하여 데이터를 조회하는 것을 의미

  • GET 요청의 경우 body가 존재하지 않기 때문에 이를 Query Parameter를 이용하여 구현해야 함

☝🏻 영화 예매를 위한 요청과 응답

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


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


오류 응답
HTTP/1.1 409 Conflict
[헤더 생략]
{ 
  "message": "예약에 실패했습니다",
  "seat" : "g10",
  "status": "다른 사용자에 의해 예약됨"
 }
  • 예약을 진행한다는 것은 "POST 요청에 의해 새로운 예약 정보가 생성되는 것"을 의미하므로, 정상 응답 코드는 201 Created가 적합합니다.
  • MDN의 201 Created에 대한 내용에 따르면, 정상적으로 생성된 리소스에 대한 내용을 응답 메시지의 본문(body)에 포함할 것을 안내하고 있습니다. 이는 REST 원칙에도 부합하며, 어떤 리소스에 영향을 끼쳤는지를 보다 명시적으로 설명할 수 있게 됩니다.
  • 오류 응답이 있더라도, 서비스를 사용할 수 없는 것이 아니므로 503 Service Unavailable은 부적절하며, 응답 메시지의 영문/한글 여부는 전혀 상관이 없습니다.

☝🏻 게시판에서 10번 게시물을 삭제하는 엔드포인트를 작성한다면?

  • DELETE /articles/10
    • 엔드포인트에서 어떤 리소스를 삭제하는지 명시하는 것이 적절
profile
중요한건 꺾이지 않는 마음이 맞는 것 같습니다

0개의 댓글