REST란?
- 분산 하이퍼미디어 시스템(ex: web)을 위한 아키텍처 스타일(제약조건의 집합)
- HTTP Method(POST, GET, PUT, DELETE, PATCH 등)를 통해 해당 리소스(URI)에 대한 CRUD Operation을 적용하는 것을 의미
REST의 구성요소
- 자원(Resource) : HTTP URI
- 자원에 대한 행위(Verb) : HTTP Method
- 자원에 대한 행위의 내용 (Representations) : HTTP Message Pay Load
그럼 우리가 사용하는 REST API라고 부르는 것들은 정말 REST를 잘 지키면서 사용하고 있는걸까?
물론 있기야 하겠지만 대부분은 지키지 않는다고 한다.
위의 정의를 보면 제약조건의 집합을 지킨 것이 REST라고 해놓았는데 대부분의 REST API는 이를 지키지 않는다.
그렇다면 REST의 제약조건에는 무엇이 있을까?
REST를 구성하는 스타일
- client-server
- stateless
- cache
- uniform interface
- layered system
- code-on-demand(Optional)
요즘의 REST라고 불리는 것도 위의 대부분을 지키는데 이들은 HTTP만 잘 따라도 지킬 수 있기 때문이다.
단, uniform interface 만 잘 지켜지지 않는다.
이 uniform interface 의 제약 조건에는 아래와 같이 4가지가 있다.
- identification of resources → 리소스가 url로 식별되면됌
- manipulation of resources through representations → 리소스를 삭제하거나 수정할 때 메세지를 담아서 보내는 것
- self-descriptive messages → 메시지는 스스로를 설명해야함
- hypermedia as the engine of application state(HATEOAS) → 애플리케이션의 상태는 Hyperlink를 이용해 전이되어야한다.
요즘 REST들 위의 3,4번 제약 조건들을 잘 지키지 못한다.
우선 self-descriptive messages가 왜 잘 지켜지지 않는 지에 대해서 알아보자
예를 들어 POSTMAN을 통해 JSON객체를 파악할 때 이게 클라이언트 입장에선 이게 무슨 문법으로 작성한지 모르기 때문에 지켜지지 않았다고 하는데 이는
위 사진과 같이 설정을 하게 되면 JSON문법을 사용하겠다고 클라이언트에게 알려준다.
그럼 self-descriptive messages가 잘 지켜졌다고 할 수 있을까?
대답은 No이다.
위의 사진을 다시 보자.
만약 내 코드를 아무도 모르는 사람이 저걸 보고 title이 뭘 의미하고, content가 뭘 의미하는지 명확히 알 수 있을까?
정확히 알 수가 없다…!
그럼 이걸 해결할 수 있는 방법은 없을까?
이 역시 해결할 수 있다.
위 처럼 명세서를 찾아서 메세지를 해석하면 클라이언트가 올바르게 내용을 이해할 수 있다.(-patch+json)
정리하면 self-descriptive messages 은 메세지를 봤을 때 클라이언트가 올바르게 메세지 내용을 이해할 수 있어야하는데 우리가 흔히 말하는 REST API는 이 점이 잘 지켜지지 않는다.
다음은 hypermedia as the engine of application state(HATEOAS) 이다.
우리가 웹을 표현하는 방식 중 하나인 HTML은 HATEOAS가 잘 지켜졌을까?
위 처럼 a태그를 통해 Hyperlink가 있고, Hyperlink를 통해 다음 상태로 이동이 가능하기 때문에 잘 지켜졌다고 할 수 있다.
그럼 JSON은 안될까? 가능하긴하다!
이렇게 Link라는 헤더를 통해 Hyperlink적용하고 다음 상태로 이동할 수 있기 때문에 HATEOAS를 만족할 수 있다.
또한 Link라는 헤더는 이미 명세서에 있기 때문에 self-descriptive messages도 지켰다고 할 수 있다.
그렇다면 uniform interface은 왜 지켜야 할까?
바로 독립적 진화를 위해서이다.
독립적 진화란?
- 서버와 클라이언트가 각각 독립적으로 진화한다라는 의미
- 다시 말해 서버의 기능이 변경되었다고 해서 클라이언트를 업데이트할 필요가 없다는 것을 의미한다
- ex) 만약 A라는 서버의 url이 /getboard 에서 /boardlist로 변경되었다면 클라이언트는 매번 이렇게 변화할 때마다 업데이트를 해야하는데 REST는 이를 방지한다.
대표적인 예로 웹이 있다.
위에 예시했던거 처럼
- 웹 페이지를 변경했다고 해서 웹 브라우저를 업데이트할 필요X
- 웹 브라우저를 업데이트했다고해서 웹 페이지 변경할 필요 X
- HTTP명세가 변경되어도 웹은 정상 작동(ex: 웨일 버전 2.x → 3.x여도 정상작동)
- HTML명세가 변경되어도 웹은 정상 작동
물론 명세가 변경되면 강제 업데이트를 통해 해결할 순 있지만 이것은 좋지 않다.
그래서 앱은 자주 업데이트를 하곤 하는데 이는 바로 앱과 서버가 서로 REST하지 않다는 걸 의미하기도 한다.
그럼 앱과 달리 웹은 이런 달라지는 것을 업데이트하지 않고 어떻게 했을까?
그것은 바로 웹은 상호운용성(interoperability)을 굉장히 중요하게 생각하기 때문이다.
다른말로 하위 호환성을 굉장히 중요하게 여긴다는 것이다.
대표적인 예로 HTTP 상태코드 중 418번을 사용하려했는데 만우절 때 어떤 개발자가 HTTP상태코드 418번을 추가하고 이미 그것을 다른 node.js와 같은 서버들이 이를 구현해버렸기 때문에 상태코드를 제거하지 않고 영구결번이 되었다…
위처럼 웹은 하위호환성을 굉장히 중요시 하기 때문에 그런 것이다.
이는 웹 뿐만 아니라 스프링에서도 버전이 올라가도 전에 있었던 기능들을 버리지 않고 쭉 끌고 오는 이유도 위와 같은
이유이다.
그럼 REST가 웹의 독립적 진화에 도움을 줬을까?
대답은 Yes이다.
REST는
- HTTP에 지속적으로 영향을 줌
- 길이 제한을 다루는 상태코드 명시(ex: 414)
- URI에서 리소스의 정의가 추상적으로 변경
REST API란?
- REST 아키텍쳐 스타일을 따르는 API
하지만 대부분의 REST API들은 REST 아키텍쳐 스타일을 따르지 않음
그렇다면 REST API도 위의 REST의 제역조건들을 다 지켜야 하는가?
대답은 Yes이다.
그럼 무조건 위의 조건들을 다 지켜가며 REST API를 사용해야 할까?
굳이 그럴필요는 없다
현재처럼 REST API를 지키지 않았지만 사용해도된다!
그럼 REST API를 직접 구현하는 방법은 무엇일까?
일단 그 전에 API에 대해서 잠깐 알아보자
API란?
- 응용 프로그램에서 사용할 수 있도록, 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 의미
- 프로그램들이 서로 상호작용하는 것을 도와주는 매개체
ex) 예를 들어
위의 사진처럼 RestController을 사용하면 웹과 서버를 연결해주는데 이를 API의 역할이라고 보면 된다.
즉, 중간 매개체라고 이해하면 편리하다.
그럼 웹과 API의 차이는 무엇일까?
웹 페이지 HTTP API
Protocol | HTTP | HTTP |
커뮤니케이션 | 사람-기계 | 기계-기계 |
Media Type | HTML | JSON |
위와 같은 차이가 있다
그럼 API는 REST가 잘 지켜지지 않는데 위의 표를 딱보면 Media Type때문에 그런거 같다는 생각이 든다.
그래서 HTML과 JSON을 비교해보면
HTML JSON
Hyperlink | O(a태그) | 정의X |
Self-descriptive | O(HTML명세) | 불완전 |
위처럼 JSON은 명세가 없기 때문에 별도의 문서가 필요하다.
그렇다면 self-descriptive messages와 HATEOAS가
독립적 진화에 어떤식으로 도움이 될까?
- self-descriptive messages
a. 서버나 클라이언트가 변경되어도 오고가는 메세지는 언제나 self-descriptive하기 때문에 언제나 해석이
가능하기 때문에 커뮤니케이션이 확장된다. - HATEOAS
a. 애플리케이션 상태 전이의 Late Binding이 가능한데 이는 링크가 동적으로 변경될 수 있다는 것을 의미한다.
그럼 직접 REST API로 변경하려면 어떻게 해야할까?
Media Type
- 미디어 타입을 직접 정의해서 각각의 컬럼들이 무엇을 의미하는지 IANA에 미디어타입을 등록하여서 명세를 만든다.
하지만 이는 매번 미디어 타입을 정의해야하기 때문에 번거롭다는 단점이 있다.
Profile
- 각 컬럼이 무엇을 의미하는지 명세를 작성하고 Link헤더에 해당 명세를 링크를 걸어서 모든 클라이언트가 메세지를
해석할 수 있도록 함
'HTTP' 카테고리의 다른 글
[HTTP] Stateful, Stateless, Connectionless (0) | 2024.01.14 |
---|---|
[HTTP] HTTP란? (1) | 2024.01.02 |
[HTTP] URI와 웹 브라우저 요청 흐름 (0) | 2023.12.30 |
[HTTP] 인터넷 네트워크 (1) | 2023.12.22 |