쉼이 넘치는 API?? 아쉽게도 RestfulAPI에서 Rest는 휴식의 의미가 아니다. REST란 Representational State Transfer 의 약자로 소프트웨어 프로그램 개발 아키텍처의 한 형식이다. 이걸 한글로 어느정도 의미를 파악한다면, '자원(resource)의 표현(representation)에 의한 상태 전달' 이라고 할 수 있다.
그렇다면, Restful API는 이걸 적용한 API 아닐까? 더 깊이 빠고들어보자.
자원에 표현에 의한 상태 전달이 즉, REST라고 했다. 그렇다면 내가 알아들을 수 있는 설명은 무엇일까?
자원의 표현
- 자원은 해당 소프트웨어가 관리하는 모든 것을 의미한다. 문서, 그림, 데이터, 해당 소프트웨어 자체 등, 정말 모든 것을 의미한다.
- 자원의 표현은 그 소프트웨어가 관리하는 자원을 표현하기 위한 이름이다. 예를 들어, DB의 고양이 정보가 자원이라고 하면, "Cats"를 자원의 표현으로 정한다.
상태전달
개발 아키텍쳐의 한 형식인 REST는 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하기에 웹의 장점을 최대한 활용하고 또 네트워크 상에서 클라이언트와 서버 사이의 통신 방식 중 하나이다.
조금 더 자세히 설명하면, REST는 자원 기반의 구조 (Resource Oriented Architecture) 설계의 중심에서 HTTP URI (Uniform Resource Identifier)로 Method를 수행해 통해 자원(Resource)를 표현하고 HTTP Methods (Post, Get, Put, Delete)을 판별해 해당 자원에 적절한 CRUD 작업 (상태전달)을 적용하는 것이다.
웹 사이트의 이미지, 텍스트, DB 내용 등 모든 자원에 고유한 ID 인 HTTP URI부여한다.
1) 자원(Resource): URI
- 모든 자원에 고유한 ID가 존재하고, 이 자원은 서버에 존재한다.
- 자원을 구별하는 ID는 "/cat/:id" 같은 URI이다.
- 클라이언트는 URI로 원하는 자원을 지정하고 해당 자원의 상태에 대한 작업을 서버에 요청한다.
2) 행위(Verb): HTTP Method
3) 표현 (Representation of Resource)
- 클라이언트가 자원의 상태에 대한 작업을 요청하면 서버는 이에 적절한 응답을 한다.
(Sends response (representation) )
- REST에서 하나의 자원은 JSON, XML, TEXT, RSS등 다양한 형태로 응답할 수 있다.
1) 서버-클라이언트 구조
- 자원이 있는 쪽이 서버, 요청하는 쪽이 클라이언트로 REST 서버는 API를 제공하고 비지니스 로직 처리 등 CRUD 작업을 책임진다. 클라이언트는 사용자 인증이나 context(세션) 등을 책임진다.
- 서로 간 의존성이 줄어든다.
2) Stateless(무상태성)
- 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다.
- HTTP 프로토콜 처럼 REST도 Stateless Protocol을 갖는다.
- 들어오는 요청만 처리하면 되기에 자유도가 높아지고 구현이 단순해 진다.
3) Cacheable
- 웹에서 사용하는 기존의 인프라를 그대로 활용할 수 있기에 HTTP의 가장 강력한 기능 중 하나인 캐싱 기능을 적용할 수 있다.
- 캐싱을 사용하면 대량의 요청을 효율적으로 처리할 수 있고 응답시간이 빨라진다. REST Server Transaction이 발생하지 않기에 전체 응답시간, 성능, 서버의 자원 이용률을 향상시킬 수 있다. (Last-Modified, E-Tag)
4) Layered System(계층화)
- 클라이언트는 REST API 서버만 호출한다. 이 서버는 다중 계층으로 구성될 수 있다.
- API 서버는 순수 비지니스 로직을 수행하고, 보안, 로드밸런싱, 암호화, 사용자 인증 등을 추가해 구조상의 유연성을 줄 수 있다. 확장성과 보안성도 향상시킬 수 있다.
- Proxy, 게이트웨이 같은 네트워크 기반의 중간 매체를 사용할 수 있다.
5) Self-descriptiveness(자체 표현 구조)
- REST API의 메시지만 보고도 이를 쉽게 이해할 수 있다.
6) Uniform Interface(인터페이스 일관성)
- URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍쳐 스타일을 말한다.
{
"departmentId": 10,
"departmentName": "Administration",
"locationId": 1700,
"managerId": 200,
"links": [
{
"href": "10/employees",
"rel": "employees",
"type" : "GET"
}
]
}
이런식으로 response에 링크가 담겨 온다.
도큐먼트: 객체 인스턴스나 디비 레코드와 유사한 개념
컬렉션: 서버에서 관리하는 디렉터리라는 리소스
스토어: 클라이언트에서 관리하는 리소스 저장소
URI는 정보의 자원을 표현해야 한다.
ex) GET /Cats/1 -> /GET /cats/1
직관적인 REST API를 위해 컬렉션과 다큐먼트를 사용할 때 단수 복수를 지켜주면 훨씬 이해하기 좋다.
자원에 대한 행위는 HTTP Method로 표현한다.
리소스 간의 관계 표현하는 법.
URI의 마지막문자로 슬래시를 포함하지 않아야 한다.
슬래시 구분자는 계층 관계를 나타내는데 사용해야 한다. ( /cats/posts)
너무 긴 경로는 하이픈을 사용해서 가독성을 높인다.
URI의 마지막문자로 슬래시를 포함하지 않는다.
너무 긴 경로는 하이픈을 사용해서 가독성을 높인다.
밑줄은 사용하지 않는다.
소문자가 적합하니 URI에는 소문자를 사용한다.
파일확장자는 URI에 포함하지 않는다. 어셉트 헤더를 사용한다.
ex) /cats/10/photo.png (X)
ex) /cats/10/photo HTTP/1.1 Host: dedicats.com Accept:image/png (O)
REST API의 규칙을 어기면, RESTful 하다고 볼 수 없다.
ex) 모든 CRUD가 POST로만 처리된다.
ex) route에 resource, id 외의 정보가 들어가는 경우 (/cats/updateName)
항상 API 작성 시 어떨 때 어떤 상태코드를 응답해줘야 할지 고민했는데, 참고한 사이트에 너무 좋은 리소스가 있어 내 블로그에 옮겨오고 싶었다. 완벽하게 자세하고 명확하진 않지만, 들어있는 설명이 너무 이해하기 좋았다. 상태코드를 구체적으로 나누어주는게 장기적으로 좋다고 생각한다.
RESTful API를 목적으로 자주 서버 코드를 개발했지만, 이렇게 자세히 이론적으로 학습한 것은 처음인 것 같다. 이렇게 많은 규칙이 있는 지 몰랐고, 또 지금까지 내가 무엇을 잘못하고 있었는지도 알 수 있었다. 특히 URI 관련 규칙들을 공부하며 많은 것을 배울 수 있었고 다음부터는 URI 설계를 할 때 고려해야 할 점들을 숙지했다. 지금까지 작성한 API URI들을 보며 고쳐야겠다고 다짐했다. REST API는 흔히 쓰기 때문에 정확하게 알아야 하고 꾸준한 복습이 필요할 것 같다. 대충하지 않고, 정확히 이해하고 싶은 마음이 크다.
명확한 표준이 없기에 REST API를 사용시 개발하는 서비스의 특징과 개발 집단의 환경과 성향등이 충분히 고려되어 설계되어야 한다.
참고
https://meetup.toast.com/posts/92
https://blog.restcase.com/7-rules-for-rest-api-uri-design/
https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html
https://restfulapi.net/hateoas/