REST API(Representational State Transfer)는 기존의 HTTP 통신 프로토콜을 제대로 활용하기 위해 만들어진 규칙이다. 또한 인터넷은 더이상 HTML형식에만 국한되지 않고 Ajax, JSON, XML, YAML등의 여러 형식을 지원하고 있다. 이에 따라 다양한 환경과 용도에 맞는 데이터를 제공하는 디자인으로 REST API를 사용하는 경우가 많아졌다. 이번 포스트에서는 REST API의 개념을 숙지하고 장고에서 REST API를 구현하는 방법들에 대해 정리해보자.

해당 포스트는 Two Scoops of Django의 16장 REST API 구현하기를 요약하여 작성하였다.


RESTful하다?

  • 모든 자원에는 ID가 부여되며 ID를 통해 서로 구별된다.
  • 모든 자원은 연결될 수 있다.
  • HTTP 및 대부분의 소프트웨어가 가지는 기본적인 데이터 처리기능인 표준 통신메서드를 사용한다.(Create-POST(생성), Retrieve-GET(조회), Update-PUT(수정), Delete-DELETE(삭제))


패키지 API를 제작하기 위한 패키지들

(장고 기준)

django-rest-framework

프로젝트시 사용했던 패키지로, 장고의 클래스 기반 뷰를 바탕으로 브라우징이 가능한 편리한 API 기능을 제공한다. 현존하는 패키지 중에서는 클래스 기반 뷰와 함수 기반 뷰를 모두 제공하기 때문에 가장 많이 사용된다.


django-tastypie

링크

django-tastypie를 사용하면 자체적으로 제공하는 클래스 기반 뷰 시스템으로 장고에서 API를 제작할 수 있다.


django-braces, django-jsonview

단순하게 API를 제작하고 싶을 경우에는 django-bracesdjango-jsonview를 사용할 수 있다.

django-braces는 클래스 기반 뷰를 제공하며 다양한 기능의 Mixin을 제공하고 있다. 현재 장고에는 자주쓰는 LoginRequiredMixin과 같은 기능은 내장되어 있다.

django-jsonview는 파이썬 객체를 JSON 형태로 변환해주는 간단한 데코레이터를 제공한다.


HTTP 메서드

REST API는 앞서 말한 것 처럼 HTTP 프로토콜을 제대로 활용하기 위해 만들어진 규칙이다. HTTP는 콘텐트를 배포하기 위한 액션을 정의한 메서드 집합을 제공하는데, REST API 구현시 반드시 이러한 메서드들에 대한 개념을 알고 사용하여야 한다.

HTTP 메서드 요청 목적 비슷한 개념의 SQL 명령어
POST 새로운 리소스 생성 INSERT
GET 리소스 읽기 SELECT
HEAD 리소스의 메타데이터 요청  
PUT 리소스 수정(업데이트) UPDATE
PATCH 리소스 부분 수정 UPDATE
DELETE 리소스 삭제 DELETE
OPTIONS 현재 웹서버에서 지원하는 method가 어떤 것들이 있는지 출력  
TRACE 요청에 대한 반환 에코(다시 알려줌), 디버깅시 유용하게 사용가능  
CONNECT TCP/IP 터널링(일반적으로 구현x)  


메타데이터?

메타(Meta)는 일반적으로 ~에 관한이라는 의미를 지니고 있다. 따라서 메타데이터는 다른 데이터를 기술하기 위해 사용하는 데이터라고 할 수 있다. 요약하면 ‘데이터에 관한 구조화된 데이터로, 다른 데이터를 설명해주는 데이터라 할 수 있다.

HEAD 메서드를 사용하면 전체 표현을 읽지 않고도 메타데이터를 통해 리소스의 정보를 파악할 수 있다. 클라이언트는 OPTIONS 또한 사용하는데, 해당 메서드를 통해 특정 리소스에 허가된 메서드를 검사할 수 있다.


CONNECT와 터널링

http 요청 메서드 중 CONNECT는 생소해서 좀 더 찾아보았다. 먼저 설명에 필요한 프록시터널 등에 대한 개념을 정리하면 다음과 같다. 프록시는 서버와 클라이언트의 양쪽 역할을 하는 중계 프로그램이다. 클라이언트로부터 요청을 서버에 전송하고 서버로부터 받은 응답을 클라이언트에 전송한다.

이러한 프록시 서버 중 일부는 터널을 구성한다. 터널은 서로 떨어진 두 대의 클라이언트와 서버 사이를 중계하면서 접속을 유지해주는 중계 프로그램이다. 터널은 요청에 따라서 다른 서버와의 통신 경로를 만들기도 하는데, 클라이언트가 인증(SSL, HTTPS)을 사용하여 서버와 안전하게 통신하려고 할 경우에도 사용한다.


HTTP 요청메서드와 REST API

  • 읽기 전용 API만 구현할 경우에는 GET을 사용한다.
  • 읽기/쓰기 API를 구현할 경우에는 POST, PUT, DELETE 등을 사용할 수 있다. PUT을 사용해도 POST와 같이 리소스를 생성할 수도 있다. 구현하기 나름이다.
  • 반대로 단순하게 작성하려면 모든 API의 통신 메서드를 GETPOST만으로 구현할 수도 있다.
  • GET, PUT,DELETE는 여러 번 실행해도 그 결과가 변하지 않는 멱등(idempotent) 관계이다.
  • POST, PATCH는 여러 번 실행할 때마다 변한다.
  • PUT을 구현했다면 PATCH도 구현하는 것이 좋다.


HTTP 메서드와 멱등 관계

멱등성(idempotence)이란 수학이나 전산학에서 연산을 여러 번 반복 적용해도 결과가 달라지지 않는 성질을 의미한다. 예를 들어 4를 계속 곱해도 같은 값이 나오게 하려면 0을 계속 곱하거나 1을 곱하면 된다.

4 * 1 * 1 * ... * 1 = 4    # 언제나 4
4 * 0 * 0 * ... * 0 = 0    # 언제나 0

이처럼 HTTP 메서드에서도 여러 번 같은 요청을 보냈을 때 같은 결과를 보내주는 메서드들이 있다. GET, PUT, HEAD, DELETE 등이 바로 멱등성을 띤다. 즉, HTTP 메서드에서 멱등성은 동일한 요청에서 동일한 결과를 보장함을 의미한다. 즉, 자체 context가 없으면 멱등성이 성립한다.

먼저, GETHEAD요청은 데이터를 읽기만 하고 서버의 상태를 바꾸지 않는다. readonly의 성격을 가지기 때문에 당연히 context가 필요 없다. 그렇다면 PUT은 왜 멱등성을 충족할까? PUT은 RESTful 관례상으로 replace를 의미하기 때문에 context를 가질 필요가 없다. 만약 개인정보를 수정해야한다면 원래의 개인정보는 사용자가 입력한 새로운 정보로 대체된다. PUT요청 시 항목 X를 B로 ‘간주’하게 되는 것이다.

POSTPATCH의 경우에는 RESTful 관례상 자체적으로 요청을 처리하는 함수가 자체 context를 가지기 때문에 매 요청마다 다른 결과가 나올 수 있다. 특히 PATCH는 RESTful 관례상 update를 의미하기 때문에 context를 가진다. PUT과는 달리 항목 X를 A에서 B로 변경하는 것이기 때문에 A의 값에 따라 결과가 달라질 수 있다.

DELETE를 쓸 때는 한번 요청을 보내면 해당 URL의 리소스가 삭제된다. 그리고 다음에 같은 요청을 보내도 이미 지워진 내용을 또 지운 것이므로 결과가 같다. 따라서 멱등법칙이 성립하는 것이다.

멱등성은 설계에 따라 성립하지 않을 수도 있다. 당연한 말이지만 위에서 설명한 HTTP 메서드들의 멱등성은 서버 개발자가 어떻게 구현하고 설계하느냐에 따라 성립하지 않을 수도 있다. 장고에서는 자동으로 관례를 따르기 때문에 알아두는 것이 좋다.

정리하면 HTTP의 멱등성은 동일한 요청(input)을 입력할 때 동일한 결과(output)가 나오는 것을 의미한다. 이러한 멱등성은 HTTP 통신의 신뢰성을 높여준다. 여러 번 요청 후에도 같은 결과가 보장될 경우 요청이 실패했다고 해도 단순히 같은 요청을 다시 보내면 되기 때문이다. 이미 먼저 보낸 요청이 처리되었을 경우에도 같은 결과이므로 상관없다. 그렇다면 멱등관계가 성립되지 않는 POST, PATCH와 같은 메서드는 어떨까? 당연히 안전하지 않다.


HTTP 상태코드

기본적이고 자주 쓰이는 상태코드는 다음 링크를 참고하면 된다. 해당 포스트에서는 상태코드 중 기억하면 좋을 것만 정리해 보았다.

범위별 응답코드 의미

  • 100번대 : 요청이 들어왔을 때 정보적인 성격을 띠는 응답을 돌려준다.
  • 200번대 : 요청이 들어왔을 때 요청의 성격에 따라 ‘성공’ 응답을 돌려준다.
  • 300번대 : 클라이언트의 요청을 수행하기 위해 부가적인 액션을 취해야한다는 응답을 돌려준다. 보통 요청을 리다이렉트(우회)할 때 사용한다.
  • 400번대 : 클라이언트에 의해 요청이 실패했을 때의 응답을 돌려준다.
  • 500번대 : 서버가 정당한 요청을 수행하지 못했을 때의 응답을 돌려준다.


API 업데이트 시 기억해두면 좋을 응답코드

HTTP 상태코드 성공/실패 의미
410 GONE 실패 모든 통신메서드 - 더이상 제공되지 않는 메서드로 호출하여 새 버전의 API를 제공하기 위해 기존 API 서비스를 중지할 때 이용된다. 예를 들어 모바일 앱의 경우에는 해당 결과에 대해 사용자에게 어플 업그레이드를 요청하는 방법을 사용한다.


HTTP 응답코드 200202의 차이에 대하여

HTTP 응답코드는 서버에서 브라우저의 요청을 받아 응답을 반환하며 보내주는 상태를 알려준다. 그런데 최근 성공코드에 해당하는 200코드와 202코드에 대한 차이를 설명하라는 질문을 받고 당황한 기억이 있다. 프로젝트 도중 202 코드를 사용한 적이 있었는데 의미를 제대로 알고 썼는지 알아보는 질문이었다. 나중에 책을 찾아보고 자주쓰이는 200 통신과 거의 사용하지 않는 202 응답 코드의 차이를 알아보았다.

200 OK의 의미는 HTTP 요청이 성공했을 때 가장 많이 사용하는 응답코드이다. 요청 메서드가 GET일 때는 응답에 요청된 자원을 포함한다. 요청 메서드가 POST일 때는 응답에 액션의 결과를 포함한다.

그렇다면 자주 쓰지 않는 202 Accepted는 어떤 의미일까? 200과 마찬가지로 성공적인 응답코드이기는 하지만 요청에 대한 응답이 돌아오는 것과 상관없이 성공 코드를 먼저 출력해버린다. 따라서 요청에 대한 응답이 맞는지 체크하는 과정을 생략하고 무조건 성공 메세지를 보내게 되는 것이다.


해당 포스트는 Two Scoops of Django 도서의 16장 REST API 구현하기 <2부>로 계속됩니다. 2부에서는 REST API를 효율적으로 설계하는 방법들에 대해 소개합니다.


참고자료



Julia Hwang

디발자를 꿈꾸는 웹개발자의 블로그입니다.