Velog-Dashboard v2의 데이터, 스크래핑, 백오피스용 레포지토리입니다.
- Python 3.13.0+
- Poetry 1.8.4+
pyenv와poetry가 설치되었다고 가정하고 진행합니다.poetry대신venv로 대체해서 사용가능합니다. (requirements.txt활용)- 참고로
poetry기반으로poetry export -f requirements.txt --without-hashes -o requirements.txt통해 배포 require를 만들어야 합니다.
# 프로젝트 Clone 및 이동
git clone https://github.com/Check-Data-Out/velog-dashboard-v2-back-office.git
cd velog-dashboard-v2-back-office
# 전역적으로 3.13 python version 이 아니라면
pyenv local 3.13
# 가상환경 생성 및 패키지 설치
poetry shell
poetry install.env.sample # 템플릿 (git 추적)
.env # 로컬용 (git 무시)
.env.prod # 프로덕션용 (git 무시)
환경 변수에서 직접 설정할 필요 없음. 진입점에서 자동 설정됨:
| 진입점 | Settings Module | 용도 |
|---|---|---|
manage.py |
local |
로컬 개발 (runserver) |
wsgi.py (gunicorn) |
prod |
프로덕션 웹 서버 |
docker-compose.yaml |
consumer |
Consumer 프로세스 |
# 1. 템플릿 복사
cp .env.sample .env
# 2. notion을 참조하여 실제 값 입력
# ⚠️ .env 파일이 없거나 SECRET_KEY가 없으면 실행 불가1. docker docs를 참고하여 Docker, Docker Compose 설치
# 로컬: db + consumer 모두 실행 (override.yml 자동 로드)
docker compose up -d- DB 세팅 이후, 실행 전 꼭
superuser을 만들어야 admin 진입 가능
docker를 띄우고python manage.py migrate실행, 아래와 같은 화면
Operations to perform:
Apply all migrations: admin, auth, contenttypes, posts, sessions, users
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
... # 생략python manage.py createsuperuser실행 해서 따라가거나, 아래 명령어 복붙으로 실행
DJANGO_SUPERUSER_USERNAME=admin \
DJANGO_SUPERUSER_EMAIL=admin@example.com \
DJANGO_SUPERUSER_PASSWORD=admin \
python manage.py createsuperuser --noinputSuperuser created successfully.결과를 만나면 성공- 그리고 아래 순서 F/U
poetry run pytest -v # 또는 pytest -v
# 또는 아주 상세 디버깅을 위해
poetry run pytest -v --full-trace --showlocals --tb=long --capture=no # 또는 pytest 이후부터 쭉conftest.py파일은pytest을 위한 자동fixture세팅 파일임coverage는 아래와 같이 사용함
poetry run coverage run -m pytest
poetry run coverage report -m
poetry run coverage html# Formatting
poetry run ruff format
# Linting
poetry run ruff check --fix- need to be done
poetry config
poetry show pre-commit # check the result
poetry run pre-commit install # the result will be >> pre-commit installed at .git/hooks/pre-commit
# pre-commit testing
poetry run pre-commit run --all-files백오피스 큐 운영 기능 가이드 — stats refresh 큐 모니터링, DLQ 관리, 컨슈머 헬스체크, 요청 추적, 배치 알림.
| URL | 용도 |
|---|---|
/admin/queue/dashboard/ |
3개 큐(pending/processing/failed) 크기 대시보드 |
/admin/queue/failed/ |
DLQ 조회 및 retry / purge |
/admin/ops_tracking/statsrefreshrequest/ |
stats refresh 요청 추적 (누가·언제·성공/실패) |
/admin/posts/post/?stats_status=missing |
오늘 통계 누락 포스트 필터 |
- Consumer 컨테이너 내부
http://127.0.0.1:8081/healthz(기본 포트, envCONSUMER_HEALTHZ_PORT) - 응답:
{"status": "ok|stale", "redis": bool, "heartbeat_age_sec": float, ...} - Docker HEALTHCHECK 로 자동 체크되며,
interval=30s / timeout=5s / retries=3 / start-period=20s - 단일 consumer 인스턴스 전제 (Reclaimer daemon thread 가 포함). 다중 인스턴스 확장 시 분산 락 도입 필요.
| 변수 | 기본값 | 설명 |
|---|---|---|
REDIS_HOST/PORT/PASSWORD/DB |
localhost/6379 | Redis 연결 |
REDIS_MAX_FAILED_QUEUE_SIZE |
10000 | DLQ 최대 크기 |
RECLAIM_VISIBILITY_TIMEOUT_SEC |
600 | processing 메시지 stuck 판정 임계 |
RECLAIM_INTERVAL_SEC |
60 | Reclaimer 루프 주기 |
RECLAIM_MAX_RECLAIMS |
3 | reclaim 초과 시 DLQ |
CONSUMER_MAX_CONSECUTIVE_ERRORS |
30 | 하드 종료 임계 (tenacity 재연결 포함) |
CONSUMER_HEALTHZ_PORT |
8081 | /healthz 포트 (내부 bind) |
CONSUMER_HEALTHZ_STALE_THRESHOLD_SEC |
60 | idle false-stale 방지 |
SLACK_OPS_WEBHOOK |
(미설정) | 운영 알림 웹훅 — 미설정 시 no-op |
MISSING_POSTS_THRESHOLD |
100 | 배치 완료 후 누락 임계 (초과 시 Slack) |
- Consumer crash 시 processing 큐에 잔존한 메시지는 재기동 직후 cold-start reclaim 에서 pending 으로 자동 복원됨.
reclaimedCount > RECLAIM_MAX_RECLAIMS는 poison pill 로 간주하여 DLQ 로 이동.- DLQ 수동 retry 는
/admin/queue/failed/에서 버튼 클릭.
외부 producer(velog-dashboard 웹) 가 보낸 메시지는 필요한 신규 필드(requestId, enqueuedAt, reclaimedCount, requestedBy, processingStartedAt) 가 누락되어 있어도 consumer 의 ensure_envelope 가 자동 보강한다. 외부 변경 불필요.
PostDailyStatistics 의 6개월 이전 데이터를 TimescaleDB drop_chunks + ORM 폴백으로 강제 폐기. 매일 KST 04:00 cron 자동 실행 (.github/workflows/run-daily-stats-cleanup.yaml). 초기 1회는 누적 데이터로 오래 걸리나 이후는 1일치만 정리되어 빠름.
운영 DB 는 Supabase 기반 PostgreSQL 15 + TimescaleDB extension. Session Mode (포트 5432) 또는 Direct Connection 사용 필수 — Transaction Mode(6543)에서는 SET LOCAL / transaction.atomic 이 보장되지 않는다. 운영 DB role 은 run-daily-aggre-set*.yaml 의 POSTGRES_USER 와 동일 (이미 매일 stats INSERT/UPDATE 권한 보유 → drop_chunks 도 동일 권한).
# 로컬 dry-run
poetry run python manage.py cleanup_old_stats --dry-run
# 운영 수동 실행 (workflow_dispatch)
gh workflow run "Daily Stats Cleanup" -f retention_months=6 -f dry_run=true# Local 환경
python manage.py runserver
# Prod 환경으로 실행, 이 경우 `.env.prod` 필수
python manage.py runserver --settings=backoffice.settings.prod
# 이후 localhost:8000로 접속
# admin / admin 으로 로그인통계 새로고침 요청을 Redis 큐에서 받아 처리하는 Consumer 프로세스입니다. 상세 사용법은 노션 링크를 참조 해주세요. (멤버 전용)
mac/windows에서 빌드 시 이미지 크기가 커지므로 linux/amd64 플랫폼으로 직접 빌드 권장:
docker buildx build \
--platform linux/amd64 \
-f Dockerfile.consumer \
-t stats-refresh-consumer:latest \
--load \
.# override.yml 자동 로드 → db + consumer 모두 실행
docker compose up -d
# 로그 확인
docker compose logs -f stats-refresh-consumer# override.yml 무시 → consumer만 실행, env_file: .env.prod
docker compose -f docker-compose.yaml -f docker-compose.prod.yaml up -d
# 로그 확인
docker compose -f docker-compose.yaml -f docker-compose.prod.yaml logs -f stats-refresh-consumer메인 큐
vd2:queue:stats-refresh: 새로고침 요청 대기열
처리 큐
vd2:queue:stats-refresh:processing: 처리 중인 작업 추적vd2:queue:stats-refresh:failed: 실패한 작업 재처리용
메시지 포맷
{
"userId": 123,
"requestedAt": "2025-12-12T10:30:00Z",
"retryCount": 0
}