[Spring] RESTful API 구현하기-(3) (HATEOAS Richardson 성숙도 모델)

yunSeok·2023년 10월 27일
0

Spring

목록 보기
4/4

그림출처 : manning.com

REST 성숙도 모델은 총 0 ~ 3단계4단계로 나누어집니다.

REST API에 대해서 처음 기술한 로이 필딩(Roy Fielding)은 3단계까지 모두 충족해야 REST API라고 부를 수 있다고 주장했습니다. 로이 필딩은 시스템 전체(클라이언트 + 서버)를 통제할 수 있을 때, 진화에 관심이 없을 때는 꼭 지킬 필요는 없다고 합니다.

사실 실제로 3단계까지 지키기 어렵기 때문에, 2단계까지 사용해도 좋은 API 디자인이라고 볼 수 있고, 이런 경우를 HTTP API라고도 부릅니다.

1. 성숙도 모델 - 0단계

  • 0단계에서는 POST 메소드만 사용가능 하며, 단순히 HTTP body에 정보를 넣어 전송하는 기존 리로스 방식입니다.

  • 일반적으로 원격 프로시저 호출 기반의 자체 원격 상호 작용 메커니즘을 위한 터널링 메커니즘으로 HTTP를 사용하는 것입니다.


✅ 0단계 방식

요청 내용요청응답
예약 시간 확인POST /appointmentService HTTP/1.1HTTP/1.1 200 OK
예약POST /appointmentService HTTP/1.1HTTP/1.1 200 OK
예약 실패POST /appointmentService HTTP/1.1HTTP/1.1 200 OK

◼ 예약 시간 확인

1. 요청

[header]
POST /appointmentService HTTP/1.1

[body]
<openSlotRequest date = "2023-01-04" doctor = "tomas"/>

tomas 라는 의사의 예약 가능 시간 요청합니다.

2. 응답

[header]
HTTP/1.1 200 OK

[body]
<openSlotList>
  <slot start = "1400" end = "1450">
    <doctor id = "tomas"/>
  </slot>
  <slot start = "1600" end = "1650">
    <doctor id = "tomas"/>
  </slot>
</openSlotList>

서버는 요청에 대한 정보를 제공하는 데이터를 반환해줍니다.

◼ 예약 요청

1. 요청

[header]
POST /appointmentService HTTP/1.1 

[body]
<appointmentRequest> 
  <slot doctor = "tomas" start = "1400" end = "1450"/> 
  <patient id = "james"/> 
</appointmentRequest>

james라는 이름으로 tomas 의사에게 14:00 ~ 14:50 진료를 요청합니다.

2. 응답

[header]
HTTP/1.1 200 OK 

[body]
<appointment> 
  <slot doctor = "mjones" start = "1400" end = "1450"/> 
  <patient id = "tomas"/> 
</appointment>

요청에 대한 성공 데이터를 반환해줍니다.

◼ 예약 오류

1. 요청

[header]
POST /appointmentService HTTP/1.1 

[body]
<appointmentRequest> 
  <slot doctor = "tomas" start = "1400" end = "1450"/> 
  <patient id = "james"/> 
</appointmentRequest>

james라는 이름으로 tomas 의사에게 14:00 ~ 14:50 진료를 요청합니다.

2. 응답

[header]
HTTP/1.1 200 OK 

[body]
<appointmentRequestFailure> 
  <slot doctor = "tomas" start = "1400" end = "1450"/> 
  <patient id = "james"/> 
  <reason>예약이 마감되었습니다.</reason> 
</appointmentRequestFailure>

요청 실패에대한 데이터를 메시지로 반환해줍니다.

📌정리
0단계에서는 요청과 응답, 오류의 코드가 항상 같고, 메시지를 통해 오류를 전달해주게됩니다.

2. 성숙도 모델 - 1단계

  • 1단계로 0단계처럼 POST 메소드 하나밖에 사용하지 않지만, 자원을 HTTP URI로 표현할 때 해당 리소스에 맞는 엔드포인드(Endpoint)를 사용합니다.

  • POST 메소드로 복잡한 기능을 여러 리소스로 분산시킨다는 점에서 한 단계 발전된 형태라고 볼 수 있습니다.

✅ 1단계 방식

요청 내용요청응답
예약 시간 확인POST /doctors/tomas HTTP/1.1HTTP/1.1 200 OK
예약POST /slots/1234 HTTP/1.1HTTP/1.1 200 OK

◼ 예약 시간 확인

1. 요청

[header]
POST /doctors/tomas HTTP/1.1

[body]
<openSlotRequest date = "2023-01-04" doctor = "tomas"/>

요청할때 개별 리소스 엔드포인트(/doctors/tomas)를 사용해 tomas 라는 의사의 예약 가능 시간 요청합니다.

2. 응답

[header]
HTTP/1.1 200 OK

[body]
<openSlotList> 
  <slot id = "1234" doctor = "tomas" start = "1400" end = "1450"/> 
  <slot id = "5678" doctor = "tomas" start = "1600" end = "1650"/> 
</openSlotList>

개별 슬롯의 아이디는 고유의 주소를 담고있습니다.

◼ 예약 요청

1. 요청

[header]
POST /slots/1234 HTTP/1.1

[body]
<appointmentRequest> 
  <patient id = "james"/> 
</appointmentRequest>

마찬가지로 엔트포인트를 이용하여 요청을 하게됩니다.

2. 응답

[header]
HTTP/1.1 200 OK 

[body]
<appointment> 
  <slot id = "1234" doctor = "tomas" start = "1400" end = "1450"/> 
  <patient id = "james"/> 
</appointment>

리소스 주소에 맞는 데이터에 대한 응답을 해줍니다.

📌 정리
해당 리소스에 맞는 엔드포인드(Endpoint)를 사용해 요청과 응답을 진행한다.

3. 성숙도 모델 - 2단계

  • 1단계까지는 모든 요청을 POST 메소드 하나만 사용했지만 2단계에서는 CRUD(Create, Read, Update, Delete)에 맞는 적절한 HTTP 메서드를 사용해야합니다.

  • 데이터의 상태를 변화시키지 않는, 동일한 결과를 얻을 수 있는 Read 요청에 GET을 사용하는 것이 중요합니다. GET의 작업은 웹 성능을 향상시키는 핵심 요소인 캐싱을 사용할 수 있도록 해줍니다.

  • 자원을 생성하는 CREATE 요청에는 POST를 사용하고 응답 코드 201로 응답하여 새로운 리소스가 생성되었음을 알립니다. 201 응답에는 생성된 해당 URI 링크 속성이 포함되어 있습니다. 만약 오류가 발생하면 2xx가 아닌 4xx 응답을 사용해야 합니다.

  • PUT은 교체, PATCH는 수정, DELETE는 삭제의 용도로 사용합니다.

✅ 2단계 방식

요청 내용요청응답
예약 시간 확인GET /doctors/tomas/slots?
date=20230104&status=open HTTP/1.1
HTTP/1.1 200 OK
예약POST /slots/1234 HTTP/1.1HTTP/1.1 200 Created
Location: slots/1234/appointment
예약 오류POST /slots/1234 HTTP/1.1HTTP/1.1 409 Conflict
예약 삭제DELETE /slots/1234 HTTP/1.1HTTP/1.1 204 No Content

◼ 예약 시간 확인

1. 요청

[header]
GET /doctors/tomas/slots?date=20230104&status=open HTTP/1.1|HTTP/1.1 200 OK
host : example.com

Read 요청의 경우 GET 메소드를 사용하고, Host 주소를 사용해 요청의 목적지를 명시해줍니다.

2. 응답

[header]
HTTP/1.1 200 OK

[body]
<openSlotList> 
  <slot id = "1234" doctor = "tomas" start = "1400" end = "1450"/> 
  <slot id = "5678" doctor = "tomas" start = "1600" end = "1650"/> 
</openSlotList>

개별 슬롯의 아이디는 고유의 주소를 담고있습니다.

◼ 예약 요청

1. 요청

[header]
POST /slots/1234 HTTP/1.1

[body]
<appointmentRequest> 
  <patient id = "james"/> 
</appointmentRequest>

예약을 하려면 Create의 요청인 PUT 메소드를 사용합니다.

2. 응답 성공

[header]
HTTP/1.1 201 CREATE
location : slots/1234/appointment  

[body]
<appointment> 
  <slot id = "1234" doctor = "tomas" start = "1400" end = "1450"/> 
  <patient id = "james"/> 
</appointment>

POST 메소드의 정상적인 응답에는 201코드인 CREATE로 응답합니다.

3. 응답 실패

[header]
HTTP/1.1 409 Conflict 

[body]
<appointment> 
  <slot id = "5678" doctor = "tomas" start = "1500" end = "1550"/> 
</appointment>

POST 메소드의 응답 실패에는 400번대 코드를 사용해 응답해줍니다.
어떤 코드를 명시해줄건지는 개발자의 몫이지만 적절한 코드를 사용하는 노력이 필요하다고합니다!

📌 정리
요청의 종류에 따라 적절한 메소드를 사용하고, 응답에도 적절한 응답코드를 사용하는 것이 중요하다고 할 수 있겠습니다!

4. 성숙도 모델 - 3단계

  • 마지막 단계에는 HATEOAS(Hypertext As The Engine Of Application State)라는 성숙도 모델의 가장 높은 단계로, 응답안에는 클라이언트가 다음으로 전이될 행동을 링크를 포함하여 응답합니다.

  • 하이퍼미디어 제어의 요점은 우리가 다음에 무엇을 할 수 있는지, 그리고 그것을 하기 위해 조작해야 하는 리소스의 URI를 알려주는 것입니다.

✅ 3단계 방식

◼ 예약 시간 확인

1. 요청

[header]
GET /doctors/tomas/slots?date=20230104&status=open HTTP/1.1|HTTP/1.1 200 OK
host : example.com

2단계에서 사용한 것과 동일한 GET 메소드로 요청을 보냅니다.

2. 응답

[header]
HTTP/1.1 200 OK

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

개별 슬롯에는 URI가 포함된 링크 요소가 포함되어 있어, 다음에 무엇을 할 수 있는지 알려주고, 조작해야 하는 리소스의 URI를 알려줍니다.

◼ 예약 요청

1. 요청

[header]
POST /slots/1234 HTTP/1.1

[body]
<appointmentRequest> 
  <patient id = "james"/> 
</appointmentRequest>

예약을 하려면 Create의 요청인 PUT 메소드를 사용합니다.

2. 응답 성공

[header]
HTTP/1.1 201 CREATE 
location http://example.com/slots/1234/appointment 

[body]
<appointment> 
  <slot id = "1234" doctor = "tomas" start = "1400" end = "1450"/> 
  <patient id = "james"/> 

  <link rel = "/linkrels/appointment/cancel" 
        uri = "/slots/1234/appointment"/> 
  <link rel = "/linkrels/appointment/addTest" 
        uri = "/slots/1234/appointment/tests"/> 
</appointment>

개별 슬롯에는 URI가 포함된 링크 요소가 포함되어 있어, 다음에 무엇을 할 수 있는지 알려주고, 조작해야 하는 리소스의 URI를 알려줍니다.

📌 정리
링크 요소가 중요한 키워드이고 응답되는 각 데이터에서 이동할 수 있는 리소스의 URI를 알려주는 것이 중요하다고 할 수 있습니다.


참고사이트
https://martinfowler.com/articles/richardsonMaturityModel.html
https://velog.io/@starrypro/HTTP%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%8B%A4%EC%8A%B5-REST-API

0개의 댓글