[Django] Unittest에서 SQL 로그를 보는 방법

Unittest에서 Debug 모드가 False로 오버라이딩 되는 이유

Debug 모드일 경우에는 별도로 동작하는 디버깅을 위한 로직, 캐싱 등을 넣을 수도 있고 이런 경우가 테스트에 미치는 영향을 막기 위해서 기본적으로 unittest 가 동작할 때는 Debug = False가 되도록 오버라이딩 한다고 한다. 아마 디버그 모드일때 기본 환경과 다르게 트릭을 주거나, 다른 행동을 하는 부분들이 정확한 테스트를 방해한다고 판단한게 아닐까 싶다.


Regardless of the value of the DEBUG setting in your configuration file, all Django tests run with DEBUG=False. This is to ensure that the observed output of your code matches what will be seen in a production setting


Unittest에서 SQL 로그를 보는 방법


1. override_settings 데코레이터 활용

테스트케이스에 아래 처럼 데코레이터 추가


from django.test import override_settings

@override_settings(DEBUG=True)


2. Test Runner Option 활용

또 다른 방법으로는 실행하는 테스트코드 실행 옵션에 --debug-sql 혹은 -d 옵션을 주어 실행하면 전체 테스트의 SQL를 볼 수 있다.



(test runner 옵션에 —debug-sql 을 준 화면)


물론 테스트 실행시 사용되는 설정 파일에 LOGGING 설정은 DB가 출력될 수 있도록 설정해두어야 한다.

LOGGING 설정 예시

"loggers": {"django.db.backends": {"handlers": ["console"], "level": "DEBUG"}},


[디버깅로그] Mac OS: pyenv 로 파이썬 낮은 버전 (3.5 or 3.6 등) 설치할때 error 발생 하는 경우 해결 개발 삽질이야기

<전제조건>
Xcode command-line tools 최신버전 설치 및 버전 선택
- 링크: https://www.lainyzine.com/ko/article/how-to-install-command-line-tools-on-macos/
- open Xcode > Preference > Locations > 올바른 command-line tools 버전 선택


<방법>
아래 명령어를 이용해보자.
버전 3.6.14 라고 되어있는 부분을 원하는 버전으로 변경하면 됨

CFLAGS="-I$(brew --prefix openssl)/include -I$(brew --prefix bzip2)/include -I$(brew --prefix readline)/include -I$(xcrun --show-sdk-path)/usr/include" LDFLAGS="-L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib" pyenv install --patch 3.6.14 < <(curl -sSL https://github.com/python/cpython/commit/8ea6353.patch\?full_index\=1)


<참고문서>
https://github.com/pyenv/pyenv/issues/1737#issuecomment-731672292


journalctl - linux systemd (systemctl, service) log 보는 법 개발 이것저것

이 글을 읽기 전에 Linux 의 sytstmed 에 대해 잘 모르시는 분은 여기 를 먼저 한번 보고 오시는걸 추천 드립니다.

sudo service MY_APP status

라는 명령어를 치면 기본적으로 데몬 정보와 아래쪽에 간략한 로그정보들이 뜬다

예를들어 sudo service gunicorn status 이라고 하면 아래처럼 뜬다.


자 위 같은경우 gunicorn 서비스에 대한 내용인데 아래쪽에 보이는 로그는 gunicorn에서 제공하는 error log 도 아니고  access log 도 아니다.
어디서 보여지는 로그일까? 

바로 gunicorn 을 데몬화 하여 실행해주는 systemd 프로세스에서 찍히는 로그이다.
그럼 이것은 어떻게 보아야 하나?

journalctl 이라는 linux 명령어가 있다.

man page 에서 보면 아래와 같이 기술하고 있다.

journalctl may be used to query the contents of the systemd(1)
journal as written by systemd-journald.service(8).

해석 해보면
= systemd-journald.service 에 의해 기록된 systemd journal 에 대한 컨텐츠를 query 할때 사용한다

즉, systemd 데몬의 동작로그를 볼 수 있다는 것이다.

옵션이 다양한데 (내 입장에서) 자주 사용되는 것은 주로 아래와 같다.

-u SERVICE_NAME : 특정 서비스의 저널만을 본다
-f : 출력되는 저널을 follow 한다 (App 에서 뿜어져 나오는 console log 를 볼 수 있음)

정리하자면,
내가 만일 gunicorn service 로그를 실시간(=follow)으로 보고싶다면 아래 명령어를 날릴 수 있다.

journalctl -u gunicorn -f



[운전 노하우] 차로 변경법

은근.. 차로 변경 무서워 하시는 분들이 많이 있다.
그래서 내 운전법을 바탕으로 가이드를 한번 적어보았다.

<차로변경 5 Steps>

1. 일단 변경하려는 방향으로 깜박이를 킨다

2. 옆차선을 살짝 바라봐서 나란히 주행중인 차가 없는지 확인한다. (백미러 사각지대이므로 육안으로 확인 필요)

3. 끼어들고자 하는 방향에 백미러를 바라본다

4. 백미러에 비치는 옆 차선 주행 차량이 짤려보이지 않고 차체 전체가 거울안에 다 들어오는지(=공간이 충분하다는 뜻) 확인한다

5. 핸들 방향을 틀고 약 3초 정도 (너무 오래걸려도 안됨) 안에 옆차선으로 완전히 이동한다



<+ 주의사항>

- 내가 변경하려는 차로의 맞은편에 있는 차도 차로변경을 하려고 하는것은 아닌지 확인
   * 예를들어, 내가 1 -> 2차로 변경 하려는데 3차로 주행 차량이 2차로로 들어오려고 시도중이거나 깜빡이를 넣지는 않았는지

- 핸들을 꺾기 직전에 사이드 미러 흘끗 한번 봐서 뒤에 오토바이 혹은 과속차량이 오지 않는지 확인
   * 이건 우회전, 좌회전 할때도 마찬가지 !!

- 변경할 차로의 전방 차량이 급브레이크를 밟을 수도 있으므로 현재 내 차로 + 변경할 차로의 전방을 수시로 주시하도록 하자
   * 도로 위에서는 누구나 언제든 브레이크를 밟을 수 있다. 
   * 차로 변경 시, 속도가 높으면 앞차가 급 브레이크를 밟았을 시 추돌사고를 낼 수도 있다.


<+ 각종 예외 상황>

일단 5스텝이라고 적어놓긴 했는데...
막상 상황에 따라 내 맘대로 안될때가 있다. 아래 경우들인데... 

각각의 경우 대처 방법을 적어보았다.

1. 변경하려는 차로에 계속 차가 있거나 공간이 충분히 나오지 않는경우 
   : 속도를 줄여서 옆차를 먼저 보내준 뒤, 그 뒤로 들어가자





[django] DRF Serializer 최적화 (=Best Practice) Python

Serializer 이해하기

  • model object ↔︎ data (dict) 변환을 위한 도구

  • 입력받는 데이터의 필드별 Validation + 가공 을 제공

  • 출력하는 데이터의 포맷과 형식을 커스터마이징 할 수 있음

  • ModelSerializer 의 경우 Model 과 직접적으로 연결하여 활용 가능

  • 1개의 요청을 처리하는데 일반적으로 약 12%의 처리시간을 소요함

ModelSerializer 가 느리다… 왜? 그럼 어떻게 해야?

  • 단순히 (un)serializing 만을 제공하는 함수를 만들어 사용하는것보다 약 370배 가까이 느림

  • 원인: 내부적으로 django.utils.functional 모듈이 validation 을 처리하는데 시간이 많이 소요되기때문

    • 해결책- 필드 validation 은 writable 일때만 적용되므로 조회만 필요한 필드들은 반드시 read-only 지정을 해줄것

  • 원인: ModelSerializer 가 각 필드값을 생성해내고 검증할때 수많은 metadata 를 사용하기때문

    • 해결책: “Regular(=일반)” Serializer 를 사용할 것

    • 일반 ModelSerializer를 사용하는것보다 약 1/6 배 빨라짐

  • 원인: DRF 의 field validation 에서 lazy 함수를 사용함

    • python functional 패키지의 lazy 함수는 proxy 를 통해 wrapped function 이 실제로 호출될때까지 함수를 evaluate 하지 않도록 만들어 놨는데 이게 캐싱이 되지 않기때문에 심각한 성능 저하를 만들게 된다

    • cached function(일반 함수) 이 lazy-wrapped function 보다 약 33배 빠름

    • DRF 에서 이에 대한 패치를 하여 ModelSerializer 의 속도 저하를 개선함

    • 해결책: Django + DRF 최신버전을 사용할 것 (릴리즈 안됨)

      1pip install git+https://github.com/encode/django-rest-framework2pip install git+https://github.com/django/django

 

동일 연산에 대한 Serializer 별 속도비교

ModelSerializer < ModelSerializer + ReadOnly < Serializer = Serializer + ReadOnly
< 직접만든 custom serializer

결론

  • read_only_fields 로 최대한 writable field 수를 줄여라

  • ModelSerializer 보다 일반 Serializer 를 사용하라

  • 반드시 써야하는게 아니면 굳이 Serializer 를 사용할 필요는 없다 (By. DRF 제작자)

  • DRF 의 ModelSerializer - field validation 에서 lazy 함수를 사용하는것에 대한 패치가 완료된 Django, DRF 최신버전을 사용하라

  • 2개 이상의 Model 이 섞인 Nested Serializer 일경우, queryset 에서 prefetch_related 또는 selected_related 함수를 사용하여 미리 join 된 데이터를 얻도록 처리한다 (안할경우 N+1 query problem 발생)

참고자료



1 2 3 4 5 6 7 8 9 10 다음


통계 위젯 (블랙)

1574
461
344785

GoogleAdsenseResponsive

Cluster map