서론
Django 4.1 버전을 사용하다 5로 업그레이드 하며 조사했던 내용.
Django 업그레이드는 왜 해야 할까?
- 보안 패치
- 버그 패치
- 신기능 추가
- 라이브러리들의 예전 버전 지원 종료
- Python 버전 업데이트
마이너 버전만 해도 가끔 쫄릴때가 있는데 메이저 버전이야 더 그렇다. Django 는 무겁다는 얘기를 하는데 그런 면이 없잖아 있다. 그럼에도 불구하고 ORM 의 편의성이 압도적이고, 웹서버에 필요한 많은 것이 내장되어 있기 때문일 것이다. 그렇기에 보안, 버그 패치 때문에라도 업데이트는 꾸준히 따라가는게 좋다. 개인적으로는 4.1 버전에서 5로 업데이트 하고 싶었던 이유가 GenericPrefetch 5.0에서 도입된걸 알게 된 후였다. 후에 코딩으로 해결하긴 했지만… 현재 버전은 5.2까지 나왔기 때문에 가는 길이 험난했다.
업그레이드 전략
- 먼저 커버리지가 높은 테스트 코드가 작성되어 있어야 한다. 만약 DRF 도 사용 중이라면 API 에 대해서도 테스트 코드가 작성되어 있는 것이 좋겠다. 테스트 코드가 없거나 커버리지가 충분하지 않다면 테스트 코드부터 보강해야 한다.
- 업그레이드 가이드를 정독 한다.
- 목표로 하는 버전으로 requirements.txt 등을 변경해서 django 를 업그레이드 한다. 그런후 django-upgrade 를 실행해본다. 마이너 버전 1단계씩 확인해가며 반복적으로 업그레이드 단계를 진행하는 것을 추천한다.
- Release Note 를 정독 한다. 특히 Backwards incompatible changes 항목은 매우 조심해야 한다. 4.2에서 save() 메소드가 변경되었는데 파급 효과에 대해 크게 생각하지 않았다가 꽤 삽질했던 기억이 생생하다. 귀찮겠지만 Backwards incompatible changes 항목을 전수조사 해야한다. django-upgrade 모듈은 많은 부분을 변경 해 주긴하는데 모든 변경 사항을 업데이트 해주거나 경고해주지 않으므로 꼭 전수조사가 필요하다.
- DB 와 연결 및 호환성 문제가 발생하는지 확인한다.
4.2 버전의 save() 메소드 변경점
QuerySet.update_or_create가 save() 메소드를 호출한다. 따라서 4.1->4.2에서 breaking change 가 발생할 수 있다.
소스 코드를 비교해보자.
1 | obj, created = self.select_for_update().get_or_create(defaults, **kwargs) |
생성 했을 때 까지는 공통코드가 유지된다. 그러면 업데이트 시 달라진다는 얘기. 그리고 save를 오버라이드하고 update_fields 를 save 안에서 수정하거나 하면 영향을 받을 수 있으니 post_save 시그널을 사용하거나 save 오버라이드 한게 있으면 테스트 케이스를 만들어서 정상 동작하는지 확인해야 합니다.
1 | obj.save(using=self.db) |
테스트 및 배포 전략
- QA 와 잘 협의해본다.
- 다수의 서버를 사용한다면 canary 배포를 활용한다.
- 테스트 용 환경을 하나 만들고, 입력된 모든 리퀘스트를 테스트 서버에 그대로 보내는 방법도 고려해 볼 수 있다.
그 외
- 4.1 에서 업그레이드 할 때는 save 변경점에 대해 주의해야 한다. post_save 시그널이 있는지도 확인 필요하다. 우리팀은 update_fields 는 보통 list 를 사용했는데, django 코드에서는 set 을 사용해서 update_fields 는 set 을 파라미터로 사용 하는 것을 추천한다.