글로벌 린다세일즈 — AI 캠페인 6/2 + 글로벌 식품 브랜드사
19개 발신 계정 라운드 로빈 분산 + 발송 stuck 완전 해소
한 줄 요약
두 캠페인 모두 정상 발송 중. AI 캠페인 6/2 는 분당 30~45 건 (19계정 동시 발송), 글로벌 식품 브랜드사는 step1 발송 4,647건 완료 후 step2 대기. 이제부터 캠페인을 일시정지 → 재활성화하면 등록된 발신 메일에 자동 라운드 로빈 분산됩니다.
📊 현재 상태 — KPI
분당 발송 peak45
활성 발신 계정19
24h 발송 (두 캠페인)8,091
분배 균등성 (max/min)2.5
1. AI 캠페인 6/2 — 19계정 라운드 로빈 분배 (최근 10분)
19개 계정 모두 동시 발송 중 (8~20 범위). max/min 2.5, CV ~30%. chat 보존분도 다른 18계정과 균등 (15건). 라운드 로빈 완전 정상.
2. 분당 발송 추세 (AI 캠페인 6/2)
| 분 | 발송 | 비고 |
|---|---|---|
| 07:46 | 22 | |
| 07:47 | 45 | peak |
| 07:48 | 32 | |
| 07:49 | 39 | |
| 07:50 | 28 |
평균 ~33/분 · peak 45/분 · 이론치 142/분 의 32% 활용
3. 글로벌 식품 브랜드사 — step1 완료, step2 대기
| 지표 | 값 |
|---|---|
| 24h 누적 발송 | 4,647건 |
| 최근 10분 발송 | 0 (step1 완료) |
| 다음 step 발송 | 3~7일 후 (sequence step interval) |
| 분배 상태 (이전 측정) | 18계정 균등 (1,265~1,424/계정, CV 3%) |
정상 상태. step1 발송 모두 완료 후 step2 까지 sequence step interval 대기 중. 자동으로 다음 step 시각 도래 시 재발송.
🎯 운영 가이드 — 일시정지 → 재활성화 자동 분산
오늘 머지된 코드 (PR #8182·#8187) 덕분에 캠페인을 일시정지 후 재활성화하면 등록된 발신 메일에 자동 라운드 로빈 분산됩니다.
1
발신 메일 풀 추가 — admin UI 캠페인 상세에서 발신자 풀 다중 선택 (예: 19개 SES 계정)
2
일시정지 클릭 — 기존 BullMQ delayed 잡 자동 정리 (
cancelSequenceJobs)3
재활성화 클릭 — 자동으로
reallocateSenderPool 호출:
- 🟢 미발송 enrollment → SHA256 sticky 해시로 새 풀에 균등 재분배
- 🔴 이미 step1 발송된 enrollment → 기존 sender 그대로 (Gmail/Outlook thread 일관성 보호)
- ⚪ 종료 상태 (stopped/bounced/unsubscribed) → 변경 없음
4
BullMQ 자동 재enqueue — sequence-email-loader 30초 tick 으로 DB 기준 새 emailAccountId 박힌 잡 재투입
5
발송 시작 — 약 1-2분 안에 모든 계정 동시 발송 가속 (분당 ~30 + peak 45)
⚠️ 풀에 1개만 등록된 캠페인은 분산 효과 없음. 발신자 풀에 다중 등록한 후 재활성화해야 자동 분산 동작.
📦 오늘 적용한 코드 수정 (5개 PR)
| # | 영역 | 변경 | 효과 |
|---|---|---|---|
| #8170/8172 | 답장 매칭 | RFC 5322 정규화 + References Tier 2 fallback (헥사고날 reply-matching 모듈) | 답장 매칭률 27.3% → 95%+ 회복. 989건 백필 완료. |
| #8175/8176 | Redis 인프라 | maxmemory 4G → 8G + 컨테이너 한도 10G + swap=0 (mem_swappiness:0, memswap_limit==mem_limit) | Redis OOM 해소, 배포 healthcheck 정상화. |
| #8182/8184 | 발신 계정 분산 | paused → active 재활성화 시 sender pool selective 재할당. 이미 sent step1 enrollment 는 보존, 미발송만 SHA256 해시로 새 풀에 재분배. | 40,799 enrollment 18계정 균등 재분배 완료 (이전 99.8% 단일 집중 해소). |
| #8187/8189 | UNNEST drizzle fix | PG array literal direct param + 5000 chunk — drizzle 의 array spread 회피 (이전 PR 의 runtime error fix). | 재할당 SQL 실행 안정성 확보. |
| #8198/8200 | 429 무한 retry 차단 | 5-Layer Defense (헥사고날): ProviderQuotaExhaustedError + adapter throw + usecase catch + worker UnrecoverableError + status='unreachable' | Hunter/Findymail 429 폭주 → sequence-email event loop 점유 해소. 발송 분당 1-3 → 30-45 (10~15배 가속). |
🔧 운영 액션 — Before / After
| 지표 | Before (오늘 아침) | After (현재) |
|---|---|---|
| Redis maxmemory | 4 GB (100% full, OOM) | 8 GB (50% 사용) |
| 답장 매핑률 | 27.3% | 95%+ |
| AI 캠페인 6/2 발신 분배 | chat 99.8% 단일 집중 | 19계정 균등 (CV 30%) |
| 발송 stuck (BullMQ wait) | 86,187 잡 적체 | 0 (drain 완료) |
| 분당 발송 (글로벌 린다세일즈) | 1~3건 (stuck) | 30~45건 |
| Hunter 429 무한 retry | 폭주 | UnrecoverableError 차단 |
🚀 다음 권장 액션 (다른 캠페인)
현재 글로벌 린다세일즈의 다른 active 캠페인 6개도 같은 fix 적용 가능 (모두 pool=1 단일 발신):
| 캠페인 | 현재 enrollment | 분배 가능 시 |
|---|---|---|
| 글로벌 브랜드사 (6.1) -6 영업 | 29,925 | throughput 19배 |
| 글로벌 제조사 AI 솔루션 제안 | 29,879 | throughput 19배 |
| 글로벌 뷰티 브랜드 AI 솔루션 제안 | 29,851 | throughput 19배 |
| 글로벌 브랜드사 (6.1) -13 영업 | 19,905 | throughput 19배 |
| 글로벌 뷰티 브랜드 AI 솔루션 제안 #2 | 19,904 | throughput 19배 |
각 캠페인에 admin UI 에서 발신자 풀 19개 추가 → 일시정지 → 재활성화 클릭하면 자동 분산.