Network

REST API 설계 원칙

kmkunk 2021. 11. 9. 19:21

1. REST(Representational State Transfer)

- URI를 통해 자원을 표시하고, HTTP Method를 이용하여 해당 자원의 행위를 규정하여 그 결과를 받는 것을 의미한다.

- 구성

종류 설명
자원(Resource) URI
행위(Verb) HTTP Method
표현(Representations) -

 

1.1 REST 특징

특징 설명
Uniform - Uniform Interface
- URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 의미한다.
Stateless - 무상태성 성격을 갖는다. 작업을 위한 상태 정보를 따로 저장하고 관리하지 않는다.
- 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 이러한 이유로 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.
Cacheable - HTTP라는 기존 웹 표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용할 수 있다. 따라서 HTTP가 가진 캐싱 기능 적용이 가능하다.
- HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-Tag를 이용해 구현할 수 있다.
Self-descriptiveness REST API 메시지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조로 되어 있다.
Client - Server 구조 -  REST서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보) 등을 직접 관리하는 구조로 각각의 역할을 확실하게 구분한다.
- 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로 간 의존성이 줄어든다.
계층형 구조 - REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조 상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간 매체를 사용할 수 있게 한다.

 

2. REST API 설계 원칙

① URI는 정보의 리소스를 표현해야 한다.

// REST를 제대로 적용하지 않은 URI 예시
GET /members/delete/1

- 행위에 대한 표현이 아닌 리소스 표현하는데 중점을 두어야 한다.

- 리소스명은 동사보다는 명사를 사용한다.

② 리소스에 대한 행위는 HTTP Method로 표현한다.

- GET, POST, PUT, DELETE 등

// REST 적용 예시 1
GET /members/delete/1 (X)
DELETE /members/1 (O)

// REST 적용 예시 2
GET /members/show/1 (X)
GET /members/1 (O)

// REST 적용 예시 3
GET /members/insert/3 (X)
POST /members/3 (O)

③ 슬래시 구분자(/)는 계층 관계를 나타내는데 사용한다.

④ URI 마지막 문자로 슬래시(/)를 포함하지 않는다.

⑤ 하이픈(-)은 URI 가독성을 높이는데 사용할 수 있다.

- URI를 쉽게 읽고 해석하기 위해, 불가피하게 긴 URI 경로를 사용하게 된다면 하이픈을 사용해 가독성을 높일 수 있다.

⑥ 언더바(_)는 URI에 사용하지 않는다.

- 보기 어렵거나 밑줄 때문에 문자가 가려지는 가독성 문제가 발생한다. 대신 하이픈을 사용한다.

⑦ URI 경로에는 소문자를 사용한다.

- 대소문자에 따라 다른 리소스로 인식하기 때문이다.

- RFC3986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하고 있다.

⑧ 파일 확장자는 URI에 포함시키지 않는다.

- REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함시키지 않는다. 대신 Accept header를 사용한다.

// REST 적용 예시
http://restapi.example.com/members/soccer/345/pthoto.jpg (X)
GET /members/soccer/345/photo HTTP/1.1 (O)
	Host: restapi.example.com
	Accept: image/jpg

 

2.1 HTTP Method

- 종류

종류 설명
GET - 리소스를 조회한다.
- 서버에 전달하고 싶은 데이터는 qeury(쿼리 파라미터, 쿼리 스트링)를 통해서 전달한다.
- 메시지 바디를 사용해서 데이터를 전달할 수 있지만, 지원하지 않는 곳이 많아서 권장되지 않는다.
POST - 새 리소스를 생성할 때 사용한다.
- 메시지 바디를 통해 서버로 요청 데이터를 전달하고 처리하는데 사용한다. 단순히 데이터를 생성하거나 변경하는 것을 넘어서 프로세스를 처리해야 하는 경우가 해당한다. POST의 결과로 항상 새로운 리소스가 생성되는 것은 아니다.
- JSON으로 조회 데이터를 넘겨야 하는데 GET 메서드를 사용하기 어려운 경우 등, 다른 메서드로 처리하기 애매한 경우 사용한다.
PUT - 리소스를 대체한다.
- 리소스가 없는 경우 생성한다.
- 클라이언트가 리소스 위치를 알고 URI를 지정하는 점이 POST와의 차이점이다.
- PATCH와의 차이점은, 리소스를 일부만 변경하는 경우에도 바뀌지 않는 속성을 모두 보내야 한다는 점이다.
PATCH - 리소스를 부분적으로 변경한다.
- PUT과 달리, 변경할 값만 보내면 된다.
DELETE 리소스를 삭제한다.
HEAD GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환한다.
OPTIONS - 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명한다.
- 주로 CORS에서 사용한다.
CONNECT 대상 자원으로 식별되는 서버에 대한 터널을 설정한다.
TRACE 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행한다.

- 속성

종류 설명
Safe 호출해도 리소스를 변경하지 않는다.
Idempotent 같은 요청을 여러 번 해도 결과가 똑같다.
Cacheable -

 

속성 요약표

 

2.2 리소스 간의 관계를 표현하는 방법

- 일반적인 소유 관계를 표현할 때 예시

GET /users/{userid}/devices

- 관계명이 애매하거나 구체적 표현이 필요할 때 예시

GET /users/{userid}/likes/devices

 

2.3 URI 설계 개념

종류 설명
문서(Document) - 하나의 문서 혹은 객체라고 볼 수 있다.
- 리소스라고 표현할 수 있으며 URI에 표현된다.
- /members/100, /files/star.jpg 등이 예시이다.
컬렉션(Collenction) - 문서, 객체들의 집합이라고 볼 수 있다.
- 복수를 의미한다.
- 리소스라고 표현할 수 있으며 URI에 표현된다.
- /members 등이 예시이다.
스토어(Store) - 클라이언트가 관리하는 자원 저장소를 의미한다.
- 클라이언트가 리소스의 URI를 알고 관리한다.
- /files 등이 예시이다.
컨트롤러(Controller), 컨트롤 URI - 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스를 실행한다.
- 동사를 직접 사용한다.
- /members/{id}/delete 등이 예시이다.

 

2.4 자원을 표현하는 Collection과 Document

- 단수, 복수를 지켜 컬렉션과 도큐먼트를 사용하면 더욱 직관적인 REST API를 만들 수 있다.

// sports 컬렉션과 soccer 도큐먼트로 표현
http://restapi.example.com/sports/soccer

// sports, players 컬렉션과 soccer, 13 도큐먼트로 표현
http://restapi.example.com/sports/soccer/players/13

 

3. HTTP 응답 상태 코드

- 1xx(Informational): 요청이 수신되어 처리 중이다. 거의 사용하지 않는다.

- 2xx(Successful): 요청이 정상 처리되었다.

- 3xx(Redirection): 요청을 완료하려면 추가 행동이 필요하다.

- 4xx(Client Error): 클라이언트 오류, 잘못된 문법 등으로 서버가 요청을 수행할 수 없다.

- 5xx(Server Error): 서버 오류, 서버가 정상 요청을 처리하지 못한다.

종류 설명
200 OK 클라이언트의 요청을 정상적으로 수행한다.
201 Created 클라이언트가 POST를 통한 어떠한 리소스 생성을 요청했을 때, 해당 리소스가 성공적으로 생성된다.
202 Accepted 요청이 접수되었으나 처리가 완료되지 않았다.
204 No Content 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없다.
300 Multiple Choices 사용하지 않는다.
301 Moved Permanently - 클라이언트가 요청한 리소스에 대한 URI가 변경되었을 때 사용한다.
- 응답 시 Location header에 변경된 URI를 적어야 한다.
- 리다이렉트 시 요청 메서드가 GET으로 변한다.
- 본문이 제거될 수도 있다.
302 Found - 리다이렉트 시 요청 메서드가 GET으로 변할 수 있다.
- 본문이 제거될 수 있다.
303 See Other - 302와 기능은 같다.
- 리다이렉트 시 요청 메서드가 GET으로 변경된다.
304 Not Modified - 캐시를 목적으로 사용한다.
- 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬 PC에 저장된 캐시를 재사용해서 리다이렉트 한다.
- 로컬 캐시를 사용하기 때문에 응답에 메시지 바디를 포함하면 안된다.
- 조건부 GET, HEAD 요청 시 사용한다.
307 Temporary Redirect - 302와 기능은 같다.
- 리다이렉트 시 요청 메서드와 본문을 유지한다.
308 Permanent Redirect - 301과 기능은 같다.
- 리다이렉트 시 요청 메서드와 본문을 유지한다.
- 처음 POST를 보내면 리다이렉트도 POST를 유지한다.
400 Bad Request 요청 구문, 메시지 등에서 오류가 발생하여 클라이언트의 요청이 부적절한 경우 사용한다.
401 Unauthorized - 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 때 사용한다.
- 로그인하지 않은 유저가 로그인 했을 때 요청 가능한 리소스를 요청했을 경우 등이 해당한다.
- 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명한다.
403 Forbidden - 유저 인증 상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용한다.
- 403은 리소스가 존재한다는 것을 의미하기 때문에, 400이나 404 사용이 더 권고된다.
- 주로 인증 자격은 있지만, 접근 권한이 불충분한 경우 사용한다.
404 Not Found - 요청 리소스가 서버에 없다.
- 클라이언트가 권한이 부족한 리소스에 접근하는 경우에, 해당 리소스를 숨기고 싶을 때 사용한다.
405 클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용한다.
500 Internal Server Error - 서버에 문제가 있을 경우 사용한다.
- 애매한 경우에는 500으로 처리하는 것이 일반적이다.
503 Service Unavailable  - 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없을 때 사용한다.
- Retry-After 헤더 필드로 얼마 뒤에 복구되는지 보낼 수 있다.

 

3.1 Redirection

Redirection 예시

- 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동한다.

종류 설명
영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동한다.
- 원래의 URL을 사용하지 않는다.
- 검색 엔진 등에서도 변경을 인지한다.
- 301, 308이 해당한다.
일시 리다이렉션 - 리소스의 URI가 일시적으로 변경된다.
- 검색 엔진 등에서 URL을 변경하면 안된다.
- 주문 완료 후 주문 내역 화면으로 이동하는 것이 대표적인 예시이다.
- 302, 303, 307이 해당한다.
- 303, 307 사용이 권장되지만 현실적으로는 302가 가장 많이 사용되고 있다. 큰 문제는 없다.
- PRG Pattern이 해당한다.
특수 리다이렉션 결과 대신 캐시를 사용한다.

 

3.2 PRG(Post/Redirect/Get) Pattern

PRG Pattern 예시

- 일시 리다이렉션에 해당한다.

- POST로 주문 후에 새로고침으로 인한 중복 주문을 방지한다.

- POST로 주문 후에 주문 결과 화면을 GET 메서드로 리다이렉트 한다.

- 새로고침해도 결과 화면을 GET으로 조회한다. 중복 주문 대신에 결과 화면만 GET으로 다시 요청하는 것이다.

 

참고

- https://meetup.toast.com/posts/92

- https://devuna.tistory.com/77

- https://ko.wikipedia.org/wiki/HTTP

- https://sanghaklee.tistory.com/57

- https://restfulapi.net/resource-naming/

- 『모든 개발자를 위한 HTTP 웹 기본 지식』