- Unit 1. RESTful API 개요
- Unit 2. Django REST Framework
- Unit 3. RESTful API 구현
REST 정의
- Representational State Transfer (REST):
- 자원(Resource)의 표현(Representation)에 의한 요청정보 전달
- 주로 JSON 또는 XML 데이터를 통해 응답
- 웹의 기존 기술과 HTTP 프로토콜을 활용하는 통신 방식
REST 개념
- HTTP URI:
- URI를 통해 자원(Resource)을 명시하고, HTTP Method(POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 CRUD 기능을 적용하는 것을 의미한다
REST API
- API(Application Programming Interface):
- 데이터와 기능의 집합을 제공하여 컴퓨터 프로그램간 상호작용을 촉진하며, 서로 정보를 교환가능 하도록 하는 것
- REST API:
- REST 기반으로 서비스 API를 구현한 것
- OpenAPI: 누구나 사용할 수 있도록 공개된 API (구글 맵, 공공 데이터 등)
- 마이크로 서비스: 하나의 큰 애플리케이션을 여러 개의 작은 애플리케이션으로 쪼개어 변경과 조합이 가능하도록 만든 아키텍처
REST API 설계 규칙
- URI:
- URI는 정보의 자원을 표현해야 한다
- 자원에 대한 행위:
- HTTP Method(GET, PUT, POST, DELETE)로 표현한다
- 슬래시 구분자:
- 계층 관계를 나타낸다
- URI 마지막 문자:
- 슬래시를 포함하지 않는다 (Django는 /를 붙이는 것을 권장함)
- 하이픈:
- URI 가독성을 높이는데 사용한다
- 밑줄:
- URI에 사용하지 않는다
- URI 경로:
- 소문자가 적합하다
- 파일확장자:
- URI에 포함하지 않는다
RESTful
- RESTful:
- REST라는 아키텍처를 구현하는 웹 서비스를 나타내기 위해 사용되는 용어이다. 'REST를 제공하는 웹 서비스를 'RESTful하다'고 할 수 있다
- RESTful의 목적:
- 이해하기 쉽고 사용하기 쉬운 REST API를 만드는 것
- RESTful한 API 구현 목적은 성능 향상이 아니라 일관적인 컨벤션을 통한 API의 이해도 및 호환성을 높이는 것
- 성능이 중요한 상황에서는 굳이 RESTful한 API를 구현할 필요는 없다
정리
RESTful API
는 자원을 명시하는URI
와HTTP Method
를 사용하여 웹 서비스 간의 상호작용을 촉진하고, 일관적인 API 설계를 통해 사용성과 호환성을 높이기 위한 아키텍처 스타일입니다.- 이를 통해 사용자는 이해하기 쉽고, 유지보수가 용이한 API를 설계할 수 있습니다.
RESTful
한API
의 목표는 성능보다는 일관성과 가독성을 중시하는 것입니다.
- 커맨드창
pip install djangorestframework
mysite2/settings.py:
INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "rest_framework", ]
mysite2/urls.py:
from django.urls import path, include from django.contrib import admin from django.conf import settings from django.conf.urls.static import static from mysite2.views import HomeView urlpatterns = [ path('', HomeView.as_view(), name='home'), path('admin/', admin.site.urls), path('blog/', include('blog.urls')), path('api/', include('api.urls')), path('api2/', include('api2.urls')), ]
api2/serializers.py:
from django.contrib.auth.models import User from rest_framework import serializers class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User fields = ['url', 'username', 'email', 'is_staff']
api2/views.py:
from django.contrib.auth.models import User from rest_framework import viewsets from .serializers import UserSerializer, PostSerializer from blog.models import Post class UserViewSet(viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer
api2/urls.py:
from django.urls import path, include from rest_framework import routers from .views import UserViewSet, PostViewSet router = routers.DefaultRouter() router.register('users', UserViewSet) router.register('posts', PostViewSet) urlpatterns = [ path('', include(router.urls)), ]
api2/serializers.py:
from django.contrib.auth.models import User from rest_framework import serializers from blog.models import Post, Comment class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User fields = ['url', 'username', 'email', 'is_staff'] class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ['id', 'title', 'image', 'like', 'category'] class CommentSerializer(serializers.ModelSerializer): class Meta: model = Comment fields = '__all__'
api2/views.py:
from django.contrib.auth.models import User from rest_framework import viewsets from .serializers import UserSerializer, PostSerializer, CommentSerializer from blog.models import Post, Comment class UserViewSet(viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer class CommentViewSet(viewsets.ModelViewSet): queryset = Comment.objects.all() serializer_class = CommentSerializer
api2/urls.py:
from django.urls import path, include from rest_framework import routers from .views import UserViewSet, PostViewSet, CommentViewSet router = routers.DefaultRouter() router.register('users', UserViewSet) router.register('posts', PostViewSet) router.register('comments', CommentViewSet) urlpatterns = [ path('', include(router.urls)), ]
정리
- 1. 새로운 앱 생성
- 이 부분은 새로운 앱을 생성하고 해당 앱의
URL
을 프로젝트의 루트URL
에 연결하는 부분입니다.
- 2. 뷰 구현
- 뷰는 요청을 받아서 처리하는 부분을 담당합니다.
Serializer
는 모델 데이터를JSON
포맷으로 변환하거나 반대로JSON
데이터를 모델 객체로 변환하는 역할을 합니다.ViewSet
은 일반적인CRUD(Create, Retrieve, Update, Delete)
기능을 제공합니다.
- 3. Post REST API 구현
- 이 부분은 게시물(
Post
)에 대한REST API
를 구현하는 부분입니다. 게시물과 관련된 모델(Post
)과Comment
를 위한Serializer
와ViewSet
을 구현합니다.- 또한,
URLs
에 대한 설정도 하여 각각의 엔드포인트가 어떤ViewSet
과 연결되는지 설정합니다.이러한 구조를 통해
Django
를 사용하여 강력하고 유연한RESTful API
를 구축할 수 있습니다.
serializers.py
from rest_framework import serializers from blog.models import Post, Comment # 게시물 목록을 위한 Serializer class PostListSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ['id', 'title', 'image', 'like'] # 게시물 상세 정보를 위한 Serializer class PostRetrieveSerializer(serializers.ModelSerializer): class Meta: model = Post exclude = ['create_at']
Serializer
는 데이터를JSON
형식으로 변환하거나JSON
데이터를 모델 객체로 변환하는 역할을 합니다.- 위 코드에서는 게시물 목록을 위한
PostListSerializer
와 게시물 상세 정보를 위한PostRetrieveSerializer
를 정의합니다.
views.py
from rest_framework.generics import ListAPIView, RetrieveAPIView, CreateAPIView from .serializers import PostListSerializer, PostRetrieveSerializer, CommentSerializer from blog.models import Post, Comment # 게시물 목록을 보여주는 API 뷰 class PostListAPIView(ListAPIView): queryset = Post.objects.all() serializer_class = PostListSerializer # 특정 게시물을 보여주는 API 뷰 class PostRetrieveAPIView(RetrieveAPIView): queryset = Post.objects.all() serializer_class = PostRetrieveSerializer # 댓글을 생성하는 API 뷰 class CommentCreateAPIView(CreateAPIView): queryset = Comment.objects.all() serializer_class = CommentSerializer
- 여기서는
Django REST Framework
의 제네릭 뷰인ListAPIView
,RetrieveAPIView
,CreateAPIView
를 사용하여 게시물 목록을 보여주는PostListAPIView
, 특정 게시물을 보여주는PostRetrieveAPIView
, 그리고 댓글을 생성하는CommentCreateAPIView
를 정의합니다.
urls.py
from django.urls import path from . import views urlpatterns = [ path('post/', views.PostListAPIView.as_view(), name="post-list"), # 게시물 목록 path('post/<int:pk>/', views.PostRetrieveAPIView.as_view(), name="post-detail"), # 특정 게시물 path('comment/', views.CommentCreateAPIView.as_view(), name="comment-list"), # 댓글 생성 ]
URL
패턴을 정의하여 각API
뷰에 대한 엔드포인트를 지정합니다. 이렇게 하면/post/
,/post/<id>/
,/comment/
와 같은 경로로API
를 호출할 수 있습니다.
views.py
from rest_framework.generics import UpdateAPIView from rest_framework.response import Response from .serializers import PostListSerializer from blog.models import Post # 게시물에 좋아요를 추가하는 API 뷰 class PostLikeAPIView(UpdateAPIView): queryset = Post.objects.all() serializer_class = PostListSerializer def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() data = {'like': instance.like + 1} # 좋아요 수 증가 serializer = self.get_serializer(instance, data=data, partial=partial) serializer.is_valid(raise_exception=True) self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): instance._prefetched_objects_cache = {} return Response(serializer.data)
UpdateAPIView
를 상속받아 게시물에 좋아요를 추가하는PostLikeAPIView
를 정의합니다. 이API
는 요청이 들어올 때마다 해당 게시물의 좋아요 수를 증가시킵니다.
from django.urls import path from . import views urlpatterns = [ path('post/', views.PostListAPIView.as_view(), name="post-list"), # 게시물 목록 path('post/<int:pk>/', views.PostRetrieveAPIView.as_view(), name="post-detail"), # 특정 게시물 path('comment/', views.CommentCreateAPIView.as_view(), name="comment-list"), # 댓글 생성 path('post/<int:pk>/like/', views.PostLikeAPIView.as_view(), name="post-like"), # 게시물에 좋아요 ]
URL
패턴을 정의하여 게시물에 좋아요를 추가하는 엔드포인트를 만들었습니다. 이렇게 하면/post/<id>/like/
와 같은 경로로 게시물에 좋아요를 추가할 수 있습니다.