REST API

2022. 4. 21. 16:12Front-End

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

특정 기술을 의미하는 것이 아님!

 

REST 구성

자원 (Resource) - URI

행위 (Verb) - HTTP Method

표현 (Representations)

 

REST의 특징

  • Uniform - HTTP 표준에만 따른다면, 특정 언어나 기술에 종속되지 않고 모든 플랫폼에서 사용할 수 있으며, URI로 지정한 리소스에 대한 조작이 가능한 아키텍처 스타일을 의미합니다.
  • Stateless - REST는 무상태성 성격을 가진다. 작업을 위한 상태정보를 따로 저장하고 관리하지 않고 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리합니다.
  • Cacheable - REST는 HTTP의 기존 웹 표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용할 수 있어 HTTP가 가진 캐싱 기능을 적용할 수 있습니다.
  • Self-Descriptivenss - REST API 메세지만 보고도 쉽게 이해할 수 있는 자체 표현 구조로 되어있습니다.
  • Client-Server - 자원이 있는 쪽이 Server, 자원을 요청하는 쪽이 Client가 됩니다. 서버는 API를 제공하고 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보) 등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로 간 의존성이 줄어들게 됩니다.
  • Layered System - REST 서버는 다중 계층으로 구성될 수 있습니다. API Server는 순수 비즈니스 로직을 수행하고 그 앞단에 보안, 로드밸런싱, 암호화, 사용자 인증 등을 추가하여 구조상의 유연성을 줄 수 있습니다. 또한 로드밸런싱, 공유 캐시 등을 통해 확장성과 보안성을 향상시킬 수 있습니다.

 

좋은 REST API를 디자인하는 방법

레오나르드 리차드슨은 REST API를 잘 적용하기 위한 4단계 모델을 만들었습니다.

REST 성숙도 모델은 총 4단계(0~3단계)로 나누어집니다. 모든 단계를 충족해야 REST API라고 부를 수 있다고 하지만 2단계까지만 적용해도 좋은 API 디자인이라고 볼 수 있습니다.

 

REST 성숙도 모델 - 0단계

// 예약 가능한 시간 확인
// request
POST /appointment HTTP/1.1
{
  "data": "2022-04-21",
  "doctor": "Lee"
}

// response
HTTP/1.1 200 OK
{
	"slots": [
    	{"doctor": "Lee", "start": "09:00", "emd": "12:00"},
        {"doctor": "Lee", "start": "14:00", "emd": "18:00"}
    ]
}

// 특정 시간 예약
// request
POST /appointment HTTP/1.1
{
  "start": "14:00",
  "emd": "15:00",
  "doctor": "Lee",
  "patient": "Kim"
}

// response
HTTP/1.1 200 OK

위 예시에서는 HTTP 프로토콜을 사용하고 있는 것을 확인할 수 있습니다. 이렇듯 단순히 HTTP 프로토콜을 사용하는 것이 REST API의 출발점입니다.

 

REST 성숙도 모델 - 1단계

REST 성숙도 모델에 따르면, 1단계에서는 개별 리소스와의 통신을 준수해야 한다고 합니다.

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

// 예약 가능한 시간 확인
// request
POST /doctor/Lee HTTP/1.1
{
  "data": "2022-04-21",
}

// response
HTTP/1.1 200 OK
{
	"slots": [
    	{"id": 777. "doctor": "Lee", "start": "09:00", "emd": "12:00"},
        {"id": 778, "doctor": "Lee", "start": "14:00", "emd": "18:00"}
    ]
}

// 특정 시간 예약
// request
POST /slots/777 HTTP/1.1
{
  "patient": "Kim"
}

// response
HTTP/1.1 200 OK
{
	"appointment": {
    	"slot": {"id": "777", "doctor": "Lee", ...},
        "patient": "Kim"
    }
}

예시와 같이, 어떤 리소스를 변화시키는지 혹은 어떤 응답이 제공되는지에 따라 각기 다른 엔드포인트를 사용하기 때문에, 적절한 엔드포인트를 작성하는 것이 중요합니다. 엔드포인트 작성 시에는 동사, HTTP 메서드, 혹은 어떤 행위에 대한 단어 사용은 지양하고, 리소스에 집중해 명사 형태의 단어로 작성하는 것이 바람직 방법입니다.

 

REST 성숙도 모델 - 2단계

REST 성숙도 모델 2단계에서는 CRUD에 맞게 적절한 HTTP 메서드를 사용하는 것에 중점을 둡니다. 그리고 2단계에서는 POST 요청에 대한 응답이 어떻게 반환되는지도 중요합니다.

  • GET메서드 같은 경우는 서버의 데이터를 변화시키지 않는 요청에 사용해야 합니다.
  • POST는 요청마다 새로운 리소스를 생성하고 PUT 은 요청마다 같은 리소스를 반환합니다. 
  • PUT은 교체, PATCH는 수정의 용도로 사용합니다.
  • DELETE는 삭제 용도로 사용합니다.
// 예약 가능한 시간 확인
// request
GET /doctor/Lee/slots?date=2022-04-21 HTTP/1.1

// response
HTTP/1.1 200 OK
{
	"slots": [
    	{"id": 777. "doctor": "Lee", "start": "09:00", "emd": "12:00"},
        {"id": 778, "doctor": "Lee", "start": "14:00", "emd": "18:00"}
    ]
}

// 특정 시간 예약
// request
POST /slots/777 HTTP/1.1
{
  "patient": "Kim"
}

// response
HTTP/1.1 201 Created
Location: slots/777/appointment
{
	"appointment": {
    	"slot": {"id": "777", "doctor": "Lee", ...},
        "patient": "Kim"
    }
}

 

REST 성숙도 모델 - 3단계

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

응답 내에 새로운 링크를 넣어 새로운 기능에 접근할 수 있도록 하는 것이 3단계의 중요 포인트입니다.

// 예약 가능한 시간 확인
// request
GET /doctor/Lee/slots?date=2022-04-21 HTTP/1.1

// response
HTTP/1.1 200 OK
{
	"slots": [
    	{"id": 777. "doctor": "Lee", "start": "09:00", "emd": "12:00"},
        {"id": 778, "doctor": "Lee", "start": "14:00", "emd": "18:00"}
    ],
    "links": {
    	"appointment": {
        	"href": "http://localhost:8080/slots/777",
            "method": "POST"
        }
    }
}

// 특정 시간 예약
// request
POST /slots/777 HTTP/1.1
{
  "patient": "Kim"
}

// response
HTTP/1.1 201 Created
Location: slots/777/appointment
{
	"appointment": {
    	"slot": {"id": "777", "doctor": "Lee", ...},
        "patient": "Kim"
    },
    "links": {
    	"self": {
        	"href": "http://localhost:8080/slots/777",
            "method": "GET"
        },
        "cancel": {
        	"href": "http://localhost:8080/slots/777/cancel",
            "method": "DELETE"
        }
    }
}

만약 클라이언트 개발자들이 응답에 담겨 있는 링크들을 눈여겨본다면, 이러한 링크들은 조금 더 쉽고, 효율적으로 리소스와 기능에 접근할 수 있게 하는 트리거가 될 수 있습니다.

'Front-End' 카테고리의 다른 글

CSR과 SSR 이란?  (0) 2022.05.04
브라우저 렌더링  (1) 2022.04.28
CORS(Cross-Origin Resource Sharing) 에러  (0) 2022.04.26
번들링(Bundling)과 번들러(Bundler)  (0) 2022.04.18
React 개념 정리  (0) 2022.04.14