Backend/Django

[Django] 유효성 검증, DRF Serializer validate (feat: FastAPI 와 비교)

뒷골목프로그래머 2022. 10. 12. 19:31
반응형

안녕하세요. 글쓰는 개발자 입니다.

 최근 Django에 대한 대체제로써 FastAPI 적용을 검토 하면서 기본적인 Restful API 테스트를 위해 인증 서버를 간단히 구현해 보았습니다. FastAPI를 직접 사용 하면서 몇 가지 '편리하다.' 라고 느낀 점이 있었으며, 그 중에서도 Request에 대한 Validation Check 가 제일 편하게 느껴졌습니다. Django에서 Request Data Valiation을 위해 DTO를 매번 구현해서 사용했던 저로서는 Pydantic을 활용해 이런 불편함을 해소하고 exception까지 자동으로 처리하는 부분은 굉장히 매력적으로 느껴졌습니다.

 

 그럼에도 불구하고 저는 곧 진행할 Project 에서 계속 Django를 사용하기로 동료와 결론을 내렸습니다. (추후 다른 포스팅에서 이유를 작성하겠습니다.) 그리하여, 매번 DTO를 만들어 사용하고 싶지 않았던 저는 FastAPI 에서 편리하게 느꼈던 것을 응용하기로 했습니다. 요구 사항과 개발 방법은 다음과 같습니다.

 

요구사항 개발 방법
View(Controller) 에서 Business Logic 진입 전에 동작 decorator를 활용해 APIView에서 바로 동작
Serializer 활용 Django RestFramework Serializer의 validate 기능 사용

 

1. Serializer 생성

  유효성 검사에 사용 할 Serializer 를 작성합니다. DRF의 serializers 를 활용하여, paramerter의 data type과 min_length, max_length 등과 같은 제약 조건을 설정할 수 있습니다. 그리고 validate_[Field 명칭] 으로 method를 활용하여 해당 Field에 대한 Custom Validation Check를 수행 합니다.

# serializers.py

from typing import List

from rest_framework import serializers


class RequestSerializer(serializers.Serializer):
    param_first: str = serializers.CharField(required=False, help_text='테스트용')
    param_second: str = serializers.IntegerField()
    
    
    def validate_param_first(self, value: str):
    	valid_values: List[str] = ['one', 'two', 'three']
        if value not in valid_values:
            raise serializers.ValidationError('one, two, three 중 하나를 입력해 주세요.')

 

2. Validation 용 decorator 작성

 저는 View의 API 호출 method에 decorator 한 줄만 입력하면 사용 가능한 유효성 검증 기능을 개발했으며 다음과 같은 조건을 만족 시킵니다.

 

1. Validator(Validation 수행) 는 생성한 Serializer가 담당

2. Decorator는 Validator를 인자로 받음

3. Decorator는 Client에서 전달 받은 request를 인자로 받음

 

 이를 위해, 바깥에서 부터 decorator_factory  > decorator > wrapper 순서로 Decorator를 작성하였습니다. decorator_factory : Validator를 인자로 받습니다.

decorator : origin_method (View의 API 호출 method) 를 인자로 받습니다.

wrapper : origin_method (View의 API 호출 method) 의 인자들을 인자로 받습니다.

 

# validator.py

from typing import Dict, Any

from rest_framework import serializers


def decorator_factory(validator: serializers.Serializer):
    """
        QueryString 으로 전달 된 Parameter 의 유효성 검증 Decorator
        validator : DRF Serializer Validate 기능 사용
    """
    def decorator(origin_method):
        def wrapper(*args, **kwargs):
            request_params: Dict[str, Any] = args[1].GET
            is_valid = validator(data=request_params).is_valid(raise_exception=True)
            return origin_method(*args, **kwargs)
        return wrapper
    return decorator

 

3. View 적용

 위에서 생성한 Serializer와 Decorator를 View에 적용하여 Validation Check를 수행합니다.

# views.py

from typing import Dict, Any

from django.http import HttpRequest
from rest_framework import views
from rest_framework.response import Response

from .serializers import RequestSerializer


class Test(vies.APIView):
    @decorator_factory(validator=RequestSerializer)
    def get(self, request: HttpRequest):
    	'''
        	business logic 호출 부
        '''
        return Response('test')

 

4. 결론

 위와 같은 방법을 통해 FastAPI 처럼 View(Controller) 단에서 유효성 검증이 가능해졌습니다. 다음 포스팅은 FastAPI와의 비교 끝에 결국 Django를 사용하게 된 이유에 관해 기술해 보겠습니다. 부족한 글 끝까지 읽어주셔서 감사합니다.

 

반응형