# RESTful API의 개념과 장고의 REST Framework

- Author: @baealex
- Published: 2020-03-02
- Updated: 2021-11-11
- Source: http://blex.me/@baealex/restful-api%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%9E%A5%EA%B3%A0%EC%9D%98-rest-framework
- Tags: 프로그래밍, 파이썬, 아키택쳐, 장고

---

> 기존 블로그의 글을 옮겨온 글임 From. 2019.10.15

제작중인 서비스형 블로그의 발전을 위해서 `RESTful`과 프론트엔드 프레임워크의 도입을 시도하고자 하였다. `RESTful API`의 개념은 어느정도 알고 있었지만 이를 어떻게 장고에서 구현하여 활용하는지가 핵심적인 궁금증이다.

<br>

![](https://static.blex.me/images/content/2020/4/16/baealex/22_oFWVYLQhNGOztjuuj3bE.jpg)

<br>

## REST API란?

> REST는 Representational State Transfer의 약어로서 웹의 장점과 HTTP의 우수성을 제대로 활용할 수 있는 아키텍처이다. HTTP URI를 통해서 자원을 명시하고 HTTP Method(POST, GET, PUT, DELETE)를 통해서 명시된 자원의 CURD 연산을 적용하는 것을 의미한다.

따라서 REST는 자원(Resource), 행위(Verb), 표현(Representations)으로 구성된 아키텍처라 볼 수 있으며 미디움의 어떤 글을 보고 필요성에 대해서 느낄 수 있었다. 해당 글을 정리하자면 코드의 재사용성을 높일 수 있으며 프론트엔드와 백엔드의 완전한 분업이 가능하다고 말한다.

- [REST의 representation이란 무엇인가](https://blog.npcode.com/2017/04/03/rest%EC%9D%98-representation%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/)
- [Django REST API의 필요성과 간단한 사용 방법](https://medium.com/@whj2013123218/django-rest-api%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1%EA%B3%BC-%EA%B0%84%EB%8B%A8%ED%95%9C-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95-a95c6dd195fd)

<br>

#### REST API의 특징

REST 아키텍처는 다음과 같은 특징을 가지고 있다.

###### Uniform Interface

URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일이다. HTTP 표준 프로토콜을 따르는 모든 플랫폼에서 사용이 가능하다.

###### Stateless

작업을 위한 상태 정보(쿠키, 세션)를 보관하거나 관리하지 않고 요청만 처리하면 되므로 구현이 단순해진다.

###### Cacheable

웹 표준 프로토콜을 그대로 사용하므로 기존의 인프라를 활용할 수 있으므로 캐싱 기능을 사용할 수 있다.

###### Self-descriptiveness

REST API 메시지만 보고도 쉽게 이해할 수 있는 자체 표현 구조로 되어 있다.

###### Client-Server

자원을 가진 쪽이 Server, 자원을 요청하는 쪽이 Client 각각의 역할이 확실히 구분되기 때문에 서로간 의존성이 줄어들게 됨

- Server : API를 제공하고 비즈니스 로직 처리 및 저장을 책임
- Client : 사용자 인증이나 상태정보를 직접 관리하고 책임

###### Layered System

REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 한다.

<br>

#### 디자인 가이드

**URI는 정보의 자원을 표현해야 한다.**

블로그 서비스라는 가정하에 아래와 같이 URI를 표현할 수 있다.

```
/posts/N   (포스트)
/members/N (멤버)
```

> 주의사항은 다음과 같다.

- 슬래시는 계층 관계를 나타낼 때 사용
- 마지막 문자로 슬래시를 포함하지 않음
- 하이픈은 가독성 높이는데 사용
- 언더바는 사용하지 않음
- 소문자가 적합함
- 파일 확장자는 포함하지 않음

> 계층 관계는 어떻게 표현할까?

```
/members
/members/N
/members/N/likes
```

**자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.**

*잘못된 예*

```
POST /members/create   (회원 정보 추가함)
GET  /members/N/get    (회원 정보 가져옴)
POST /members/N/update (회원 정보 수정함)
POST /members/N/delete (회원 정보 삭제함)
```

*올바른 예*

```
GET    /members/N (회원 정보 가져옴)
POST   /members/N (회원 정보 추가함)
PUT    /members/N (회원 정보 수정함)
DELETE /members/N (회원 정보 삭제함)
```

<br>

#### HTTP 응답코드

| 코드 | 내용 |
| --- | --- |
| 200 | 클라이언트의 요청을 정상적으로 수행함 |
| 201 | 클라이언트가 어떠한 리소스 생성을 요청 이후 성공적으로 생성됨 |
| 400 | 클라이언트의 요청이 부적절함 |
| 401 | 클라이언트가 인증되지 않은 상태에서 보호된 리소스를 요청했을 때 사용하는 응답 코드(로그인 하지 않은 유저가 로그인 했을 때, 요청 가능한 리소스를 요청했을 때) |
| 403 | 유저 인증과 관계 없이 응답하고 싶지 않은 리소스를 클라이언트가 요청했을 때(400, 404를 사용하는 것을 추천) |
| 405 | 클라이언트가 요청한 리소스에서는 사용 불가능한 Method를 이용했을 경우 사용하는 응답 코드 |
| 301 | 클라이언트가 요청한 리소스에 대한 URI가 변경 되었을 때 사용 |
| 500 | 서버에 문제가 있을 경우 사용하는 응답 코드 |

<br>

## 장고 REST API 구현

이것을 서비스에 적용하려면 어떻게 구현해야 할까? 직접 `HTTP Method`와 `Content-type`을 알아내고 적절한 응답을 해야할까 고민했으나 곧이어 `DjangoRESTframework`가 있다는 것을 알게 되었다. 튜토리얼을 보고 따라했는데 의외로 정말 간단한 것에 대하여 놀랐으나 실제로 서비스에 적용하려면 응용을 더 해봐야 할 듯 하다.

- [퀵스타트 튜토리얼](https://www.django-rest-framework.org/tutorial/quickstart/?source=post_page-----a95c6dd195fd----------------------)

장고를 이용하여 일반적인 웹 서버를 개발할 때와 REST Framework를 활용했을 때 느껴진 차이점은 아래와 같았다.

```python
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']
```

그간 한번도 다뤄보지 않았던 `Serializer`라는 것을 구현한다. `Form`과 비슷한 구조로 구현하는 듯 보였다.

```python
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`에서는 위와 같이 `view`를 구현하고

```python
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`의 내부 동작이므로 자세한 내용은 문서를 읽어야 파악이 가능할 듯 보인다. 또한 디자인 가이드 몇몇이 지켜지지 않는 것 같아 보였는데, 이도 세부설정이 가능한지 살펴봐야 할 것 같다.

<br>

## 느낀점

구현이 간단해지는 프레임워크의 도입은 환영이라 생각한다. 튜토리얼만 진행한 RESTful API는 그러한 느낌이었다. 다만 REST API가 정말 쉬운 아키택쳐 인지는 잘 모르겠다. HTTP와 REST에 대한 명확한 이해가 필요해 보인다.

- [그런 REST API로 괜찮은가](https://slides.com/eungjun/rest#/)
- [REST API 제대로 알고 사용하기](https://meetup.toast.com/posts/92)

@youtube[RP_f5dMoHFc]

위 영상을 최근에야 제대로 보았는데 웹과 `REST`에 대해서 전체적인(왜? 어떻게? 만들었는지 등) 설명을 해주셔서 굉장히 좋았다. 또한 필자는 항상 궁금증을 가지고 있었다. 정말 내 프로젝트에 이 REST API를 도입하는게 맞는가에 대해서. 그 고민을 이 영상이 해결해 주었다. 적용하지 않을 것 같다. (현재는 부분부분 도입중) 공부는 하겠지만...

![](https://static.blex.me/images/content/2020/4/16/baealex/22_ynSKkdyUdIiyYhEWNO1h.jpg)

![](https://static.blex.me/images/content/2020/4/16/baealex/22_5vvpj2PZhheqiyvhDhZJ.jpg)
