포트폴리오 사이트에서 방문자가 이메일 주소를 복사하는 불편함 없이, 즉시 메시지를 보낼 수 있는 기능을 구현했습니다. 외부 유료 서비스 대신 Gmail SMTP와 Nodemailer를 활용해 완전 무료로 구축한 과정을 공유합니다.
기술 스택
왜 Gmail SMTP를 선택했나?
처음에는 이메일 API 서비스인 Resend를 고려했습니다. 하지만 개인 포트폴리오 프로젝트에는 다음과 같은 이유로 Gmail SMTP가 훨씬 합리적인 선택이었습니다.
| 비교 | Resend (무료 플랜) | Gmail SMTP (선택) |
| 비용 | 무료 (제한적) | 완전 무료 |
| 전송 제한 | 월 100통 | 일 500통 |
| 설정 | 도메인 인증 등 복잡함 | 앱 비밀번호 발급만 하면 끝 |
| 수신 | 대시보드 확인 | 내 Gmail로 즉시 수신 |
개인적인 용도에서는 별도 가입 없이 기존 구글 계정을 활용할 수 있는 점이 가장 큰 장점이었습니다.
구현 과정
1. 패키지 설치
터미널에서 nodemailer와 TypeScript 지원을 위한 타입 정의 패키지를 설치합니다.
Bash
pnpm add nodemailer
pnpm add -D @types/nodemailer
2. 이메일 전송 API 생성 (route.ts)
Next.js의 API Route를 활용해 백엔드 로직을 작성합니다. 핵심은 nodemailer.createTransport()로 Gmail과 연결하고, transporter.sendMail()로 메일을 쏘는 것입니다.
주요 설정 포인트:
service: 'gmail': 별도의 호스트 설정 없이 간편하게 지정auth: 본인 Gmail 주소와 앱 비밀번호 사용replyTo: 이메일 수신 후 '답장하기'를 눌렀을 때, 문의자의 이메일로 바로 답장가도록 설정 (UX 핵심!)3. 반응형 이메일 모달 (Frontend)
단순한 폼이 아닌, 사용자 경험을 고려한 모달 컴포넌트를 구현했습니다.
4. Contact Section 업데이트
기존의 정적인 "이메일 주소 복사" 버튼 옆에 "이메일 보내기" 버튼을 추가했습니다.
핵심: Gmail 앱 비밀번호 발급
일반 Google 계정 비밀번호로는 SMTP 보안 연결이 불가능합니다. 반드시 앱 비밀번호를 발급받아야 합니다.
Google 계정 → 보안 탭 → 2단계 인증 켜기보안 탭 하단 확인MyPortfolio) 후 '만들기' 클릭.env.local):GMAIL_USER=본인이메일@gmail.com GMAIL_APP_PASSWORD=xxxx xxxx xxxx xxxx
이메일 템플릿 디자인
제게 도착하는 문의 메일이 딱딱해 보이지 않도록 HTML 템플릿을 입혔습니다.
mailto: 링크가 걸린 '답장하기' 버튼 포함결과 및 마무리
이제 Contact Me 섹션에서 폼을 작성하고 전송하면, 제 개인 Gmail 받은편지함에 예쁘게 디자인된 문의 메일이 즉시 도착합니다. '답장하기' 버튼 한 번으로 소통이 가능해져 매우 편리합니다.
외부 서비스 의존도(Dependency)를 줄이고, 순수하게 Gmail 계정 하나로 기능을 구현했다는 점에서 만족도가 높습니다.