Django REST Framework에서 직렬화와 역직렬화 완벽 이해하기
목차
- 소개
- 직렬화와 역직렬화란 무엇인가?
- `request.data`의 형태 알아보기
- Serializer의 역할과 동작 원리
- 직렬화 과정 상세 설명
- 역직렬화 과정 상세 설명
- 유효성 검사와 에러 처리
- 실제 코드로 보는 직렬화와 역직렬화
- 자주 하는 실수와 해결 방법
- 추가 활용 예제
- 결론
- 참고 자료
소개
Django REST Framework(DRF)는 Django를 기반으로 한 강력한 API 개발 도구입니다. 이 프레임워크를 사용하면서 직렬화(Serialization)와 역직렬화(Deserialization)의 개념을 정확히 이해하는 것은 API 서버 개발에 있어서 매우 중요합니다. 이 글에서는 직렬화와 역직렬화가 무엇인지, 왜 필요한지, 그리고 DRF에서 이를 어떻게 구현하는지 자세히 알아보겠습니다.
직렬화와 역직렬화란 무엇인가?
직렬화(Serialization)
- 정의: 파이썬 객체(예: Django 모델 인스턴스)를 JSON, XML 등과 같은 포맷으로 변환하는 과정입니다.
- 왜 필요한가?: 클라이언트는 일반적으로 JSON과 같은 포맷을 통해 데이터를 주고받기 때문에 서버 측의 데이터를 이러한 포맷으로 변환해야 합니다.
역직렬화(Deserialization)
- 정의: 클라이언트로부터 받은 JSON, XML 등의 데이터를 파싱하여 파이썬 객체로 변환하는 과정입니다.
- 왜 필요한가?: 서버는 클라이언트로부터 데이터를 받아 내부 로직 처리나 데이터베이스 저장을 위해 이를 파이썬 객체로 변환해야 합니다.
왜 중요한가?
- 데이터 교환: 직렬화와 역직렬화는 서버와 클라이언트 간의 원활한 데이터 교환을 가능하게 합니다.
- 보안 및 유효성 검사: 역직렬화 과정에서 입력된 데이터의 유효성을 검증하여 보안성을 높일 수 있습니다.
`request.data`의 형태 알아보기
`request.data`는 클라이언트로부터 전달된 요청 데이터를 파싱하여 제공하는 속성입니다. 이 데이터의 형태는 요청의 `Content-Type`에 따라 달라집니다.
- JSON 데이터의 경우 (`Content-Type: application/json`):
- `request.data`는 JSON 데이터를 파싱한 파이썬의 `dict` 객체입니다.
- 폼 데이터의 경우 (`Content-Type: multipart/form-data` 또는 `application/x-www-form-urlencoded`):
- `request.data`는 Django의 `QueryDict` 객체이지만, DRF에서는 이를 일반 `dict`처럼 사용할 수 있도록 처리해줍니다.
따라서, `request.data`는 보통 파이썬의 `dict` 객체로 생각하고 사용하면 됩니다.
Serializer의 역할과 동작 원리
Serializer의 역할
Serializer는 DRF에서 직렬화와 역직렬화 모두를 담당하는 핵심 구성 요소입니다.
- 직렬화(Serialization):
- 파이썬 객체를 JSON 등의 포맷으로 변환하여 클라이언트에게 전달합니다.
- 역직렬화(Deserialization):
- 클라이언트로부터 받은 데이터를 파싱하여 파이썬 객체로 변환하고, 유효성 검사를 수행합니다.
Serializer의 동작 원리
- 필드 매핑: Serializer는 모델의 필드와 입력 데이터의 키를 매핑합니다.
- 유효성 검사: 각 필드에 대한 유효성 검사를 수행하고, 전체 데이터에 대한 검증도 가능합니다.
- 데이터 변환: 직렬화 시 모델 인스턴스를 `dict`로 변환하고, 역직렬화 시 입력 데이터를 `validated_data`로 변환합니다.
- 데이터 저장: `save()` 메서드를 통해 데이터베이스에 인스턴스를 생성하거나 업데이트합니다.
예시 코드:
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'content', 'author']
직렬화 과정 상세 설명
1. 모델 인스턴스 획득
article = Article.objects.get(pk=pk)
- 데이터베이스에서 원하는 객체를 가져옵니다.
2. Serializer를 통한 직렬화
serializer = ArticleSerializer(article)
- 모델 인스턴스를 Serializer에 전달하여 파이썬의 `dict` 형태로 변환합니다.
- `serializer.data`에 직렬화된 데이터가 저장됩니다.
3. 응답 생성
from rest_framework.response import Response
return Response(serializer.data)
- `Response` 객체를 사용하여 JSON 응답을 생성합니다.
- DRF는 내부적으로 `renderer`를 사용하여 `serializer.data`를 JSON으로 변환합니다.
정리:
- 직렬화된 데이터는 JSON이 아닌 `dict` 형태입니다.
- `Response` 객체를 통해 클라이언트는 JSON 응답을 받게 됩니다.
역직렬화 과정 상세 설명
1. 입력 데이터 수신
data = request.data
- 클라이언트로부터 전달된 데이터를 받습니다.
2. Serializer를 통한 역직렬화
serializer = ArticleSerializer(article, data=data, partial=True)
- 입력 데이터를 Serializer에 전달하여 역직렬화를 수행합니다.
- `partial=True`는 일부 필드만 업데이트할 수 있도록 허용합니다.
3. 유효성 검사
if serializer.is_valid(raise_exception=True):
- `is_valid()` 메서드를 호출하여 데이터의 유효성을 검사합니다.
- 유효한 데이터는 `serializer.validated_data`에 저장됩니다.
4. 데이터 저장
serializer.save()
- `validated_data`를 사용하여 데이터베이스에 저장하거나 업데이트합니다.
- 인스턴스 생성 시 `create()` 메서드, 업데이트 시 `update()` 메서드를 내부적으로 호출합니다.
5. 응답 생성
return Response(serializer.data)
- 저장된 데이터를 직렬화하여 응답합니다.
정리:
- 역직렬화된 데이터는 `serializer.validated_data`에 `OrderedDict` 형태로 저장됩니다.
- `save()` 메서드를 통해 데이터베이스에 변경 사항이 반영됩니다.
유효성 검사와 에러 처리
유효성 검사
- 필드 수준 유효성 검사: 각 필드마다 `validators`를 통해 검증합니다.
- 객체 수준 유효성 검사: `validate()` 메서드를 오버라이딩하여 객체 전체에 대한 검증을 수행합니다.
예시 코드:
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
def validate_title(self, value):
if '금지어' in value:
raise serializers.ValidationError("제목에 금지어가 포함되어 있습니다.")
return value
에러 처리
- `is_valid(raise_exception=True)`를 사용하면 유효성 검사 실패 시 자동으로 `ValidationError`가 발생하고, DRF는 적절한 에러 응답을 생성합니다.
if serializer.is_valid(raise_exception=True):
serializer.save()
else:
return Response(serializer.errors, status=400)
실제 코드로 보는 직렬화와 역직렬화
직렬화 예제
from rest_framework.views import APIView
class ArticleDetailView(APIView):
def get(self, request, pk):
article = Article.objects.get(pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
설명:
- `GET` 요청 시 `Article` 인스턴스를 가져와 Serializer를 통해 직렬화합니다.
- 직렬화된 데이터를 `Response`를 통해 클라이언트에게 반환합니다.
역직렬화 예제
class ArticleUpdateView(APIView):
def put(self, request, pk):
article = Article.objects.get(pk=pk)
serializer = ArticleSerializer(article, data=request.data, partial=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
설명:
- `PUT` 요청 시 클라이언트로부터 입력된 데이터를 받아 Serializer에 전달합니다.
- 유효성 검사를 통과하면 `save()` 메서드로 데이터베이스를 업데이트합니다.
- 업데이트된 데이터를 직렬화하여 응답합니다.
자주 하는 실수와 해결 방법
1. `serializer.data`를 JSON이라고 착각하는 경우
- 실수: 직렬화된 데이터가 이미 JSON이라고 생각하여 추가 처리 없이 사용함.
- 해결 방법: `serializer.data`는 `dict` 형태이며, `Response` 객체를 사용하여 JSON으로 변환해야 합니다.
2. 유효성 검사를 누락하는 경우
- 실수: `is_valid()` 메서드를 호출하지 않고 `save()`를 호출함.
- 해결 방법: 항상 `is_valid()`를 통해 유효성 검사를 수행한 후 `save()`를 호출해야 합니다.
3. 역직렬화 시 `instance`를 전달하지 않는 경우
- 실수: 업데이트 시 기존 인스턴스를 `Serializer`에 전달하지 않음.
- 해결 방법: 업데이트 시에는 `Serializer`를 생성할 때 `instance`와 `data`를 모두 전달해야 합니다.
추가 활용 예제
1. 토큰 인증과의 연계
- 사용자 인증 시 토큰을 발급하고 직렬화를 통해 응답합니다.
2. 파일 업로드 처리
- 파일을 포함한 폼 데이터를 처리할 때도 Serializer를 사용하여 역직렬화합니다.
3. Nested Serializer 활용
- 관계형 데이터를 처리할 때 중첩 Serializer를 사용하여 복잡한 데이터를 직렬화하고 역직렬화할 수 있습니다.
예시 코드:
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ['id', 'content', 'author']
class ArticleSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True)
class Meta:
model = Article
fields = ['id', 'title', 'content', 'author', 'comments']
결론
Django REST Framework에서 직렬화와 역직렬화는 서버와 클라이언트 간의 원활한 데이터 교환을 가능하게 하는 핵심 요소입니다.
- `request.data`는 일반적으로 파이썬의 `dict` 형태이며, Serializer를 통해 직렬화와 역직렬화를 수행합니다.
- 직렬화된 데이터는 JSON이 아닌 `dict`이고, `Response` 객체를 통해 클라이언트에게 JSON 형식으로 전달됩니다.
- 역직렬화 과정에서 유효성 검사를 통과한 데이터는 `serializer.validated_data`에 저장되며, `save()` 메서드를 통해 데이터베이스에 반영됩니다.
- Serializer는 내부적으로 데이터 변환과 저장 로직을 처리하므로, 개발자는 복잡한 데이터 처리 로직에 집중할 수 있습니다.
참고 자료
'Python > Django' 카테고리의 다른 글
| Django User정보 넣기 (0) | 2025.01.22 |
|---|---|
| DRF(Serializer) (1) | 2025.01.21 |
| Django 에서 commit (0) | 2025.01.20 |
| 웹보안을 위해 쿠키, 세션, 해시 그리고 JWT (Django 관점) (1) | 2025.01.17 |
| DRF학습전 API, RESTful API 미리보기 (1) | 2025.01.16 |