[트러블슈팅] 리뷰 작성할 때 content 필드에 데이터가 저장되지 않는 문제와 블러 처리 구현

2star_·2025년 1월 19일
0

최종 프로젝트

목록 보기
23/32

content 필드에 데이터가 저장되지 않는 문제와 블러 처리 구현


문제

새 리뷰를 생성할 때, POST 요청에 포함된 content 값이 데이터베이스에 저장되지 않는 문제가 발생했습니다. 이와 동시에 차단된 사용자의 리뷰를 조회할 때 내용을 블러 처리하는 기능을 구현하려고 했습니다. 하지만 두 기능이 충돌하면서 아래와 같은 문제가 발생했습니다:

  1. content 필드가 SerializerMethodField로 설정되어 있었습니다.
    • 문제: SerializerMethodField는 읽기 전용 필드로, 요청 데이터를 받아들이지 않기 때문에 새 리뷰 생성 시 content 값이 무시되었습니다.
  2. 블러 처리 로직이 content 필드와 연결되어 리뷰 생성과 조회 기능 간의 혼란이 발생했습니다.
    • content 필드가 저장되지 않아 블러 처리 이전에 기본 동작부터 실패했습니다.

원인 분석

  1. SerializerMethodField의 읽기 전용 특성

    • SerializerMethodField는 데이터를 직렬화할 때 get_<field_name> 메서드의 반환값만 사용하며, 모델 필드와 연결되지 않습니다.
    • 결과적으로, POST 요청에서 content 데이터를 저장하지 못했습니다.
  2. 블러 처리와 데이터 저장의 충돌

    • content 필드를 블러 처리 로직과 동일하게 처리하려다 보니, 읽기와 쓰기가 충돌했습니다.
    • 블러 처리 로직은 데이터 조회 시 적용되어야 하지만, 데이터 저장 로직에 영향을 미쳤습니다.

해결 방안

  1. 읽기와 쓰기를 분리

    • content 필드는 데이터 저장용으로 유지하고, 차단된 사용자 리뷰를 숨김 처리하는 블러 처리 로직은 content_display라는 추가 필드로 분리했습니다.
    • content: 원본 리뷰 데이터를 저장하고 반환.
    • content_display: 차단된 사용자의 리뷰 내용을 숨김 처리하여 반환.
  2. 직렬화 및 로직 구현

    • content_displaySerializerMethodField를 사용하여 읽기 전용으로 설정.
    • content는 모델 필드와 연결하여 리뷰 생성 시 데이터를 저장.

수정된 코드

1. ReviewSerializer

class ReviewSerializer(serializers.ModelSerializer):
    """Review 모델 직렬화"""
    nickname = serializers.SerializerMethodField()  # 사용자 닉네임 반환
    content_display = serializers.SerializerMethodField()  # 차단된 사용자 콘텐츠 처리
    comments = ReviewCommentSerializer(many=True, read_only=True)  # 연결된 댓글들
    total_likes = serializers.IntegerField(read_only=True)  # annotate로 계산된 값
    total_dislikes = serializers.IntegerField(read_only=True)  # annotate로 계산된 값
    game_name = serializers.CharField(read_only=True)
    header_image = serializers.CharField(read_only=True)


    class Meta:
        model = Review
        fields = [
            'id', 'user', 'nickname', 'content', 'content_display', 'app_id', 'game_name', 'header_image', 'score', 'categories',
            'created_at', 'updated_at', 'comments', 'total_likes', 'total_dislikes'
        ]
        read_only_fields = [
            'id', 'created_at', 'updated_at', 'comments', 'total_likes', 'total_dislikes', 'game_name', 'header_image', 'categories', 'content_display'
        ]

    def get_nickname(self, obj):
        """유저 닉네임 반환 (유저가 없으면 '알수없음')"""
        return obj.user.nickname if obj.user else "알수없음"

    def get_content_display(self, obj):
        blocked_users = self.context.get('blocked_users', [])
        if obj.user and obj.user.id in blocked_users:
            return "이 사용자의 리뷰는 차단되어 표시되지 않습니다."
        return obj.content

2. ReviewDetailAPIView

class ReviewDetailAPIView(APIView):
    def get(self, request, pk):
        """특정 리뷰 조회"""
        review = get_object_or_404(Review, pk=pk)
        blocked_users = Block.objects.filter(blocker=request.user).values_list('blocked_user', flat=True) if request.user.is_authenticated else []
        
        serializer = ReviewSerializer(review, context={'blocked_users': list(blocked_users)})
        return Response(serializer.data, status=status.HTTP_200_OK)

해결 결과

  1. 리뷰 생성 시 content 저장 정상화

    • POST 요청 시 content 데이터가 Review 모델에 정상적으로 저장됩니다.
  2. 블러 처리 기능 분리

    • content_display 필드가 차단된 사용자의 리뷰를 숨김 처리하여 반환합니다.
    • 원본 데이터(content)는 변경되지 않고, 필요할 때 블러 처리 로직만 동작합니다.
  3. 코드의 명확성과 확장성 증가

    • 데이터 저장과 블러 처리 로직이 분리되어 각 기능이 독립적으로 유지됩니다.
    • 블러 처리 로직을 유저별로 다르게 설정하거나 조건을 추가하는 등의 확장이 용이해졌습니다.
profile
안녕하세요.

0개의 댓글

관련 채용 정보