TIL136. DRF : Serializer에 관하여

6554 단어 drfdrf

📌 이 포스팅에서는 직렬화(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 매서드를 사용하게 된다.

좋은 웹페이지 즐겨찾기