feat: EDM 이메일 HTML 구현을 위한 스킬 및 자산 파일 추가

This commit is contained in:
hyeonggil
2026-04-11 21:14:48 +09:00
parent d3f7b86f1b
commit 5f1b0e9130
5 changed files with 714 additions and 0 deletions

View File

@@ -0,0 +1,310 @@
---
name: edm-email-html
description: |
EDM(이메일 다이렉트 마케팅) HTML을 구현하는 전체 워크플로우 스킬.
Figma 디자인 → HTML table 마크업 → 아웃룩 호환 → 검수까지 단계별 가이드를 제공합니다.
다음 상황에서 반드시 사용하세요:
- "EDM 만들어줘", "이메일 템플릿 구현", "뉴스레터 HTML"
- "아웃룩에서 깨지는 이메일 수정", "이메일 HTML 마크업"
- Figma 디자인을 받고 이메일 HTML로 변환할 때
- "메일 발송용 HTML", "eDM 퍼블리싱", "HTML 이메일"
- 이메일 클라이언트 호환성 문제가 있을 때
---
# EDM HTML 구현 가이드
이메일 HTML은 일반 웹과 다른 세계입니다. 2000년대 테이블 코딩이 아직도 정답이며, Flexbox와 Grid는 쓸 수 없습니다. 이 스킬은 Figma 디자인에서 시작해 모든 이메일 클라이언트에서 깨지지 않는 HTML을 만드는 과정을 안내합니다.
## 워크플로우
```
1. Figma 디자인 파악 → 2. HTML 마크업 → 3. 아웃룩 호환 → 4. 검수
```
---
## Phase 1: Figma 디자인 파악
### Figma MCP 사용 가능 시
Claude Code에 Figma MCP가 설정되어 있다면 Figma URL로 직접 디자인 데이터를 읽을 수 있습니다. MCP가 연결되어 있는지 먼저 확인하고, 가능하다면 자동 추출을 시도하세요.
추출 가능한 속성:
- 컬러 HEX값 (RGBA → HEX 자동 변환)
- 폰트 패밀리, 사이즈(px), 굵기, 줄간격
- 레이아웃 치수: 너비, 높이, padding, 섹션 간격
- 이미지 에셋 URL (CDN 업로드 필요)
- CTA 링크 (레이어 설명 필드에서 추출)
### Figma MCP 없이 진행 시
사용자에게 다음 정보를 요청하거나 스크린샷으로 파악하세요.
**필수 확인 항목:**
- 전체 이메일 너비 (권장: **600px**)
- 각 섹션 배경색, 텍스트 색상 (HEX)
- 폰트: 패밀리, 사이즈(px), 굵기, 줄간격
- 이미지: 가로×세로(px)
- 여백: 섹션 간 간격, 좌우 패딩
- CTA 버튼: 크기, 색상, 텍스트, 링크 URL
- 푸터: 회사 정보, 수신거부 링크
---
## Phase 2: HTML table 마크업
### 절대 원칙
이메일 HTML에서 반드시 지켜야 하는 규칙들입니다. 이 규칙을 어기면 특정 클라이언트에서 레이아웃이 무너집니다:
| 규칙 | 이유 |
|------|------|
| `table`, `tr`, `td`만 레이아웃에 사용 | div는 Outlook 등에서 무시됨 |
| inline CSS 우선 | Gmail이 `<head>` style 태그를 제거함 |
| `width`/`height` 속성 필수 | CSS만으론 Outlook이 무시함 |
| `margin` 사용 금지 | 빈 `<tr>`행이나 `padding`으로 대체 |
| `padding` 개별 속성 사용 | 단축 속성(`padding: 10px 20px`)은 일부 클라이언트 미지원 |
| 모든 `<table>``cellpadding="0" cellspacing="0" border="0"` | 브라우저 기본 스타일 초기화 |
### 기본 템플릿
```html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="format-detection" content="telephone=no, date=no, address=no">
<title>이메일 제목</title>
<style type="text/css">
body { margin: 0; padding: 0; width: 100%; background-color: #f5f5f5; }
table { border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
img { display: block; border: 0; outline: none; text-decoration: none; }
/* 미디어쿼리는 여기서만 (Outlook은 무시하지만 Gmail/Apple Mail에서 적용) */
@media only screen and (max-width: 600px) {
.mobile-full { width: 100% !important; display: block !important; }
.mobile-padding { padding-left: 16px !important; padding-right: 16px !important; }
.mobile-center { text-align: center !important; }
}
</style>
</head>
<body style="margin: 0; padding: 0; background-color: #f5f5f5;">
<!-- 외부 래퍼: 배경색과 수평 중앙 정렬 -->
<table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#f5f5f5">
<tr>
<td align="center" style="padding-top: 20px; padding-bottom: 20px;">
<!-- 600px 컨테이너 -->
<table width="600" cellpadding="0" cellspacing="0" border="0"
style="width: 600px; max-width: 100%; background-color: #ffffff;">
<!-- 헤더 -->
<tr>
<td style="padding-top: 0;">
<!-- 로고 이미지 등 -->
</td>
</tr>
<!-- 본문 -->
<tr>
<td style="padding-top: 30px; padding-bottom: 30px;
padding-left: 30px; padding-right: 30px;">
<!-- 메인 콘텐츠 -->
</td>
</tr>
<!-- 푸터 -->
<tr>
<td bgcolor="#f5f5f5"
style="background-color: #f5f5f5;
padding-top: 20px; padding-bottom: 20px;
padding-left: 20px; padding-right: 20px;
text-align: center;">
<!-- 회사 정보 + 수신거부 링크 (필수) -->
<p style="font-family: Arial, sans-serif; font-size: 12px;
color: #999999; margin: 0; line-height: 1.5;">
회사명 | 주소<br>
<a href="[수신거부URL]"
style="color: #999999; text-decoration: underline;">
수신거부
</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
```
### 안전한 폰트
웹폰트(`@font-face`, Google Fonts)는 대부분의 이메일 클라이언트에서 지원하지 않습니다. Pretendard, Noto Sans KR 같은 폰트를 Figma에서 사용했어도 이메일에서는 안전 폰트로 대체해야 합니다.
```css
/* 권장 스택 (한국어 이메일) */
font-family: -apple-system, Arial, 'Helvetica Neue', Helvetica, sans-serif;
/* Outlook 전용 (MSO 조건부 주석 내) */
font-family: Arial, sans-serif;
```
---
## Phase 3: 아웃룩 호환성
아웃룩 2007~2019는 Word 엔진으로 이메일을 렌더링해서 현대 CSS를 거의 무시합니다. MSO 조건부 주석으로 아웃룩과 그 외 클라이언트를 분리해서 처리하세요.
### MSO 조건부 주석
```html
<!--[if mso]>
<!-- 아웃룩에서만 렌더링 -->
<![endif]-->
<!--[if !mso]><!-->
<!-- 아웃룩 제외 클라이언트에서 렌더링 -->
<!--<![endif]-->
```
### 아웃룩이 무시하는 주요 속성
| CSS 속성 | 아웃룩 동작 | 대체 방법 |
|----------|-----------|---------|
| `background-image` | 미지원 | `<img>` 태그 직접 사용 |
| `border-radius` | 무시 | VML 사용 또는 이미지 버튼 |
| `margin` | 무시 | `padding` 또는 빈 `<tr>` 행 |
| `box-shadow` | 무시 | 포기 또는 이미지로 대체 |
| `@media query` | 2007/2010 미지원 | 테이블 고정폭으로 데스크톱 설계 |
### VML 버튼 (반드시 사용)
아웃룩에서 CSS 버튼은 배경색 없는 텍스트 링크로 표시됩니다. CTA 버튼은 항상 VML을 포함하세요:
```html
<div style="text-align: center;
padding-top: 20px; padding-bottom: 20px;">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w="urn:schemas-microsoft-com:office:word"
href="https://example.com"
style="height: 44px; v-text-anchor: middle; width: 200px;"
arcsize="5%"
stroke="f"
fillcolor="#FF6B6B">
<w:anchorlock/>
<center style="color: #ffffff; font-family: Arial, sans-serif;
font-size: 16px; font-weight: bold;">
지금 확인하기
</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<a href="https://example.com"
style="background-color: #FF6B6B;
color: #ffffff;
display: inline-block;
padding-top: 12px; padding-bottom: 12px;
padding-left: 30px; padding-right: 30px;
text-decoration: none;
border-radius: 5px;
font-family: Arial, sans-serif;
font-size: 16px;
font-weight: bold;">
지금 확인하기
</a>
<!--<![endif]-->
</div>
```
### 이미지 처리
이미지 차단 시에도 레이아웃이 깨지지 않도록 `alt` 텍스트와 배경색을 함께 지정하세요:
```html
<td bgcolor="#FF6B6B" style="background-color: #FF6B6B;">
<img src="https://cdn.example.com/banner.jpg"
alt="7월 여름 세일 최대 50% 할인"
width="600"
height="300"
style="display: block; width: 100%; max-width: 600px;
height: auto; border: 0;">
</td>
```
이미지는 반드시 `https://` CDN 절대 경로를 사용하세요. 로컬 경로나 상대 경로는 이메일에서 작동하지 않습니다.
---
## Phase 4: 검수 체크리스트
### 코드 구조 (필수)
- [ ] 모든 `<table>``cellpadding="0" cellspacing="0" border="0"`
- [ ] 모든 `<img>``width`, `height`, `alt` 속성
- [ ] `margin` 미사용 (padding 또는 빈 `<tr>` 행으로 대체)
- [ ] `padding` 단축 속성 제거 (개별 속성 사용)
- [ ] CTA 버튼에 VML 코드 포함
- [ ] 이미지 `src`가 HTTPS 절대 URL
### 콘텐츠 (필수)
- [ ] 푸터에 수신거부 링크 포함
- [ ] 모든 링크 href 유효성 확인
- [ ] 이미지 alt 텍스트 의미있게 작성 (장식용이면 `alt=""`)
### Figma 디자인 대비 검수
- [ ] 전체 너비 600px
- [ ] 색상 HEX값 일치
- [ ] 폰트 사이즈, 굵기 일치
- [ ] 버튼 크기, 색상 일치
- [ ] 섹션 간 여백 일치
### 테스트 도구
| 도구 | 용도 | 비용 |
|------|------|------|
| [Litmus](https://www.litmus.com) | 100+ 클라이언트 렌더링 미리보기 | 유료 |
| [Email on Acid](https://www.emailonacid.com) | 크로스 클라이언트 + 접근성 감사 | 유료 |
| [Mailtrap](https://mailtrap.io) | 개발 환경 샌드박스, 스팸 점수 | 무료 플랜 |
| [SpamTest.io](https://spamtest.io/) | 스팸 점수, SPF/DKIM/DMARC 확인 | 무료 |
**최소 테스트 클라이언트:** Gmail 웹, Outlook (Windows), Apple Mail, 모바일 Gmail
---
## 2컬럼 레이아웃 예시
```html
<!-- 데스크톱: 2열 | 모바일: 스택 -->
<table width="600" cellpadding="0" cellspacing="0" border="0"
style="width: 600px;">
<tr>
<td width="280" valign="top"
style="width: 280px; padding-right: 20px;"
class="mobile-full">
<!-- 왼쪽 -->
</td>
<td width="280" valign="top"
style="width: 280px; padding-left: 20px;"
class="mobile-full">
<!-- 오른쪽 -->
</td>
</tr>
</table>
```
---
## 참고 자료
상세 내용은 references 폴더를 참조하세요:
- `references/html-patterns.md` — 헤더/푸터/버튼/이미지 완성 코드 패턴
- `references/verification-checklist.md` — 전체 검수 체크리스트 (시각적/기능/스팸)

View File

@@ -0,0 +1,24 @@
# Example Asset File
This placeholder represents where asset files would be stored.
Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed.
Asset files are NOT intended to be loaded into context, but rather used within
the output Claude produces.
Example asset files from other skills:
- Brand guidelines: logo.png, slides_template.pptx
- Frontend builder: hello-world/ directory with HTML/React boilerplate
- Typography: custom-font.ttf, font-family.woff2
- Data: sample_data.csv, test_dataset.json
## Common Asset Types
- Templates: .pptx, .docx, boilerplate directories
- Images: .png, .jpg, .svg, .gif
- Fonts: .ttf, .otf, .woff, .woff2
- Boilerplate code: Project directories, starter files
- Icons: .ico, .svg
- Data files: .csv, .json, .xml, .yaml
Note: This is a text placeholder. Actual assets can be any file type.

View File

@@ -0,0 +1,34 @@
# Reference Documentation for Edm Email Html
This is a placeholder for detailed reference documentation.
Replace with actual reference content or delete if not needed.
Example real reference docs from other skills:
- product-management/references/communication.md - Comprehensive guide for status updates
- product-management/references/context_building.md - Deep-dive on gathering context
- bigquery/references/ - API references and query examples
## When Reference Docs Are Useful
Reference docs are ideal for:
- Comprehensive API documentation
- Detailed workflow guides
- Complex multi-step processes
- Information too lengthy for main SKILL.md
- Content that's only needed for specific use cases
## Structure Suggestions
### API Reference Example
- Overview
- Authentication
- Endpoints with examples
- Error codes
- Rate limits
### Workflow Guide Example
- Prerequisites
- Step-by-step instructions
- Common patterns
- Troubleshooting
- Best practices

View File

@@ -0,0 +1,327 @@
# EDM HTML 코드 패턴 모음
---
## 1컬럼 레이아웃 (전체 템플릿)
```html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="format-detection" content="telephone=no, date=no, address=no">
<title>이메일 제목</title>
<!--[if mso]>
<style type="text/css">
body, table, td, p, a { font-family: Arial, sans-serif !important; }
</style>
<![endif]-->
<style type="text/css">
body { margin: 0; padding: 0; width: 100%; background-color: #f5f5f5; }
table { border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
img { display: block; border: 0; outline: none; text-decoration: none; }
a { color: inherit; }
@media only screen and (max-width: 600px) {
.container { width: 100% !important; }
.mobile-full { width: 100% !important; display: block !important; }
.mobile-padding { padding-left: 16px !important; padding-right: 16px !important; }
.mobile-center { text-align: center !important; }
.mobile-img { width: 100% !important; height: auto !important; }
}
</style>
</head>
<body style="margin: 0; padding: 0; background-color: #f5f5f5;">
<table width="100%" cellpadding="0" cellspacing="0" border="0" bgcolor="#f5f5f5">
<tr>
<td align="center" style="padding-top: 20px; padding-bottom: 20px;">
<table width="600" cellpadding="0" cellspacing="0" border="0"
class="container"
style="width: 600px; max-width: 100%; background-color: #ffffff;">
<!-- 헤더 -->
<tr>
<td align="center"
style="padding-top: 24px; padding-bottom: 24px;
padding-left: 30px; padding-right: 30px;
border-bottom: 1px solid #e5e7eb;">
<img src="https://cdn.example.com/logo.png"
alt="회사 로고" width="120" height="40"
style="display: block; border: 0;">
</td>
</tr>
<!-- 히어로 이미지 -->
<tr>
<td style="padding: 0; line-height: 0;">
<img src="https://cdn.example.com/hero.jpg"
alt="이벤트 배너"
width="600" height="280"
class="mobile-img"
style="display: block; width: 100%; max-width: 600px;
height: auto; border: 0;">
</td>
</tr>
<!-- 본문 -->
<tr>
<td style="padding-top: 32px; padding-bottom: 32px;
padding-left: 32px; padding-right: 32px;"
class="mobile-padding">
<h1 style="font-family: Arial, sans-serif;
font-size: 24px; font-weight: bold;
color: #111827; line-height: 1.3;
margin: 0 0 16px 0;">
이메일 제목이 여기 들어갑니다
</h1>
<p style="font-family: Arial, sans-serif;
font-size: 15px; color: #374151;
line-height: 1.7;
margin: 0 0 24px 0;">
본문 내용이 여기 들어갑니다. 가독성을 위해 line-height를
1.5 이상으로 설정하는 것이 좋습니다.
</p>
<!-- CTA 버튼 -->
<div style="text-align: center;">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w="urn:schemas-microsoft-com:office:word"
href="https://example.com"
style="height: 48px; v-text-anchor: middle; width: 200px;"
arcsize="8%" stroke="f" fillcolor="#1a56db">
<w:anchorlock/>
<center style="color: #ffffff; font-family: Arial, sans-serif;
font-size: 16px; font-weight: bold;">
자세히 보기
</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<a href="https://example.com"
style="background-color: #1a56db; color: #ffffff;
display: inline-block;
padding-top: 14px; padding-bottom: 14px;
padding-left: 32px; padding-right: 32px;
text-decoration: none; border-radius: 6px;
font-family: Arial, sans-serif;
font-size: 16px; font-weight: bold;">
자세히 보기
</a>
<!--<![endif]-->
</div>
</td>
</tr>
<!-- 푸터 -->
<tr>
<td bgcolor="#f9fafb"
style="background-color: #f9fafb;
border-top: 1px solid #e5e7eb;
padding-top: 24px; padding-bottom: 24px;
padding-left: 32px; padding-right: 32px;
text-align: center;">
<p style="font-family: Arial, sans-serif; font-size: 12px;
color: #9ca3af; line-height: 1.6; margin: 0 0 8px 0;">
<strong>회사명</strong> | 서울시 강남구 테헤란로 123
</p>
<p style="font-family: Arial, sans-serif; font-size: 12px;
color: #9ca3af; line-height: 1.6; margin: 0;">
<a href="https://example.com/unsubscribe"
style="color: #9ca3af; text-decoration: underline;">
수신거부
</a>
&nbsp;|&nbsp;
<a href="https://example.com/privacy"
style="color: #9ca3af; text-decoration: underline;">
개인정보처리방침
</a>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
```
---
## 2컬럼 이미지 + 텍스트
```html
<table width="600" cellpadding="0" cellspacing="0" border="0"
style="width: 600px;">
<tr>
<!-- 이미지 열 (40%) -->
<td width="220" valign="top"
style="width: 220px; padding-right: 0;"
class="mobile-full">
<img src="https://cdn.example.com/product.jpg"
alt="상품명" width="220" height="220"
class="mobile-img"
style="display: block; width: 100%; height: auto; border: 0;">
</td>
<!-- 간격 -->
<td width="20" style="width: 20px; min-width: 20px;">&nbsp;</td>
<!-- 텍스트 열 (60%) -->
<td width="360" valign="top"
style="width: 360px; padding-top: 8px;"
class="mobile-full mobile-padding">
<h2 style="font-family: Arial, sans-serif;
font-size: 18px; font-weight: bold;
color: #111827; margin: 0 0 8px 0;
line-height: 1.3;">
상품명
</h2>
<p style="font-family: Arial, sans-serif; font-size: 14px;
color: #6b7280; line-height: 1.6;
margin: 0 0 16px 0;">
상품 설명이 들어갑니다. 간결하게 핵심만 작성하세요.
</p>
<p style="font-family: Arial, sans-serif; font-size: 20px;
font-weight: bold; color: #ef4444;
margin: 0 0 16px 0;">
₩29,900
</p>
<a href="https://example.com/product"
style="background-color: #111827; color: #ffffff;
display: inline-block;
padding-top: 10px; padding-bottom: 10px;
padding-left: 20px; padding-right: 20px;
text-decoration: none; border-radius: 4px;
font-family: Arial, sans-serif;
font-size: 13px; font-weight: bold;">
구매하기
</a>
</td>
</tr>
</table>
```
---
## 헤더 배너 (이미지 기반)
이미지가 차단됐을 때도 배경색이 보이도록 `bgcolor` 속성을 함께 지정합니다:
```html
<table width="600" cellpadding="0" cellspacing="0" border="0"
style="width: 600px;">
<tr>
<td bgcolor="#1a56db" style="background-color: #1a56db; line-height: 0; padding: 0;">
<img src="https://cdn.example.com/header-banner.jpg"
alt="여름 세일 최대 70% 할인"
width="600" height="240"
style="display: block; width: 100%; max-width: 600px;
height: auto; border: 0;">
</td>
</tr>
</table>
```
---
## 섹션 구분선
```html
<!-- 섹션 간 여백 -->
<tr>
<td height="32" style="height: 32px; line-height: 32px;">&nbsp;</td>
</tr>
<!-- 수평선 -->
<tr>
<td style="padding-left: 32px; padding-right: 32px;">
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td height="1" bgcolor="#e5e7eb"
style="height: 1px; background-color: #e5e7eb; line-height: 1px;">
</td>
</tr>
</table>
</td>
</tr>
```
---
## 아웃라인(외곽선) 버튼
```html
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w="urn:schemas-microsoft-com:office:word"
href="https://example.com"
style="height: 44px; v-text-anchor: middle; width: 180px;"
arcsize="5%"
stroke="t"
strokeweight="2px"
strokecolor="#1a56db"
fillcolor="#ffffff">
<w:anchorlock/>
<center style="color: #1a56db; font-family: Arial, sans-serif;
font-size: 14px; font-weight: bold;">
더 알아보기
</center>
</v:roundrect>
<![endif]-->
<!--[if !mso]><!-->
<a href="https://example.com"
style="background-color: #ffffff;
color: #1a56db;
display: inline-block;
padding-top: 12px; padding-bottom: 12px;
padding-left: 24px; padding-right: 24px;
text-decoration: none;
border: 2px solid #1a56db;
border-radius: 5px;
font-family: Arial, sans-serif;
font-size: 14px;
font-weight: bold;">
더 알아보기
</a>
<!--<![endif]-->
```
---
## 소셜 아이콘 행
```html
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding-right: 8px;">
<a href="https://instagram.com/example" style="text-decoration: none;">
<img src="https://cdn.example.com/icon-instagram.png"
alt="Instagram" width="32" height="32"
style="display: block; border: 0;">
</a>
</td>
<td style="padding-right: 8px;">
<a href="https://facebook.com/example" style="text-decoration: none;">
<img src="https://cdn.example.com/icon-facebook.png"
alt="Facebook" width="32" height="32"
style="display: block; border: 0;">
</a>
</td>
<td>
<a href="https://youtube.com/example" style="text-decoration: none;">
<img src="https://cdn.example.com/icon-youtube.png"
alt="YouTube" width="32" height="32"
style="display: block; border: 0;">
</a>
</td>
</tr>
</table>
```

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env python3
"""
Example helper script for edm-email-html
This is a placeholder script that can be executed directly.
Replace with actual implementation or delete if not needed.
Example real scripts from other skills:
- pdf/scripts/fill_fillable_fields.py - Fills PDF form fields
- pdf/scripts/convert_pdf_to_images.py - Converts PDF pages to images
"""
def main():
print("This is an example script for edm-email-html")
# TODO: Add actual script logic here
# This could be data processing, file conversion, API calls, etc.
if __name__ == "__main__":
main()