ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL 2023.06.22
    내일배움캠프 2023. 6. 22. 19:32

    DRF의 페이지네이션은

    파일 경로에 서버 url를 같이 담아서 보내준다는 걸 알았다.

     

    이걸 발견한 게 백엔드 서버를 배포했을 때,

    사진을 제대로 불러오지 못한 부분에서 왜 그런지 한참 찾아보다가 알게 되었다.

    img src=에 http://backend:8000 이 부분은 써 준 적도 없는데 붙어있던 것이다.

     

    이미지 파일 경로는 DB에 /media/~ 이런 식으로 저장되지만

    페이지네이션으로 가져올 때는 앞에 서버 주소를 자동으로 붙여서 보내주게 된다.

    로컬서버에서는 http://127.0.0.1:8000/media/~ 이런식으로

    경로를 알아서 만들어줘서 오 이거 왜 자동으로 써 있지 하며 좋아했지만,

    docker로 배포한 환경에서는 http://backend:8000/media/~ 이런 식으로 나왔다.

    저 경로로는 이미지를 불러 올 수 없다.

     

    그래서 페이지네이션을 커스텀하면 앞에 서버 주소를 지워줄 수 있다.

    먼저 이미지 파일 경로는

    class PostListAPIView(ListAPIView):
        queryset = Post.objects.all()
        serializer_class = PostListSerializer
        pagination_class = PostPageNumberPagination
    
        def get_serializer_context(self):
            return {
                'request': None, # None이 아닌 경우에 full url 표시
                'format': self.format_kwarg,
                'view': self
            }

    이렇게 ListAPIView를 상속 받아서, get_serializer_context 함수를 오버라이딩해서 지워주면 된다.

    이걸 각 앱에 적용 시켰다.

     

    또 next와 previous 경로에서도 서버 주소가 붙어서 나왔는데,

    이건 다른 방식으로 해결해야 했다.

    from rest_framework.utils.urls import remove_query_param, replace_query_param
    from rest_framework import pagination
    
    
    class CustomPagination(pagination.PageNumberPagination):
        def get_next_link(self):
            if not self.page.has_next():
                return None
            url = self.request.build_absolute_uri()
            url = url.split('/')[3:]
            url = "/" + "/".join(url)
            page_number = self.page.next_page_number()
            return replace_query_param(url, self.page_query_param, page_number)
    
        def get_previous_link(self):
            if not self.page.has_previous():
                return None
            url = self.request.build_absolute_uri()
            url = url.split('/')[3:]
            url = "/" + "/".join(url)
            page_number = self.page.previous_page_number()
            if page_number == 1:
                return remove_query_param(url, self.page_query_param)
            return replace_query_param(url, self.page_query_param, page_number)

    PageNumberPagination 을 상속하여 커스텀페이지네이션을 만들고

    url로 선언한 경로를 / 를 기준으로 쪼개서 앞 부분을 슬라이싱 해주고

    다시 붙여준다.

    그리고 settings.py에 기본 페이지네이션 클래스를 지정해준다.

    REST_FRAMEWORK = {
        "DEFAULT_PAGINATION_CLASS": "spots.core.pagination.CustomPagination",
        "PAGE_SIZE": 6,
    }

    이렇게 페이지네이션 시 서버 주소를 자동으로 붙여주는 문제를 해결할 수 있었다.

     

     

    다른 문제

    nginx 에선 기본 파일 업로드 제한을 1MB 로 걸어 두고 있다.

    이 때 413 Request Entity Too Large 코드를 뱉어 내는 게 정상인데,

    이상하게도 우리 서버는 cors 에러를 뱉어 냈다.

    어쨌든 그 문제를 해결하고자 nginx의 파일 크기 제한을 3MB로 늘려 주었다.

    sudo vi /etc/nginx/nginx.conf

    nignx.conf 를 열어서

    http { 안에

    client_max_body_size 3M;

    이런 설정을 추가 해주면 된다.

     

    그리고 프론트에서도 예외처리를 해준다.

        const image = document.getElementById("image-select").files[0];
    
        let maxSize = 3 * 1024 * 1024; //=>3MB
        
        if (image.size > maxSize) {
            return alert("3MB 이하의 파일만 업로드 가능합니다.")
        }

    나는 이렇게 코드를 짰다.

     

     

    token refresh 기능도 추가했다.

    document.addEventListener('DOMContentLoaded', async function () {
      tokenRefresh()
    })
    
    async function tokenRefresh() {
      const refresh = localStorage.getItem("refresh")
    
      if (refresh) {
        const response = await fetch(`${proxy}/users/api/token/refresh/`, {
          headers: {
            "content-type": "application/json",
          },
          method: "POST",
          body: JSON.stringify({
            refresh: refresh
          })
        });
    
        if (response.status == 200) {
          const response_json = await response.json();
          localStorage.setItem("access", response_json.access);
        } else {
          handleLogout()
        }
      }
    }

    페이지가 로드 되면 tokenRefresh() 함수를 호출한다.

    tokenRefresh() 함수는 로컬스토리지에 리프레시 토큰이 있는 지 확인하고

    있다면 서버로 전송해 엑세스 토큰을 새로 받아와 로컬스토리지에 저장한다.

    만약 스테이터스 코드가 200이 아니라면 리프레시 토큰이 만료됐을 확률이 크기 때문에

    handleLogout() 함수를 호출하는데 handleLogout() 는 로컬스토리지의 토큰을 모두 지운다.

    '내일배움캠프' 카테고리의 다른 글

    WIL 내일배움캠프 15주차  (0) 2023.06.23
    TIL 2023.06.23  (0) 2023.06.23
    TIL 2023.06.21  (0) 2023.06.21
    TIL 2023.06.20  (0) 2023.06.20
    TIL 2023.06.19  (0) 2023.06.19
Designed by Tistory.