TIL136. DRF : Serializer에 관하여

ID짱재·2022년 3월 28일
1

Django REST Framework

목록 보기
10/10
post-thumbnail

📌 이 포스팅에서는 직렬화(Serializeing)와 역직렬화(Deserializing)를 이해하기 위해 이 과정을 정리하였습니다.



🌈 Serializer 이해

🔥 Serialize & Deserialize 란?

🔥 Serializing과 Deserializing 과정

🔥 Serializing과 Deserializing 비교



1. Serialize & Deserialize 란?

🤔 Serialize & Deserialize는 왜 필요할까?

✔️ DRF에서 Serialize & Deserialize는 직렬화, 역직렬화란 의미로 사용하고, 이를 이해하기 위해서는 메모리 내부와 외부의 차이 그리고 복원시 데이터 유지라는 측면을 이해해야 한다.

✔️ 메모리에 올라간 "Django"라는 데이터를 메모리 외부로 전달한다고 했을 때, 파일 또는 DB에 저장할 수 있고 네트워크로 전송할 수도 있다.

✔️ 이런 경우, 메모리 내부와 외부의 환경이 다르기 때문에 이 문자열을 그대로 보낼 수는 없다는 것이다. 실제로는 bytes 로 변환한 다음에 저장하거나 전송이 이뤄진다.

✔️ 이에 프로그램의 object에 담긴 데이터를 어떤 외부 파일에 작성 및 전송할 때는 직렬화(Serialize)가 필요하고, 어떤 외부 파일의 데이터를 프로그램 내의 object로 읽어올 때는 역직렬화(Deserialize)가 필요하다.

✔️ 이런 과정을 JSON 포맷으로 DRF에서 가능하게 해주는 것이 Serializer의 기능이다.

🤔 Serializer가 From 또는 Model과 비슷하단 느낌이 드는 이유

✔️ Django의 From 클래스는 HTML의 From을 다루기 위한 클래스이고, Model은 Database의 Table을 다루기 위한 클래스이다.

✔️ DRF의 Serializer에서 직렬화(Serialization)와 유효성 검사(Validation)의 기능이 이루어지기 때문에 Django의 Form 또는 Model과 비슷하다 특징을 가지고 있다.



2. Serializing과 Deserializing 과정

🤔 models.py과 serializers.py 살펴보기

✔️ Comment 모델을 우선 아래와 같이 field가 구성되어 있다.

class Comment(models.Model):
    post      = models.ForeignKey('Post', on_delete=models.CASCADE)
    content   = models.TextField()
    create_dt = models.DateTimeField(auto_now_add=True)
    update_dt = models.DateTimeField(auto_now=True)

✔️ Comment 모델에 대한 serializers.py은 아래와 같이 작성되어 있다.

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = '__all__'

🤔 객체를 Serializering 해보기

✔️ Django Shell에서 CommentSerializer를 호출하면 아래와 같이 ModelSerializer가 생성된 것을 볼 수 있다.

✔️ Serializering 과정은 Database로부터 객체를 가져온 후, Serialize 하고 Response하는 과정 순으로 이뤄진다.

✔️ 우선 Database에서 맨 처음 객체를 가져와 Serialize에 넣어 Dict 객체로 반환 받는다. 아래와 같이 반환된 객체의 타입을 살펴보면 ReturnDict이라해서 DRF에서 지원하는 Dict 형태이다.

✔️ 이제 JSON 포맷의 Byte String 타입으로 클라이언트에 전달하기 위해 JSONRenderer를 사용한다. 한글이기 때문에 16진수로 변환되는 것을 볼 수 있다. 타입을 찍어보면 bytes로 확인된다.

✔️ 즉, c1이라는 Database에서 가져온 Object를 직렬화하여 dict 형태로 변환 후, JSONRenderer로 클라이언트에게 전달하면 JSON 포맷의 Byte로 데이터를 전달하기 때문에 클라이언트에서도 데이터 복원시 데이터 유지가 가능하다. 이것이 직렬화(Serializering) 과정이다.

🤔 객체를 Deserializering 해보기

✔️ 이와 반대로, 클라이언트로 전달 받은 JSON 포맷의 Byte 데이터를 딕셔너리 형태로 변환하고, 인스턴스 시킨 후 Database에 저장하는 과정이 Deserializering 흐름이다.

✔️ 위 과정에서 만든 JSONRenderer().render(data)이 클라이언트에 전달된 JSON 포맷의 Byte 데이터라고 가정하고 이를 딕셔너리 형태로 변환하기 위해서는 JSONParser를 사용한다.

✔️ 단, parse 매서드에 byte 타입의 데이터를 직접 넣으면 에러가 발생하기 때문에 BytesIO를 통해 parse 매서드에 전달한다.

✔️ 이 dict 타입의 데이터를 인스턴스로 변환할 때 serializer를 사용하고, 이 전 과정을 역직렬화(Deserializering)이라 한다.

✔️ Serializering 할 때는 instance 인자에 넣었지만, Deserializering 때에는 data 인자에 dict 데이터를 전달한다.

✔️ 또한 위에 is_valid() 매서드를 통해 유효성 검사를 해야하는 이유는 클라이언트에 전달된 데이터 자체의 오류가 존재할 수 있기 때문이다. 참고로 프론트엔드의 유효성 검사는 사용자의 편의를 위해서 진행하지만, 백엔드의 유효성 검사는 필수이다. 만일 유효성 검사에서 문제가 존재한다는 errors에 dict 형태로 담기게된다.

✔️ 유효성 검사에 통과한 데이터들은 validated_data 라는 속성에 담기게 되고, 이 인스턴스를 모델에 전달하여 아래와 같이 Database에 저장할 수 있다.



3. Serializing과 Deserializing 비교

✔️ Serializing은 Database로부터 Object를 가져와 Serializer의 instance 인자에 전달하여 dict 데이터로 변환한다. 이 dict 데이터를 JSON 포맷의 Byte로 변환하여 클라리언트에 전달하는 흐름이며, 이 과정에서 JSONRenderer가 사용된다.

✔️ 반대로, Deserializing는 클라이언트로 전달받은 JSON 포맷의 Byte 데이터를 JSONParser의 parse 매서드를 통해 우선 dict 데이터로 변환한다.

✔️ 이 dict 데이터를 바로 사용하는 것이 아닌, Serializer의 data 인자에 전달하여 is_valid 매서드로 유효성 검사를 진행한다. 유효성 검사에 문제가 있다면 errors의 에러 정보가 담기지만, 유효성 검사를 통화했다면 validated_data 속성에 데이터가 존재한다.

✔️ validated_data를 만들고 나서야 이 데이터를 사용해서 모델에 전달해 인스턴스를 만들고, Database에 저장한다.

✔️ 즉, Serializing과 Deserializing 반대의 과정이지만, DRF에서는 Serializer 클래스를 통해 이 모든 작업이 이뤄진다는 공통점이 있다.

✔️ 단, Serializer 클래스 사용의 차이로는 직렬화 과정에서는 instance 인자에 객체를 전달하고, 역직렬화 과정에서는 data 인자에 dict 데이터를 전달하여 처리한다.

✔️ 이에 Serializing 과정에서는 Serializer가 Read Operation으로 작동하기 때문에 GET 매서드를 사용하고, DeSerializing 과정에서는 Serializer가 Write Operation으로 작동하여 POST, UPDATE, DELETE, PATCH 매서드를 사용하게 된다.

profile
Keep Going, Keep Coding!

0개의 댓글

관련 채용 정보