REST API

Borahm·2021년 4월 25일
0

Web

목록 보기
5/5
post-thumbnail

1. REST 구성

REST

Representational State Transfer의 약자이며,

  • 웹에 존재하는 모든 자원(이미지, 영상, 텍스트 등 데이터)에 고유한 URI를 부여하여 해당 자원에 대한 주소를 부여하는 것을 말합니다.
  • 또는 웹 서비스를 만드는 데 사용되는 제약(constraint)의 모음이라고도 할 수 있습니다. 까다로운 제약들을 모두 만족했을 때 'RESTful' 하다 라고 표현할 수 있습니다.

REST는 간단히 아래와 같이 구성됩니다.

  • 자원(Resource) - URI

    • REST에서 가장 중요한 부분은 Resource 입니다. REST에서는 데이터를 얻기 위해 기능을 어떻게 구현했는지에 집중하지 않습니다. REST에서 집중하는 것은 구현이 아닌 데이터입니다.

    • URI는 URL를 포함하는 개념입니다.

      URI > URL
      (Uniform Resource Identifier) > (Uniform Resource Locator)

      • URL로는 Locator가 지시하는 경로까지만 따라 들어갈 수 있지만 그 이상은 어렵다.
      • 하지만 URI로는 그 경로의 Resource까지도 접근할 수 있다. (Identifier가 Resource를 구별해준다)
  • 행위(Verb) - HTTP Method

  • 표현(Representations)

2. REST의 탄생

  • REST는 2000년 로이 필딩 (Roy Fielding)의 박사 학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 설계자 중 한 사람으로, 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되지 못하는 모습을 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표하였습니다.

로이 필딩의 논문 '네트워크 기반 소프트웨어 아키텍처의 구조적 스타일과 설계(Architectural Styles and the Design of Network-based Software Architectures)'에 정의된 것처럼 RESTful 시스템의 다음 6가지 주요 제약 조건을 준수했을 때 RESTful API라고 간주할 수 있습니다.

  • 결국 REST란 API 디자인에서 HTTP 프로토콜을 의도에 맞게 사용하도록 정의한 아키텍처 스타일을 말합니다.

3. REST의 특징

1/ 클라이언트-서버 아키텍처

  • REST 아키텍처는 클라이언트, 서버, 리소스로 구성되며 HTTP를 통해 요청을 처리합니다.
  • 사용자 인터페이스데이터 저장 문제를 클라이언트와 서버의 역할로 각각 분리합니다. 이러한 분리를 통해 두 구성 요소는 독립적으로 진화할 수 있고 확장성을 높일 수 있습니다. 핵심적으로 클라이언트는 애플리케이션이 어떻게 데이터를 구성하고 관리하는지 알 필요가 없습니다.

2/ 상태 비 저장

  • 클라이언트-서버 상호 작용에 Stateless 제약을 하나 추가한 것입니다.
  • 서버는 클라이언트 상태를 유지하지 않습니다. 그렇기 때문에 클라이언트에서 서버로 보내는 각 요청에는 요청을 이해하는 데 필요한 모든 정보가 포함되어야 합니다. 클라이언트는 서버에 저장된 컨텍스트를 이용할 수 없습니다. 다만 세션 상태에 대한 모든 정보는 전적으로 클라이언트에 의해 유지됩니다.
  • 요청과 요청 사이에 상태를 따로 저장할 필요가 없기 때문에 서버 쪽에서는 리소스를 빠르게 해제할(내릴) 수 있습니다(확장성 향상). 또한, 여러 요청에 걸쳐있는 리소스를 유지하고 관리하지 않아도 되므로 구현이 더욱 단순화됩니다.

3/ 캐시 가능

  • 네트워크 효율성 향상을 위해 client-cache-stateless-server 스타일을 사용합니다. 서버는 응답 데이터에 캐시 가능 여부를 표시해야 합니다. 캐시 조건에 따라 암시적으로나 명시적으로 캐시 가능 또는 캐시 불가능 레이블을 지정해야 합니다. 캐시할 수 있는 경우, 나중에 같은 요청에서 클라이언트 캐시는 응답 데이터를 재사용할 수 있습니다.
  • 캐시 조건을 추가할 때의 장점은 일부 상호 작용을 제거하여 지연 시간을 줄이고 이로써 사용자 인식 성능을 향상시킬 수 있다는 것입니다.
  • 단점은 캐시 내의 오래된 데이터와, 서버로 직접 요청하여 얻은 데이터가 크게 다를 때 캐시의 안정성이 떨어진다는 것입니다.

4/ 유니폼 인터페이스

  • REST 서비스는 일관된 네임 스페이스를 사용하여 데이터를 리소스로 제공합니다.
  • 이를 통해 전체 시스템 아키텍처는 단순화되고 상호 작용의 가시성이 향상됩니다.
  • REST 인터페이스는 대형 하이퍼 미디어 데이터 전송에 효율적으로 설계되어 웹의 일반적인 경우에 최적화되지만 다른 형태의 아키텍처 상호 작용에는 최적화되지 않을 수 있습니다.

5/ 계층형 구조

  • 시스템의 구성 요소는 해당 계층 너머를 볼 수 없습니다. 따라서 로드 밸런서 및 프록시를 쉽게 추가하여 보안 또는 성능을 향상시킬 수 있습니다.

  • 보안, 로드 밸런싱, 암호화 계층을 추가할 때 구조를 유연하게 할 수 있고, Proxy, 게이트 웨이와 같은 네트웨크 기반의 중간매체를 사용할 수 있습니다.

6/ 자체 표현 구조

  • REST API 메시지만으로도 내용을 쉽게 이해할 수 있기 때문에 자체 표현 구조로 되어 있다고 말합니다.

내용 및 이미지 참조: 로이 필딩의 논문 '네트워크 기반 소프트웨어 아키텍처의 구조적 스타일과 설계(Architectural Styles and the Design of Network-based Software Architectures)

4. REST API 디자인 가이드

REST API 설계 시 가장 중요한 항목은 크게 2가지로 요약할 수 있습니다.

  1. URI는 정보의 자원을 표현해야 한다.
  2. 자원에 대한 행위는 HTTP Method (GET, POST, PUT, DELETE)로 표현한다.

1/ REST API 중심 규칙

1) URI는 정보의 자원을 표현해야 한다. (리소스명은 동사보다는 명사를 사용한다.)

  • 잘못된 예시

    • 리소스명으로 동사(행위)를 사용하여, URI가 자원을 표현해야 한다는 원칙을 어겼습니다.
    GET /members/show/1
  • 올바른 예시

    • ID를 1로 하는 회원 정보를 가져온다고 가정할 때 아래와 같이 수정할 수 있습니다.
    GET /members/1

2) 자원에 대한 행위는 HTTP Method (GET, POST, PUT, DELETE)로 표현한다.

  • 잘못된 예시

    • 위에서 살펴본 예시와 동일하게 행위에 대한 표현은 URI에 포함하지 않습니다.
    GET /members/delete/1
  • 올바른 예시

    • 행위는 HTTP Method를 사용하여 표현합니다.
    DELETE /members/1

참고로, HTTP 메소드를 올바르게 사용할 수 있어야 합니다. 모든 행위를 GET으로 표현하는 식으로 상황에 맞지 않는 메소드를 사용해서는 안 됩니다.

참고- HTTP Method별 역할

  • HTTP 메소드 (GET, POST, PUT, DELETE)를 사용하여 CRUD를 할 수 있습니다.

    메소드역할
    GET해당 리소스를 조회하여 (자세한) 정보를 가져옵니다.
    POST해당 리소스를 생성합니다.
    PUT해당 리소스를 수정합니다.
    DELETE해당 리소스를 삭제합니다.

REST API의 중심 규칙을 다시 상기해보면, URI는 자원을 표현하는 데 집중하고, 자원에 대한 행위는 HTTP 메소드를 사용하여 표현한다 입니다.

2/ URI 설계시 주의할 점

1) 슬래시 구분자(/)는 계층 관계를 나타낼 때 사용합니다.

http://restapi.example.com/animals/mammals/whales

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

  • URI에 포함되는 모든 글자는 리소스의 유일한 식별자로 사용되어야 합니다. 따라서 URI가 다르다는 것은 리소스가 다르다는 의미이며, 역으로 리소스가 다르면 URI도 달라져야 합니다. REST API는 분명한 URI를 만들어 통신을 해야 하기 때문에 혼동이 없도록 URI 경로의 마지막에는 슬래시(/)를 사용하지 않습니다.
http://restapi.example.com/animals/mammals/whales/

3) 대시(-)은 URI 가독성을 높이는 데 사용합니다.

  • 불가피하게 긴 URI 경로를 사용해야 할 때, URI를 쉽게 읽고 해석하기 위해 대시를 사용해 가독성을 높일 수 있습니다.

4) 언더스코어(_)은 사용하지 않습니다.

  • 때로 밑줄은 글꼴에 따라 보기 어려울 수 있고, 반대로 밑줄 때문에 글자가 가려지기도 합니다. 이런 문제를 피하기 위해 밑줄 대신 대시(-) 사용을 권장합니다.

5) URI 경로에는 소문자가 적합합니다.

  • URI 경로에 대문자 사용은 피하도록 합니다. 대소문자에 따라 다른 리소스를 인식하므로 두 가지를 혼용하면 복잡성이 커집니다. RFC 2986(URI 문법 형식)은 URI 스키마와 호스트를 제외하고는 대소문자를 구별하도록 규정하고 있습니다.

    RFC 3986 is the URI (Unified Resource Identifier) Syntax document

6) 파일 확장자는 URI에 포함시키지 않습니다.

  • 잘못된 예시

    http://restapi.example.com/members/soccer/345/photo.jpg
  • REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI에 포함시키지 않습니다. 대신 Accept header를 사용합니다.

    GET /members/soccer/10/photo HTTP/1.1 Host: restapi.example.com Accept: image/jpg

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

  • REST 리소스 간에는 연관 관계가 있을 수 있습니다. 이 경우 아래와 같이 표현합니다.

    /리소스명/리소스 id/관계가 있는 다른 리소스명

    GET /users/{userid}/devices (일반적으로 소유 'has'의 관계를 표현할 때)
  • 만약 관계명이 복잡하다면 이를 서브 리소스에 명시적으로 표현하는 방법이 있습니다. 예를 들어 사용자가 '좋아하는' 디바이스 목록을 표현해야 할 경우 아래와 같이 표현할 수 있습니다.

    GET /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)

4/ 자원을 표현하는 Collection과 Document

컬렉션은 문서들의 집합 또는 객체들의 집합입니다. 그리고 도큐먼트는 하나의 문서 또는 객체입니다. 이 두 가지를 모두 리소스라고 표현하며, 이들은 URI에 표현됩니다.

http://restapi.example.com/sports/soccer

위의 URI에서는 sports 라는 컬렉션이 있고, soccer 라는 도큐먼트가 있습니다. 한 가지 더 예를 들어보겠습니다.

http://restapi.example.com/sports/soccer/players/7

이 경우, sports, players 라는 컬렉션이 있고, soccer , 7 (id가 7인 선수) 라는 도큐먼트가 있습니다. 여기서 중요한 점은 컬렉션은 복수를 사용하고, 도큐먼트는 단수를 사용한다는 점입니다.

5/ HTTP 응답 상태 코드

  • 잘 설계된 REST API는 URI가 잘 설계되어 있을 뿐 아니라, 그 리소스에 대한 응답까지 잘 내어줄 수 있어야 합니다. 정확한 응답의 상태 코드만으로도 여러 가지 정보를 전달할 수 있기 때문에 중요합니다. 아래 응답 상태 코드와 관련하여 내용이 정리되어 있습니다.

200번대

상태 코드설명
200클라이언트의 요청을 정상적으로 수행합니다.
201클라이언트가 리소스 생성을 요청할 시, 해당 리소스가 성공적으로 생성되었음을 나타냅니다. (POST 메소드를 통한 리소스 생성 시)

400번대

상태 코드설명
400클라이언트가 적절하지 않은 요청을 한 경우에 사용합니다.
401클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 때 사용합니다.
(로그인 하지 않은 유저가, 로그인 이후 요청 가능한 리소스를 요청했을 때)
403유저의 인증 상태와 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때 사용합니다.
(403 자체는 리소스가 존재한다는 것을 의미하기 때문에, 403 보다는 400이나 404 사용을 권고합니다.)
405클라이언트가 요청한 리소스에서는 사용할 수 없는 HTTP 메소드를 호출할 경우 사용합니다.

그 외

상태 코드설명
301클라이언트가 요청한 리소스에 대한 URI가 변경되었을 경우에 사용합니다.
(응답시 Location header에 변경된 URI를 적어주어야 합니다.)
500서버에 문제가 있을 경우에 사용합니다.

References

0개의 댓글