Django 2.1이 지난주에 릴리즈됐다. 제목처럼 async view 기대하고 있었는데 결론부터 쓰면 2.1에 async는 아직 안 들어왔다. 2.1은 admin/permission 쪽 다듬기 위주. 관련해서 장기 그림과 당장 어떻게 버틸지 메모.
2.1 실제 변경점
- Model view permission. 기존엔 add/change/delete 3종이었는데 view가 추가되어 총 4종. 관리자 화면에서 "보긴 되는데 수정은 불가" 권한이 드디어 1급 시민으로. ContentType 마이그레이션이 돌면서 기존 perm codename이
view_modelname으로 자동 추가 - PostgreSQL distinct on field.
qs.order_by("a").distinct("a")같은 필드 단위 DISTINCT ON이 ORM 선언으로 가능. Postgres 전용이라 MySQL엔 해당 없음 - ContentType natural key 캐시. 중복 쿼리 잘라냄. 자잘한 개선
- Python 3.5 드롭. 3.6 이상이 최소 요구. 2.1은 3.7도 공식 지원. 3.7의 dataclass가 이제 Django 쪽 서비스 레이어에서 안전하게 쓸 수 있다
- QuerySet.iterator()의 chunk_size 파라미터 추가. 대용량 배치 처리 시 명시적으로 청크 크기 조정 가능
2.1 업그레이드 자체는 작업량 적음. pip install -U django==2.1 하고 makemigrations 돌려서 view perm 추가 마이그 수락하는 정도. admin 커스터마이즈한 곳에서 has_view_permission 오버라이드 필요한 경우가 있을 수 있으니 점검.
async는 어디까지 왔나
DEP 0009(Django Enhancement Proposal) 로드맵에 비동기 지원이 올라가 있다. 단계별로 가는 게 맞는 그림이고, ORM 마지막. 순서는 대략:
- ASGI 표준과 핸들러 레이어 정의
- Middleware async 호환 계층
- View가 async def 수용
- ORM async 메서드(aget, acreate...)
- 기타 부대 기능(cache, email, templates 일부)
1~2단계가 Django 3.0 타겟. 3.0 GA가 2019년 말 예정이고, view async는 3.1~3.2 사이, ORM async는 더 뒤가 될 공산이 크다. 커뮤니티 메일링 리스트에서 Andrew Godwin이 Channels 경험을 기반으로 직접 끌고 가는 중이라 방향은 명확.
왜 어려운가
Django ORM이 지연 평가 + 동기 쿼리 전제로 설계되어 있어서 async 전환이 단순히 async/await을 더하는 문제가 아니다. QuerySet은 이터레이션 시점에 쿼리를 날리는데, sync 이터레이터와 async 이터레이터의 인터페이스가 다르다. 기존 API를 깨지 않으면서 async for obj in qs를 지원하려면 별도 메서드(.aiter()) 추가가 필요. 커넥션도 psycopg2가 동기라 asyncpg나 aiopg로 가야 하는데 기존 DB feature 매트릭스 유지가 만만치 않다.
그 사이 어떻게 버틸까
우리 서비스에서 async가 아쉬운 엔드포인트는 대개 "외부 API 호출이 많고, 응답 시간의 대부분이 I/O 대기"인 애들. 실시간 스펠체크 프록시, 외부 검색 어그리게이션, 푸시 알림 fanout 같은 것. 지금 당장의 해법 세 가지 정도 쓰고 있음.
- aiohttp 별도 서비스로 분리. 비동기 I/O 헤비한 엔드포인트만 aiohttp 앱으로 빼고, 같은 도메인의 경로 하나를 nginx에서 upstream 분기. 인증은 JWT(앱 서비스에서 발급 + Redis 세션 공유)로 Django 세션과 호환. 신규 기능 중 I/O 집중 부분이 이렇게 3개 쪼개져 있음
- Channels로 WebSocket 쪽만. HTTP 쪽은 Django 그대로, WS 쪽은 Channels 2.x(ASGI). Redis backing
- Celery + 동기 view. view에서 긴 작업 직접 하지 않고 태스크로 던지고 202 Accepted. 이게 정석 중 정석. 이미 적용되어 있는 부분이 많음
1번이 제일 실용적인데 운영 부담이 올라간다는 단점. 두 개 프레임워크의 배포/로깅/메트릭 파이프라인이 나란히 간다. Django에 async가 붙으면 이 중 상당 부분을 회수할 수 있어서 기다려진다.
짧은 결론
2.1은 패치 레벨 업그레이드 + view perm 정리 정도의 체감. async 열광은 3.x 본격 도입 시점까지 참는 게 맞겠다. 2.1 자체는 production 올리는 데 큰 장애물 없음.
댓글 없음:
댓글 쓰기