create-entity-server 0.0.26 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/package.json +1 -1
  2. package/template/.env.example +26 -0
  3. package/template/configs/auth/cors.json +15 -0
  4. package/template/configs/auth/identity.json +27 -0
  5. package/template/configs/auth/jwt.json +12 -0
  6. package/template/configs/{oauth.json → auth/oauth.json} +7 -4
  7. package/template/configs/auth/password.json +33 -0
  8. package/template/configs/auth/privacy_policy.json +28 -0
  9. package/template/configs/{security.json → auth/security.json} +4 -2
  10. package/template/configs/auth/two_factor.json +12 -0
  11. package/template/configs/extensions/pg.json +37 -0
  12. package/template/configs/extensions/tax-invoice.json +59 -0
  13. package/template/configs/keys/.gitkeep +0 -0
  14. package/template/configs/keys/apns.p8.example +7 -0
  15. package/template/configs/keys/firebase.pem.example +7 -0
  16. package/template/configs/notification/alimtalk.json +75 -0
  17. package/template/configs/notification/sms.json +54 -0
  18. package/template/configs/server.json +1 -0
  19. package/template/entities/README.md +13 -16
  20. package/template/entities/System/Auth/account.json +17 -1
  21. package/template/entities/System/Auth/account_audit.json +23 -0
  22. package/template/entities/System/Auth/account_device.json +63 -0
  23. package/template/entities/System/Auth/account_login_log.json +54 -0
  24. package/template/entities/System/Auth/account_oauth.json +45 -0
  25. package/template/entities/System/Auth/api_keys.json +1 -1
  26. package/template/entities/System/Auth/identity_verification.json +95 -0
  27. package/template/entities/System/Auth/license.json +1 -1
  28. package/template/entities/System/Auth/password_history.json +20 -0
  29. package/template/entities/System/Auth/rbac_roles.json +1 -1
  30. package/template/entities/System/Backup/backup_log.json +62 -0
  31. package/template/entities/System/Email/smtp_log.json +83 -0
  32. package/template/entities/System/Email/smtp_msg.json +104 -0
  33. package/template/entities/System/Notification/alimtalk_log.json +45 -0
  34. package/template/entities/System/Notification/alimtalk_msg.json +39 -0
  35. package/template/entities/System/Notification/friendtalk_log.json +48 -0
  36. package/template/entities/System/Notification/friendtalk_msg.json +63 -0
  37. package/template/entities/System/Notification/sms_log.json +26 -0
  38. package/template/entities/System/Notification/sms_msg.json +52 -0
  39. package/template/entities/System/Notification/sms_verification.json +40 -0
  40. package/template/entities/System/Payment/pg_cancel.json +45 -0
  41. package/template/entities/System/Payment/pg_order.json +88 -0
  42. package/template/entities/System/Payment/pg_webhook_log.json +37 -0
  43. package/template/entities/System/Push/push_log.json +71 -0
  44. package/template/entities/System/Push/push_msg.json +55 -0
  45. package/template/entities/System/Storage/file_backup_log.json +46 -0
  46. package/template/entities/System/Storage/file_download_log.json +41 -0
  47. package/template/entities/System/Storage/file_meta.json +59 -0
  48. package/template/entities/System/system_audit_log.json +2 -1
  49. package/template/entities/company.json +1 -1
  50. package/template/entities/{product.json → goods.json} +6 -10
  51. package/template/entities/todo.json +1 -1
  52. package/template/templates/email/account/dormancy_warning.html +20 -0
  53. package/template/templates/email/account/password_expiry_warning.html +21 -0
  54. package/template/templates/email/auth/2fa_disabled.html +23 -0
  55. package/template/templates/email/auth/2fa_recovery_regenerated.html +31 -0
  56. package/template/templates/email/auth/2fa_setup_complete.html +43 -0
  57. package/template/templates/email/auth/email_verification.html +18 -0
  58. package/template/templates/email/auth/force_reset.html +18 -0
  59. package/template/templates/email/auth/password_reset.html +19 -0
  60. package/template/templates/email/auth/verification.html +15 -0
  61. package/template/templates/email/auth/verification_link.html +25 -0
  62. package/template/templates/email/auth/welcome.html +18 -0
  63. package/template/templates/email/backup/backup_completed.html +35 -0
  64. package/template/templates/email/backup/backup_failed.html +27 -0
  65. package/template/templates/email/backup/backup_partial.html +31 -0
  66. package/template/templates/email/layout.html +47 -0
  67. package/template/templates/email/order/order_confirmation.html +30 -0
  68. package/template/templates/email/storage/storage_quota_exceeded.html +37 -0
  69. package/template/templates/email/storage/storage_quota_warning.html +37 -0
  70. package/template/configs/cors.json +0 -7
  71. package/template/configs/jwt.json +0 -8
  72. package/template/entities/Account/account_audit.json +0 -16
  73. /package/template/configs/{backup.json → extensions/backup.json} +0 -0
  74. /package/template/configs/{storage.json → extensions/storage.json} +0 -0
  75. /package/template/configs/{push.json → notification/push.json} +0 -0
  76. /package/template/configs/{smtp.json → notification/smtp.json} +0 -0
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "file_meta",
3
+ "description": "파일 메타데이터. 업로드된 파일의 저장 위치·크기·해시·상태를 관리합니다. 파일 핸들러가 자동 기록하며 API를 통한 직접 수정은 허용되지 않습니다. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
4
+ "history": false,
5
+ "hard_delete": true,
6
+ "read_only": true,
7
+ "index": {
8
+ "backup_status": {
9
+ "comment": "백업 동기화 상태",
10
+ "type": ["none", "pending", "synced", "failed", "skipped"],
11
+ "default": "none"
12
+ },
13
+ "size": {
14
+ "comment": "파일 크기 (bytes)",
15
+ "type": "bigint unsigned"
16
+ },
17
+ "status": {
18
+ "comment": "파일 상태",
19
+ "type": ["active", "pending", "orphan", "deleted"],
20
+ "default": "pending",
21
+ "required": true
22
+ },
23
+ "uuid": {
24
+ "comment": "파일 고유 식별자 (UUID v4). 저장 경로·다운로드 URL의 키로 사용",
25
+ "type": "varchar(36)",
26
+ "required": true,
27
+ "unique": true
28
+ }
29
+ },
30
+ "fields": {
31
+ "backup_retries": {
32
+ "comment": "백업 재시도 횟수"
33
+ },
34
+ "content_hash": {
35
+ "comment": "파일 SHA-256 해시 (중복 탐지·무결성 검증용)"
36
+ },
37
+ "entity_name": {
38
+ "comment": "파일이 첨부된 엔티티 이름"
39
+ },
40
+ "entity_seq": {
41
+ "comment": "파일이 첨부된 엔티티 레코드 seq. 업로드 직후 엔티티 미연결 시 NULL"
42
+ },
43
+ "field_name": {
44
+ "comment": "파일이 첨부된 필드 이름 (file/file[] 타입 필드)"
45
+ },
46
+ "mime_type": {
47
+ "comment": "파일 MIME 타입 (image/jpeg, application/pdf 등)"
48
+ },
49
+ "original_name": {
50
+ "comment": "업로드 시 원본 파일명 (보안 대상 — 암호화 저장)"
51
+ },
52
+ "storage_key": {
53
+ "comment": "스토리지 백엔드 내 상대 경로 (예: 2026/02/27/contact/uuid.jpg)"
54
+ },
55
+ "storage_path": {
56
+ "comment": "라이선스 접두어 포함 전체 경로 (예: 3/2026/02/27/contact/uuid.jpg)"
57
+ }
58
+ }
59
+ }
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "system_audit_log",
3
- "description": "시스템 감사 로그. 서버 레벨에서 자동 기록되며 API를 통한 직접 수정은 허용되지 않습니다. JWT 인증 시에만 account_seq 기록",
3
+ "description": "시스템 감사 로그. 서버 레벨에서 자동 기록되며 API를 통한 직접 수정은 허용되지 않습니다. JWT 인증 시에만 account_seq 기록. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
4
4
  "db_group": "system",
5
5
  "hard_delete": true,
6
6
  "history_ttl": 0,
7
7
  "read_only": true,
8
8
  "license_scope": false,
9
+ "compress": true,
9
10
  "index": {
10
11
  "transaction_id": {
11
12
  "comment": "요청 트랜잭션 ID. entity_history 테이블과 JOIN 키",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "company",
3
- "description": "company Entity",
3
+ "description": "company Entity. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
4
4
  "index": {
5
5
  "company_name": {
6
6
  "comment": "회사명",
@@ -1,19 +1,15 @@
1
1
  {
2
- "name": "product",
3
- "description": "product Entity",
2
+ "name": "goods",
3
+ "description": "goods Entity. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
4
4
  "index": {
5
5
  "name": {
6
- "comment": "제품명",
6
+ "comment": "상품명",
7
7
  "required": true,
8
8
  "unique": true
9
9
  },
10
10
  "category": {
11
11
  "comment": "카테고리",
12
- "type": [
13
- "전자제품",
14
- "가구",
15
- "생활용품"
16
- ]
12
+ "type": ["전자제품", "가구", "생활용품"]
17
13
  },
18
14
  "price": {
19
15
  "comment": "가격"
@@ -21,13 +17,13 @@
21
17
  },
22
18
  "reset_defaults": [
23
19
  {
24
- "name": "샘플 제품 A",
20
+ "name": "샘플 상품 A",
25
21
  "category": "전자제품",
26
22
  "price": 10000,
27
23
  "stock": 50
28
24
  },
29
25
  {
30
- "name": "샘플 제품 B",
26
+ "name": "샘플 상품 B",
31
27
  "category": "가구",
32
28
  "price": 50000,
33
29
  "stock": 20
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "todo",
3
- "description": "todo Entity",
3
+ "description": "todo Entity. 사용자 환경에 맞게 index·fields를 자유롭게 확장할 수 있습니다.",
4
4
  "index": {
5
5
  "title": {
6
6
  "comment": "할 일 제목"
@@ -0,0 +1,20 @@
1
+ <h2 style="margin: 0 0 8px; font-size: 22px; font-weight: 700; color: #1a1a2e;">계정 휴면 예정 안내</h2>
2
+ <p style="margin: 0 0 24px; font-size: 13px; color: #999;">D-${days_left|30}</p>
3
+ <p style="margin: 0 0 20px; font-size: 15px; color: #555; line-height: 1.6;">
4
+ 안녕하세요.<br>
5
+ <strong>${email}</strong> 계정이 <strong>${days_left|30}일 후</strong> 장기 미접속으로 인해 휴면 상태로 전환될 예정입니다.
6
+ </p>
7
+ <div style="background-color: #fff8e1; border-left: 4px solid #f59e0b; border-radius: 4px; padding: 16px 20px; margin: 0 0 24px;">
8
+ <p style="margin: 0; font-size: 14px; color: #92400e; line-height: 1.6;">
9
+ 휴면 계정은 로그인이 제한되며, 서비스 이용을 위해 별도의 본인 인증이 필요합니다.
10
+ </p>
11
+ </div>
12
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
13
+ 지금 로그인하면 휴면 전환을 방지할 수 있습니다.
14
+ </p>
15
+ <div style="text-align: center; margin: 0 0 28px;">
16
+ <a href="${login_url|#}" style="display: inline-block; padding: 14px 40px; background-color: #1a1a2e; color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 15px; font-weight: 600;">지금 로그인하기</a>
17
+ </div>
18
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
19
+ 이미 최근에 로그인하셨다면 이 안내는 무시하셔도 됩니다.
20
+ </p>
@@ -0,0 +1,21 @@
1
+ <h2 style="margin: 0 0 8px; font-size: 22px; font-weight: 700; color: #1a1a2e;">비밀번호 변경 안내</h2>
2
+ <p style="margin: 0 0 24px; font-size: 13px; color: #999;">D-${days_left|14}</p>
3
+ <p style="margin: 0 0 20px; font-size: 15px; color: #555; line-height: 1.6;">
4
+ 안녕하세요.<br>
5
+ <strong>${email}</strong> 계정의 비밀번호가 <strong>${days_left|14}일 후</strong> 만료됩니다.
6
+ </p>
7
+ <div style="background-color: #fef2f2; border-left: 4px solid #ef4444; border-radius: 4px; padding: 16px 20px; margin: 0 0 24px;">
8
+ <p style="margin: 0; font-size: 14px; color: #991b1b; line-height: 1.6;">
9
+ 만료된 비밀번호로는 로그인 후 즉시 비밀번호 변경이 요구될 수 있습니다.<br>
10
+ 정기적인 비밀번호 변경으로 계정을 안전하게 보호하세요.
11
+ </p>
12
+ </div>
13
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
14
+ 아래 버튼을 클릭하여 지금 비밀번호를 변경하세요.
15
+ </p>
16
+ <div style="text-align: center; margin: 0 0 28px;">
17
+ <a href="${change_password_url|#}" style="display: inline-block; padding: 14px 40px; background-color: #1a1a2e; color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 15px; font-weight: 600;">비밀번호 변경하기</a>
18
+ </div>
19
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
20
+ 이미 비밀번호를 변경하셨다면 이 안내는 무시하셔도 됩니다.
21
+ </p>
@@ -0,0 +1,23 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">2단계 인증이 비활성화되었습니다</h2>
2
+ <p style="margin: 0 0 16px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ <strong>${email}</strong> 계정의 2단계 인증(TOTP)이 해제되었습니다.<br>
4
+ 앞으로 이메일과 비밀번호만으로 로그인됩니다.
5
+ </p>
6
+
7
+ <div style="margin: 0 0 24px; padding: 20px; background-color: #f8d7da; border-radius: 8px; border-left: 4px solid #dc3545;">
8
+ <p style="margin: 0; font-size: 14px; color: #721c24; line-height: 1.6;">
9
+ <strong>보안 알림:</strong> 2단계 인증이 해제되면 계정 보안 수준이 낮아집니다.<br>
10
+ 가능하면 다시 2단계 인증을 설정하는 것을 권장합니다.
11
+ </p>
12
+ </div>
13
+
14
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
15
+ 해제 시각: ${disabled_time}
16
+ </p>
17
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
18
+ 해제 방법: ${disabled_by|본인 요청}
19
+ </p>
20
+
21
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
22
+ 본인이 해제하지 않은 경우, 즉시 비밀번호를 변경하고 관리자에게 문의하세요.
23
+ </p>
@@ -0,0 +1,31 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">복구 코드가 재생성되었습니다</h2>
2
+ <p style="margin: 0 0 16px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ <strong>${email}</strong> 계정의 2단계 인증 복구 코드가 새로 생성되었습니다.<br>
4
+ 이전 복구 코드는 모두 <strong>폐기</strong>되었습니다.
5
+ </p>
6
+
7
+ <div style="margin: 0 0 24px; padding: 20px; background-color: #fff3cd; border-radius: 8px; border-left: 4px solid #ffc107;">
8
+ <p style="margin: 0 0 8px; font-size: 14px; font-weight: 700; color: #856404;">⚠ 새 복구 코드를 안전한 곳에 저장하세요</p>
9
+ <p style="margin: 0; font-size: 13px; color: #856404; line-height: 1.5;">
10
+ 각 코드는 <strong>한 번만</strong> 사용할 수 있으며, 이 이메일 이후에는 다시 확인할 수 없습니다.
11
+ </p>
12
+ </div>
13
+
14
+ <div style="text-align: center; margin: 0 0 24px;">
15
+ <table role="presentation" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
16
+ <tr>
17
+ <td style="padding: 16px 32px; background-color: #f0f0f5; border-radius: 8px;">
18
+ <pre style="margin: 0; font-size: 18px; font-weight: 700; color: #1a1a2e; font-family: 'Courier New', monospace; letter-spacing: 2px; line-height: 2;">${recovery_codes}</pre>
19
+ </td>
20
+ </tr>
21
+ </table>
22
+ </div>
23
+
24
+ <p style="margin: 0 0 16px; font-size: 14px; color: #888; line-height: 1.6;">
25
+ 새 복구 코드: <strong>${recovery_count|10}개</strong><br>
26
+ 재생성 시각: ${regenerated_time}
27
+ </p>
28
+
29
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
30
+ 본인이 요청하지 않은 경우, 계정이 보안 위협에 노출되었을 수 있습니다. 즉시 비밀번호를 변경하고 관리자에게 문의하세요.
31
+ </p>
@@ -0,0 +1,43 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">2단계 인증이 활성화되었습니다</h2>
2
+ <p style="margin: 0 0 16px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ <strong>${email}</strong> 계정에 2단계 인증(TOTP)이 설정되었습니다.<br>
4
+ 앞으로 로그인 시 Authenticator 앱의 인증 코드가 필요합니다.
5
+ </p>
6
+
7
+ <div style="margin: 0 0 24px; padding: 20px; background-color: #fff3cd; border-radius: 8px; border-left: 4px solid #ffc107;">
8
+ <p style="margin: 0 0 8px; font-size: 14px; font-weight: 700; color: #856404;">⚠ 복구 코드를 안전한 곳에 저장하세요</p>
9
+ <p style="margin: 0 0 12px; font-size: 13px; color: #856404; line-height: 1.5;">
10
+ Authenticator 앱에 접근할 수 없는 경우 아래 복구 코드로 로그인할 수 있습니다.<br>
11
+ 각 코드는 <strong>한 번만</strong> 사용할 수 있으며, 이 이메일 이후에는 다시 확인할 수 없습니다.
12
+ </p>
13
+ </div>
14
+
15
+ <div style="text-align: center; margin: 0 0 24px;">
16
+ <table role="presentation" cellpadding="0" cellspacing="0" style="margin: 0 auto;">
17
+ <tr>
18
+ <td style="padding: 16px 32px; background-color: #f0f0f5; border-radius: 8px;">
19
+ <pre style="margin: 0; font-size: 18px; font-weight: 700; color: #1a1a2e; font-family: 'Courier New', monospace; letter-spacing: 2px; line-height: 2;">${recovery_codes}</pre>
20
+ </td>
21
+ </tr>
22
+ </table>
23
+ </div>
24
+
25
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
26
+ 남은 복구 코드: <strong>${recovery_count|10}개</strong>
27
+ </p>
28
+ <p style="margin: 0 0 16px; font-size: 14px; color: #888; line-height: 1.6;">
29
+ 설정 시각: ${enabled_time}
30
+ </p>
31
+
32
+ <div style="margin: 0 0 16px; padding: 16px; background-color: #f8f9fa; border-radius: 6px;">
33
+ <p style="margin: 0; font-size: 13px; color: #666; line-height: 1.6;">
34
+ 💡 <strong>권장 사항</strong><br>
35
+ • 복구 코드를 출력하거나 비밀번호 관리자에 저장하세요<br>
36
+ • 복구 코드가 3개 이하로 줄면 재생성하세요<br>
37
+ • 본인이 설정하지 않았다면 즉시 비밀번호를 변경하세요
38
+ </p>
39
+ </div>
40
+
41
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
42
+ 본인이 설정하지 않은 경우, 계정이 보안 위협에 노출되었을 수 있습니다. 즉시 비밀번호를 변경하고 관리자에게 문의하세요.
43
+ </p>
@@ -0,0 +1,18 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">이메일 인증</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 아래 인증 코드를 입력하여 이메일 주소를 인증하세요.
4
+ </p>
5
+ <div style="text-align: center; margin: 0 0 28px;">
6
+ <div style="display: inline-block; padding: 18px 40px; background-color: #f4f4f7; border-radius: 8px; border: 1px solid #e0e0e0;">
7
+ <span style="font-size: 32px; font-weight: 700; letter-spacing: 10px; color: #1a1a2e; font-family: 'Courier New', Courier, monospace;">${code|------}</span>
8
+ </div>
9
+ </div>
10
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
11
+ 이 코드는 <strong>${expires_in|5분}</strong> 동안 유효합니다.
12
+ </p>
13
+ <p style="margin: 0 0 8px; font-size: 13px; color: #aaa; line-height: 1.6;">
14
+ 인증 대상 이메일: <strong>${email|}</strong>
15
+ </p>
16
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
17
+ 본인이 요청하지 않은 경우 이 이메일을 무시하세요.
18
+ </p>
@@ -0,0 +1,18 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">임시 비밀번호 안내</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 관리자에 의해 비밀번호가 초기화되었습니다. 아래 임시 비밀번호로 로그인 후 즉시 비밀번호를 변경하세요.
4
+ </p>
5
+ <div style="text-align: center; margin: 0 0 28px;">
6
+ <div style="display: inline-block; padding: 14px 32px; background-color: #f4f4f7; border-radius: 8px; border: 1px solid #e0e0e0;">
7
+ <span style="font-size: 22px; font-weight: 700; letter-spacing: 4px; color: #1a1a2e; font-family: 'Courier New', Courier, monospace;">${temp_password|}</span>
8
+ </div>
9
+ </div>
10
+ <p style="margin: 0 0 16px; font-size: 14px; color: #d9534f; font-weight: 600; line-height: 1.6;">
11
+ ⚠ 보안을 위해 로그인 즉시 비밀번호를 변경하시기 바랍니다.
12
+ </p>
13
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
14
+ 이메일: <strong>${email|}</strong>
15
+ </p>
16
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
17
+ 본인이 요청하지 않은 경우 즉시 관리자에게 문의하세요.
18
+ </p>
@@ -0,0 +1,19 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">비밀번호 재설정</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 비밀번호 재설정이 요청되었습니다. 아래 버튼을 클릭하여 새 비밀번호를 설정하세요.
4
+ </p>
5
+ <div style="text-align: center; margin: 0 0 24px;">
6
+ <a href="${reset_url|#}" style="display: inline-block; padding: 14px 36px; background-color: #1a1a2e; color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 15px; font-weight: 600;">비밀번호 재설정</a>
7
+ </div>
8
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
9
+ 버튼이 작동하지 않으면 아래 링크를 브라우저에 붙여넣으세요:
10
+ </p>
11
+ <p style="margin: 0 0 16px; font-size: 13px; color: #4a90d9; word-break: break-all; line-height: 1.6;">
12
+ ${reset_url|https://example.com/reset?token=sample}
13
+ </p>
14
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
15
+ 이 링크는 <strong>${expires_in|1시간}</strong> 동안 유효합니다.
16
+ </p>
17
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
18
+ 본인이 요청하지 않은 경우 이 이메일을 무시하세요. 비밀번호는 변경되지 않습니다.
19
+ </p>
@@ -0,0 +1,15 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">인증 코드</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 아래 코드를 입력하여 본인 인증을 완료하세요.
4
+ </p>
5
+ <div style="text-align: center; margin: 0 0 24px;">
6
+ <div style="display: inline-block; padding: 16px 40px; background-color: #f0f0f5; border-radius: 8px; letter-spacing: 8px; font-size: 36px; font-weight: 700; color: #1a1a2e; font-family: 'Courier New', monospace;">
7
+ ${code|000000}
8
+ </div>
9
+ </div>
10
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
11
+ 이 코드는 <strong>${expires_in|10분}</strong> 동안 유효합니다.
12
+ </p>
13
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
14
+ 본인이 요청하지 않은 경우 이 이메일을 무시하세요.
15
+ </p>
@@ -0,0 +1,25 @@
1
+ ```php
2
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">이메일 인증</h2>
3
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
4
+ 아래 버튼을 클릭하여 이메일 인증을 완료하세요.
5
+ </p>
6
+ <div style="text-align: center; margin: 0 0 24px;">
7
+ <a href="${activation_url}" target="_blank" rel="noopener noreferrer"
8
+ style="display: inline-block; padding: 14px 40px; background-color: #1a1a2e; color: #ffffff; text-decoration: none; border-radius: 8px; font-size: 16px; font-weight: 600; letter-spacing: 0.5px;">
9
+ 이메일 인증하기
10
+ </a>
11
+ </div>
12
+ <p style="margin: 0 0 8px; font-size: 14px; color: #888; line-height: 1.6;">
13
+ 이 링크는 <strong>${expires_in|10분}</strong> 동안 유효합니다.
14
+ </p>
15
+ <p style="margin: 0 0 16px; font-size: 13px; color: #aaa; line-height: 1.6;">
16
+ 버튼이 작동하지 않는 경우 아래 링크를 브라우저에 직접 붙여넣으세요:
17
+ </p>
18
+ <p style="margin: 0; font-size: 12px; color: #999; word-break: break-all; line-height: 1.6;">
19
+ ${activation_url}
20
+ </p>
21
+ <p style="margin: 16px 0 0; font-size: 13px; color: #aaa; line-height: 1.6;">
22
+ 본인이 요청하지 않은 경우 이 이메일을 무시하세요.
23
+ </p>
24
+
25
+ ```
@@ -0,0 +1,18 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">환영합니다, ${name|회원}님!</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 회원가입이 완료되었습니다. ${app_name|서비스}를 이용해 주셔서 감사합니다.
4
+ </p>
5
+ <div style="text-align: center; margin: 0 0 24px;">
6
+ <a href="${login_url|#}" style="display: inline-block; padding: 14px 36px; background-color: #1a1a2e; color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 15px; font-weight: 600;">시작하기</a>
7
+ </div>
8
+ <div style="padding: 20px; background-color: #f8f8fa; border-radius: 6px; margin: 0 0 24px;">
9
+ <p style="margin: 0 0 8px; font-size: 14px; font-weight: 600; color: #1a1a2e;">계정 정보</p>
10
+ <p style="margin: 0; font-size: 14px; color: #555; line-height: 1.8;">
11
+ 이메일: ${email|user@example.com}<br>
12
+ 아이디: ${account_id|user001}<br>
13
+ 가입일: ${created_at|오늘}
14
+ </p>
15
+ </div>
16
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
17
+ 궁금한 점이 있으시면 언제든 문의해 주세요.
18
+ </p>
@@ -0,0 +1,35 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #27ae60;">✅ 백업 완료</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 데이터 백업이 정상적으로 완료되었습니다.
4
+ </p>
5
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin: 0 0 24px;">
6
+ <tr>
7
+ <td style="padding: 16px 20px; background-color: #eafaf1; border-radius: 6px; border-left: 4px solid #27ae60;">
8
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
9
+ <tr>
10
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">세션 ID</td>
11
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${session_id|—}</td>
12
+ </tr>
13
+ <tr>
14
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">상태</td>
15
+ <td style="padding: 4px 0; font-size: 14px; font-weight: 700; color: #27ae60;">완료</td>
16
+ </tr>
17
+ <tr>
18
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">레코드 수</td>
19
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${total_records|0}건</td>
20
+ </tr>
21
+ <tr>
22
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">백업 크기</td>
23
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${total_size|0 B}</td>
24
+ </tr>
25
+ <tr>
26
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">소요 시간</td>
27
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${elapsed|—}</td>
28
+ </tr>
29
+ </table>
30
+ </td>
31
+ </tr>
32
+ </table>
33
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
34
+ 이 알림은 백업 완료 시 자동 발송됩니다.
35
+ </p>
@@ -0,0 +1,27 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #e74c3c;">❌ 백업 실패</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 데이터 백업에 실패했습니다. 오류 내용을 확인하고 조치해 주세요.
4
+ </p>
5
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin: 0 0 24px;">
6
+ <tr>
7
+ <td style="padding: 16px 20px; background-color: #fdedec; border-radius: 6px; border-left: 4px solid #e74c3c;">
8
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
9
+ <tr>
10
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">세션 ID</td>
11
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${session_id|—}</td>
12
+ </tr>
13
+ <tr>
14
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">상태</td>
15
+ <td style="padding: 4px 0; font-size: 14px; font-weight: 700; color: #e74c3c;">실패</td>
16
+ </tr>
17
+ </table>
18
+ </td>
19
+ </tr>
20
+ </table>
21
+ <div style="margin: 0 0 24px;">
22
+ <p style="margin: 0 0 8px; font-size: 14px; font-weight: 600; color: #1a1a2e;">오류 내용</p>
23
+ <pre style="margin: 0; padding: 12px 16px; background-color: #f8f8fa; border-radius: 6px; font-size: 13px; color: #e74c3c; line-height: 1.6; white-space: pre-wrap; word-break: break-all;">${error_message|알 수 없는 오류}</pre>
24
+ </div>
25
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
26
+ 이 알림은 백업 실패 시 자동 발송됩니다.
27
+ </p>
@@ -0,0 +1,31 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #e67e22;">⚠️ 백업 부분 완료</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 백업이 완료되었으나 일부 엔티티에서 오류가 발생했습니다. 실패한 항목을 확인해 주세요.
4
+ </p>
5
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin: 0 0 24px;">
6
+ <tr>
7
+ <td style="padding: 16px 20px; background-color: #fef9e7; border-radius: 6px; border-left: 4px solid #e67e22;">
8
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
9
+ <tr>
10
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">세션 ID</td>
11
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${session_id|—}</td>
12
+ </tr>
13
+ <tr>
14
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">상태</td>
15
+ <td style="padding: 4px 0; font-size: 14px; font-weight: 700; color: #e67e22;">부분 완료</td>
16
+ </tr>
17
+ <tr>
18
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">레코드 수</td>
19
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${total_records|0}건</td>
20
+ </tr>
21
+ </table>
22
+ </td>
23
+ </tr>
24
+ </table>
25
+ <div style="margin: 0 0 24px;">
26
+ <p style="margin: 0 0 8px; font-size: 14px; font-weight: 600; color: #1a1a2e;">실패한 엔티티</p>
27
+ <pre style="margin: 0; padding: 12px 16px; background-color: #f8f8fa; border-radius: 6px; font-size: 13px; color: #555; line-height: 1.6; white-space: pre-wrap; word-break: break-all;">${failed_entities|없음}</pre>
28
+ </div>
29
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
30
+ 이 알림은 백업 결과에 오류가 포함되었을 때 자동 발송됩니다.
31
+ </p>
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html lang="ko">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <!--[if mso]>
7
+ <noscript>
8
+ <xml>
9
+ <o:OfficeDocumentSettings>
10
+ <o:PixelsPerInch>96</o:PixelsPerInch>
11
+ </o:OfficeDocumentSettings>
12
+ </xml>
13
+ </noscript>
14
+ <![endif]-->
15
+ </head>
16
+ <body style="margin: 0; padding: 0; background-color: #f4f4f7; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%;">
17
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f4f4f7;">
18
+ <tr>
19
+ <td align="center" style="padding: 24px 16px;">
20
+ <table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width: 600px; width: 100%; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.08);">
21
+ <!-- Header -->
22
+ <tr>
23
+ <td style="padding: 32px 40px 24px; border-bottom: 1px solid #eaeaea;">
24
+ <span style="font-size: 18px; font-weight: 700; color: #1a1a2e;">${app_name|Entity Server}</span>
25
+ </td>
26
+ </tr>
27
+ <!-- Content -->
28
+ <tr>
29
+ <td style="padding: 32px 40px;">
30
+ ${content}
31
+ </td>
32
+ </tr>
33
+ <!-- Footer -->
34
+ <tr>
35
+ <td style="padding: 24px 40px; border-top: 1px solid #eaeaea; background-color: #fafafa;">
36
+ <p style="margin: 0; font-size: 12px; color: #999; line-height: 1.6;">
37
+ 이 이메일은 자동 발송되었습니다. 회신하지 마세요.<br>
38
+ &copy; ${company|Entity Server}
39
+ </p>
40
+ </td>
41
+ </tr>
42
+ </table>
43
+ </td>
44
+ </tr>
45
+ </table>
46
+ </body>
47
+ </html>
@@ -0,0 +1,30 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #1a1a2e;">주문이 확인되었습니다</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ ${name|고객}님, 주문해 주셔서 감사합니다.
4
+ </p>
5
+ <div style="padding: 20px; background-color: #f8f8fa; border-radius: 6px; margin: 0 0 24px;">
6
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
7
+ <tr>
8
+ <td style="padding: 8px 0; font-size: 14px; color: #888;">주문번호</td>
9
+ <td style="padding: 8px 0; font-size: 14px; color: #1a1a2e; font-weight: 600; text-align: right;">${order_id|ORD-000001}</td>
10
+ </tr>
11
+ <tr>
12
+ <td style="padding: 8px 0; font-size: 14px; color: #888; border-top: 1px solid #eaeaea;">주문일시</td>
13
+ <td style="padding: 8px 0; font-size: 14px; color: #1a1a2e; text-align: right; border-top: 1px solid #eaeaea;">${order_date|2026-01-01}</td>
14
+ </tr>
15
+ <tr>
16
+ <td style="padding: 8px 0; font-size: 14px; color: #888; border-top: 1px solid #eaeaea;">상품</td>
17
+ <td style="padding: 8px 0; font-size: 14px; color: #1a1a2e; text-align: right; border-top: 1px solid #eaeaea;">${items|상품 1건}</td>
18
+ </tr>
19
+ <tr>
20
+ <td style="padding: 12px 0; font-size: 16px; font-weight: 700; color: #1a1a2e; border-top: 2px solid #1a1a2e;">총 결제금액</td>
21
+ <td style="padding: 12px 0; font-size: 16px; font-weight: 700; color: #1a1a2e; text-align: right; border-top: 2px solid #1a1a2e;">${total|50,000원}</td>
22
+ </tr>
23
+ </table>
24
+ </div>
25
+ <div style="text-align: center; margin: 0 0 24px;">
26
+ <a href="${detail_url|#}" style="display: inline-block; padding: 14px 36px; background-color: #1a1a2e; color: #ffffff; text-decoration: none; border-radius: 6px; font-size: 15px; font-weight: 600;">주문 상세 보기</a>
27
+ </div>
28
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
29
+ 주문 관련 문의사항이 있으시면 고객센터로 연락해 주세요.
30
+ </p>
@@ -0,0 +1,37 @@
1
+ <h2 style="margin: 0 0 16px; font-size: 22px; font-weight: 700; color: #e74c3c;">🚫 저장공간 초과</h2>
2
+ <p style="margin: 0 0 24px; font-size: 15px; color: #555; line-height: 1.6;">
3
+ 저장공간 사용량이 제한 용량을 초과했습니다. 파일 업로드가 차단됩니다. 즉시 불필요한 파일을 삭제하거나 쿼터를 늘려주세요.
4
+ </p>
5
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="margin: 0 0 24px;">
6
+ <tr>
7
+ <td style="padding: 16px 20px; background-color: #fdedec; border-radius: 6px; border-left: 4px solid #e74c3c;">
8
+ <table role="presentation" width="100%" cellpadding="0" cellspacing="0">
9
+ <tr>
10
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">사용량</td>
11
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${used|0 B}</td>
12
+ </tr>
13
+ <tr>
14
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">제한 용량</td>
15
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${limit|0 B}</td>
16
+ </tr>
17
+ <tr>
18
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">사용률</td>
19
+ <td style="padding: 4px 0; font-size: 15px; font-weight: 700; color: #e74c3c;">${percent|0}%</td>
20
+ </tr>
21
+ <tr>
22
+ <td style="padding: 4px 0; font-size: 14px; color: #555; width: 120px; font-weight: 600;">업로드 시도</td>
23
+ <td style="padding: 4px 0; font-size: 14px; color: #333;">${upload_size|0 B}</td>
24
+ </tr>
25
+ </table>
26
+ </td>
27
+ </tr>
28
+ </table>
29
+ <!-- 사용률 바 (100%) -->
30
+ <div style="margin: 0 0 24px;">
31
+ <div style="background-color: #eee; border-radius: 4px; height: 12px; overflow: hidden;">
32
+ <div style="background-color: #e74c3c; height: 100%; width: 100%; border-radius: 4px;"></div>
33
+ </div>
34
+ </div>
35
+ <p style="margin: 0; font-size: 13px; color: #aaa; line-height: 1.6;">
36
+ 이 알림은 저장공간 사용량이 제한 용량을 초과했을 때 자동 발송됩니다.
37
+ </p>