이메일 템플릿 — 최적 적용방법 설계

knowledge-base?tab=email-templates 템플릿을 실제 시퀀스 발송에 적용하는 최적 아키텍처

결정: Copy-on-apply SSOT 재사용 · 스키마 추가 0 설계 수렴 완료 (R3)
TL;DR — 유저가 knowledge-base에서 공들여 만든 4/6/8-스텝 템플릿은 실제 시퀀스에 "적용"되지 않는다. AI 프롬프트에 top-5·240자 스니펫으로만 약하게 반영될 뿐이다. 최적 적용법은 copy-on-apply(인스턴스화) — 템플릿 그룹을 sequence_step_contents(발송 SSOT)로 복사해 시퀀스를 시드하고, emailTemplateId는 provenance로만 유지한다. live-reference는 진행 중 캠페인 안정성을 깨므로 기각.

1현재 상태 (코드 실측 검증)

항목상태근거
sequenceSteps.emailTemplateId FK스텁sequences.ts:173 // add relation later
발송 워커가 email_templates read✕ 없음workers/ grep 0건
발송 콘텐츠 SSOTsequence_step_contentsemail-content-resolver.service.ts:174 (stepId+leadId)
템플릿 실제 용도AI 참고만campaign-email-streaming:776, sequence-proposal/…query.ts:30

→ 템플릿 저장소와 발송 파이프라인이 기능적으로 단절. emailTemplateId는 dangling 스텁.

2핵심 결정: Copy-on-apply vs Live-reference

기준A. Copy-on-applyB. Live-reference
진행 중 캠페인 안정성 템플릿 수정이 발송 중 코호트에 영향 없음 수정 시 in-flight 변조
SSOT 기존 sequence_step_contents 재사용 콘텐츠 모델 2개 → drift
개인화 모델 (leadId NULL/UUID) 그대로 동작 충돌
발송 hot-path 비용 추가 read 없음 템플릿 join 추가
템플릿 개선 전파 자동 안 됨 (→ 명시적 re-sync 보완) 자동
A 채택. 콜드메일은 enroll 후 불변이어야 하고, 새 SSOT를 만들지 않는다.

3적용 2-모드 (기존 약한 링크 흡수)

M1 · 직접 적용

verbatim 복사

템플릿 스텝을 그대로 복사 → sequence_step_contents(leadId=NULL). 정성 작성한 source=manual 템플릿 대상. 결정적·빠름.

M2 · AI-보조 적용

톤/스타일 참고 재생성

템플릿을 참고로 AI가 리드별 재생성 (이미 부분 존재). source=ai_generated·개인화 강조 대상.

4구현 계획

L0(병렬)           L1                       L2
┌──────────────┐  ┌─────────────────────┐  ┌──────────────┐
│N0.1* S       │═▶│N1.1* M apply API    │═▶│N2.1* M 빌더  │
│apply preview │  │POST /sequences/     │  │"템플릿에서   │
│+ 변수커버리지 │  │  from-template (tx) │  │ 시작" picker │
└──────────────┘  └─────────────────────┘  └──────────────┘
┌──────────────┐  ┌─────────────────────┐
│N0.2 S 도달율 │─▶│N1.2 S provenance    │
│HTML→text 적용│  │emailTemplateId 기록  │
└──────────────┘  └─────────────────────┘
노드내용verify
N0.1* [S]apply-preview: 템플릿 그룹→시퀀스 스텝 매핑 + 변수 커버리지(리드 스키마의 {{var}}) + country/lang 일치 리포트미해결 변수 0건이면 green
N0.2 [S]도달율 정규화: 적용 시 HTML-only→text/plain 자동생성(커밋 73397ca1b) 재사용text 대체본 존재
N1.1* [M]apply API: POST /api/v1/sequences/from-template { templateIds[] }, 단일 tx로 N스텝+contents 시드, workspaceAuth+assertWorkspaceMatch부분실패 시 전체 rollback
N1.2 [S]provenance: sequenceSteps.emailTemplateId 채움(감사용, 발송엔 미사용)FK 채워짐
N2.1* [M]빌더 UX: "템플릿에서 시작" → useWorkspaceEmailTemplatesGrouped 재사용 picker + PresetPreviewDrawer 패턴 미리보기 → Apply 후 편집 가능적용 후 스텝 편집 정상
추가 안전장치: 템플릿 개선 전파는 명시적 "변경분 가져오기" diff 액션으로만(자동 금지), 미발송 스텝에만 적용.

5평가 루프 (수렴)

라운드발견 갭반영
R1변수 미스매치 / country 불일치 / 자동전파 위험preview에 변수커버리지·언어경고 추가, 전파는 명시적 opt-in
R2부분실패 원자성apply 단일 tx (createSequenceStep 기존 tx 활용)
R3잔여 트레이드오프(자동전파 없음)의도된 설계 — 콜드메일 안정성 우선, 기각

→ R3에서 신규 갭 0건. 설계 수렴 완료.

Verdict — 설계 완료

최적 적용법 = copy-on-apply 인스턴스화 + 2-모드(직접/AI-보조) + preview 변수검증 + tx 원자성 + 명시적 re-sync. 신규 SSOT·스키마 추가 없이 기존 sequence_step_contents·emailTemplateId 재사용으로 dangling 스텁을 실제 적용 경로로 승격.