들어가며

안녕하세요! 가든 팀의 마린입니다.
개발자라면 REST라는 이름은 한번쯤 들어보셨을 것입니다. 트렌비에 입사하고 나서 파트너와 연동하는 API를
개발하면서 우리가 작성하는 API가 RESTful한지 의문이 생기면서 REST API가 무엇인지에 대해 명확하게 알고자
이번 포스팅을 작성하게 되었습니다.
REST API란 무엇인가와 REST API의 몇 가지 디자인 규칙을 소개하고자 합니다.

REST API란 무엇인가

REST API란 REST를 기반으로 만들어진 API를 의미합니다. 그렇다면 REST는 무엇일까요?
REST는 REpresentational State Transfer의 약자로 소프트웨어 프로그램 아키텍처의 한 형식이며,
자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미합니다.

즉, REST란

  1. HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고,
  2. HTTP Method(POST, GET, PUT, DELETE)를 통해
  3. 해당 자원(URI)에 대한 CRUD Operation을 적용하는 것을 의미합니다.

💡 CRUD Operation이란?
CRUD는 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능인 Create(생성), Read(읽기), Update(갱신), Delete(삭제)를 묶어서 일컫는 말로 REST에서의 CRUD Operation 동작 예시는 다음과 같습니다.

Create : 데이터 생성(POST)
Read : 데이터 조회(GET)
Update : 데이터 수정(PUT)
Delete : 데이터 삭제(DELETE)

REST의 특징

REST에 의미에 대해서 알아보았으니 어떤 특징이 있는지 살펴보도록 하겠습니다.

  • 클라이언트 / 서버 구조 (Client-Server)
    자원이 있는 Server, 자원을 요청하는 Client의 구조를 가집니다.
  • 무상태 (Stateless)
    Stateless 프로토콜이므로 REST 역시 무상태성을 가집니다. 클라이언트의 Context를 서버에 저장하지 않습니다.
  • 캐시 처리 가능 (Cacheable)
    웹 표준 HTTP 프로토콜을 그대로 사용하므로, 웹에서 사용하는 기존의 인프라를 그대로 활용할 수 있습니다.
  • 계층화
    API 서버는 순수 비즈니스 로직을 수행하고 그 앞단에 사용자 인증, 암호화, 로드밸런싱 등을 하는 계층을 추가하여 구조상의 유연성을 줄 수 있습니다.
  • 인터페이스 일관성(Uniform Interface)
    URI로 지정한 자원에 대한 조작을 통일하고 한정적인 인터페이스로 수행한다. HTTP 표준에만 따른다면 모든 플랫폼에 사용할 수 있습니다.
  • 자체 표현 구조
    동사(Method) + 명사(URI)로 이루어져 있어 어떤 메서드에 무슨 행위를 하는지 알 수 있으며 REST API 자체가 매우 쉬워서 API 메시지 자체만 보고도 API를 이해할 수 있습니다.

REST의 장단점

REST의 다양한 특징 중에 장점과 단점은 어떤 것들이 있을까요?

장점
  • 쉬운 사용
    HTTP 프로토콜 인프라를 그대로 사용하므로 별도의 인프라를 구축할 필요가 없습니다.
  • 클라이언트-서버 역할의 명확한 분리
    클라이언트는 REST API를 통해 서버와 정보를 주고받는다. REST의 특징인 Stateless에 따라 서버는 클라이언트의 Context를 유지할 필요가 없습니다.
  • 특정 데이터 표현을 사용 가능
    HTTP 프로토콜을 사용하면 헤더 부분에 URI 처리 메소드를 명시하고 필요한 실제 데이터를 ‘body’에 표현할 수 있다. JSON, XML 등 원하는 format으로 사용 가능합니다.
단점
  • 표준이 자체가 존재하지 않아 정의가 필요합니다.
  • 메소드의 한계
    REST는 HTTP 메소드를 이용하여 URI를 표현합니다. 이러한 표현은 쉬운 사용이 가능하다는 장점이 있지만 반대로 메소드 형태가 제한적인 단점이 있습니다.
  • 구형 브라우저가 아직 제대로 지원해주지 못하는 부분이 존재합니다.
    (PUT, DELETE를 사용하지 못하는 점)

이제 REST API가 어떠한 것인지 충분히 알았으니, 우리가 말하는 RESTful한 API는 무엇일까요?
REST에는 위에 특징처럼 기본 원칙이 있고, 이 가이드를 준수한 인터페이스는 RESTful하다고 표현합니다.
그렇다면, 실제 RESTful 한 API 설계는 어떠한 것이 있는지 알아보겠습니다.

RESTful한 API

1. 소문자를 사용합니다.
  • 주소에서 대소문자를 구분하므로, 카멜방식이 아닌 소문자를 사용하여 작성합니다.
    BAD
    open-api.marine.com/Partners
    
    GOOD
    open-api.marine.com/partners
    

    💡 카멜표기법이란?
    이른바 낙타표기법은 말 그대로 낙타의 등 모습을 닮은 표현법입니다. 카멜표기법은 기본적으로 변수명을 모두 소문자로 씁니다. 다만 여러 단어가 이어지는 경우 첫 단어를 제외하고 각 단어의 첫 글자만 대문자로 적습니다.
    integer type의 변수를 예시로 보면,
    int myFirstVariable;
    방금 선언한 변수는
    my, first, variable의 세 단어로 되어있습니다.
    모두 소문자로 작성하되, 첫 단어를 제외한 각 단어의 첫 글자를 대문자로 사용합니다.
    즉, my를 제외한 first와 variable의 첫 단어만을 바꿔주는 표기법입니다!

2. 언더바(_) 대신 하이픈(-)을 사용합니다.
  • 가급적 하이픈(-)의 사용도 최소화하며, 정확한 의미나 표현을 위해 단어의 결합이 불가피한 경우에 사용합니다.
    BAD
    open-api.marine.com/partner_boards
    
    GOOD
    open-api.marine.com/partner-boards
    
3. 마지막에 슬래시(/)를 포함하지 않습니다.
  • 슬래시(/)는 계층을 구분하는 것으로, 마지막에는 사용하지 않습니다.
    BAD
    open-api.marine.com/partners/
    
    GOOD
    open-api.marine.com/partners
    
4. 행위는 포함하지 않습니다.
  • 행위는 URL 대신 Method를 사용하여 전달합니다.(GET, POST, PUT, DELETE 등)
    BAD
    GET open-api.marine.com/get-partner/1
    
    GOOD
    GET open-api.marine.com/partner/1
    
5. 파일 확장자는 URI에 포함하지 않습니다.
  • REST API에서는 메시지 바디 내용의 포맷을 나타내기 위한 파일 확장자를 URI 안에 포함하지 않습니다.
  • HTTP에서 제공하는 형식 선택 메커니즘인 Accept header를 사용하도록 합니다.
    BAD
    GET open-api.marine.com/partners/photo.jpg
    
    GOOD
    GET open-api.marine.com/partners/photo  
    HTTP/1.1 Host : open-api.marine.com Accept : image/jpg
    
6. Control Resoruce의 경우 동사 형태를 허용합니다.
  • Function, Control Resource등을 나타내는 URL은 동작을 포함하는 동사 형태의 이름을 허용합니다. 즉, HTTP Method(GET, POST, PUT, PATCH, DELETE)로 표현되는 행위들인, 조회, 생성, 전체 수정, 단일 수정, 삭제 관련 행위 외에 다른 행위를 표현해야 하는 경우, 동사 형태를 허용합니다.
    open-api.marine.com/products/{id}/duplicate  
    open-api.marine.com/orders/{id}/search
    
7. 리소스 간에는 연관 관계가 있는 경우
  • 옵션 1 : 서브 리소스로 표현하는 방법 예를 들면, 등록된 상품들 중 1번 상품의 리뷰 목록을 표현한다면,
    /”리소스명”/”리소스 id”/”관계가 있는 다른 리소스명” 형태
    open-api.marine.com/order-items/{id}/reviews  
    open-api.marine.com/order-items/1/reviews
    
  • 옵션 2 : 서브 리소스에 관계를 명시하는 방법 만약에 관계명이 복잡하다면 이를 명시적으로 표현하는 방법이 있습니다. 예를 들어 “marine” 이라는 이름을 가진 사용자가 찜(좋아요)한 상품 목록을 표현한다면,
    open-api.marine.com/users/{id}/likes/items  
    open-api.marine.com/users/marine/likes/items
    

와 같이 작성하는 방식이 있습니다.
옵션 1의 경우 일반적으로 소유 ‘has’의 관계를 묵시적으로 표현할 때 좋으며,
옵션 2의 경우에는 관계명이 애매하거나 구체적인 표현이 필요할 때 사용합니다.

마치며

이번 포스팅을 진행하면서 특정 URI가 리소스를 적절히 설명했을 때 가장 좋은 디자인이면서,
특정 URI는 누구든 예측 가능하게 작성되어야한다고 생각합니다.

RESTful API는 소비자이며,
URI의 이름이나 구조는 이러한 소비자에게 의미를 전달할 수 있어야 합니다.

위의 규칙들을 적용한다면 조금 더 명확한 REST API를 구축해보면서 API를 호출하는 개발자는 편하게 작성된 API를 사용할 수 있을 것입니다.
반드시 지켜야 하는 제약은 아니지만, 위의 규칙들을 준수해봄으로써 API는 깨끗해질 수 있을 거라고 생각합니다.

이 글을 마무리하며, REST API에 대해 많은 이해가 생겼기를 바랍니다.

thanks