선별 시스템 백엔드
전국 20곳 이상 온프레미스 AI 선별 시스템의 Django 중앙 백엔드
배경
기존 농산물 AI 자동 등급 분류 시스템은 PyQt 로컬 앱과 분산 스크립트로 운영되어 현장 설정 변경마다 출장이 필요했고, 원격 모니터링이 불가능했다. Flask Blueprint 기반 초기 백엔드는 팀 확장과 함께 역할 분리·관리 페이지 직접 개발·AI 모델 변경에 따른 스키마 마이그레이션 부담이 쌓였다. 초당 30건 이상의 선별 요청을 처리하면서 대시보드 성능과 캐시·실시간 통신을 같이 풀어야 했다.
시스템 구조
- 8 Django 앱: 인증, 관리자 설정, 대시보드, 모니터링, PLC 통신, 서버 코어, 선별 설정, 선별.
- Celery 5 큐 × 3 워커 풀: 큐는
default / io / maintenance / image_processing / plc_polling. 워커는 일반·I·O·PLC 전용 세 개로 나눠 프로토콜 충돌을 막는다. - 3단계 폴백 캐시: Worker-level → Redis → DB. 설정 조회는 DTO 기반 캐시 관리자가 워밍·무효화·스레드 안전 초기화를 맡는다.
- Docker Compose 7 서비스: PostgreSQL, Redis, Django, Celery 워커 3종(priority / general / plc), Celery Beat.
해결 과정
8 앱 Django 재구축. JWT 인증, RBAC 권한, 설정 프로파일(버전·Import/Export·Soft Delete)을 포함한 v3.5 릴리스까지 약 2개월에 걸쳐 도메인 앱을 나눴다. Django Admin 덕에 관리 페이지를 따로 만들지 않아도 됐고, DRF로 API 문서를 자동화했다.
초당 30건 이상 처리. 등급 연산·PLC 폴링·이미지 업로드가 API를 블로킹하지 않게 Celery 큐를 5개로 나누고, 워커 풀을 3개로 분리했다. PLC 폴링 큐는 전용 워커 한 곳(concurrency:1)에만 붙여 Modbus 프로토콜 충돌을 원천 차단한다. 기본 큐에 Lock-free Redis 분산 카운터를 붙이고, 50건 Batch Insert + 1초 Timeout으로 DB 트랜잭션 오버헤드를 줄였다.
파티셔닝으로 대시보드 속도 회복. 매일 수만 건씩 쌓이는 선별 데이터에 PostgreSQL RANGE 파티셔닝(psqlextra)을 도입했다. Celery Beat가 매일 00:05에 파티션을 롤링하고 30일 초과 데이터를 정리한다. pg_inherits로 파티션 관계를 조회하고, SAVEPOINT 기반 부분 롤백으로 개별 파티션 실패가 나머지에 영향을 주지 않게 했다. 핵심 7 모델에 복합 인덱스를 추가.
3단계 폴백 캐시. 매 선별 요청마다 DB에서 설정을 읽던 구조를 Worker-level(5초 TTL) → Redis → DB 3단으로 바꿨다. DTO 기반 캐시 관리자가 서버 시작 시 워밍하고, 설정이 바뀔 때는 무효화 이벤트를 Pub/Sub으로 전파한다.
실시간 통신 이중화. Django Channels + Redis Pub/Sub으로 장비 상태·온도·선별 데이터를 WebSocket 서버 푸시 방식으로 제공한다. 데스크톱 클라이언트는 Adaptive Polling과 WebSocket 채널을 함께 받아, 유휴 시간 네트워크 부하를 낮추면서 상태 변화는 즉시 반영한다.
성과
- 대시보드 로딩 시간 85% 단축, 그래프 API 응답 속도 90% 개선 (커밋
663e3a0기준). - Celery 5 큐 × 3 워커 풀로 초당 30건 이상의 선별 요청을 블로킹 없이 처리.
- 핵심 7 모델 복합 인덱스 + RANGE 파티셔닝 + 파티션 자동 롤링으로 장기 누적 데이터에도 쿼리 속도 유지.
- 4 도메인(Vision / Weight / Discharge / Farm) DTO 기반 캐싱 프레임워크로 설정 조회 DB 부하 감소.
- Docker Compose 7 서비스, 현장별 release 브랜치로 전국 20곳 이상 현장에 v3.5.2 납품.
- Django Channels + Redis Pub/Sub 이중 실시간 통신으로 장비 상태·온도·선별 데이터를 서버 푸시로 제공.