캡처(/sequences/edit)에 실제 노출되는 항목 기준 — 요구사항 5개 중 일부만 반영됨.
| UI 항목 (현재) | 대응 기능 | 상태 |
|---|---|---|
| intent별 액션 6종(미팅/긍정/관심없음/부재중/질문/이의 → 완료·중단·일시정지) | 시퀀스 제어 | 있음 |
| 자동 재개 기간 7일 | OOO → 일시정지 후 N일 재개 | 있으나 "영업시간 재발송" 아님 |
| 담당자 자동 전달 + 전달 방식(검토 후/자동) | 기능: 담당자 전달 | 완전 개발 #8060 |
| — (없음) | 미응답 후속 "확인되셨을까요?" | UI 없음 |
| — (없음) | OOO 영업시간 재발송 | UI 없음 |
| — (없음) | 긍정/미팅 즉시 이메일 알림 | UI 없음 |
| — (없음) | 국가별 영업일 발송 | 별도 섹션 필요 |
SequenceForm(편집)에만 마운트 — 캠페인 상세화면에선 수정 불가. 생성 마법사(UnifiedCampaignPage)에도 없음(연결 안 된 CreateCampaignStep3 orphan).| 기능 | 보내는 메일 | 대상 | 콘텐츠 출처(기존 데이터) | AI | 언어 | 개발 |
|---|---|---|---|---|---|---|
| ① 미응답 후속 "확인되셨을까요?" |
원본 스레드에 이어지는 후속 reply | 바이어 | 해당 리드의 마지막 발송 step sequence_step_contents(AI본문) 재사용 |
✓ 1콜 원본 seed→짧은 리마인드 재생성 |
원본 언어 그대로 | 미개발 |
| ② OOO 영업시간 재발송 | 동일 원본 메일 그대로 재스케줄 | 바이어 | emails 원본(이미 발송분) |
불필요 | 원본 그대로 | 미개발(dead) |
| ③ 담당자 전달 | 원본 메일 그대로 전달 | referredEmail |
emails 원본 |
불필요 | 원본 그대로 | 완료 #8060 |
| ④ 긍정/미팅 즉시 알림 | 시스템 알림 메일(transactional) | 담당자 user.email |
알림 템플릿 + 답장 메타 | 불필요 | 유저 browser_language |
24h 지연만 |
| ⑤ 국가별 영업일 발송 | 시퀀스 step 메일(발송 시각만 제어) | 바이어 | sequence_step_contents |
불필요 | — | 부분(주말skip만) |
sequence_step_contents.source='ai'). 후속·재발송은 이걸 그대로/seed로 재사용 → 별도 데이터 불필요. 언어도 라틴 70% / 한국어 21% / 일본어 9%로 콘텐츠에 이미 반영돼 있어 원본 기반이면 언어 대응이 자동.질문: 7일 간격 8차 시퀀스의 경우, 후속을 마지막 step 이후에만 보내야 하나?
결론: 그렇다. "시퀀스 전체 소진(completed) + N일 무응답"일 때만 1회. 중간 step마다 후속을 끼우면 과발송.
| 근거 | 내용 |
|---|---|
| multi-step 자체가 이미 후속 | step2~8이 "확인되셨을까요" 역할. completed 전엔 시퀀스가 계속 닿고 있음 → 추가 후속 불필요·스팸 |
| 발생 빈도 (beta) | 8차 시퀀스 239개로 흔함(3차 446 다음). 간격은 5일 최다 / 7·10·14일도 존재 → completed 시점이 제각각이므로 enrollment 단위 판정이 정확 |
| 게이트 | status=completed ∧ repliedAt=null ∧ (now − completedAt ≥ coolDownDays) ∧ nudgeCount < maxNudges(=1) ∧ not bounced/unsubscribed |
| 1-step 시퀀스(402개)도 동일 | step1 발송→completed→무응답 시 동일 경로 |
shouldSendNudge()/scanForNudges()와 정확히 일치 — 단 ports(어댑터)가 미구현이라 dead. 어댑터만 배선하면 됨(신규 로직 불필요).| 지표 | 값 | 함의 |
|---|---|---|
| leads.country 채움 | 30% (70% 비어있음) | 국가 없으면 워크스페이스 기본 tz로 fallback 필요 |
| country 정규화 | 안 됨 "United States" 33,955 vs "미국" 10,050 혼재 | 발송 전 canonical 정규화 선행(현 NORMALIZERS는 4개국만) |
| leads.timezone 채움 | 13% (110,970 / 850,292) | country→tz 매핑 백필 필요 |
| 일 발송량 | 최대 4,693건/일 | SES 10초/건 → ≈13시간 > 영업시간(9h) → 사용자 우려 실증 |
calculateScheduledTime()(utils/timezone.ts) — buyer 모드(skipWeekends)에서 lead.timezone 기준 + 주말 건너뜀 + 시간 지나면 +1일 이미 동작.follow_up_settings.workingHoursStart/End(9–18) 정의돼 있으나 시퀀스 발송 경로에서 무시. 영업"시간" 가드 없음(영업"일"만).scheduled_at이 lead tz 기준 09–18·평일 밖이면 다음 영업일 09:00로 클램프(주말 skip 로직 재사용).lead.timezone → country→tz 매핑 → 워크스페이스 기본(Asia/Seoul).현재 섹션에 토글 3개 추가 + 부재중 옵션 1개 확장 + 상세화면에서도 수정 가능하게 마운트. 복잡도 최소.
| 추가 | 컨트롤 | 저장 위치(기존 재사용) |
|---|---|---|
| ★① 미응답 후속 | 토글 + coolDown 일수 | reply_automation_config.reEngageEnabled / coolDownDays |
| ★② OOO 영업시간 재발송 | 부재중 드롭다운에 항목 1개 | out_of_office: "resend_business_hours" |
| ★④ 긍정/미팅 즉시 알림 | 토글 | reply_automation_config.arrivalEmailEnabled |
| 상세화면 노출 | ReplyAutomationSettings를 상세 페이지에 마운트 + 인라인 저장 | 동일 컴포넌트 재사용(중복 0) |
reply_automation_config(jsonb) 필드 추가 + 같은 컴포넌트 1개를 편집/상세/생성에 공유. DB 마이그레이션 없음. 새 화면·새 테이블 없음.| 기능 | 핵심 부품 | 상태 |
|---|---|---|
| ③ 담당자 전달 | wrong_contact 분류·forward·토글 | 완전 개발 #8060 |
| ④ 긍정/미팅 알림 | 벨·Slack=즉시 / 이메일=reply-nudge-email | 이메일은 24h 지연만, 즉시 ✗ |
| ⑤ 영업일 발송 | 주말 skip+tz=있음 / 영업"시간"·국가정규화·tz백필=없음 | 부분 |
| ① 미응답 후속 | 게이트 도메인=있음(dead) / 어댑터·콘텐츠 재생성·UI=없음 | 미개발 |
| ② OOO 영업시간 재발송 | handleOOOReply=있음(dead) / 배선·UI=없음 | 미개발 |
| # | 작업 | 비용 |
|---|---|---|
| 1 | 캠페인 UI 통합 — 토글 3종 추가 + 상세화면 마운트(같은 컴포넌트 공유) + 즉시 알림 배선 동시 | S~M |
| 2 | ④ 긍정/미팅 즉시 이메일 알림 (SES, intent 게이트, ko fallback) | S |
| 3 | ② OOO 영업시간 재발송 — handleOOOReply 어댑터 배선 | M |
| 4 | ① 미응답 후속 — scanForNudges 어댑터 + 콘텐츠 재생성(원본 seed) | M |
| 5 | ⑤ 영업시간 가드 + country 정규화 + tz 백필 | M~L |
전부 DB 스키마 변경 없음(jsonb config + 기존 데이터 재사용). 각 항목 독립 PR + alpha squash 머지.
레거시 답습이 아니라 현행 베스트프랙티스 기준으로 각 기능을 설계.
| 영역 | 2026 최적 패턴 | 본 설계 적용 |
|---|---|---|
| 도달성 / 컴플라이언스 | Gmail·Yahoo 발신자 규정(SPF+DKIM+DMARC 정렬, RFC 8058 one-click List-Unsubscribe, 스팸율 <0.3%), 워밍업 ramp | 후속①·재발송②도 영업 메일과 동일 인증 도메인(mail.rinda.ai)·List-Unsubscribe 헤더 사용. 워밍업 ramp는 운영 중 → 후속도 일 한도 내 |
| 타임존 / 발송시각 | IANA tz + DST 자동(luxon/Temporal), country 추정 대신 수신자 tz 우선, Send-Time Optimization(과거 오픈시각 기반) | ⑤ tz 우선순위 lead.timezone→매핑→ws기본. 영업시간 가드는 luxon tz 계산(현 calculateScheduledTime 확장). STO는 후속 고도화로 |
| AI 사용 (deterministic-first) | 가능한 곳은 결정적 로직, LLM은 분류·생성에만. 빠른 모델 + structured output + confidence 게이트 + HITL | ②OOO·③전달은 AI 0(원본 그대로). ①후속만 LLM 1콜(원본 seed → 짧은 리마인드, hallucination 최소). 분류는 flash-lite + 임계값 |
| 이벤트 / 큐 (멱등) | webhook → 큐 → at-least-once + idempotency key dedup, fire-and-forget | 이미 BullMQ + followup_emails unique·스레드당 1회 게이트로 중복 차단. 후속도 nudgeCount 멱등 |
| 클린 아키텍처 | 포트&어댑터로 도메인·인프라 분리, fake port 단위 테스트(인프라 0) | 도메인(shouldSendNudge·nextBusinessSlot·handleOOOReply)는 이미 작성·테스트됨 → 어댑터만 배선(신규 로직 최소) |
| 프라이버시 | opt-out 존중(CAN-SPAM/GDPR/PECR), 거주국 불명 시 트래킹 보수적 OFF | ④알림 replyNudgeEmailOptOut·admin 게이트. 후속/알림 트래킹은 lead 거주국 불명 시 OFF(현 reply-nudge 정책 계승) |
| 프론트 / 설정 | SSOT 단일 컴포넌트 재사용, jsonb 점진 확장(무중단·무마이그레이션), TanStack Query optimistic | ⑥ ReplyAutomationSettings 1개를 편집·상세·생성 공유. reply_automation_config jsonb 필드 추가만 → DDL 0 |