Django

    Swagger - SerializerMethodField의 return type hint

    django rest framework에서 SerializerMethodField 필드의 return 타입이 원시형이 아닌 Serializer의 형태일 때 어떻게 API Docs에서 보여줄 것인가에 대한 고민이 있었다. drf-yasg를 검색해 본 결과 아래의 어노테이션을 선언하면 object 형태의 Serializer 도 보여줄 수 있었다 @swagger_serializer_method(serializer_or_field=FooSerializer) def get_foo_list(self, obj) return FooSerializer(obj.instance).data 참고: https://drf-yasg.readthedocs.io/en/stable/custom_spec.html#support-for-s..

    [Django] - 사용자 로그인 - JWT 적용하기 - 2. JWT 이해하기

    2023.07.02 - [Django] - 사용자 로그인 - JWT 적용하기 - 1. Session 이해하기 JWT (Json Web Token) 이란? JWT는 JSON Web Token의 약자로, 웹 표준으로 지정된 토큰 기반의 인증 방식이다. JWT는 사용자의 정보를 JSON 객체로 안전하게 전송하기 위한 방법으로, 특히 분산 시스템에서 인증 정보를 공유할 때 유용하다. JWT의 구성 JWT는 세 부분으로 구성되어 있다. Header JWT의 헤더(Header)는 JWT의 유형과 암호화 알고리즘 정보를 포함하는 부분입니다. 헤더는 Base64로 인코딩 된 JSON 객체로 구성되어 있다. 헤더는 다음과 같은 두 가지 주요 속성을 포함한다. 토큰 유형(Type): 토큰의 유형을 나타내는 속성이다. 일반..

    사용자 로그인 - JWT 적용하기 - 1. Session 이해하기

    사용자 로그인을 구현하였다. 기존에는 Session만을 이용했는데, 이번엔 JWT를 활용하였다. JWT를 이용하면서 이론적으로만 알던 부분을 적용하면서 이해도가 깊어진 느낌이다. 우선 전통적인 Session 기반 인증을 공부해 보자. 1. 세션(Session)이란? 세션은 웹 서버에서 클라이언트를 구분하기 위한 방법 중 하나이다. 클라이언트가 웹 서버에 접속하면, 웹 서버는 해당 클라이언트의 브라우저에게 세션 ID를 부여한다. 이후 클라이언트가 서버로 요청을 보낼 때마다, 해당 세션 ID를 함께 보내게 된다. 1.1 세션 로그인(Session Login)이란? 세션 로그인은, 사용자가 로그인을 하면 서버에서 해당 사용자에 대한 세션을 생성하는 방식이다. 이후 사용자가 로그인 상태를 유지하는 동안, 해당 ..

    인증 구현하기

    Django 인증 절차를 Custom 하고 싶었다. 나는 모든 View에서 인증 절차를 처리하는 AuthenticationMiddleware를 조작하거나 AUTHENTICATION_CLASSES를 재정의해서 request.user를 확인하는 절차를 처리할 수 있다. 나는 AuthenticationMiddleware 보다는 AUTHENTICATION_CLASSES 를 재정의하고자 했다. 그 이유는 AuthenticationMiddleware는 상위의 위치하는 레이어이기 때문에 이걸 섣부르게 커스텀했다가는 내가 인지 못하는 부작용이 발생할 거 같았다. AuthenticationMiddleware AuthenticationMiddleware 는 각 View에서 인증을 위한 절차를 검사하는 middleware이..

    Django Channels - 채팅 기능 구현하기 - 1

    채팅 기록을 저장하는 부분에서 고민이 있었다. DB 에 insert 하기에는 RDB에 자꾸 hit 하면 성능 문제가 있을 거 같았다. 그래서 redis 에 저장하는 것으로 결정했다. 우선 채팅룸은 sender 의 id 와 receiver 의 id 로 만들었다. id 의 크기를 비교해서 id 가 작은 쪽으로 채팅방을 만들었다. 그리고 chat room 을 들어갔을 때 redis 에서 history 를 가져오도록 했다. redis 에서 채팅 기록을 저장할 때 json 형식으로 저장하는데 이를 파이썬 객체로 load 시켰다. 그리고 프론트에서 풀어서 보여주었다. 이제 고민은 읽은 사람 표시를 어떻게 보여주냐인데, 당장 떠오르는 건 실시간 채팅에서는 채팅방에 접속한 인원수를 빼면 될 거 같은데, 이전 기록에서는..

    Django Channels - Consumer 살펴보기

    채팅 기능을 구현하려고 찾아보다 Django channels 라는 라이브러리를 보았다. 구현도 tutorial을 보고 따라가면 무리없이 구현할 수 있을 정도로 잘 정리되어 있었다. 그래서 구현에 대한 글을 쓰기보단 consumer, routing 등을 자세하게 살펴보고자 한다. Django Channel Introduction Channels는 Django의 기본 비동기 뷰 지원을 래핑하여, HTTP뿐만 아니라 장기 실행 연결이 필요한 프로토콜 - WebSockets, MQTT, 챗봇, 아마추어 라디오 등을 처리할 수 있도록 합니다. 이를 위해 Django의 동기 및 사용하기 쉬운 특성을 유지하면서, 동기식 Django 뷰와 유사한 스타일로 동기식으로, 완전히 비동기식으로 또는 둘 다의 혼합 방식으로 코..

    WebSocket 살펴보기 - 2

    2023.05.05 - [Django] - WebSocket 살펴보기 어제 쓴 글에 이어 WebSocket 에 대해 좀 더 살펴보고자 한다. WebSockets 특징 서버와 브라우저 간 연결을 유지한 상태로 데이터를 교환할 수 있다. 이때 데이터는 패킷 형태로 전달되며, 전송은 커넥션 중단과 추가 HTTP 요청 없이 양방향으로 이뤄진다.(HTTP는 요청에 대한 응답이 오면 연결을 끊기 때문에 지속적인 연결을 할 수 없다.) 이런 특징 때문에 온라인 게임이나 주식 트레이딩 시스템같이 데이터 교환이 지속적으로 이뤄져야 하는 서비스에 아주 적합하다. 작동 원리 웹소켓은 TCP/IP 프로토콜 위에서 동작한다. 클라이언트가 서버에 웹소켓 연결 요청을 보낸다. 서버는 웹소켓 연결 요청을 받으면, 연결을 수립한다. ..

    DRF - Null인 경우 마지막에 배치하도록 하기

    drf에서 제공하는 Ordering Filter 기능을 커스텀했다. 공식 문서는 요기 문제 상황 ordering 을 하는 과정에서 null 값이 존재하는 경우 정렬 순서를 맨 끝으로 보내야 했다. 따라서 OrderingFilter 의 filter_queryset을 override 하기로 했다. param은 "-" 의 경우 내림 차순이므로 맨 앞글자를 검사해서 "-" 있을 경우 내림 차순 표현식으로 만들고 아닌 경우 오름차순으로 만들었다. 밑에는 해당 코드이다. class FooOrdering(OrderingFilter): @staticmethod def nullish_ordering(field: str) -> F: """ ordering 에서 오름차순 혹은 내림차순으로 변경하고 이때 null이 맨 마지막..

    django-import-export 비동기 활용하기

    django-import-export 를 활용해서 data 를 적재하고자 했다. 여기서 문제가 발생했는데 import 데이터가 5,000개를 넘어가니 꽤 오랜시간이 걸렸다. 약 8분 정도였다. 따라서 이 작업을 줄이고자 노력했다. use_bulk 나 batch_size, chunk_size 등 다양한 옵션을 활용했지만 도무지 시간이 줄어들지 않았다. 따라서 어떤 부분이 시간이 오래걸리나 살펴보다가 import_data 메소드에서 비동기를 활용해 데이터를 처리하면 어떨까? 라는 생각이 들어서 적용했다. 어느정도 성과가 있어서 비동기를 적용한 후에 3분 안팎으로 걸리게 수정했다. 사용한 비동기 함수는 2 가지다. aync iterator와 import_data 를 async 하게 바꿨다. 0. django-..

    E2E 테스트할 때 외부 API Mock으로 대체하기

    외부 API가 있는 view를 E2E 테스트를 하고 싶다. 하지만 테스트를 할 때마다 외부 API를 요청하는 건 자원 낭비다.(사실 다른 이유가 있을 순 있는데 내가 생각하기에는) 예를 들어 파일 업로드를 S3에 한다고 치자. 만약 테스트 할 때마다 S3에 업로드한다면 말이 되는가?(사실 내가 했다. 근데 뭔가 이상한 점을 눈치챘으니 봐주자) 이럴 때 Mock을 써보자! 테스트코드 예를 들어보자. 당신은 foo api를 테스트해보고 싶다. foo api는 외부 API를 요청받아 보여준다. 그런데 외부 API는 트래픽 제한이 있다. 100번의 트래픽 제한 중에 50번을 테스트한다고 치면 실제 서비스에서는 50번 밖에 사용자에게 못 보여준다. 어쩔 건가? 아무런 조치를 취하지 않은 API Test test...