44> 모든 개발과 문서는 이 결정을 기반으로 진행됩니다.
55
66** 최종 업데이트:** 2026-04-12
7- ** 문서 버전:** 1.3 .0
7+ ** 문서 버전:** 1.4 .0
88
99---
1010
@@ -615,6 +615,113 @@ temp_password_hash: string | null -- 임시 비밀번호 해시 (변경 완
615615
616616---
617617
618+ ## 결정 #7 : 이메일 전송 방식 — SMTP 설정 기반
619+
620+ ### ✅ 결정 사항
621+
622+ ** 사용자가 직접 외부 SMTP 서버 정보를 설정** 하여 이메일을 전송하는 방식을 채택합니다.
623+ Fieldstack이 자체 메일 서버를 운영하지 않으며, 전용 이메일 서비스(SendGrid 등)도 강제하지 않습니다.
624+
625+ ### 📖 배경
626+
627+ 비밀번호 복구 링크 전송, 구독 알림 등 이메일 발송이 필요한 기능이 존재합니다.
628+ Fieldstack은 self-hosted 앱이므로 사용자가 선호하는 외부 SMTP 서버를 자유롭게 연결할 수 있어야 합니다.
629+
630+ ### 🔍 고려했던 옵션
631+
632+ #### Option A: 전용 이메일 서비스 고정 (SendGrid, Resend 등)
633+ ```
634+ 장점:
635+ - 높은 전송 신뢰도
636+ - 별도 서버 불필요
637+
638+ 단점:
639+ - 특정 외부 서비스에 의존
640+ - API 키 관리 필요
641+ - 사용자가 해당 서비스에 가입해야 함
642+ ```
643+
644+ #### Option B: Self-hosted SMTP 서버 (Postfix 등)
645+ ```
646+ 장점:
647+ - 완전한 자체 운영
648+
649+ 단점:
650+ - 설정 복잡도 높음
651+ - 스팸 필터 회피 어려움
652+ - 개인 용도에 과도함
653+ ```
654+
655+ #### Option C: 외부 SMTP 서버 연동 (사용자 설정) ⭐ (선택)
656+ ```
657+ 장점:
658+ - 사용자가 기존에 쓰는 이메일 서비스 그대로 활용 가능
659+ - Gmail, Outlook, Naver 등 어디든 연결 가능
660+ - Fieldstack이 특정 서비스에 종속되지 않음
661+ - 설치 초기 SMTP가 없어도 앱 사용 가능 (Lazy 이메일 정책과 일관)
662+
663+ 단점:
664+ - 사용자가 직접 SMTP 정보를 입력해야 함
665+ ```
666+
667+ ### 💡 선택 이유
668+
669+ ** Option C** 를 선택한 이유:
670+
671+ 1 . ** self-hosted 철학과 일치** — 특정 외부 서비스에 묶이지 않음
672+ 2 . ** Lazy 이메일 검증 정책(결정 #6 )과 일관성** — SMTP 없이도 앱이 동작하며, 비밀번호 복구가 필요한 시점에만 SMTP 설정이 요구됨
673+ 3 . ** 유연성** — Gmail, Outlook, Naver, 기업 SMTP 등 어떤 서버든 호스트/포트/인증 정보만 있으면 연결 가능
674+
675+ ### 🎯 구현 방향
676+
677+ #### 지원 대상 SMTP 서버 (예시)
678+
679+ | 서비스 | 호스트 | 포트 | 비고 |
680+ | ---| ---| ---| ---|
681+ | Gmail | smtp.gmail.com | 587 | App Password 필요 (2FA 활성화 시) |
682+ | Outlook / Hotmail | smtp-mail.outlook.com | 587 | 계정 비밀번호 사용 |
683+ | Naver | smtp.naver.com | 587 | SMTP 사용 설정 필요 |
684+ | 기타 | 사용자 입력 | 사용자 입력 | 임의 SMTP 서버 |
685+
686+ #### Admin 설정 화면 입력 항목
687+
688+ ```
689+ SMTP 호스트 예: smtp.gmail.com
690+ SMTP 포트 예: 587
691+ 보안 TLS / STARTTLS / None
692+ 사용자 이름 예: yourname@gmail.com
693+ 비밀번호 App Password 또는 계정 비밀번호
694+ 발신자 이름 예: Fieldstack
695+ 발신자 이메일 예: yourname@gmail.com
696+ ```
697+
698+ #### 이메일 발송 대상 기능 (Phase 2~ )
699+
700+ - 비밀번호 복구 링크 발송
701+ - 구독 결제일 알림 (D-7, D-3, D-1)
702+ - 신규 유저 임시 비밀번호 발송 (선택 — SMTP 설정 완료 시)
703+
704+ #### SMTP 미설정 시 동작
705+
706+ - 비밀번호 복구: SMTP 미설정 안내 + 관리자 임시 비밀번호 발급 경로 안내
707+ - 구독 알림: 알림 기능 비활성화 상태 유지
708+
709+ ### 📚 관련 문서
710+
711+ > 📖 ** 인증 설계:**
712+ > → ` technical/02-authentication.md `
713+
714+ > 📖 ** 계정 관리 정책:**
715+ > → ` architecture/01-decisions.md § 결정 #6 `
716+
717+ ### ⚠️ 주의사항
718+
719+ 1 . ** SMTP 비밀번호 암호화 저장** — DB에 평문 저장 금지, Argon2id 또는 AES-256 암호화
720+ 2 . ** 연결 테스트 제공** — Admin 설정 화면에서 테스트 이메일 발송 기능 제공
721+ 3 . ** Gmail 사용 시 App Password 안내** — Google 계정 2FA 활성화 상태에서는 계정 비밀번호 직접 사용 불가, App Password 발급 필요
722+
723+ ---
724+
618725## 📝 요약표
619726
620727| 결정 | 선택 | 핵심 이유 | 상태 |
@@ -625,6 +732,7 @@ temp_password_hash: string | null -- 임시 비밀번호 해시 (변경 완
625732| #4 API 네임스페이스 | Internal/External 분리 | 보안 및 AI 연동 최적화 | ✅ 확정 |
626733| #5 Hard-Core 폐기 | Core 단일 통합 | Ring 3 분리 실익 없음, 외부 프로세스 매니저로 대체 | ✅ 확정 |
627734| #6 계정 관리 | 정책 3종 | 비밀번호 정책 + Lazy 이메일 검증 + 임시 비번 온보딩 | ✅ 확정 |
735+ | #7 이메일 전송 | 외부 SMTP 연동 | self-hosted 철학, 서비스 무종속 | ✅ 확정 |
628736
629737---
630738
@@ -637,6 +745,7 @@ temp_password_hash: string | null -- 임시 비밀번호 해시 (변경 완
637745| 2026-04-12 | 1.1.0 | 결정 번호 순서 정렬 (#5 → #4 ), 헤더 날짜/버전 동기화 |
638746| 2026-04-12 | 1.2.0 | Hard-Core 계층 폐기 및 Core 단일 통합 결정 추가 (#5 ) |
639747| 2026-04-12 | 1.3.0 | 계정 관리 정책 추가 — 비밀번호 정책, Lazy 이메일 검증, 임시 비번 온보딩 (#6 ) |
748+ | 2026-04-12 | 1.4.0 | 이메일 전송 방식 결정 추가 — 외부 SMTP 연동, 지원 서버 목록, 미설정 시 동작 정의 (#7 ) |
640749
641750---
642751
0 commit comments