Django에서 Swagger를 적용해보자

wodnr_P·2023년 6월 28일
0

Django + Swagger

목록 보기
1/2
post-thumbnail

Swagger?

  • 어플리케이션의 REST API 문서를 자동으로 구성하는 도구입니다.

왜 사용하는 것일까?

  • 적용하기 어렵지 않습니다
  • 어플리케이션의 모든 엔드포인트를 Swagger UI로 한눈에 볼 수 있고, 즉시 테스트도 할 수 있습니다.

Swagger를 적용하는 이유

지금까지는 API의 명세를 주로 Notion에 작성하며 활용했지만 API별로 문서화한다는게 생각보다 시간도 많이 소모되고, 실수로 인해 오타가 나거나 빼먹는 일도 있기 때문에 앞으로의 프로젝트에서 이러한 점을 개선시켜보고자 Swagger를 적용해보도록 하겠습니다.


Swagger 환경 만들기

  • 설치 환경 : MacOS, Django 4.2.2 기준,
  • Test API : RD프로젝트의 user app copy
  • Django에서 지원하는 Swagger 모듈 중 대표적인 drf-yasg 를 사용했습니다.
    (django rest framework-Yet another Swagger generator)
  • 기본적으로 DRF 위에서 동작하기 때문에 django rest framework도 함께 설치하는 것이 필수 입니다.

    pip install djangorestframework
    pip install drf-yasg

1. settings.py 환경 설정

INSTALLED APPS = [
		... 
        'drf-yasg',
        'rest_framework'
		...
]

2. urls.py 설정

  • swagger문서에 접속할 수 있도록 설정하는 과정입니다.

project/urls.py

from drf_yasg.views import get_schema_view
from drf_yasg import openapi

...

schema_view = get_schema_view(
    openapi.Info(
        title="Swagger_Practise API",
        default_version='v1',
        description="Swagger Test를 위한 유저 API 문서",
        terms_of_service="https://www.google.com/policies/terms/",
        contact=openapi.Contact(email="contact@snippets.local"),
        license=openapi.License(name="BSD License"),
    ),
    public=True,
    permission_classes=[permissions.AllowAny],
)

...

# 디버그일때만 swagger 문서가 보이도록 해주는 설정, 
# 여기에 urlpath도 작성 가능해서 debug일때만 작동시킬 api도 설정할 수 있음
if settings.DEBUG:
    urlpatterns += [
        re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
        re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
        re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
    ]
  • python manage.py runseerver 실행 후, /swagger로 접속

3. API에 @Swagger auto Schema 추가

  • Swagger가 API의 내용을 문서화 시켜주는 기능입니다.
  • 개발자가 직접 해당 API에 대해 docs를 작성하는 방법과 Serializer를 통해 자동 포맷 시켜주는 방법이 있습니다.

3-1. 개발자가 직접 docs를 작성하는 방법

views.py

class SWAGGERTESTAPIView(APIVIEW):
	permission_classes = [permissions.AllowAny] #swagger에서 해당 API에 접근할 수 있는 권한 설정 (AllowAny - 모두)
    
    @swagger_auto_schema(
      operation_description="API 설명",
      operation_summary="API의 간단한 타이틀, 통합하는 주제",
      operation_id='API 구분하는 고유 값 (중복의 가능성있기 때문에 신경써야함)',
      tags=['그룹핑화 할 수 있는 곳'],
      manual_parameters=[Authorization], #query_params, request_header를 작성하는 부분
      query_serializer=ManagementUserSerializer, #query_params, request_header 작성(Serializer로 자동 포맷할 경우)
      responses={ #request_body도 responses와 같은 방법으로 작성, Mock-up 형태
      )
    def post(self, request):
  	...

3-2. Serializer를 통해 자동 포맷

serializer.py

from rest_framework import serializers
...
# request_body
class LoginUserSerializer(serializers.Serializer):
    username = serializers.CharField(help_text="아이디")
    password = serializers.CharField(help_text="패스워드")

class UserUpdateSerializer(serializers.Serializer):
    password = serializers.CharField(help_text="패스워드")
    nickname = serializers.CharField(help_text="닉네임")
    profile = serializers.ImageField(help_text="프로필이미지")

views.py에서 작성한 Serializer를 import해준 후 적용

# 로그인 API - jwt인증방식의 로그인 api
class LoginAPIView(APIView):
    permission_classes = [permissions.AllowAny]

    @swagger_auto_schema(
        tags=["로그인"], 
        request_body=LoginUserSerializer, # serializer 자동 포맷한 경우
        responses = { # 직접한 경우
            201: openapi.Response( # status code별로 구분해서 적용가능
                description="201 OK", 
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties = {
                        'access_token': openapi.Schema(type=openapi.TYPE_STRING, description="access_token"),
                        'access_exp': openapi.Schema(type=openapi.TYPE_STRING, description="access_exp"),
                        'refresh_token': openapi.Schema(type=openapi.TYPE_STRING, description="refresh_token"),
                    }
                )
            ),
            400: 'KeyNotFound',
            500: 'Server Error'
        }
    )
    def post(self, request):
  • /swagger 접속 후, 확인

적용 과정 중 Error 처리

  • drf-yasg가 적용되지 않았다는 문제 발생


  • 해결
    drf-yasg설치 후, 환경 설정을 제대로 해주었고 pip install -U drf-yasg로 업데이트
    에러가 해결되지 않음 --> 설치와 설정과정에서는 문제 없음으로 판단
    VSCODE 재실행으로 해결 - 일시적인 오류 발생으로 결론

회고

  • 익숙해지기만 하면 API명세를 작성하는 시간도 많이 줄어들고, 프론트엔드와 협업하는 과정에서 매우 유용할 것임을 체감했습니다.
  • views.py에 @swagger_auto_schema()를 직접 작성했을 경우, 코드가 복잡해져서 가독성이 떨어지는 것 같습니다.
  • 현재 Swagger 자체 API 테스트 과정에서 jwt를 header에 넣지 않고 endpoint만 입력하더라도 status code 200과 함께 테스트가 통과되는 문제가 발생했습니다.
    (토큰이 없을 경우 unauthenticated 반환이 정상 : API 자체 로직의 문제인지, swagger 적용을 잘못한 것인지 검토 필요)
  • 전체 코드는 https://github.com/wodnrP/Swagger_practise 에 올려두었습니다.
profile
발전하는 꿈나무 개발자 / 취준생

0개의 댓글