제가 혼자 이해한 개념을 정리한 글입니다! 더 좋은 글이 많으니 꼭 제 글을 참고하시지 않아도 괜찮습니다! 또한 혹시라도 시간내어 읽어보셨으면 제가 잘못 이해한 부분에 대해 댓글로 알려주시면 감사합니다!
또한 해당 글의 내용은 대부분 그런 REST API로 괜찮은가 유튜브 영상을 참고하여 작성하였습니다.
회사에서 로그인 API를 구현하면서 내가 구현하고 있는게 REST API가 맞나? 라는 생각이 들었다. 왜냐하면 REST API는 항상 구현하기 어렵다는 말을 많이 들어왔기 때문에...
사실 REST API를 처음 들었을 때는 몇가지 규칙만 지키면 된다고 들었다. 예를 들어
url은 resource를 표현한다.
HTTP mehtod를 GET, PUT, POST, DELETE, PATCH 등으로 표현한다.
응답 코드는 상태에 맞게 응답한다.
등등...
그저 기존의 HTTP 통신에서 반환만 json으로 하고 mehtod랑 url만 잘 바꿔주면 되겠네? 라는 생각이였지만
그런 REST API로 괜찮은가 유튜브 영상을 한번이라도 봤다면 생각이 달라질 것이다.
우선 REST API를 알아보기 전에 API가 뭔지 생각해보자.
Application Programming Interface
컴퓨터나 컴퓨터 프로그램 사이의 연결. 일종의 소프트웨어 인터페이스이며 다른 종류의 소프트웨어에 서비스를 제공한다.
라고 위키백과에 정의되어 있다. 말 그대로 컴퓨터와 컴퓨터 사이에 데이터를 주고 받을 수 있도록 하나의 소프트웨어가 다른 소프트웨어에 제공하는 서비스 인것이다.
예를들어
나는 웹 개발자로써 백엔드 서버에서 google이나 kakao, naver와 같은 api server를 가진 회사의 api에 url에 요청을 보내고 그에 대한 반환 값을 받는다. 이것은 내가 받았지만 백엔드 서버에서 받아 처리하기 때문에 컴퓨터간의 통신이라고 할 수 있다.
GET /user/1 HTTP/1.1
Host: localhost
HTTP/1.1 200 OK
Content-Type: application/json
{
"code" : "000",
"msg" : "success",
"data" : {
...
}
}
API를 살펴보면 엥? 그래서 내가 생각한 REST API가 저거 맞는데?
하지만 사실 꼭 그럴 필욘 없다. REST API라고 불러도 로이 필딩이 어떻게 할순 없다. 또한 이미 많은 REST API들이 로이 필딩이 정의한 REST에 충족하지 않는 API들이 많이 설계되었고 현재도 이용되고 있다.
카카오 뿐만아니라 MS에서도 로이 필딩이 정의한 REST API에 충족하지 않는 API를 그대로 REST API로 사용하기도 했다.
MS API 설계 하지만 MS도 요즘엔 REST API에 대해 잘 정의해서 사용하고 있는것 같다.
그럼 이제 왜 위의 반환 내용이 REST API가 아닌가에 대해 알아보자.
REST를 정의한 로이 필딩에 의하면 REST는 다음 조건을 모두
만족해야만 REST API라고 말할 수 있다. 이 외의 API들은 제발 REST API라고 부르지 말아달라고 한다.
Resource가 있는 쪽이 Server이고 요청하는 쪽이 Client이다.
서버와 클라이언트는 분리되어 있어야한다.
HTTP 프로토콜을 사용하는 REST API 또한 무상태이다.
클라이언트의 상태를 서버에 저장하지 않는다.
HTTP 프로토콜에서 지원하는 캐시에 대한 기능을 REST API에서도 사용할 수 있다.
클라이언트는 API Server의 응답값을 캐싱할 수 있다.
Client는 REST API Server만 호출한다. REST Server는 다중 계층으로 구성될 수 있다.
REST API는 꼭 데이터만 반환하는 계층만 존재하는게 아닌 인증, 로드 밸런싱, 공유 캐시등을 제공하여 시스템 확장성을 향상시킬 수 있다.
URI로 지정한 Resource에 대한 조작은 통일되고 한정적인 인터페이스로 수행한다.
동일한 api 스펙으로 전송되어야 한다.
Self-descriptive (메세지가 스스로 메세지에 대한 설명이 가능해야한다.)
메세지를 이해하기 위해 필요한 정보가 메세지 자체에 포함되어 있어야한다.
hypermedia as the engine of application state (HATEOAS)
hypermedia로 애플리케이션 상태를 설명해야한다.
클라이언트는 응답 코드를 실행할 수 있다.
기본적으로 위 주요 제약은 대부분 지켜지고 있지만 한가지가 잘 지켜지지 않는다 그건 Uniform interface
에 대한 조건인데. 해당 조건은 대부분의 API에서 찾기 힘들것이다. 물론 동일한 스펙으로 반환한다는 것은 당연히 지켜지는 경우가 많지만 Self-descriptive
이나 HATEOAS
의 경우 잘 지켜지지 않는 API가 많이 있다.
그럼 얘네를 왜 지켜야할까?
우리는 사실 Self-descriptive를 지키지 않아도 api를 사용하기 위해 해당 사이트에서 문서를 찾아보면서 진행하기 때문에 해당 제약을 지키지 않아도 api를 이용할 수 있다. 하지만 문서가 없는 api라면?? 그건 정말 이용할 수 없는 api가 된다. 또한 HATEOAS도 문서에서 모두 읽고 고쳐쓰고 있기 때문에 굳이 없어도 잘 만들어서 동작시킬 수 있다.
그럼 왜 로이 필딩은 왜 이거 안지킬거면 REST API라고 하지 말라고 하는 걸까?
메세지 스스로를 설명하는 방법으로는
첫번째
로 MediaType을 IANA 사이트에 등록하는 것이다.
예를 들어 새로운 미디어 타입으로 내가 정의한 스펙을 등록해두면 MediaType으로 내가 정의한 MediaType으로 HTTP 요청을 하게된다면 자동으로 파싱해주어 사용할 수 있게된다.
하지만 너무 어려울지도?...
두번째
로 header에 사용자들이 들어오는 api 문서 url을 포함시켜서 보내는 것이다.
HATEOAS를 지켜서 상태를 설명하는 방법으로는
{
"orderID":3,
"productID":2,
"quantity":4,
"orderValue":16.60,
"links": [
{"rel":"product","href":"https://adventure-works.com/customers/3", "action":"GET" },
{"rel":"product","href":"https://adventure-works.com/customers/3", "action":"PUT" }
]
}
위와 같이 links
를 통해 하이퍼링크를 첨부할 수도 있고
{
"data": { // HAL JSON의 리소스 필드
"id": 1000,
"name": "게시글 1",
"content": "HAL JSON을 이용한 예시 JSON"
},
"_links": { // HAL JSON의 링크 필드
"self": {
"href": "http://localhost:8080/api/article/1000" // 현재 api 주소
},
"profile": {
"href": "http://localhost:8080/docs#query-article" // 해당 api의 문서
},
"next": {
"href": "http://localhost:8080/api/article/1001" // article 의 다음 api 주소
},
"prev": {
"href": "http://localhost:8080/api/article/999" // article의 이전 api 주소
}
}
}
출처
HATEOAS를 모르면 당신이 알고 있는 REST API는 REST API가 아니라고 장담할게요.
현재 상태값과 해당 url에서 다른 동작에 대해 정의해둘 수도 있다.
우리가 지금까지 알던 REST API는 해당 API에 대한 설명이 없었기 때문에 요청후에 반환 값으로 API의 주소값이 변경되었는지 아니면 API에 대한 문서를 제공해서 이 외에 다른 API가 있는지 혹은 해당 API를 사용하고 다른 동작들을 추가로 더 제공해주는지에 대한 정보가 없었다.
하지만 위 제약을 모두 지킨 REST API는 그것에 대한 정보가 모두 들어가 있게되어 API가 진화하면 Client도 자연스럽게 같이 진화할 수 있게 되는 것이다. API를 사용하는 Client 입장에서 요청 후 다음과 같이 추가적인 정보들이 제공된다면 아~ 이 url이 나중엔 이렇게 바뀌겠구나? 혹은 제공된 문서를 보며 API를 이해하기 더 쉬울것이다.
REST API에 대해 잠깐 규칙만 보려던게 REST API에 대해 정리를 하는 시간을 갖게 되었다. 위 내용을 꼭 다 지켜가면서 할 필요까진 없지만 정말 REST API를 만들고 싶다면 위 규칙을 모두 지켜서 API를 설계해보는 것도 괜찮을거 같다. 하지만 위 내용을 모두 지켰을 경우 REST API의 반환 값에 데이터가 크게 증가하여 서버간 통신에 무리가 생길수도 있으니 개발 입장에서 잘 생각해보고 적용하는 것도 나쁘지 않을 거 같다.
또한 하두 말이 많아서 그런가? Martin Fowler이 제안한 성숙도 모델과 같은 글에서는 REST API를 단계적으로 나눠놓기도 했다. 대부분 REST API들은 2단계 충족하고 있다.