REST API와 REST 성숙도 모델

Erin A. Yoo·2022년 10월 5일
0
post-thumbnail

🔵API란?

REST API에 대해 설명하기 전, API가 무엇인지 잠깐 훑고 가겠다.

클라이언트는 원하는 정보/기능에 접근하기 위해 일종의 명령 메뉴얼이 필요하다. 서버는 이 메뉴얼을 제공하는데, 이를 API(Application Programming Interface)라고 한다. 이 말이 잘 이해가 안간다면 아래 예시를 보자.

최근 장을 보러갔는데 무 가격때문에 놀랐던게 갑자기 생각나서 무를 예시로 들겠다. 요새 동물의숲 무트코인 마냥 현실 무값도 굉장히 올랐는데, 오늘 무 요리를 하기 위해 무를 사야한다고 가정해보자. 나의 전재산이 1000원밖에 없어서 무가 그보다 비싸면 살 수 없기 때문에 서버를 통해 데이터베이스(무 현재 가격)에 접근해 오늘 무를 살지 말지 결정하려고 한다.

그런데 서버한테 "님 오늘 무 얼마임?"라고 물어봐야 할지, "금일 무의 개당 시세는 얼마입니까?"라고 물어봐야 할지 모른다. 이 상황에서 API는 무 가격을 확인할 수 있는 올바른 방법을 지정해 준다. 서버에서 무 값을 확인하기 위해서 "오늘 무값 알려줘"라고 말해야 한다고 API가 정해줬다고 가정하면 나는 서버에 문장 그대로 물어보면 된다.


🔵REST API

REST(Representational State Transfer) API는, 로이 필딩(엄청 유명한 컴퓨터 공학자)의 논문에서 처음 소개 되었다. REST API는 웹에서 사용되는 데이터/자원을 HTTP URI로 표현하고, HTTP 프로토콜을 통해 요청과 응답을 정의하는 방식을 말한다.


🔵REST 성숙도 모델

REST 성숙도 모델은 레너드 리처드슨(REST API 전문가)에 의하여 창시되었으며, 0-3단계가 있다. 좋은 REST API를 만들기 위해서는 이 모델을 참조하면 된다.

다음은 각 단계를 알아보자.


🟣 0단계

클라이언트와 서버의 request/response 과정에서 HTTP 프로토콜을 사용하기만 하면 0단계는 충족된다.


성숙도 모델의 0단계를 적용한 병원 예약 예시의 그래프다. 해당 예시는 3단계 까지 계속 쓰인다.


🔴클라이언트의 HTTP 메세지(request message): 예약 가능 슬롯 요청

POST /appointmentService HTTP/1.1
[various other headers]

<openSlotRequest date = "2010-01-04" doctor = "mjones"/>

클라이언트(정보 요청자)는 mjones라는 의사에게 진찰을 받고싶어 한다.
클라이언트는 위 HTTP 메세지를 통해 예약 가능한 시간대 슬롯을 요청하고 있다.
/appointmentService라는 엔드포인트를 이용해 필요한 정보에 접근한다.

🔴서버의 HTTP 메세지(response message): 예약 가능 슬롯 리턴

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot start = "1400" end = "1450">
    <doctor id = "mjones"/>
  </slot>
  <slot start = "1600" end = "1650">
    <doctor id = "mjones"/>
  </slot>
</openSlotList>

서버(응답자)는 예약 가능한 슬롯들을 XML 형식으로 리턴해주고 있다.
예시에서 XML을 사용하였을 뿐, 그 이외의 다른 형태의 정보(JSON 등)여도 상관없다.


⚫클라이언트의 HTTP 메세지(request message): 예약 요청

HTTP/1.1 200 OK
[various headers]

<appointment>
  <slot doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

클라이언트 jsmith는 예약하고 싶은 슬롯을 골라서 정보를 보낸다.

⚫서버의 HTTP 메세지(response message): 예약 확인

HTTP/1.1 200 OK
[various headers]

<appointment>
  <slot doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

서버는 jsmith가 원하는 슬롯에 예약이 되었다고 응답한다.


🟣 1단계

개별 리소스와의 통신을 준수해야 한다. REST API는 웹상의 모든 데이터/자원을 HTTP URI로 표현하는데, 모든 자원은 특정 데이터/자원에 맞는 엔드포인트를 사용해야 하며 요청/전달되는 데이터/자원에 대한 정보를 응답으로 전달해야 한다.

이전 0단계 예시에서는 예약 슬롯의 요청과 슬롯을 골라 예약하는 과정 모두 /appointmentService라는 단일 엔드포인트를 사용하였다. 그러나 REST Maturity Model의 1단계에선 두 리소스에 접근하는 엔드포인트를 구분해야 한다.


🔴클라이언트의 HTTP 메세지(request message): 예약 가능 슬롯 요청

POST /doctors/mjones HTTP/1.1
[various other headers]

<openSlotRequest date = "2010-01-04"/>

mjones라는 의사는 그 의사만의 리소스를 가지고 있으며, 0단계에서 모든 request에 동일한 엔드포인트를 사용했음과 대비, 엔드포인트도 '/doctors/mjones' 로 개별화 된다.

🔴서버의 HTTP 메세지(response message): 예약 가능 슬롯 리턴

HTTP/1.1 200 OK
[various headers]


<openSlotList>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>
</openSlotList>

리턴되는 슬롯도 아이디가 부여되어 개별화 되어있는데 이 아이디는 밑 예시인 예약 요청 endpoint에 사용된다.


⚫클라이언트의 HTTP 메세지(request message): 예약 요청

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
  <patient id = "jsmith"/>
</appointmentRequest>

역시 id가 1234인 슬롯을 예약하기 위해 그 슬롯만을 위한 엔드포인트인 '/slots/1234' 를 사용하고 있다.

⚫서버의 HTTP 메세지(response message): 예약 확인

HTTP/1.1 200 OK
[various headers]

<appointment>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

예약이 되었다는 응답을 주고 있다.


🟣 2단계

2단계에서는 HTTP 문법을 사용해야 한다. 이는 CRUD에 맞는 HTTP 메소드 사용이다.
0단계, 1단계 에서는 모든 요청에 POST를 사용했지만 2단계 에서는 실행하는 동작에 따라 다른 메소드를 사용한다.


🔴클라이언트의 HTTP 메세지(request message): 예약 가능 슬롯 요청

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

이전에는 정보 요청에도 POST 메소드를 사용하였지만, 이제는 정보를 요청(CRUD 중 READ)하는 동작에 맞게 GET 메소드를 쓰고 있다.

🔴서버의 HTTP 메세지(response message): 예약 가능 슬롯 리턴

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/>
</openSlotList>

response는 이전 단계와 같다.


⚫클라이언트의 HTTP 메세지(request message): 예약 요청

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
  <patient id = "jsmith"/>
</appointmentRequest>

예약을 요청하는 HTTP request는 이전과 같이 POST 메소드를 사용하고 있다. 슬롯의 예약 여부 정보를 생성(CRUD 중 CREATE) 해주어야 하기 때문이다.

⚫서버의 HTTP 메세지(response message): 예약 확인

HTTP/1.1 201 Created
Location: slots/1234/appointment
[various headers]

<appointment>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
</appointment>

예약이 되었다는 응답을 주고 있다. 여기서 201이 뜨는데, 이 HTTP 코드 속성에는 나중에 누군가 GET 메소드로 해당 정보를 읽어올 수 있게 위치 속성이 포함된다.


🟣 3단계

REST API Maturity Model의 마지막 단계인 3단계에서는 HATEOAS(Hypertext As The Engine Of Application State)라는 개념이 등장한다. 이 개념을 활용한 3단계 에서는 리턴되는 정보가 추가적인 URI를 포함해야만 한다.


🔴클라이언트의 HTTP 메세지(request message): 예약 가능 슬롯 요청

GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1
Host: royalhope.nhs.uk

request는 2단계와 같다.

🔴서버의 HTTP 메세지(response message): 예약 가능 슬롯 리턴

HTTP/1.1 200 OK
[various headers]

<openSlotList>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450">
     <link rel = "/linkrels/slot/book" 
           uri = "/slots/1234"/>
  </slot>
  <slot id = "5678" doctor = "mjones" start = "1600" end = "1650">
     <link rel = "/linkrels/slot/book" 
           uri = "/slots/5678"/>
  </slot>
</openSlotList>

그러나 response에 새로운 것이 생겼다. 어떤 URI로 가야 해당 슬롯을 예약할수 있는지의 추가 정보를 담고 있다.


⚫클라이언트의 HTTP 메세지(request message): 예약 요청

POST /slots/1234 HTTP/1.1
[various other headers]

<appointmentRequest>
  <patient id = "jsmith"/>
</appointmentRequest>

레벨 2와 같다.

⚫서버의 HTTP 메세지(response message): 예약 확인

HTTP/1.1 201 Created
Location: http://royalhope.nhs.uk/slots/1234/appointment
[various headers]

<appointment>
  <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/>
  <patient id = "jsmith"/>
  <link rel = "/linkrels/appointment/cancel"
        uri = "/slots/1234/appointment"/>
  <link rel = "/linkrels/appointment/addTest"
        uri = "/slots/1234/appointment/tests"/>
  <link rel = "self"
        uri = "/slots/1234/appointment"/>
  <link rel = "/linkrels/appointment/changeTime"
        uri = "/doctors/mjones/slots?date=20100104&status=open"/>
  <link rel = "/linkrels/appointment/updateContactInfo"
        uri = "/patients/jsmith/contactInfo"/>
  <link rel = "/linkrels/help"
        uri = "/help/appointment"/>
</appointment>

슬롯 정보 response와 같이 이번 response로 추가 URI 정보를 담고있다. 예약 취소, 검사 추가, 시간 변경 등 리턴된 정보에서 파생될 수 있는 추가적인 action을 위한 URI가 있다.

출처: https://martinfowler.com/articles/richardsonMaturityModel.html

1개의 댓글

comment-user-thumbnail
2022년 10월 6일

세상에나 ㄷㄷ
잘보고가욥 :D

답글 달기