Block
기능
처음에는 Django의 Many-to-Many 필드를 사용하려고 했습니다. 하지만 아래와 같은 이유로 명시적인 Block
모델을 설계하기로 결정했습니다:
1. 추가 메타데이터 저장 필요성: 차단 시점(created_at
)이나 차단 사유(reason
)를 저장하려면 Many-to-Many 필드만으로는 한계가 있음
2. 명확한 관계 표현: blocker
(차단자)와 blocked_user
(차단된 사용자)의 비대칭적 관계를 명확히 하기 위해 중간 모델이 더 적합
3. 확장성: 추후 차단 상태 변경 이력 기록, 통계 분석 등의 기능을 고려
class Block(models.Model):
blocker = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="blocked_users"
)
blocked_user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="blocked_by_users"
)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = [('blocker', 'blocked_user')]
ordering = ['-created_at']
초기에는 요청과 응답 데이터 처리를 위해 Serializer
를 추가할지 고민했습니다. 하지만 구현 초기에 Serializer를 생략한 이유는 다음과 같습니다:
1. 단순한 데이터 처리:
blocked_user_id
)로 이루어짐get_object_or_404
로 충분히 처리 가능하지만, 추후 확장성을 고려하여 Serializer
를 추가하는 방안을 열어둠
APIView
를 기반으로 차단, 차단 해제, 차단된 유저 목록 조회 기능을 구현했습니다.
Block.objects.get_or_create
를 사용하여 동일한 유저를 중복 차단하는 경우를 방지Block
레코드 삭제 시 삭제된 레코드가 없으면 적절한 에러 메시지를 반환select_related
를 사용해 쿼리 최적화를 고려class BlockedUserAPIView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
blocked_users = Block.objects.filter(blocker=request.user).select_related('blocked_user')
data = [{"id": block.blocked_user.id, "nickname": block.blocked_user.nickname} for block in blocked_users]
return Response(data, status=status.HTTP_200_OK)
def post(self, request):
blocked_user_id = request.data.get("blocked_user_id")
blocked_user = get_object_or_404(Account, id=blocked_user_id)
block, created = Block.objects.get_or_create(blocker=request.user, blocked_user=blocked_user)
if not created:
return Response({"message": "이미 차단된 사용자입니다."}, status=status.HTTP_400_BAD_REQUEST)
return Response({"message": "유저를 차단했습니다."}, status=status.HTTP_201_CREATED)
def delete(self, request):
blocked_user_id = request.data.get("blocked_user_id")
blocked_user = get_object_or_404(Account, id=blocked_user_id)
deleted, _ = Block.objects.filter(blocker=request.user, blocked_user=blocked_user).delete()
if not deleted:
return Response({"message": "차단된 유저가 아닙니다."}, status=status.HTTP_400_BAD_REQUEST)
return Response({"message": "유저 차단을 해제했습니다."}, status=status.HTTP_204_NO_CONTENT)
차단된 유저의 리뷰를 블러 처리하거나 목록에서 제외하는 방안을 결정했습니다.
"차단된 사용자가 작성한 리뷰입니다."
를 반환ReviewAPIView
에서 차단된 유저의 리뷰를 필터링API 뷰를 다음 URL에 연결:
GET /accounts/block/
: 차단된 유저 목록POST /accounts/block/
: 유저 차단DELETE /accounts/block/
: 유저 차단 해제POSTMAN을 사용하여 다음 시나리오를 테스트:
1. 유저 차단: 동일 유저 중복 차단 방지 확인
2. 유저 차단 해제: 차단되지 않은 유저 해제 시 에러 반환
3. 차단된 유저 목록 조회: 올바른 데이터를 반환하는지 확인