ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Django] Swagger를 통한 API 문서 작성하기 with. Django
    파이썬/Django 2023. 1. 29. 19:41
    728x90
    반응형

    Swagger란?

    API 문서 자동화해주는 툴
    우리가 개발하면 개발하는 내용 그대로 모든 내용들이 자동으로 문서화가 되어 우리가 굳이 설명하거나 문서로 전달하지 않더라도 프론트엔드 개발자 혹은 다른 개발자들이 API 명세를 확인할 수 있는 것이다.

    API 명세 뿐 아니라, API에 대한 목업(Mock-up) 테스트도 지원을 하기 때문에, 프론트엔드와 연동을 하지 않을 상태에서도 Response를 확인해볼 수 있는 테스트를 진행해 볼 수 있다는것도 강점이다.

     


    1.  Swagger 관련 패키지 설치

    방법으로는 두가지가 있는데, SwaggerHub라는 Swagger를 만든 곳의 Cloud를 이용해서 직접 관리하는 방법이 있고, 각자 회사의 서버에 직접 Swagger 모듈을 도입하여 적용하는 방법이 있는데, 나는 그중에서 후자의 방법에 대해 이야기하고자 한다.

    1-1.  Swagger 모듈 라이브러리설치

    Django에서 지원하는 여러가지 Swagger 모듈이 있는데 그중에서 가장 대표적인 drf-yasg를 사용했다. drf-yasg는 장고로 정의된 API를 문서화할 수 있는 패키지로, (django rest framework- Yet another Swagger generator)의 약자이다.

    설치를 하기전에 django-rest-framework도 설치가 되어있어야한다. 우리가 사용하는 것은 drf-yasg. 즉 drf 환경 위에서 동작하도록 되어있기때문에 설치가 필요하다.

    아마 Django로 REST API를 만드는 사람들이라면 거의 설치가 되어있겠지만, 만약 처음 프로젝트를 시작할 때 부터 도입하고자 하는 분이라면 django-rest-framework패키지도 추가로 설치하도록 한다.

     

    pip install drf-yasg
    pip install djangorestframework

     

    나는 poetry 가상환경을 사용 중이라서 poetry add [패키지명] 형식으로 설치해주었다.

     

    1-2. Swagger 환경 설정 추가

    모듈을 설치했다면 Django 내에 있는 settings.py 파일 안에 환경설정을 추가 해준다.

    첫번째는 아래와 같이 INSTALLED_APPS 항목 안에 추가해주도록 하자.

    INSTALLED_APPS = [
        ... # another apps
        
        'drf_yasg', #drf_yasg
        'rest_framework', #djangorestframework
        
        ... # another apps
    ]

     

    다음으로는 urls.py 에서 우리가 일반적인 API처럼 특정 URL을 통해 Swagger 문서에 접속할 수 있도록 설정하는 과정이다.

    from drf-yasg.views import get_schema_view
    from drf-yasg import openapi
    
    ...
    
    schema_view = get_schema_view(
        openapi.Info(
            title="Your Server Name or Swagger Docs name",
            default_version="Your API version(Custom)",
            description="Your Swagger Docs descriptions",
            # terms_of_service="https://www.google.com/policies/terms/",
            # contact=openapi.Contact(name="test", email="test@test.com"),
            # license=openapi.License(name="Test License"),
        ),
        public=True,
        permission_classes=(permissions.AllowAny,),
    )

    import를 통해 drf-yasg를 임포트하여 get_schema_views라는 메서드를 가져와 설정한다. openapi는 앞으로 Swagger에서 자주쓰게 될 내용이다. 이녀석이 api에 대한 명세를 작성하는것을 도와주는 역할을 한다.

    다음으로는 Swagger를 보기위한 URL설정을 추가해주면 된다.

    urlpatterns = [
    # other user API end-point URL
    ...
    
        url(r'^swagger(?P<format>\.json|\.yaml)$', schema_view_v1.without_ui(cache_timeout=0), name='schema-json'),
        url(r'^swagger/$', schema_view_v1.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
        url(r'^redoc/$', schema_view_v1.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
    ]
    

    위처럼 설정하게되면 모든 환경에서 스웨거를 접속할수도 있게 되는데 urlpatterns에 있는 url은 변경이 가능해서 각각의 개발환경마다 접속되는 스웨거를 다르게 설정 할 수도 있다.

    우리의 경우 아래와 같이 서버실행시에 실행환경이 DEV인경우라면 개발 환경의 Swagger를 보여주도록 하고있다.
    해당 설정은 디버그일때만 swagger 문서가 보이도록 해주는 설정이라는 데, urlpath도 이 안에 설정 가능해서, debug일때만 작동시킬 api도 설정할 수 있다.

    # 서버 동작 환경이 개발서버인 경우 개발서버 Swagger 접속시 운영 서버의 Swagger가 아닌 개발서버 기준의 Swagger를 노출시킴
    
    if settings.DEPLOY_SERVER_TYPE == 'dev':
        urlpatterns += [
            re_path(r'^v1/dev/swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0),
                    name="schema-json"),
            re_path(r'^v1/dev/swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
            re_path(r'^v1/dev/redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
        ]

     


    2. 개발한 API에 대해 Swagger 연동 설정

    Swagger를 보기 위한 설정은 모두 끝났고, 이제 우리가 개발한 API를 스웨거가 인식하고 볼 수 있도록 추가하면 된다.

     

    2-1. API URL 설정

    첫번째는 API URL 설정이다. 우리가 API를 호출하기위해 설정한 end-point를 urls.py 안에 지정해주면 된다.

    CBV(Class-Based-View)로 개발한 경우와 FBV(Funtion-Based_View) 방식으로 개발한 경우에 URL 설정 방법이 다르기 때문에 아래 코드를 참고해서 각자가 개발한 방법에 맞게 URL을 지정하면 될 것 같다.

    # If Using Class-Based-View
    urlpatterns = [
    	path('/users/<user_guid>', VwUserControlClass.as_view({"get": "get_user_info"})),
    	path('/users/<user_guid>/modify', VwUserControlClass.as_view({"put": "update_user_info"})),
    ]
    
    # If Using Function-Based-View
    urlpatterns = [
    	path('/users/<user_guid>', get_user_info),
    	path('/user/<user_guid>/modify', update_user_info)
    ]

    나는 class based view 방식으로 개발했기 때문에 위의 방식대로 설정해주었다.

     

    2-2. API에 @Swagger auto Schema추가

    @Swagger Auto Schema 란, 스웨거가 API에 대한 내용을 문서화 시켜주는 기능인데, 두가지 방법이 있다.

    1. DRF를 사용하는경우에 Serializer를 통해 파라미터등을 지정하여 scheme를 추가하는 방법
      DRF를 통해 모델이라던가 함수에 대해서 Serializer를 활용하고 있는 개발자라면 해당 방법이 깔끔하고 좋다. drf-yasg자체가 DRF를 통해 동작하다보니 공식적으로도 Serializer를 통해 자동 포맷 시키는걸 권장하고 있기도 하다.
      파라미터나 리퀘스트 바디등을 제외한 나머지 부분은 2번과 동일하게 작성해주어야한다.
    2. @swagger_auto_schema를 사용해서 개발자가 직접 해당 API에 대해 docs를 작성하는 방법
      1번의 방법과 비슷하지만, manual_parameter부분과 request_body, query_parameter 모두 auto_schema 안에 전부 작성해주는 방법이다.

    1번 2번 차이는 이정도 일 듯하다.

    1번의 방법을 사용하면 비즈니스로직만 분포한 곳에 조금 더 깔끔하게 스웨거 오토 스키마를 작성 가능하다는 장점이 있지만, 어떠한 파라미터가 있는지는 시리얼라이저를 통해서 확인해야하는 단점이 존재한다.

    2번방법을 사용한다면 전체적인 모든 내용을 한번에 볼 수 있지만, 스웨거 오토 스키마로 인해 비즈니스 로직이 남긴 파일들이 과도하게 길어지고 헷갈릴 수 있다는 단점이 존재한다.

    편한 방법으로 하면 될 듯? (나는 2번 방법으로 하다가 최근에 로직들이 많아지다보니, 1번 방법으로 전환 중에 있다)

    1번에 관련한 시리얼라이저 적용 방법은 참고한 블로그 링크를 아래에 걸어두었으니 1번방법을 사용할 사람들은 참고해봐도 좋을 듯 하다.

     

    2-3. @swagger_auto_schema 작성 기능 설명

    @swagger_auto_schema(
      operation_description="회원관리_유저 정보 조회",
      operation_summary="회원관리_유저 정보 조회",
      operation_id='메인_회원관리_01',
      tags=['메인_회원관리'],
      manual_parameters=[Authorization],
      query_serializer=ManagementUserSerializer,
      responses={
      ... 중략

    API 맨 위에 이런식으로 작성을 하게 될 텐데, 오토 스키마 사용을 위해서는 항상 @swagger_auto_schema 데코레이터를 붙여 주고 시작해야한다.

    • operation_description
      API 설명 부분이다. API에 대한 설명을 작성하면 됨.
    • operation_summary
      API 간단한 타이틀 혹은, 통합하는 주제를 적는 부분
    • operation_id
      API를 스웨거에서 구분하는 고윳값이라고 생각하면 된다. 이 부분에서 operation_id가 겹칠 경우 swagger 상에서 가장 먼저 나온 API만 출력하여 겹쳐 보이거나, 서로 다른 API가 동일한 operation_id를 가지고 나타날 수 있기 때문에 신경을 써주어야한다.
    • tags
      하나의 그룹핑화를 할 수 있는 곳이라고 보면된다. 예를 들어, 위와 같이 회원관리와 관련된 API들을, 메인_회원관리로 묶었을 때 swagger 상에서는 회원관리 탭이 생겨 그 탭을 눌러서 확장시키면 해당 태그들을 가진 API들을 모아서 볼 수 있다.
    • manual_parameters
      여기서 query_params , request_header (token 등 헤더에 포함되는 정보들)와 같은 곳에 들어가는 내용들을 작성해 줄 수 있는데 위에 설명한 2가지 방법에 따라 작성 방식이 다르다.

      1번 방법으로 했을 경우 아래와 같이 query_serializer라는 곳에 시리얼라이저를 지정해야하고, 헤더는 이곳에 작성해야 한다.

      2번 방법인 경우에는 query_params, request_header 모두 @swagger 시작전에 사용할 파라미터와 헤더들을 선언을 해주고 manual_parameters 부분에 작성해주면 된다.
    • query_serializer / request_body
      쿼리파리미터, 리퀘스트 바디와 같은 내용들을 작성하는 곳이다.
      시리얼라이저를 사용하는 경우에는 본인이 작성한 시리얼라이저로 기입해주면 되고, 그게 아니라면 query_serializer는 위에 있는 manual_parameters에, request_body는 response처럼 동일하게 작성해주면 된다.
    • response
      API의 응답값의 Mock-up 형태를 작성해주면 된다.

    response_body나 request_body의 작성방법 같은 경우에는 swagger 공식문서에 잘 공유되어있으니 참고해서 필요한대로 작성하면 될 것 같다.

     


    3. Swagger 접속 확인

    설정이 모두 완료되었다면 아래와 같이 http://127.0.0.1:8000에 접속하여 확인 할 수 있다.

    로컬 주소의 경우에는 각자 사용하는 포트 번호가 다를 것이니 확인하여 접속하도록 하자.

     

     

    CORS 오류 해결

     

    settings.py 에 아래 코드를 추가해준다.

    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

     

    https://stackoverflow.com/questions/45372428/django-rest-swagger-https-requests

     

    Django REST Swagger HTTPS requests

    How configure django-rest-swagger to get a HTTPS requests? upd: SSL cert is present and ALL app working with it, but swagger make a http requests.

    stackoverflow.com

     

    참고 블로그

     

    Django + Swagger 기본 사용법

    장고랑 스웨거랑

    velog.io

     

     

    [Django]Swagger를 통한 API 문서 작성하기

    Swagger with DRF_yasg를 통한 Django API 문서 작성하기

    velog.io

     

    LIST
Designed by Tistory.