AI 부트캠프 - DRF

Cookie Baking·2024년 12월 26일

AI 부트 캠프 TIL

목록 보기
35/42

DRF

HTTP 요청

- 200 : GET 요청 성공
- 201 : POST 요청 성공
- 400 : Client 요청이 잘못됨
- 401 : 인증이 되어 있지 않음
- 403 : 처리할 권한이 없음 
- 404 : URL (리소스) 가 존재하지 않음
- 500 : Server에서 문제가 생김
- 503 : Server에서 요청 처리를 못함 (잠깐 사용 못함)

URI : 통합 자원 식별자, 웹상에 자원이 어디 있는지 나타내기 위한 문자열
RestFul API : URL로 소통하는 것
URL은 동사가 아닌 명사의 나열로 사용해야 함
(POST /articles/create 가 아닌 POST /articles/ 로 사용해야 함)

Author이 게시글 생성일 때에 필요가 없기 때문에 readonlyField로 해줘야 함
클래스 기반으로 처리를 함

직렬화 (Serialization)

  • 객체 또는 데이터 구조를 저장, 전송을 위해 다른 포캣으로 변경하는 것, 데이터의 구조는 유지하면서 추후 재구성이 가능한 포맷으로 변환함
  • 현재 Python 객체 형태인 Queryset 혹은 Model의 Instance를 전송 가능한 형태로 직렬화를 통해 JSON, XML, YAML 등의 형태로 변환하는 것
  • Django도 내부적으로 다른 데이터 포맷으로 쉽게 직렬화 할 수 있는 기능을 제공

BUT! Django의 serializer는

  • 한정된 모델 구조임
  • 직렬화된 데이터의 구조를 변경하거나 새로운 필드를 구성하는 것에 많은 추가 작업이 필요
  • 유연한 API를 위한 기능이라기보다 모델 구조로 저장되어 있는 데이터를 export 하는 용도에 가까움

함수형 View VS 클래스형 View

  • 함수형 View에서는 반드시 데코레이터를 달아줘야 함

함수형 View
1. view 어노테이션을 달아준다.
2. view method를 선택한다.
3. object를 불러온다.
4. serializer를 불러와 Response 표출 혹은 유효성 검증을 함

Serializer에서 들어가는 객체가 여러개일 경우 many=True 옵션을 줘야 함
POST 즉 생성의 요청의 경우에는 serializer.save() 요청이 필요함

예시 코드 CRUD


@api_view(["GET"])
def json_drf(request):
    articles = Article.objects.all()
    # Serializer에 들어가는 객체가 여러 개이기 때문에 many=True 옵션을 줘야 힘
    serializer = ArticleSerializer(articles, many=True)
    return Response(serializer.data)

@api_view(["GET", "POST"])
def article_list(request):

    if request.method == "GET":
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)
    
    elif request.method == "POST":
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data, status=201)
        

@api_view(["GET", "PUT", "DELETE"])
def article_detial(request, pk):

    if request.method == 'GET':
        article = get_object_or_404(Article, pk=pk)
        serializer = ArticleSerializer(article)
        return Response(serializer.data)
    
    elif request.method == "PUT":
        article = get_object_or_404(Article, pk=pk)
        serializer = ArithmeticError(article, data=request.data, partial=True)
    
    elif request.method == "DELETE":
        article = get_object_or_404(Article, pk=pk)
        article.delete()
        return Response(status=200)

SEEDING을 이용한 더미 데이터 생성

python3 manage.py seed articles --number=20

JWT

Access Token VS Refresh Token

Access Token

  • 요청할 때 인증을 위해 헤더에 포함해야 하는 토큰
  • 매 요청 시 보내는 토큰으로 보안에 취약함
  • 만료 기한을 짧게 잡아 만약 탈취 당해도 짧은 시간안에 유효하지 않은 토큰 형태가 됨

Refresh Token

  • Access Token이 만료되었을 때 Access Token을 발급하기 위한 Token
  • Access Token보다 긴 유효기간을 가짐
  • 주로 사용자의 기기에 저장해두고 사용되며 만약 Refresh Token까지 만료되었다면 다시 인증(로그인) 과정이 필요함
  • Refresh Token의 탈취를 보완하기 위해 DB 리소스를 사용하는 다양한 방식도 존재 (BlackList 등)

Django의 ORM

조건 연결 -> Q() 이용

Product.objects.filter(Q(price__get=15000) | Q(quantity__lt=3000))

필드값 가져오기 -> F()

  • F()는 쿼리를 작성할 때 이전의 필드 값에 의존하는 작업을 숩게 할 수 있음
  • 주로 필드의 값을 가져오거나 업데이트해서 값을 참조하는데 사용함
  • python 메모리로 값을 가져오지 않고 필요한 작업을 데이터베이스에서 수핼할 수 있음
Products.objects.update(price = F('price') + 1000)

추가적인 정보를 제공하는 데 사용하기 -> annotate()

# total_price = price * quantity

products = Product.objects.annotate(
	total_price = F('price') * F('quantity')
)

종합/집약하는 데 사용하기 -> aggregate()

  • 주로 집계 함수 (Avg, Sum, Count 등)와 많이 사용
products = Product.objects.all()
products.aggregate(Avg('price'))

# 평균 이름을 지정해주고 싶다면
products.aggregate(avg_price=Avg('price'))

카테고리형으로 뽑는 방법 -> group_by()

  • values()
  • annotate(Count())
products.values('category')
products.values('category').annotate(Count('category'))

지연로딩

  • 우리가 ORM을 작성하면 작성하자마자 SQL로 변환되어 쿼리되는 것이 아닌 최대한 쿼리를 미루다가 해당 데이터가 실제로 사용될 때 쿼리를 진행하는 것을 지연 로딩이라 함
  • 지연 로딩은 불필요한 데이터베이스 쿼리를 방지하여 필요한 데이터만 쿼리하여 성능을 보장
  • 모든 관련된 데이터를 한 번에 로드하지 않고 필요한 경우에만 쿼리하므로 메모리 사용을 줄임
  • 데이터베이스의 부담을 줄임

다만 지연로딩은 관련된 모델을 가져와야 하는 작업이 필요할 경우에는 N+1 Problem이 발생함

즉시로딩

  • 데이터를 로드할 때 필요하다고 판단되는 연관된 데이터 객체들을 한 번에 가져오는 것
  • 이를 통해 지연로딩에서 팔생하는 N+1 문제를 해결할 수 있음 But 너무 많은 데이터를 초기에 가져오는 문제가 발생할 수 있음

select_related

  • 정참조
    EX.
    Comment.objects.all().select_related("article")
  • one-to-many 또는 one-to-one 관계에서 사용
  • SQL의 JOIN을 이용해서 관련된 객체들을 한 번에 로드하는 방식

prefetch_related

  • many-to-many 또는 역참조 관계에서 주로 사용
    (select_related를 사용하는 관계에서도 동작)
  • 내부적으로 두번의 쿼리를 사용해서 동작
    첫번째 쿼리는 원래 객체를 조회하며 두 번째 쿼리는 연관된 객체를 가져오는 방식
ModelClass.object.filter(조건절)
	.selected_related('정방향 참조') # JOIN
    .prefetch_related('역방향 참조') # Additional Query

Query를 손쉽게 로그하려면?

pip install django-silk 
MIDDLEWARE에 'silk.middleware.SilkyMiddleware', 추가
urlpatterns += [path("silk/", include("silk.urls", namespace="silk"))]

  • 외의 django toolbar

0개의 댓글