RESTful API란 무엇인가요? - AWS
REST API 성숙도 모델
RESTful API는 많은 블로그에서 다루고, 참고 자료인 AWS에서도 깔끔하게 설명하고 있기 때문에 따로 글을 작성해봤자 배끼는 것이라는 생각이 들었다.
따라서 이 글에서는 "참고 자료"에서 설명하는 REST 아키텍처의 원칙들의 예시를 추가해보려고한다.
해당 부분에 설명에 앞서 우선 REST API 단계에 대해 언급하고 가는 것이 좋을 것같다.
DB에도 정규화의 단계가 있듯이, REST API에도 정규화 단계가 존재한다.
이는 참고자료: REST API 성숙도 모델에 잘 기술되어 있으며, 대부분의 경우 아래 그림의 Level2 정도만 지키는 모습을 심심치않게 볼 수 있다.
(예를들어, 페북이나 배민 등)

감히 예상컨데 그 이유는 DB의 정규화와 동일하다고 생각한다.
DB 정규화의 경우에도 많은 단계가 나눠져있지만, 일반적으로는 일정 단계 이상의 정규화를 적용하지 않는다.
그건 바로, 그것이 크게 의미를 가지는 일이 아니기 때문이다.
물론, 팀에 따라, 개발에 따라 다르겠지만, 필요 이상의 정규화는 해당 DB를 사용하는데 비효율성과 개발 피로도(개발 비용)을 높일 수 있다.
그래서 적당히, 팀이나 프로젝트에 맞는 규칙 준수가 더 중요하고, Trade-off 관계에 있는 규칙 준수와 효율성, 개발 비용을 팀과의 커뮤니케이션을 통해 잘 정해 두는 것이 중요하다고 생각한다.
균일한 인터페이스는 모든 RESTful 웹 서비스 디자인의 기본입니다. 이는 서버가 표준 형식으로 정보를 전송함을 나타냅니다. 형식이 지정된 리소스를 REST에서 표현이라고 부릅니다. 이 형식은 서버 애플리케이션에 있는 리소스의 내부 표현과 다를 수 있습니다. 예를 들어, 서버는 데이터를 텍스트로 저장하되, HTML 표현 형식으로 전송할 수 있습니다.
균일한 인터페이스에는 4가지 아키텍처 제약 조건이 있습니다.
예를 들어, 상품과 관련된 RESTful API에서 각각의 상품(리소스)는 각각 고유한 URI을 가질 수 있었야한다는 것이다.
GET /products/123PUT /products/123DELETE /products/123"클라이언트는 원하는 경우", 즉, 필요에 따라 달라 질 수 있는 구문이다.
아래 예시에서는 수정, 삭제에 필요한 URL을 넘겨주는 방식으로 처리했지만, 필자가 생각하기에 제일 중요한 부분은 "리소스를 수정하거나 삭제하기에 충분한 정보" 이다.
즉, 클라이언트와 합의된 내용에서, 주어진 정보를 이용해 해당 리소스의 수정 삭제가 가능한 메타데이터를 응답으로 보내야한다는 것이다.
{
"id": 123,
"name": "Product ABC",
"price": 50.0,
"description": "A description of Product ABC.",
"category": "Electronics",
"links": {
"self": "/products/123",
"edit": "/products/123",
"delete": "/products/123"
}
}
{
"orderId": 789,
"status": "pending",
"totalAmount": 100.0,
"links": {
"self": "/orders/789",
"updateStatus": {
"href": "/orders/789/status",
"method": "PUT",
"description": "Update the status of this order."
}
}
}
{
"orderId": 789,
"status": "pending",
"totalAmount": 100.0,
"links": {
"self": "/orders/789",
"shippingDetails": "/orders/789/shipping",
"customer": "/customers/456"
}
}
개인적으로 생각하기에는, 위에 2, 3, 4번의 링크를 전송하는 방식은 특정 경우를 제외하면 투머치라는 생각이 든다.
대부분의 웹사이트는 리소스에 대한 작업이 버튼이나 이미지로 나타나있고, 이를 굳이굳이 응답으로 받을 이유가 없다.

예를 들어, 위에 UI를 보고 클라이언트가 해당 리소스(장바구니 아이템)에 대해 적절한처리 방식이나 메타데이터가 부족하다고 생각하지는 않을 것이다.
때문에 이런 "HTML, CSS, JS 없더라도, 클라이언트가 알 수 있게하는 것을 기준으로 작성되어 있는 예시"에 대해서는 크게 의식하지 않아도 된다고 생각한다.
REST 아키텍처에서 무상태는 서버가 이전의 모든 요청과 독립적으로 모든 클라이언트 요청을 완료하는 통신 방법을 나타냅니다. 클라이언트는 임의의 순서로 리소스를 요청할 수 있으며 모든 요청은 무상태이거나 다른 요청과 분리됩니다. 이 REST API 설계 제약 조건은 서버가 매번 요청을 완전히 이해해서 이행할 수 있음을 의미합니다.
이는 간단히 택배랑 비슷하다고 할 수 있다.
같은 택배회사를 통해 여러 번 택배를 요청했더니 이를 귀찮게 혹은 특별하게 생각한 택배회사가 택배에 요청하지 않은 무언가를 해놓으면, 그건 좋은 택배 시스템일까?
답은 아니다. 물론 그게 좋다고 생각하는 사람 역시 있을 수도 있다.
하지만, 그게 좋다고 생각할 수 있는 것은, 극히 작은 규모에 한해서이다.
규모가 커질 수록 상태(이전 요청이나 요청의 순서 등)를 첨부한 요청은 택배회사와 고객 둘 모두에게 피로감을 키울 뿐이다.
(프랜차이즈 시스템을 생각하면, 이해가 쉬울 수 있다.)
계층화된 시스템 아키텍처에서 클라이언트는 클라이언트와 서버 사이의 다른 승인된 중개자에게 연결할 수 있으며 여전히 서버로부터도 응답을 받습니다. 서버는 요청을 다른 서버로 전달할 수도 있습니다. 클라이언트 요청을 이행하기 위해 함께 작동하는 보안, 애플리케이션 및 비즈니스 로직과 같은 여러 계층으로 여러 서버에서 실행되도록 RESTful 웹 서비스를 설계할 수 있습니다. 이러한 계층은 클라이언트에 보이지 않는 상태로 유지됩니다.
REST 아키텍쳐는 클라이언트 -> 서버로 요청이 가는 도중에 승인된 중개자를 거쳐갈 수 있고, 도착하는 서버가 꼭 1개가 아니라도 된다는 것이다.
예를 들어 당신이 온라인 게임에 접속한다고 가정해보자, 어떤 게임 서버는 다음과 같이 요청을 처리할 수 있다.
로드 밸런서 -> 인증 서버 -> 애플리케이션 서버 -> 데이터베이스 서버
그러면 해당 요청은 로드 밸런서에서 트래픽에 따라 적절한 서버로 보내지고, 인증 서버에서 올바른 권한의 요청인지 인증할 것이다.
그리고, 애플리케이션 서버에서 요청에 대한 작업을 실행하고, 필요하다면, 데이터베이스 서버에 요청을 보내 정보를 수정할 것이다.
또, nginx 같은 리버시 프록시 서버 같은 것을 중개자로 넣어 요청에 따라 이미지 서버, 애플리케이션1 서버, 데이터 베이스 서버 등 요청을 다양한 서버에 전달할 수도 있다.
이러한 방식들 모두 REST 아키텍쳐의 일부라고 해당 문서는 설명하고있다.
RESTful 웹 서비스는 서버 응답 시간을 개선하기 위해 클라이언트 또는 중개자에 일부 응답을 저장하는 프로세스인 캐싱을 지원합니다. 예를 들어 모든 페이지에 공통 머리글 및 바닥글 이미지가 있는 웹 사이트를 방문한다고 가정해 보겠습니다. 새로운 웹 사이트 페이지를 방문할 때마다 서버는 동일한 이미지를 다시 전송해야 합니다. 이를 피하기 위해 클라이언트는 첫 번째 응답 후에 해당 이미지를 캐싱하거나 저장한 다음 캐시에서 직접 이미지를 사용합니다. RESTful 웹 서비스는 캐시 가능 또는 캐시 불가능으로 정의되는 API 응답을 사용하여 캐싱을 제어합니다.
RESTful한 웹 서비스는 Cache-Control, Expires, Last-Modified, ETag 등의 헤더를 통해 캐싱을 지원한다.
예를 들어, 머리글 이미지를 클라이언트에게 전송할 때, 다음과 같은 헤더가 추가되어 있다고 가정하자
Cache-Control: public, max-age=3600
그러면 해당 이미지는 1시간(3600초) 동안 브라우저나 중개자(프록시 서버) 등에 저장되어 서버의 부하와 네트워크 트래픽 등을 개선할 수 있게된다.
REST 아키텍처 스타일에서 서버는 소프트웨어 프로그래밍 코드를 클라이언트에 전송하여 클라이언트 기능을 일시적으로 확장하거나 사용자 지정할 수 있습니다. 예를 들어, 웹 사이트에서 등록 양식을 작성하면 브라우저는 잘못된 전화번호와 같은 실수를 즉시 강조 표시합니다. 서버에서 전송한 코드로 인해 이 작업을 수행할 수 있습니다.
서버가 클라이언트에게 소프트웨어 프로그래밍 코드(주로 JS)를 동적으로 전송하여 클라이언트의 기능을 일시적으로 확장하거나 사용자 지정할 수 있는 개념이다.
이는 Optional한 제약 조건으로 진행 중인 프로젝트에 따라 적용하면 된다.
제약 조건에 기술된 것은 모두 설명했고, 이점이나 종류 등의 정보는 참고자료: RESTful API란 무엇인가요? - AWS를 참고하길 바란다.
뭔가... 뭔가... 익숙하면서 어색한 느낌이다.
대부분의 제약 조건에 대해서는 의식하지 않고 지키고있었다는 점에서 놀랐다.
물론 옛날에 잠깐 훑어본적은 있지만, 이후에 "REST하다는게 뭐에요?"라고 물어볼 때마다 애매한 대답 밖에 못했고, 대답할 때도 상대가 영 시원찮은 얼굴을 하길래 "아.. 내가 모르는 더 엄격한 제약이 있구나" 라는 생각을 자주했다.
하지만, 오늘 이 글을 작성하면서 생각보다 많은 사이트가 적절한 정도의 REST함을 지키고 있었으며, 그동안 답했던 것들도 그리 틀린 것은 아니지만, 완전히 맞다고도 답할 수 없는 무언가였고, 그 표정들의 이유도 알 수 있었다.
또, 정리하면서 REST함이 어려운 듯, 쉽게 느껴지는 이 싱숭생숭한 느낌...
그래도 이번에 정리함으로서 나름의 개념을 확보했고, 앞으로는 누가 물어보면 확신을 가지고 대답할 수 있다는 점에서 꽤 의미있는 정리였다.
공신력있는 기업에서 아름답게 정리해준 Amazon에게 감사하게되는 하루다.