한눈에 (TL;DR)
P0
3개 즉시 조치
- pino logger crash — 3,295건 동일 에러로 step 실패 (전체 실패의 2.7%)
- OOO auto-resume 미구현 — pause 후 무한 정지
- reply automation 0.23% 채택 — 1,288 / 1,291 시퀀스가 기능 미사용
P1
운영 안정성 회귀
- pending 적체 348K — 7일 초과 169K, 1~7일 120K
- Step 4 abandoned 152,989 (sent 33,331의 4.6배)
- stuck processing 자동 복구 job 부재
- timezone 변경 시 pending execution 재계산 누락
P2
UX·관찰성
- step별 답장률 자동 모니터링·alert 없음
- A/B winner 자동 선정 미구현 (assignedVariant 만 존재)
- sequence archive·version history 없음
- admin failed jobs 상세 표시 미흡
Beta DB 운영 스냅샷 2026-05-28
시스템 규모
| 지표 | 값 | 비고 |
|---|---|---|
| 총 시퀀스 | 1,291 | active 50 (3.9%) — 활성률 매우 낮음 |
| 총 enrollment | 605,258 | active 260,663 (43.1%) |
| 총 step execution | 1,658,845 | sent + delivered 672,663 (40.5%) |
| pending execution | 599,858 | 그 중 1일+ 적체 348,753 (58.1%) |
| processing execution | 0 | stuck processing 현재는 없음 (좋음) |
| failed execution | 121,034 | 전체 7.3% — 누적 실패율 임계 초과 |
실패 원인 TOP 5 sequence_step_executions.error_message GROUP BY
| # | error_message | 건수 | 해석 · 영향 |
|---|---|---|---|
| 1 | undefined is not an object (evaluating 'this[msgPrefixSym]') | 3,295 | JS 런타임 에러 — pino logger child 호출 시 msgPrefixSym undefined. 코드 버그 — 즉시 수정 가능 |
| 2 | No valid email found after verification | 2,871 | verification 실패 → 발송 직전 차단. lead 단계 검증 강화 또는 enrollment 시점에 미리 검증 |
| 3 | Unsubscribed Address | 1,501 | 수신거부 도메인이 enrollment 단계에서 안 걸러짐 — pre-flight check 추가 필요 |
| 4 | Bounced Address | 1,113 | 이전 반송 이력 lead 가 재발송됨 — bounce list 자동 회피 미동작 |
| 5 | Provider rate limit (cannot accept any more requests) | 618 | throttle 도달 후 재시도 없이 fail — backoff retry 추가 필요 |
Pending 적체 분포 scheduled_at 기준
| 구간 | 건수 | 비중 | 의미 |
|---|---|---|---|
| 7일 초과 | 169,058 | 28.2% | 사실상 abandoned — 회수 또는 정리 정책 필요 |
| 1~7일 | 119,687 | 20.0% | 워커 처리량 부족 또는 stuck |
| 24시간 내 overdue | 61,008 | 10.2% | 일시 backlog |
| 미래 예약 | 250,108 | 41.7% | 정상 |
단계별 처리 품질 step_order GROUP BY status
| Step | sent / delivered | failed | skipped | abandoned (1d+ pending) | 관찰 |
|---|---|---|---|---|---|
| 1 | 327,180 | 54,564 | 155,164 | 1,919 | 발송 1차 — 표준 분포 |
| 2 | 168,274 | 35,772 | 17,564 | 15,402 | 적체 시작 |
| 3 | 138,307 | 28,037 | 19,598 | 44,180 | 답장률 0.14% 구간 진입 |
| 4 | 33,331 | 657 | 22,095 | 152,989 | abandoned 가 sent 의 4.6배 — Step 4 부터 파이프라인 실질 붕괴 |
| 5 | 2,986 | 347 | 20,741 | 68,859 | 거의 처리 안 됨 |
| 6 | 1,431 | 1,503 | 5,993 | 1,963 | 실패율 51% — 극소수 처리 |
| 7 | 769 | 33 | 5,577 | 1,689 | — |
| 8 | 386 | 121 | 5,512 | 1,744 | — |
Enrollment 상태 + Drift
| 상태 | 건수 | % |
|---|---|---|
| active | 260,663 | 43.07% |
| completed | 173,812 | 28.72% |
| stopped | 157,393 | 26.00% |
| bounced | 9,028 | 1.49% |
| paused | 3,127 | 0.52% |
| unsubscribed | 1,235 | 0.20% |
current_step_order ↔ 실제 마지막 sent step 일치 여부 (active enrollment)
- in_sync 258,363 (99.12%)
- drift_behind 2,288 (0.88%)
- drift_ahead 12
drift_behind 2,288건 — currentStepOrder 가 실제보다 뒤처짐. 다음 step 발송이 중복 발생할 위험. sync repair job 필요.
핵심 기능 채택률
| 기능 | 시퀀스 채택 | % | 해석 |
|---|---|---|---|
| reply_automation_config 설정 | 3 / 1,291 | 0.23% | 기능이 사실상 사용되지 않음. UI 진입성 또는 default 설정 부재가 원인일 가능성 |
A. 아키텍처
| 경로 · 라인 | 이슈 | 제안 | P |
|---|---|---|---|
lib/queue/sequence-email-scheduler.ts:38-40 | producer-side scheduling feature flag 전환 중. worker reserveSendThrottle 잔존 — double throttle 위험 | 3단계 전환 (on → drain → cleanup) + admin-sequence-health 시각화 | P1 |
workers/bullmq/sequence-lifecycle.worker.ts:53-61 | defaultJobOptions 상속만 — retry 정책 미명시. 4KB truncation 시 원본 스택 손실 | attempts: 1 명시 (lifecycle 멱등). logger.error 에 full message 유지 | P1 |
lib/queue/sequence-email-scheduler.ts:91-106 | 10min maxFuture 하드코딩 — Lua script 와 BullMQ delayed queue 관계 주석만 | THROTTLE_SLOT_CAP_MS config 상수 추출 + 경계 테스트 | P2 |
services/sequence-execution.service.ts:149+ | processing 클레임 후 worker crash 시 영구 stuck — recover job 부재 | recoverStuckProcessingExecutions cron 5분 주기. timeout = cluster 배포×2 | P1 |
(워커 미확인) sequence-activation.worker.ts | 대량 enrollment 일괄 enqueue 시 메모리·Redis burst | chunk 5,000 + backoff 2→4→8s. 진행 상태 Redis publish → SSE | P1 |
routes/sequences.routes.ts:76-95 | cursor 디코드 실패 silent fallback to offset — 클라이언트가 깨진 cursor 반복 | HTTP 400 명시 반환 + decode failure metric | P2 |
B. 데이터 모델
| 경로 · 라인 | 이슈 | 제안 | P |
|---|---|---|---|
db/schema/sequences.ts:166 | step_order gap 가능 ([1,2,4]) — DB 제약 없음 | step 추가·삭제 시 항상 0..N-1 재인덱싱. 야간 integrity check | P2 |
db/schema/sequences.ts:53-60 | enrollment status 전환 그래프 미문서화 — completed→active 가능한지 불명 | enrollment_status.md 상태 다이어그램 + transition validation | P2 |
db/schema/sequences.ts:207 | currentStepOrder ↔ sequence_step_executions sync drift — 실측 2,288건 drift_behind | step 완료 hook 보강. 야간 sync job 으로 inconsistent 행 자동 복구 | P1 |
db/schema/sequences.ts:127 | replyAutomationConfig jsonb null-safety 없음 | DEFAULT_REPLY_AUTOMATION_CONFIG 상수 + DB NOT NULL DEFAULT '{}' | P2 |
db/schema/sequences.ts:113 | timezone mode 변경 시 pending step 의 timezone 미갱신 | updateSequence 에서 pending/processing batch update + audit | P1 |
db/schema/sequences.ts:217,229 | uniqueSequenceLead 동시 enroll race — CONFLICT 핸들링 미흡 | bulkEnroll CONFLICT 시 skip + 응답에 "N중 K개 기존등록" 카운터 | P1 |
C. 관찰성
| 경로 · 라인 | 이슈 | 제안 | P |
|---|---|---|---|
services/admin-sequence-health.service.ts:127-140 | BullMQ failed zset 의 error message 미읽음 — 무엇이 왜 실패했는지 admin UI 불가 | top 5 failed jobs + failedReason 노출. admin dashboard 타일 | P1 |
services/sequence-metrics.service.ts:31-100 | 재시도 발송 메일 중복 카운팅 가능 — provider deliveredAt null 대응 동적 계산 | emails.messageId 또는 dedupeKey group by | P2 |
services/sequence-notification.service.ts | failed enrollment wave 알림 없음 | 5분간 failed 10건 누적 시 Slack #admin-alerts | P2 |
admin/lib/api/hooks/sequences.ts:83-86 | category count staleTime 15s — 매 15초 refetch | 로컬 optimistic update + 1분 정확값 refetch | P3 |
services/sequence-execution.service.ts:82-143 | scheduler sleep 깬 후 backlog 누적 감지 어려움 — 실측 pending 599K 중 348K overdue | last-processed cursor Redis. 월간 audit report | P1 |
D. 사용자 행동 분기
| 경로 · 라인 | 이슈 | 제안 | P |
|---|---|---|---|
db/schema/sequences.ts:28-40 | OOO pause 후 auto-resume 메커니즘 없음 — 수동 재개만 가능 | oooDetectedAt + 휴가 종료일 cron resume + admin 필터 | P0 |
services/reply-sequence-context.service.ts:42-100 | orphan reply (sequence 삭제) fallback 없음 — LLM null context 답변 시도 | fallback 템플릿 발송 + enrollment stop + admin 알림 | P2 |
| (intent detection path 미확인) | auto_reply / meeting_request / positive_interest 감지 경로 불명 — NLP 제공자, fallback, accuracy 메트릭 없음 | (1) 현재 path 다큐먼트 (2) fallback 명시 (3) intent별 정확도 메트릭 | P0 |
db/schema/sequences.ts:35 | question intent 정의 모호 (고객 질문 vs 자동응답기 질문 vs 의문문) | intent taxonomy 문서. admin 에서 intent별 샘플·정확도 표시 | P2 |
| (전체) | reply_automation_config 채택 0.23% (3/1,291) — 기능이 사실상 미사용 | (1) 기본값 자동 활성화 (2) UI 진입성 진단 (3) 시퀀스 생성 마법사에서 권장 | P0 |
E. 성능
| 경로 · 라인 | 이슈 | 제안 | P |
|---|---|---|---|
services/sequence-enrollment.service.ts:88-136 | email filter 시 leadIds IN 절 비대 — 쿼리 플랜 degradation | TEMP TABLE join 또는 denormalized last_opened_at·clicked_at | P2 |
lib/queue/sequence-email-scheduler.ts:48-66 | provider cache FIFO eviction — hot provider 제거 위험 | LRU 구현 또는 Redis 이동 | P3 |
services/sequence-pagination.ts | OFFSET 5000 cap + truncated flag — cursor 마이그레이션 미완료 | 2주 warn → 400 강제. migration guide | P2 |
services/sequence-execution.service.ts:95-143 | limit 큰 경우 memory load 적재 — stream 미사용 | bulk worker limit=500 고정 + 동시 worker 수로 throughput 제어 | P3 |
admin/lib/api/hooks/sequences.ts:79-130 | workspace 전환 시 keepPreviousData 가 stale 유지 시간 늘림 | workspaceId 를 query key 에 포함하여 자동 분리 | P2 |
F. 프론트엔드
| 경로 · 라인 | 이슈 | 제안 | P |
|---|---|---|---|
pages/sequences/CampaignStatusTabs.tsx:41-42 | activation 90초 timeout 후 UI 동작 불명 | 명시적 에러 상태 + retry. admin health 로 last-known progress 조회 | P2 |
admin/lib/api/hooks/sequences.ts:24-73 | queryKey 조합 복잡 — invalidation prefix match 누락 위험 | invalidateSequenceCaches 통합 + 빌드타임 체크 | P3 |
| (ActivationProgressBanner) | SSE 끊김 시 last progress 가 fresh 인지 stale 인지 불명 | 재연결 시 즉시 GET /activation-progress sync + isStale 플래그 | P2 |
admin/lib/api/types/sequence.ts | jsonb 필드 TypeScript interface 불명확 | personalizationConfig·replyAutomationConfig zod schema + type guard | P1 |
pages/sequences/CampaignStatusTabs.tsx:44-63 | CampaignReadiness · ActivationFailure 타입 분산 | lib/api/types/sequence.ts 로 통합 | P2 |
G. 누락 기능 & UX 개선
| 영역 | 현황 | 제안 | P |
|---|---|---|---|
| A/B 자동 winner 선정 | assignedVariant 필드만 존재. 자동 선정 로직 없음 | variant별 메트릭 + significance test (95%) → admin 제안 → accept 시 신규 enrollment 자동 적용 | P2 |
| 단계별 답장률 자동 모니터링 | 전체 시퀀스 답장률만. step별 부재 | getSequenceMetrics 확장. step별 막대 + 평균 이하 경고 배지 | P2 |
| OOO 자동 재개 | pause 후 무한 정지 — 결국 수동 재개만 가능 | OOO 메일에서 "돌아올 날짜" 파싱 + cron resume + 지연 이유 필터 | P1 |
| 시퀀스 archive · version history | delete 만 있음. version diff 없음 | status='archived' 전환 + sequence_version_history 테이블 + diff UI | P2 |
| 대량 enrollment 예상 완료 시간 | 활성화 시 ETA 없음 | lead count × avg step interval + throttle buffer → "약 35일 소요" | P3 |
| step별 latency · percentile | 전체 aggregation 만 | BullMQ enqueue→claimed→completed 추적. p50/p95/p99. SLA alert | P2 |
권고 액션 플랜
P0 · 이번 주
운영 회복
- pino logger crash 수정 —
msgPrefixSym에러 3,295건. logger child 호출 path 수정. 즉시 사후 검증으로 실패율 −2.7%p 기대 - OOO auto-resume —
oooDetectedAt+ 휴가 종료 파싱 cron resume - reply automation 기본 활성화 — 신규 시퀀스 생성 시 default config 주입. 기존 1,288개에 마이그레이션 (opt-out 가능)
P1 · 2주 내
적체 해소 + Self-healing
- pending 169K (7일+) 회수 전략 — 3가지 옵션 비교:
(a) 자동 stop + 관리자 알림
(b) scheduled_at 재계산 후 재시도
(c) enrollment 단위 archive - Step 4 abandoned 152K 원인 조사 — throttle? worker? enrollment 만료?
- stuck processing recovery cron — 5분 주기
- currentStepOrder drift 2,288건 sync job
- uniqueSequenceLead CONFLICT graceful skip
- BullMQ failed jobs admin 노출 — top 5 + failedReason
- backlog cursor 추적 — last-processed Redis
- timezone 변경 시 pending batch update
- sequence types 통합 (jsonb zod)
P2 · 1개월
UX · 관찰성
- step별 메트릭 + 경고 배지 + p50/p95/p99
- A/B winner 자동 선정 (significance test)
- sequence archive + version history
- OFFSET → cursor 완전 전환 (2주 warn → 400)
- email filter 시 TEMP TABLE 또는 denorm
- SSE 재연결 sync + isStale
- intent taxonomy 문서 + 정확도 메트릭
- orphan reply fallback
- step_order gap 방지 reindex
- enrollment status transition validation
P3 · 분기
최적화
- provider cache LRU 또는 Redis
- bulk processing stream
- workspace queryKey 분리
- activation ETA 표시
- category count optimistic update
결론
시퀀스 시스템은 기본 구조(scheduler, BullMQ, schema)는 견고하나, 운영 현장은 3가지 침묵 실패에 노출되어 있습니다.
- 침묵 적체 — 7일+ overdue pending 169K. 사용자는 모르게 진행이 멈춤
- 침묵 버그 — 동일 JS 에러 3,295건 + reply automation 0.23% 채택. 기능이 작동 안 하는데 alert 없음
- 침묵 자동화 — OOO pause 후 영구 정지, A/B winner 수동, intent path 불명. "자동"이 라벨일 뿐 실질 없음
가장 빠른 회복은 P0 3개 (pino 수정 · OOO resume · reply automation 기본화) 이며, 이 셋이 안정화되면 P1 적체 해소로 이동을 권합니다.