F-Lab
🚀
깊이 있는 개발자 커뮤니티, 데브클럽에 함께 하세요

OpenAPI Specification 과 Swagger 를 활용한 협업

writer_thumbnail

F-Lab : 상위 1% 개발자들의 멘토링

오늘 생각해 볼 협업이란?

 좋은 제품의 요건 중 하나는 고객 친화적인 인터페이스입니다. 백엔드 엔지니어로서 고객에게 노출되는 API 를 만들면서 이해하기 쉽고 사용하기 편리한 API 를 만드는 것도 고객 친화적인 인터페이스를 만드는데 기여할 수 있는 방법이지만 대개는 프론트엔드나 모바일 어플리케이션 엔지니어와의 협업을 통해서 고객이 쉽게 제품을 사용하도록 돕는 인터페이스들을 만들게 됩니다. 여러 다른 영역을 다루는 엔지니어들이 성공적으로 협업하는것은 고객에게 좋은 경험을 제공하는데 중요한 역할을 합니다.

 

 협업에서 흔히 발견되는 문제 중 하나는 백엔드가 제공하는 API 의 명세를 항상 최신 상태로 관리하는것이 생각보다 어려운 점이라는 것입니다. 이 문제는 빠른 반복을 통한 제품 개발을 추구하는 애자일 환경에서 특히 두드러지게 드러납니다. 대개 변경사항을 문서로 전달하는 등의 방법을 사용하지만 문서를 이용해서 지속적으로 바뀌는 정보를 전달하는 것은 실수의 여지가 많고 시간이 많이 소모되기 때문에 한계가 빨리 드러납니다. 

 

 이 블로그 글에서는 이러한 문제를 해결할 수 있는 방법으로써 OpenAPI Specification 를 소개하고 OpenAPI Specification 을 협업에 빠르게 도입할수 있는 도구로써 Swagger 를 제시합니다.

 

 

OpenAPI Specification

 OpenAPI Specification 은 Restful API 의 명세를 기술하기 위한 표준으로 API 를 사용하기 위해서 알아야 하는 호스트, 경로, 파라미터, 인증 과 같은 정보들을 규격화된 형태로 기술하는데 사용됩니다. OpenAPI Specification 을 이용하면 API 명세를 통일된 방식으로 공유할수 있고 OpenAPI Specification 을 처리할 수 있는 소프트웨어들을 이용해 여러가지 자동화를 수행할 수 있습니다. 

 

 예를 들자면 API 명세를 웹사이트에서 보여주고 API 를 호출하는 사용자 인터페이스를 자동으로 생성하거나(1) API 명세에 맞는 클라이언트 코드를 생성하고(2), API에 대한 테스트를 자동화하는 등의 활용이 가능합니다(3). OpenAPI Specification 은 코드와 가까이 존재하기 때문에 문서 등의 방법으로 명세를 관리하는것에 비해서 유지보수에 개발자의 노력이 적게 들어가고 실수를 할 여지도 줄어듭니다.

 

 OpenAPI Specification 을 처리할 수 있는 소프트웨어들 중 가장 잘 알려진 것이 Swagger 입니다. Swagger 도구 모음은 예시로 든 자동화를 포함해서 OpenAPI Specification 을 이용해서 API 생명주기를 관리하기 위한 다양한 도구들을 제공합니다. Swagger 는 2011년 Wordnik이라는 서비스의 개발을 위해서 회사 내부에서 사용되는 도구로써 만들어졌습니다. Swagger 는 2015년 SmartBear 라는 회사에 매각되었고 SmartBear 는 Swagger 의 오픈소스화를 결정한 후 같은 해 Swagger 를 리눅스 재단에 기부했습니다. 그 이후로 Swagger 는 리눅스 재단과 오픈소스 기여자들에 의해서 유지되고 있습니다.

 

 

직접 해봅시다.

 OpenAPI Specification 과 Swagger 가 어떤 문제를 해결할 수 있고 왜 유용한지에 대해서 알아봤습니다. 이 블로그 글의 나머지 부분에서는 Django REST Framework 를 이용해서 간단한 백엔드 서비스를 만들고 API 명세를 OpenAPI spec 을 이용해서 관리할수 있도록 설정하는 예시를 독자들에게 시연하겠습니다. 

 

 OpenAPI Specification 은 사람이 직접 정의할 수도 있지만, 백엔드 서비스의 코드를 기반으로 생성을 자동화할 수도 있습니다. 이러한 자동화에 사용할수 있는 오픈소스 도구가 많이 있지만, 이 글에서는 별도의 설정 없이 사용하기 쉬운 drf-yasg 를 사용하도록 하겠습니다.

 

 

프로젝트 구조 만들기 (1)

 시연을 위해서 Django, Django REST framework(이하 'djangorestframework') 그리고 drf-yasg 모듈을 설치합니다.

 

bash$ pip install Django djangorestframework drf-yasg

 

 

‘swagger-demo’ 라는 이름의 새로운 django 프로젝트를 만듭니다.

 

bash$ django-admin startproject swagger-demo

 

 

‘swagger-demo’ 디렉토리로 들어간 후 ‘app’ 이라는 이름의 django 앱을 만듭니다.

 

bash$ python manage.py startapp app

 

 

'swagger-demo/settings.py' 파일에서 INSTALLED_APPS 를 찾아서 djangorestframework 와 app을 추가해줍니다.

 

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'app'
]

 

 

마지막으로 ‘swagger-demo/urls.py’ 파일에서 app 어플리케이션의 url을 참조하도록 해줍니다.

 

from app import urls as app_urls

urlpatterns = [
	path('admin/', admin.site.urls),
	path('sticky-note/', include(app_urls)),
]

 

이것으로 시연을 위한 프로젝트의 구조를 만들었습니다.

 

 

샘플 API 만들기 (2)

 이제 동작하는 API를 만들어 보겠습니다. 이 시연에서는 가상 '포스트잇’ 서비스를 위한 API를 만듭니다. 우선 아래와 같이 포스트잇 모델(Model)을 정의합니다.

 

class StickyNote(models.Model):
    content = models.TextField()
    created_time = models.DateTimeField()
    created_user = models.EmailField()

 

 

포스트잇 모델을 위한 Serializer 를 아래와 같이 정의합니다.

 

class StickyNoteSerializer(serializers.Serializer):
    content = serializers.CharField()
    created_time = serializers.DateTimeField()
    created_user = serializers.EmailField()

 

 

API View 만들기 (3)

 그리고 위에서 정의한 모델과 Serializer 를 기반으로 API view 를 구현합니다. 이 시연에서는 Django REST Framework 에서 제공하는 ModelViewSet 을 이용해서 아래와 같이 API view 를 구현했습니다.

 

class StickyNoteViewSet(viewsets.ModelViewSet):
    queryset = StickyNote.objects.all()
    serializer_class = StickyNoteSerializer

 

 

마지막으로 ‘app/urls.py’ 파일 내에서 API view를 아래와 같이 등록해줍니다.

 

router = routers.DefaultRouter()
router.register(r'sticky-note', StickyNoteViewSet)
urlpatterns = router.urls

 

 

실행 (4)

 아래의 runserver 명령을 이용하면 테스트 서버를 쉽게 실행시킬수 있습니다.

 

bash$ python manage.py runserver

 

API를 통해서 가상 포스트잇의 생성, 수정, 삭제, 조회가 가능해졌습니다.

 

이제 drf_yasg를 이용해서 API의 OpenAPI Specification을 자동으로 생성하고 API 명세를 제공하는 웹페이지도 자동으로 만들어 보겠습니다.

 

 

API 명세와 UI 생성 (5)

 우선 ‘swagger-demo/settings.py’ 파일에서 INSTALLED_APPS 를 찾아서 drf_yasg 를 추가해줍니다.

 

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'drf_yasg',
    'app'
]

 

 

위에서 정의했던 StickyNoteViewSet 의 메소드들을 swagger_auto_schema 데코레이터로 수식해줍니다.

 

class StickyNoteViewSet(viewsets.ModelViewSet):
    queryset = StickyNote.objects.all()
    serializer_class = StickyNoteSerializer

    @swagger_auto_schema(request_body=StickyNoteSerializer)
    def create(self, request, *args, **kwargs):
        return super(StickyNoteViewSet, self).create(request, *args, **kwargs)

    @swagger_auto_schema(responses={200: None, 302: 'Redirect somewhere'})
    def retrieve(self, request, *args, **kwargs):
        return super(StickyNoteViewSet, self).retrieve(request, *args, **kwargs)

    @swagger_auto_schema(request_body=StickyNoteSerializer)
    def update(self, request, *args, **kwargs):
        return super(StickyNoteViewSet, self).update(request, *args, **kwargs)

    @swagger_auto_schema(request_body=StickyNoteSerializer)
    def partial_update(self, request, *args, **kwargs):
        return super(StickyNoteViewSet, self).update(request, *args, **kwargs)

    def destroy(self, request, *args, **kwargs):
        return super(StickyNoteViewSet, self).destroy(request, *args, **kwargs)

    @swagger_auto_schema(responses={200: StickyNoteSerializer(many=True)})
    def list(self, request, *args, **kwargs):
        return super(StickyNoteViewSet, self).list(request, *args, **kwargs)

 

 

'swagger-demo/urls.py' 파일에서 OpenAPI Specification 의 메타정보를 담은 객체 openapi_info와 OpenAPI Specification 을 자동으로 읽어서 제공하기 위한 객체 schema_view 를 선언하고 url 을 등록합니다.

 

from drf_yasg import openapi
from drf_yasg.views import get_schema_view
from rest_framework import permissions

from app import urls as app_urls

openapi_info = openapi.Info(
    title="StickyNote API",
    default_version='v1',
    description="This is a demo project.",
    contact=openapi.Contact(email="jacob@f-lab.kr"),
    license=openapi.License(name="BSD License"),
)

schema_view = get_schema_view(
    openapi_info,
    public=True,
    permission_classes=(permissions.AllowAny,),
)

# Copied from https://drf-yasg.readthedocs.io/en/stable/readme.html
urlpatterns = [
    path('admin/', admin.site.urls),
    path('sticky-note/', include(app_urls)),
    path('swagger<format>/', schema_view.without_ui(cache_timeout=0), name='schema-json'),
    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
    path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]

 

 

웹브라우저를 이용해서 [host]/swagger/ 로 접속하면 아래와 같은 화면을 확인할 수 있습니다.

 

 

 

Django REST Framework 를 이용해서 구현한 API 들을 확인할 수 있습니다. 각각의 API 에 대해서 확인하기 위해서는 드롭다운 버튼을 누르면 됩니다. 아래와 같이 파라미터, 반환되는 Response의 코드와 값이 나타납니다.

 

 

[host]/swagger.json 이나 [host]/swagger.yaml 로 접근하면 JSON이나 YAML 포맷으로 정의된 OpenAPI Specification 을 확인할 수 있습니다.
 

 

협업에서의 가치

 위의 예시에서는 drf_yasg 에서 제공하는 데코레이터로 API view 에 해당하는 함수들을 수식하는것만으로 OpenAPI Specification 을 생성하고 자동으로 생성된 명세를 기반으로 한 Swagger UI 를 구현할 수 있었습니다. 

 

 이렇듯이 OpenAPI Specification 과 Swagger 는 기존 프로젝트에 쉽게 추가할 수 있고 이 도구들을 도입하면 적은 비용으로 협업의 난이도를 큰 폭으로 낮출 수 있습니다. 더해서 drf-yasg 와 같은 OpenAPI Specification generator 를 활용하면 코드를 기반으로 API 명세가 자동으로 생성되기 때문에 일관성 있고 실수 없는 API 협업이 가능해집니다. 예시에서는 단순한 CRUD API 를 기반으로 OpenAPI Specification 과 Swagger 를 도입했지만 복잡하고 많은 API 를 가지고 있는 서비스일수록 자동화를 기반으로 한, 명세 생성과 명세를 보기 좋게 표현해주는 Swagger UI와 같은 도구들이 빛을 발합니다. 

 

 필자는 복잡한 요구사항의 프로젝트를 수행하면서 프론트엔드 팀과의 협업에서 어려움을 겪고 있을때 예시에서 사용된 drf_yasg 를 도입해서 문제를 해결한 경험이 있습니다. 이 글을 읽고 있는 백엔드 엔지니어분들께 OpenAPI Specification 을 활용해서 협업의 효율을 높이는 경험을 꼭 한번 해보시라고 추천드리고 싶습니다.

 

이 글의 예시 코드는 https://github.com/jacob-f-lab/swagger-demo 에서 확인 가능합니다.

ⓒ F-Lab & Company

이 컨텐츠는 F-Lab의 고유 자산으로 상업적인 목적의 복사 및 배포를 금합니다.

조회수

멘토링 코스 선택하기

  • 코스 이미지
    Java Backend

    아키텍처 설계와 대용량 트래픽 처리 능력을 깊이 있게 기르는 백앤드 개발자 성장 과정

  • 코스 이미지
    Node.js Backend

    아키텍처 설계와 대용량 트래픽 처리 능력을 깊이 있게 기르는 백앤드 개발자 성장 과정

  • 코스 이미지
    Python Backend

    대규모 서비스를 지탱할 수 있는 대체 불가능한 백엔드, 데이터 엔지니어, ML엔지니어의 길을 탐구하는 성장 과정

  • 코스 이미지
    Frontend

    기술과 브라우저를 Deep-Dive 하며 성능과 아키텍처, UX에 능한 개발자로 성장하는 과정

  • 코스 이미지
    iOS

    언어와 프레임워크, 모바일 환경에 대한 탄탄한 이해도를 갖추는 iOS 개발자 성장 과정

  • 코스 이미지
    Android

    아키텍처 설계 능력과 성능 튜닝 능력을 향상시키는 안드로이드 Deep-Dive 과정

  • 코스 이미지
    Flutter

    네이티브와 의존성 관리까지 깊이 있는 크로스 플랫폼 개발자로 성장하는 과정

  • 코스 이미지
    React Native

    네이티브와 의존성 관리까지 깊이 있는 크로스 플랫폼 개발자로 성장하는 과정

  • 코스 이미지
    Devops

    대규모 서비스를 지탱할 수 있는 데브옵스 엔지니어로 성장하는 과정

  • 코스 이미지
    ML Engineering

    머신러닝과 엔지니어링 자체에 대한 탄탄한 이해도를 갖추는 머신러닝 엔지니어 성장 과정

  • 코스 이미지
    Data Engineering

    확장성 있는 데이터 처리 및 수급이 가능하도록 시스템을 설계 하고 운영할 수 있는 능력을 갖추는 데이터 엔지니어 성장 과정

  • 코스 이미지
    Game Server

    대규모 라이브 게임을 운영할 수 있는 처리 능력과 아키텍처 설계 능력을 갖추는 게임 서버 개발자 성장 과정

  • 코스 이미지
    Game Client

    대규모 라이브 게임 그래픽 처리 성능과 게임 자체 성능을 높힐 수 있는 능력을 갖추는 게임 클라이언트 개발자 성장 과정

F-Lab
소개채용멘토 지원
facebook
linkedIn
youtube
instagram
logo
(주)에프랩앤컴퍼니 | 사업자등록번호 : 534-85-01979 | 대표자명 : 박중수 | 전화번호 : 1600-8776 | 제휴 문의 : info@f-lab.kr | 주소 : 서울특별시 강남구 테헤란로63길 12, 438호 | copyright © F-Lab & Company 2024