제작중인 서비스형 블로그의 발전을 위해서 RESTful과 프론트엔드 프레임워크의 도입을 시도하고자 하였다. RESTful API의 개념은 어느정도 알고 있었지만 이를 어떻게 장고에서 구현하는지가 이 글의 핵심이다.


RESTful API


REST란?

REST는 Representational State Transfer의 약어로서 웹의 장점과 HTTP의 우수성을 제대로 활용할 수 있는 아키텍처이다. HTTP URI를 통해서 자원을 명시하고 HTTP Method(POST, GET, PUT, DELETE)를 통해서 해당 자원의 CURD 연산을 적용하는 것을 의미한다.

따라서 REST는 자원(Resource), 행위(Verb), 표현(Representations)으로 구성된 아키텍처라 볼 수 있으며 이 글을 보고 필요성에 대해서 느낄 수 있었다. 해당 글을 정리하자면 코드의 재사용성을 높일 수 있으며 프론트엔드와 백엔드의 완전한 분업이 가능하다고 말한다.


REST의 특징

Uniform Interface : URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일, HTTP 표준 프로토콜을 따르는 모든 플랫폼에서 사용 가능

Stateless : 작업을 위한 상태정보(쿠키나 세션)를 보관하고 관리하지 않는다. 요청만 처리하면 되므로 구현이 단순해짐

Cacheable : 웹 표준 프로토콜을 그대로 사용하므로 기존의 인프라를 활용할 수 있으므로 캐싱 기능을 사용할 수 있음

Self-descriptiveness : REST API 메시지만 보고도 쉽게 이해할 수 있는 자체 표현 구조로 되어 있음

Client-Server : 자원을 가진 쪽이 Server, 자원을 요청하는 쪽이 Client 각각의 역할이 확실히 구분되기 때문에 서로간 의존성이 줄어들게 됨

  • Server : API를 제공하고 비즈니스 로직 처리 및 저장을 책임
  • Client : 사용자 인증이나 상태정보를 직접 관리하고 책임

Layered System : REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게함


디자인 가이드

URI는 정보의 자원을 표현해야 한다.

블로그 서비스라는 가정하에 아래와 같이 URI를 표현할 수 있다.

1
2
/posts/N   (포스트)
/members/N (멤버)

주의사항은 다음과 같다.

  • 슬래시는 계층 관계를 나타낼 때 사용
  • 마지막 문자로 슬래시를 포함하지 않음
  • 하이픈은 가독성 높이는데 사용
  • 언더바는 사용하지 않음
  • 소문자가 적합함
  • 파일 확장자는 포함하지 않음

계층 관계는 어떻게 표현할까?

1
2
3
/members
/members/N
/members/N/likes

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

잘못된 예

1
2
3
4
POST /members/create   (회원 정보 추가함)
GET  /members/N/get    (회원 정보 가져옴)
POST /members/N/update (회원 정보 수정함)
POST /members/N/delete (회원 정보 삭제함)

올바른 예

1
2
3
4
GET    /members/N (회원 정보 가져옴)
POST   /members/N (회원 정보 추가함)
PUT    /members/N (회원 정보 수정함)
DELETE /members/N (회원 정보 삭제함)


HTTP 응답코드

코드 내용
200 클라이언트의 요청을 정상적으로 수행함
201 클라이언트가 어떠한 리소스 생성을 요청 이후 성공적으로 생성됨
400 클라이언트의 요청이 부적절함
401 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 때 사용하는 응답 코드(로그인 하지 않은 유저가 로그인 했을 때, 요청 가능한 리소스를 요청했을 때)
403 유저 인증과 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때(400, 404를 사용하는 것을 추천)
405 클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드
301 클라이언트가 요청한 리소스에 대한 URI가 변경 되었을 때 사용
500 서버에 문제가 있을 경우 사용하는 응답 코드


장고 REST API 구현

어떻게 구현해야 할까? 직접 HTTP MethodContent-type을 알아내고 적절한 응답을 해야할까 고민했지만 DjangoRESTframework가 있다는 것을 알게 되었다. 퀵스타트 튜토리얼을 보고 따라했는데 의외로 정말 간단하게 구현할 수 있음에 놀랐고 실제로 적용하려면 응용을 더 해봐야 할 듯 하다.

장고를 이용하여 일반적인 웹 서버를 개발할때와 REST Framework를 활용했을때 느껴진 차이점은 아래와 같았다.

1
2
3
4
5
6
7
8
9
10
11
12
13
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']

한번도 활용해보지 않았던 serializers를 사용하는 것이 새로웠으며 forms.py를 구현하지 않는 대신 사용하는 것인가 하는 생각이 들었다.

1
2
3
4
5
6
7
8
9
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

class GroupViewSet(viewsets.ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

또한 urls.py에선 직접 호출가능한 view.py에 함수를 구현하는 것이 지금까지 일반적이라 생각했지만 REST에서는 위와 같이 구현하고

1
2
3
4
5
6
7
8
9
10
11
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

views.py에서 구현된 함수들은 urls.py에서 router라는 객체가 실행시켜준다. 이는 rest_framework의 내부 동작이므로 자세한 내용은 문서를 읽어야 파악이 가능할 듯 보인다.


결과

구현이 간단해지는 프레임워크의 도입은 환영이다. 튜토리얼만 진행한 RESTful API는 그러한 느낌이지만 REST API가 정말 쉬운 아키택쳐 인지는 잘 모르겠다. HTTP와 REST에 대한 명확한 이해가 필요해 보인다.

추가(2019-11-11)

위 영상을 이제야 제대로 보았는데 웹과 REST에 대해서 전체적인(왜 어떻게 만들었는지 등) 설명을 해주셔서 굉장히 좋았다. 또한 필자가 제작하는 사이트는 혼자 풀스택을 개발하고 있는 프로젝트이기 때문에 굳이 백엔드를 REST API로 바꾸고 프론트엔드 프레임워크를 사용하는게 맞는 걸까하는 고민을 해결해 주었다. 적용하지 않을거다!! 공부는 하겠지만…

영상 내용 정리

영상 내용 정리


참고

WRITTEN BY

배진오

소비적인 일보단 생산적인 일을 추구하며, 좋아하는 일을 잘하고 싶어합니다 :D
im@baejino.com