Programming-[Backend]/Django

OpenAPI 명세, Swagger 기본 개념 : Django restframework, drf-spectacular로 swagger split

컴퓨터 탐험가 찰리 2022. 8. 3. 09:57
728x90
반응형

 

 

 

 

OpenAPI 명세 개념

 

 

 

 

 

개요

여기서 말하는 것은 Open API가 아니라 붙여쓰는 OpenAPI이다. 참조 1에 따르면 Open API는 말 그대로 개방된 API로 날씨, 주소 정보 등 공개된 API를 의미한다. OpenAPI는 Restful API의 명세(Spec)를 규칙에 맞게 json이나 yaml로 표현하는 방식을 말한다.

 

 

 

https://jojoldu.tistory.com/31

 

 

 

 

 

규칙: JSON, YAML로 표현

 

규칙에 맞게라고 했는데, 어떤 규칙을 가질까? 우선 json과 yaml 파일 형식에 대한 것은 대부분의 개발자가 알고 있으리라 생각된다. 그냥 어떤 정보를 표현하는 양식이라고 생각하면 된다. 아래 그림을 참고하자.

 

 

참조 2.https://levelup.gitconnected.com/yaml-tutorial-everything-you-need-to-know-in-5-mins-14f333a23ed1

 

 

 

 

 

 

Schema와 설정

OpenAPI에서는 위 YAML 또는 JSON 방식으로 어떤 API 서비스의 구조를 표현한다. 어떤 API의 url, request, response, auth 등에 들어가야하는 정보가 무엇인지, 그 예시 값들은 어떤 값으로 지정할 것인지를 표현하는 것이다. 아래 참조3. 페이지의 Schema 파트를 보면, 어떤 API를 구성하는 정보들을 JSON 형식으로 표현한 Schema 파일의 일부를 볼 수 있다. 여러가지 Component로 이루어져서 하나의 거대한 파일로 서비스의 명세를 표현하는 것이다.

 

 

 

 


SchemaGenerator, AutoSchema
Java-Spring 계열이든, Python-Django 계열이든 API를 작성하는 틀은 정해져있다. 그리고 각 Framework(Spring | Django)에서 이런 틀을 기준으로 상기 언급한 Schema를 자동으로 만들어준다!(몇 가지 설정만 해주면). 이렇게 사람이 직접 작성하기에는 너무 복잡한 Schema 파일을 각 프레임워크가 만들어주는 것이 Schema Generator이고, 자동으로 만들 수 있도록 해주는 객체가 AutoSchema 이다.

중요한 것은 이런 json, yaml로 만들어진 Schema를 참고로하여 각 프레임워크가 Swagger, Redoc으로 렌더링해준다는 걸 이해하고 있는 것이다.


 

 

 

 


 

 

 

 

drf-spectacular로 Swagger Split 하기


최근 사용하고 있는 Python-Django 기준으로 Schema 생성과 Swagger 연결, 그리고 Swagger를 Split(multiple Schema)하는 방법에 대해서 기록해둔다.

 

 

 

 

Django restframework

Django를 백엔드-프론트엔드 협업으로 사용하는 사용자라면 Django restframework(DRF)를 사용할 것이다. DRF에서는 OpenAPI spec을 구현할 수 있도록 schemas 모듈을 제공한다. 상세한 내용은 아래 링크에서 참고할 수 있다.
https://www.django-rest-framework.org/api-guide/schemas/#overview

 

 

 

 

Schema Generation

상기 공식 홈페이지의 글을 읽어보면, 대략 get_schema_view라는 메서드에 기본 설정값을 주어서 Swagger 화면을 얻어낼 수 있다고 한다. 여기에 들어가는 옵션으로 generator_class라는 것이 있는데 이것이 Django의 rest_framework 스펙을 바탕으로 OpenAPI의 Schema를 만들어주는 클래스이다. 보통 아래와 같이 REST_FRAMEWORK의 설정에서 기본값을 지정해줄 수 있다.

settings.py

REST_FRAMEWORK = {"DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema",}

 

 

 

 

 

drf-spectacular

이렇게 AutoSchema만 적용하면 Django rest-framework에서 각 클래스의 Serializer_Class를 참고로하여 schema를 생성해준다. 자동이라 좋긴하지만, swagger 상에서 다른 사용자에게 따로 example 값을 수정해서 보여주거나 하는 custom한 기능을 더욱 편리하게 제공하는 라이브러리가 있다. 그것이 drf-spectacular이다.

https://drf-spectacular.readthedocs.io/en/latest/ 

 

 

 

 

 

 


drf-spectacular는 Open API 3.0을 기반으로 한다. 원래 drf-yasg 라는 라이브러리도 있어서, 이 라이브러리는 OpenAPI 2.0을 기반으로 했다. 그래서 그런지 위 사진에 보면 From drf-yasg to OpenAPI 3라는 페이지도 있는 것을 볼 수 있다.

나는 최신 스펙을 적용하기 위해서 drf-spectacular를  사용했다. 그리고 프로젝트가 Viewset 기반으로 되어있어서 viewset 클래스 위에 @extend_schema_view를 달아서 사용했다.(이외에도 view나 함수에 적용하는 @extend_schema 등 데코레이터가 더 있다)

 

 

 

 

 

 

 

UPDATE = extend_schema(
    summary="...",
    description="...",
    tags=["이 값을 기반으로 카테고라이징 됨"],
    examples=[
        OpenApiExample(
            request_only=True,
            name="기본",
            value={"name": "이름", "description": "설명", "color": "#3aa0b2"},
        ),
        OpenApiExample(
....중략

 

 

아무튼, drf-spectacular를 적용하면 Example을 상황에 따라 다르게 보여준다거나, 일반 Json 값이 아니라 inputbox 형태로 보여준다던가하는, 여러가지 커스터마이징을 할 수 있다. 기본적인 사용법은 아래 참조 블로그를 보면 많이 도움이 된다. 여기서 자세한 사용법을 다루지는 않는다. 혹시 이 글을 참조하시는 분이 있다면, 궁금한게 있으시면 댓글로 소통했으면 좋겠다!
https://velog.io/@catveloper/DRF-Spectacular-사용법

 

 

 

 

 


추천 옵션 설정 사항
다만, 기억하고 있으면 좋은 추천할 설정 옵션 사항을 기록해둔다.

 

 

SPECTACULAR_SETTINGS = {
    "TITLE": "서비스 이름",
    "DESCRIPTION": "<h5>자세한 설명, html 태그 적용 가능<h5>",
    "VERSION": "1.0.0.0",
    "LICENSE": "BSD License",
    "CONTACT": {"email": "이런 식으로 달면 contact가 Link로 활성화됨"},
    "TOS": "사용 계약서 같은, Term Of Service 링크",
    "SERVE_INCLUDE_SCHEMA": False,
    "SCHEMA_PATH_PREFIX": None,  # URL 정규표현식에 따라 범주화해준다. '/api/v[0-9]' 가능
    "SWAGGER_UI_SETTINGS": {
        "deepLinking": True,  # API를 클릭할때 마다 SwaggerUI의 url이 변경
        "persistAuthorization": True,  # 새로고침해도 로그인 정보 저장
        "displayOperationId": True,  # urlId 값 노출
        "filter": True,  # filter UI 표시 여부
        **"docExpansion": "none",  # 드롭다운 접어놓기. ["none", "list", "full"]**
    },
    **"DISABLE_ERRORS_AND_WARNINGS": True, #콘솔에 drf-spectacular가 Serializer를 해석할 수 없어서 나오는 warning 및 error가 안뜨게 설정**
}



 

 

 


 

 

Swagger page split


마지막으로 swagger page를 Split하는 방법에 대해서 기록해둔다. 아래 그림과 같이 특정 URL 쪽만 분리할 수 있는 방법이다. Main 쪽은 내부적으로 쓰고, Sub 쪽은 외부(external)에 공개하여 참고하도록 만들 수 있다.

 

 

 



Main 페이지(내부용, for internal)



Sub 페이지(외부용, for external)

 

 

 

 

 

 

개념

맨 처음 개념부분에 적어놓았듯이, Swagger는 OpenAPI의 Schema 파일을 기반으로 렌더링을 해줄 뿐이다. 따라서,

  1. Schema 파일이 있거나, AutoGeneration으로 Schema를 만들어야한다.
  2. Schema를 참조로하는 json 페이지를 라우팅해야한다.
  3. json 페이지를 참조로해서 swagger가 렌더링하도록 해야한다.

코드 및 주석으로 보면 다음과 같다.

urlpatterns = external_docs_path + [
    path("docs/json/", SpectacularJSONAPIView.as_view(), name="schema-json"),
		#SpectacularJSONView 객체로 docs/json/ 주소로 접근 시 프로젝트의 API들을 json 페이지로 라우팅한다.
		#이 페이지가 drf-spectacular가 기본적으로 참고하는 페이지가 된다. 반드시 이 페이지가 있어야만 Swagger가 동작한다!!
		...,
		path(
            "swagger/",
            SpectacularSwaggerView.as_view(url_name="schema-json"),
            name="swagger-ui",
        ),
		#이제 위 name=schema-json으로 설정된 페이지를, SpectacularSwaggerView 객체로 렌더링한다.
		#url_name='schema-json'으로 참조하는 것이다.
		#name 옵션은 Django의 URL-conf(라우팅 객체)에서 참고하는 네임스페이스라서 아무렇게나 짓고 다른데서 참조하면 된다.
		]

이렇게 path를 설정해서 json 페이지, Swagger 렌더링 페이지를 만들 수 있다!

 

 

 

 

 

 

페이지 스플릿 방법

이제 페이지를 스플릿해본다. 원리를 이해했다면 옵션 하나만 추가하면 된다!!!

#외부용 url 모음
cooperate_urlpatterns = [
    path("auth/", include("...")),
    path("external/", include("...")),
]

#외부용 json 페이지 생성, patterns 옵션으로 외부용 Url을 연결한다.
external_schema_view_json = SpectacularJSONAPIView.as_view(
    patterns=cooperate_urlpatterns,
)

url_patterns = [
	path(
        "docs/external",
        external_schema_view_json,
        name="schema-external-json",
	    ),
	...,
	path(
        "docs/",
        SpectacularSwaggerView.as_view(url_name="schema-external-json"),
        name="schema-external",
	    ),
	#외부용 json 페이지를 참고하여 SwaggerView로 렌더링 하도록 한다!
]

 

 

 

 

 

 

 

view 옵션들

SpectacularJsonAPIView와 SpectacularSwaggerView 코드를 보고, 옵션을 정리하면서 마무리한다.



SpectacularJsonAPIView의 부모인 SpectacularAPIView

class SpectacularAPIView(APIView):
    __doc__ = _("""
    OpenApi3 schema for this API. Format can be selected via content negotiation.

    - YAML: application/vnd.oai.openapi
    - JSON: application/vnd.oai.openapi+json
    """)
    renderer_classes = [
        OpenApiYamlRenderer, OpenApiYamlRenderer2, OpenApiJsonRenderer, OpenApiJsonRenderer2
    ]
    permission_classes = spectacular_settings.SERVE_PERMISSIONS
    authentication_classes = AUTHENTICATION_CLASSES
    generator_class = spectacular_settings.DEFAULT_GENERATOR_CLASS
    serve_public = spectacular_settings.SERVE_PUBLIC
    urlconf = spectacular_settings.SERVE_URLCONF
    api_version = None
    custom_settings = None
    patterns = None
		...

 

 



SpectacularSwaggerView

class SpectacularSwaggerView(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    permission_classes = spectacular_settings.SERVE_PERMISSIONS
    authentication_classes = AUTHENTICATION_CLASSES
    url_name = 'schema'
    url = None
    template_name = 'drf_spectacular/swagger_ui.html'
    template_name_js = 'drf_spectacular/swagger_ui.js'
    title = spectacular_settings.TITLE

    @extend_schema(exclude=True)
    def get(self, request, *args, **kwargs):
        return Response(

 



SpectacularSwaggerView에는 patterns 옵션이 없다. 왜냐하면 SwaggerView는 JSONView를 기반으로 렌더링해주는 클래스일 뿐이기 때문이다!

 

 

 

 


참조

1. 호롤리한 하루 블로그- OpenAPI 란?(feat. Swagger)
https://gruuuuu.github.io/programming/openapi/

2. Medium - YAML Tutorial: Everything You Need to Know in 5 Mins
https://levelup.gitconnected.com/yaml-tutorial-everything-you-need-to-know-in-5-mins-14f333a23ed1

3. Swagger.io - specification
https://swagger.io/specification/




728x90
반응형