Nonamed Develog
[TIL][240914] DRF Permission Class 본문
오늘은 Django REST Framework(DRF)에서 사용되는 Permission Class에 대해 학습했다. DRF에서 API 요청에 대한 권한을 설정할 때 request.user를 통해 간단히 접근할 수 있지만, 그럼에도 불구하고 Permission Class를 사용하는 이유가 무엇인지에 대해 고민했다.
1. request.user로 권한 설정
Django는 기본적으로 request.user를 통해 현재 요청을 보낸 사용자의 정보를 제공한다. 이 정보를 활용하면, 간단한 권한 체크가 가능하다. 예를 들어, 로그인된 사용자만 접근 가능하게 하려면 뷰에서 다음과 같은 방식으로 처리할 수 있다.
def get(self, request):
if not request.user.is_authenticated:
return Response({"detail": "Authentication required"}, status=401)
이처럼 request.user를 직접 활용하여 권한을 제어하는 것은 쉽고 직관적이다.
2. Permission Class를 사용하는 이유
그렇다면, DRF에서 이미 request.user로 권한을 제어할 수 있음에도 왜 Permission Class를 추가로 사용하는 걸까?
a. 코드 재사용성과 가독성
권한 검사를 각 뷰에서 request.user를 통해 직접 처리하게 되면, 같은 검사가 여러 뷰에 반복될 수 있다. Permission Class를 사용하면 권한 검사를 하나의 클래스에서 정의하고 여러 뷰에서 재사용할 수 있어 코드의 중복을 줄이고, 관리가 쉬워진다.
from rest_framework.permissions import BasePermission
class IsAdminUser(BasePermission):
def has_permission(self, request, view):
return request.user and request.user.is_staff
이렇게 정의한 Permission Class는 다양한 뷰에서 적용 가능하며, 가독성 측면에서도 권한과 관련된 로직을 분리하여 뷰 코드를 간결하게 유지할 수 있다.
b. 역할과 목적의 명확화
request.user는 기본적으로 사용자의 인증 정보를 제공하는 역할을 한다. 하지만 권한 관리는 이와 별개로 더 세밀한 통제가 필요한 경우가 많다. 예를 들어, 사용자가 관리자인지 여부, 특정 리소스에 대한 접근 권한이 있는지 등을 확인하려면 더 복잡한 로직이 필요할 수 있다. Permission Class는 이러한 "권한"에 대한 논리를 명확하게 분리해 관리할 수 있게 해준다.
c. DRF의 공식적인 구조 활용
DRF는 권한 설정을 위한 공식적인 구조로 Permission Class를 제공하며, 이를 사용하면 DRF의 다른 기능과 통합하여 쉽게 관리할 수 있다. 예를 들어, permission_classes 속성을 통해 뷰별로 간단히 권한을 설정할 수 있다.
from rest_framework.permissions import IsAuthenticated
class MyView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
# 인증된 사용자만 이 뷰에 접근 가능
pass
d. 다양한 권한 조합 가능
Permission Class는 여러 권한 클래스를 조합하여 사용할 수 있다. 예를 들어, 사용자가 로그인했는지 여부와 관리자 권한을 동시에 체크할 때 다음과 같이 설정할 수 있다:
from rest_framework.permissions import IsAuthenticated, IsAdminUser
class MyAdminView(APIView):
permission_classes = [IsAuthenticated, IsAdminUser]
def get(self, request):
# 인증된 관리자만 이 뷰에 접근 가능
pass
3. 자주 쓰이는 Permission Class
DRF에서 자주 사용되는 Permission Class는 다음과 같다:
1. IsAuthenticated
- 로그인한 사용자만 접근을 허용한다.
- 익명 사용자(비로그인 상태)는 접근할 수 없으며, 인증이 필요하다.
- 보통 인증이 필요한 API에 자주 사용된다.
from rest_framework.permissions import IsAuthenticated
class MyView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
# 인증된 사용자만 이 뷰에 접근 가능
pass
2. IsAdminUser
- 관리자인 사용자(즉, is_staff=True인 사용자)만 접근 가능하다.
- 관리자 페이지나 특정 권한을 가진 사용자만 접근할 수 있도록 할 때 사용된다.
from rest_framework.permissions import IsAdminUser
class AdminView(APIView):
permission_classes = [IsAdminUser]
def get(self, request):
# 관리자만 이 뷰에 접근 가능
pass
3. AllowAny
- 모든 사용자에게 접근을 허용한다.
- 일반적으로 로그인 여부와 상관없이 접근 가능한 API에 사용되며, 기본적으로 사용자가 인증되지 않아도 접근 가능한 페이지에서 사용된다.
from rest_framework.permissions import AllowAny
class PublicView(APIView):
permission_classes = [AllowAny]
def get(self, request):
# 누구나 접근 가능
pass
4. IsAuthenticatedOrReadOnly
- 인증된 사용자에게는 모든 작업을 허용하지만, 인증되지 않은 사용자에게는 읽기 작업(GET 요청)만 허용한다.
- 일반적인 게시글 목록 조회는 누구나 가능하지만, 게시글 작성은 로그인된 사용자만 할 수 있도록 할 때 유용하다.
from rest_framework.permissions import IsAuthenticatedOrReadOnly
class PostViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
# 인증된 사용자만 글을 작성할 수 있다
serializer.save(author=self.request.user)
5. DjangoModelPermissions
- Django 모델에서 정의된 권한을 기반으로 접근을 허용한다.
- 기본적으로 조회, 추가, 변경, 삭제 권한이 부여된 사용자만 해당 작업을 수행할 수 있다.
from rest_framework.permissions import DjangoModelPermissions
class RestrictedModelViewSet(viewsets.ModelViewSet):
permission_classes = [DjangoModelPermissions]
4. 결론
비록 request.user를 통해 간단한 권한 체크를 할 수 있지만, DRF의 Permission Class는 코드의 재사용성, 관리의 용이성, 그리고 역할의 명확성을 고려했을 때 매우 유용하다. Permission Class를 사용함으로써 권한 관련 로직을 중앙화하고, DRF의 기능을 더 효과적으로 활용할 수 있다. 또한, DRF에서 제공하는 다양한 Permission Class를 적절히 활용하면 훨씬 더 유연하고 강력한 권한 관리를 할 수 있다.
'WHAT I LEARN > TIL' 카테고리의 다른 글
[TIL][240920] 트러블 슈팅 (0) | 2024.09.23 |
---|---|
[TIL][240919] Readme에 이미지 올리는 2가지 방법 (0) | 2024.09.19 |
[TIL][240912] Pull Request와 Local Merge (1) | 2024.09.13 |
[TIL][240911] 프로젝트 시작, 끝 없는 문서 작성...(SA) (1) | 2024.09.11 |
[TIL][240910] Django와 웹 크롤링 (2) | 2024.09.10 |