이메일은 사용자 온보딩 및 알림부터 비밀번호 재설정 및 마케팅 캠페인에 이르기까지 모든 것에 사용되는 최신 웹 애플리케이션의 핵심 구성 요소입니다. 그러나 안정적인 이메일 전송 인프라를 구축하고 관리하는 것은 복잡하고 시간이 많이 소요될 수 있습니다. 바로 이 지점에서 Resend와 같은 이메일 API 서비스가 등장합니다.
Resend는 트랜잭션 및 마케팅 이메일 전송 프로세스를 간소화하도록 설계된 개발자 친화적인 플랫폼을 제공합니다. 강력한 API, 상세한 분석 및 뛰어난 전달률을 제공하여 개발자가 이메일 인프라에 대해 걱정하는 대신 애플리케이션 구축에 집중할 수 있도록 합니다.
이 종합 가이드는 Resend API를 시작하기 위해 알아야 할 모든 것을 핵심 개념 및 가격 이해부터 다양한 인기 프레임워크 및 플랫폼과의 통합까지 안내합니다.
개발자 팀이 최대한의 생산성으로 함께 작업할 수 있는 통합 올인원 플랫폼을 원하십니까?
Apidog는 모든 요구 사항을 충족하며 Postman을 훨씬 저렴한 가격으로 대체합니다!
Resend란 무엇인가요?

Resend는 개발자를 위해 구축된 이메일 API 플랫폼입니다. 기존 이메일 서비스 제공업체(ESP)에 비해 우수한 개발자 경험을 제공하는 것을 목표로 합니다. 주요 기능은 다음과 같습니다.
- 최신 API: 모든 애플리케이션에 쉽게 통합할 수 있는 깔끔한 RESTful API.
- 높은 전달률: 사용자 지정 도메인 확인(DKIM, SPF, DMARC), 전용 IP(추가 기능으로 제공), 자동 차단 목록 관리와 같은 기능을 통해 이메일이 스팸 폴더가 아닌 받은 편지함에 도달하도록 보장하는 데 중점을 둡니다.
- 프레임워크 통합: Node.js, Next.js, Python, Ruby, PHP, Go 등 인기 있는 프레임워크에 대한 공식 SDK 및 가이드를 제공합니다.
- React Email 통합: React Email과 원활하게 통합되어 React 구성 요소를 사용하여 아름답고 반응형 이메일 템플릿을 구축할 수 있습니다.
- 웹훅: 전달, 바운스, 열림, 클릭, 스팸 불만 등 이메일 이벤트에 대한 실시간 알림을 제공합니다.
- 상세 분석: 사용자 친화적인 대시보드를 통해 이메일 성능에 대한 통찰력을 제공합니다.
- 개발자 중심: 개발자를 염두에 두고 설계되었으며, 명확한 문서, 유용한 SDK, 테스트 이메일과 같은 도구를 제공하여 개발 및 디버깅을 더 쉽게 만듭니다.
Resend는 SendGrid, Mailgun 또는 AWS SES와 같은 기존 업체에 비해 사용 편의성, 안정성, 최신 웹 개발 워크플로우와의 통합에 중점을 둔 보다 현대적이고 개발자 중심적인 대안으로 자리매김하고 있습니다.
Resend 가격은 어떻게 되나요?

Resend는 월별 전송 이메일 수에 따라 계층형 가격 구조를 제공하며, 트랜잭션 및 마케팅 이메일에 대한 별도의 고려 사항이 있습니다(가격 페이지는 주로 트랜잭션 플랜을 자세히 설명하지만).
다음은 트랜잭션 이메일 플랜에 대한 분석입니다(작성 시점 기준).
무료 플랜:
- 비용: 월 $0
- 이메일: 월 최대 3,000개 이메일
- 일일 제한: 하루 100개 이메일
- 도메인: 사용자 지정 도메인 1개
- 데이터 보존: 1일
- 지원: 티켓 지원
- 주요 기능: RESTful API, SMTP 릴레이, SDK, 열림/링크 추적, React Email 통합, 자동 차단 목록, DKIM/SPF/DMARC 인증, 웹훅 엔드포인트 1개.
- 제한 사항: SSO(Single Sign-On) 없음, 전용 IP 없음, 제한된 도메인 및 일일 전송.
Pro 플랜:
- 비용: 월 $20
- 이메일: 월 최대 50,000개 이메일 (초과 시 추가 요금 적용)
- 일일 제한: 일일 제한 없음
- 도메인: 사용자 지정 도메인 10개
- 데이터 보존: 3일
- 지원: 티켓 지원
- 주요 기능: 모든 무료 플랜 기능 + SSO, 웹훅 엔드포인트 10개.
- 제한 사항: 전용 IP 미포함 (추후 추가 기능으로 사용 가능), Slack 지원 없음.
Scale 플랜:
- 비용: 월 $90
- 이메일: 월 최대 100,000개 이메일 (초과 시 추가 요금)
- 일일 제한: 일일 제한 없음
- 도메인: 사용자 지정 도메인 1,000개
- 데이터 보존: 7일
- 지원: Slack 및 티켓 지원
- 주요 기능: 모든 Pro 플랜 기능 + 전용 IP 추가 기능으로 사용 가능 (월 $30, 하루 500개 이상 이메일 필요).
- 제한 사항: 전용 IP는 추가 기능입니다.
Enterprise 플랜:
- 비용: 맞춤형 가격
- 이메일: 맞춤형 볼륨
- 일일 제한: 일일 제한 없음
- 도메인: 유연
- 데이터 보존: 유연
- 지원: 우선 지원, 긴급 응답 SLA, 전달 전문 지식
- 주요 기능: 모든 Scale 플랜 기능 + 전용 IP 웜업, 전달 통찰력, 유연한 웹훅, SSO 포함.
주요 고려 사항:
- 초과 사용: 플랜에서 허용하는 것보다 많은 이메일을 전송하면 이메일당 추가 비용이 발생합니다.
- 전용 IP: 공유 IP 평판에 대해 우려하는 대용량 발신자에게 권장되는 Scale 및 Enterprise 플랜의 추가 기능으로 추가 월별 요금이 부과됩니다.
- 데이터 보존: Resend가 전송된 이메일에 대한 로그 및 세부 정보를 저장하는 기간은 플랜에 따라 다릅니다.
- 마케팅 이메일: 가격 페이지에 마케팅 이메일 토글이 있어 다른 플랜 또는 가격 구조가 적용될 수 있음을 시사하지만, 스크랩된 콘텐츠에서는 트랜잭션 이메일에 중점을 두었습니다. 최신 마케팅 이메일 가격은 Resend 웹사이트를 확인하십시오.
무료 플랜은 소규모 프로젝트 또는 테스트 목적으로 충분히 관대합니다. Pro 및 Scale 플랜은 이메일 볼륨 및 기능 요구 사항이 증가하는 성장하는 애플리케이션에 적합합니다. Enterprise 플랜은 대규모 운영을 위한 맞춤형 솔루션을 제공합니다.
Resend 시작하기
이메일을 보내려면 Resend 계정을 설정하고 전송 도메인을 구성해야 합니다.
1. 가입 및 API 키 생성
- Resend 웹사이트로 이동하여 계정에 가입합니다.
- Resend 대시보드(https://resend.com/api-keys)의 API 키 섹션으로 이동합니다.
- API 키 생성을 클릭합니다.
- API 키에 설명적인 이름(예:
my-app-key
)을 지정합니다. - 권한 수준을 선택합니다.
- 전체 액세스: 모든 API 작업(리소스 생성, 삭제, 가져오기, 업데이트)을 허용합니다. 주의해서 사용하십시오. 일반적으로 백엔드 관리 작업에만 필요합니다.
- 전송 액세스: 이메일 전송만 허용합니다. 이는 애플리케이션의 전송 로직에 권장되는 권한입니다. 선택적으로 이 키를 특정 확인된 도메인에서만 전송하도록 제한할 수 있습니다.
- 생성을 클릭합니다.
- 중요: Resend는 API 키를 한 번만 보여줍니다. 즉시 복사하여 안전하게 저장하십시오(예: 환경 변수, 비밀 관리자). 코드베이스에 직접 커밋하지 마십시오.
2. 도메인 확인
전문적으로 보이고 스팸 필터를 피하는 이메일을 보내려면 소유한 도메인을 반드시 확인해야 합니다. 확인되지 않은 도메인이나 onboarding@resend.dev
와 같은 기본 주소에서 보내는 것은 초기 테스트에만 적합합니다.
- Resend 대시보드(https://resend.com/domains)의 도메인 섹션으로 이동합니다.
- 도메인 추가를 클릭하고 이메일을 보내려는 도메인(예:
yourcompany.com
)을 입력합니다. - 목록에서 DNS 제공업체를 선택하거나 '기타'를 선택합니다.
- Resend는 도메인의 DNS 설정에 추가해야 하는 DNS 레코드(일반적으로 SPF용 MX, TXT, DKIM용 CNAME/TXT)를 제공합니다.
- SPF(Sender Policy Framework): 도메인을 대신하여 이메일을 보낼 수 있는 메일 서버를 지정합니다.
- DKIM(DomainKeys Identified Mail): 이메일에 디지털 서명을 추가하여 수신 서버가 이메일이 변조되지 않았으며 승인된 서버에서 시작되었음을 확인할 수 있도록 합니다.
- 도메인 등록기관 또는 DNS 제공업체(예: GoDaddy, Cloudflare, Namecheap)에 로그인하여 Resend가 제공한 레코드를 추가합니다.
- DNS 변경 사항이 전파되는 데 시간이 걸릴 수 있습니다(몇 분에서 몇 시간, 때로는 최대 48시간).
- 레코드가 추가되면 Resend 도메인 대시보드로 돌아가 도메인 옆에 있는 확인 버튼을 클릭합니다. Resend는 DNS 레코드가 올바르게 설정되었는지 확인합니다. 확인되면 상태가 업데이트되고 해당 도메인과 연결된 주소(예:
support@yourcompany.com
,noreply@yourcompany.com
)에서 이메일을 보낼 수 있습니다.
3. 테스트 이메일 전송
개발 중에 도메인의 평판에 영향을 주거나 실수로 실제 사용자에게 전송하지 않고 이메일 전송을 테스트하는 것이 중요합니다. Resend는 다양한 시나리오를 테스트하기 위한 특별한 이메일 주소를 제공합니다.
- 전달 테스트:
delivered@resend.dev
로 보냅니다. 이는 성공적으로 전달된 이메일을 시뮬레이션합니다. - 바운스 테스트:
bounced@resend.dev
로 보냅니다. 이는 하드 바운스(예: 수신자 주소가 존재하지 않음)를 시뮬레이션하여 바운스 이벤트를 트리거합니다. - 스팸으로 표시 테스트:
complained@resend.dev
로 보냅니다. 이는 수신자가 이메일을 스팸으로 표시하는 것을 시뮬레이션하여 불만 이벤트를 트리거합니다.
이러한 테스트 주소를 사용하면 통합을 확인하고 바운스 및 불만 이벤트에 대한 웹훅 핸들러를 안전하게 테스트할 수 있습니다.
프레임워크와 Resend 통합
Resend는 다양한 언어 및 프레임워크에 대한 공식 SDK 및 간단한 통합 방법을 제공합니다. 제공된 문서를 기반으로 몇 가지 인기 있는 예제를 다룰 것입니다. 핵심 개념은 일반적으로 다음을 포함합니다.
- Resend SDK 설치(사용 가능한 경우) 또는 표준 HTTP 요청 사용.
- API 키(환경 변수에서 안전하게 로드)를 사용하여 Resend 클라이언트 초기화.
from
,to
,subject
,html
또는react
와 같은 매개변수로emails.send
메서드(또는 동등한 메서드) 호출.
Next.js로 전송
Next.js는 인기 있는 React 프레임워크입니다. Resend는 특히 React Email과 잘 통합됩니다.
1. 설치:
npm install resend
# or
yarn add resend
# or
pnpm add resend
2. 이메일 템플릿 생성(선택 사항이지만 권장):React Email을 사용하거나 이메일 본문을 위한 간단한 React 구성 요소를 생성합니다.
// components/email-template.tsx
import * as React from 'react';
interface EmailTemplateProps {
firstName: string;
}
export const EmailTemplate: React.FC<Readonly<EmailTemplateProps>> = ({
firstName,
}) => (
<div>
<h1>Welcome, {firstName}!</h1>
</div>
);
3. API 라우트 생성:이메일을 보내는 API 라우트 핸들러를 생성합니다.
- App Router:
app/api/send/route.ts
- Pages Router:
pages/api/send.ts
// app/api/send/route.ts (App Router 예제)
import { EmailTemplate } from '../../../components/email-template'; // 필요한 경우 경로 조정
import { Resend } from 'resend';
// .env.local에 RESEND_API_KEY가 설정되어 있는지 확인
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST() {
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>', // 확인된 도메인 사용
to: ['delivered@resend.dev'], // 수신자 또는 테스트 주소로 교체
subject: 'Hello from Resend and Next.js!',
react: EmailTemplate({ firstName: 'Test' }), // 템플릿에 props 전달
// 또는 `html` 사용:
// html: '<strong>It works!</strong>'
});
if (error) {
return Response.json({ error }, { status: 400 });
}
return Response.json(data);
} catch (error) {
return Response.json({ error }, { status: 500 });
}
}
// pages/api/send.ts (Pages Router 예제 - import/response 조정)
// import type { NextApiRequest, NextApiResponse } from 'next';
// import { EmailTemplate } from '../../components/EmailTemplate';
// import { Resend } from 'resend';
//
// const resend = new Resend(process.env.RESEND_API_KEY);
//
// export default async (req: NextApiRequest, res: NextApiResponse) => {
// try { // 더 나은 오류 처리를 위해 try...catch 추가
// const { data, error } = await resend.emails.send({
// from: 'Your Name <you@yourverifieddomain.com>',
// to: ['delivered@resend.dev'],
// subject: 'Hello world',
// react: EmailTemplate({ firstName: 'John' }),
// });
//
// if (error) {
// return res.status(400).json(error);
// }
//
// res.status(200).json(data);
// } catch (e) {
// res.status(500).json({ error: 'Internal Server Error' });
// }
// };
4. 트리거:프런트엔드에서 fetch
또는 axios
와 같은 라이브러리를 사용하여 이 API 엔드포인트를 호출합니다(예: 양식 제출 후). 자리 표시자 값을 실제 확인된 도메인 및 수신자 목록으로 바꾸는 것을 잊지 마십시오.
Astro로 전송
Astro는 서버 측 렌더링(SSR)도 지원하는 최신 정적 사이트 빌더입니다.
1. Resend 설치:
npm install resend
# or
yarn add resend
# or
pnpm add resend
2. SSR 어댑터 설치:Astro는 필요에 따라 서버 측 코드를 실행하기 위해 SSR 어댑터가 필요합니다. 배포 대상에 적합한 어댑터를 설치합니다(예: @astrojs/node
, @astrojs/vercel
, @astrojs/cloudflare
).
npx astro add node # Node.js 어댑터 예제
astro.config.mjs
에서 어댑터의 설정 지침을 따릅니다.
3. API 키 추가:RESEND_API_KEY
를 .env
파일에 저장합니다.
4. Astro 액션 생성:Astro 액션(작성 시점 기준 실험적 기능, 현재 상태는 Astro 문서 확인) 또는 표준 API 엔드포인트를 사용합니다.
// src/actions/index.ts (Astro 액션 사용)
import { ActionError, defineAction, z } from 'astro:actions';
import { Resend } from 'resend';
// import.meta.env를 통해 RESEND_API_KEY를 사용할 수 있는지 확인
const resend = new Resend(import.meta.env.RESEND_API_KEY);
export const server = {
send: defineAction({
// 예제: 필요한 경우 입력 유효성 검사 정의
// input: z.object({ email: z.string().email() }),
handler: async (/* { email } - 입력을 사용하는 경우 */) => {
try { // try...catch 추가
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // 수신자로 교체
subject: 'Hello from Resend and Astro!',
html: '<strong>Astro works!</strong>',
// Astro에서 React를 설정했다면 React 템플릿을 사용할 수도 있습니다.
// react: <YourAstroCompatibleReactEmail firstName="Astro" />
});
if (error) {
console.error("Resend Error:", error); // 오류 로깅
// ActionError를 발생시키면 Astro가 오류를 정상적으로 처리하는 데 도움이 됩니다.
throw new ActionError({
code: 'BAD_REQUEST', // 또는 오류에 따라 더 구체적으로 지정
message: error.message || 'Failed to send email',
});
}
return data; // 성공 데이터 반환
} catch (e) {
console.error("Handler Error:", e);
// 다시 발생시키거나 새 ActionError 발생
throw new ActionError({
code: 'INTERNAL_SERVER_ERROR',
message: 'An unexpected error occurred.',
});
}
},
}),
};
// 대안: API 엔드포인트 (예: src/pages/api/send.ts)
// import type { APIRoute } from 'astro';
// import { Resend } from 'resend';
//
// const resend = new Resend(import.meta.env.RESEND_API_KEY);
//
// export const POST: APIRoute = async ({ request }) => {
// // const body = await request.json(); // 데이터가 요청 본문에서 오는 경우
// try {
// const { data, error } = await resend.emails.send({ /* ... 이메일 매개변수 ... */ });
// if (error) {
// return new Response(JSON.stringify(error), { status: 400 });
// }
// return new Response(JSON.stringify(data), { status: 200 });
// } catch (e) {
// return new Response(JSON.stringify({ message: "Server Error"}), { status: 500 });
// }
// }
5. 트리거:Astro 구성 요소 또는 페이지에서 액션 또는 엔드포인트를 호출합니다. 일반적으로 양식 제출 핸들러 내에서 호출합니다.
Bun으로 전송
Bun은 내장 번들러, 트랜스파일러, 태스크 러너 및 npm 클라이언트를 갖춘 빠른 JavaScript 런타임입니다.
1. 설치:
bun install resend
2. 이메일 템플릿 생성(선택 사항):Next.js와 유사하게 React 이메일 템플릿용 .tsx
파일을 생성할 수 있습니다.
// email-template.tsx
import * as React from 'react';
interface EmailTemplateProps {
firstName: string;
}
export const EmailTemplate: React.FC<Readonly<EmailTemplateProps>> = ({
firstName,
}) => (
<div>
<h1>Welcome, {firstName}!</h1>
</div>
);
3. Bun 서버 스크립트 생성:Bun을 사용하여 간단한 HTTP 서버를 실행하는 스크립트(예: index.tsx
)를 생성합니다.
// index.tsx
import { Resend } from 'resend';
import { EmailTemplate } from './email-template'; // 동일 디렉토리에 있다고 가정
// 환경 변수에서 API 키 로드
const resendApiKey = process.env.RESEND_API_KEY;
if (!resendApiKey) {
console.error("Error: RESEND_API_KEY environment variable not set.");
process.exit(1); // 키가 없으면 종료
}
const resend = new Resend(resendApiKey);
const server = Bun.serve({
port: 3000,
async fetch(req) { // 'req' 인자 추가
// 선택 사항: 요청 메서드, 경로 등 확인
// if (new URL(req.url).pathname !== '/send') {
// return new Response("Not Found", { status: 404 });
// }
// if (req.method !== 'POST') {
// return new Response("Method Not Allowed", { status: 405 });
// }
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'],
subject: 'Hello from Resend and Bun!',
react: EmailTemplate({ firstName: 'Bun User' }),
// 또는 html 사용: '<strong>Bun works!</strong>'
});
if (error) {
console.error("Resend Error:", error);
// 적절한 JSON 오류 응답 반환
return new Response(JSON.stringify({ error: error.message || 'Failed to send email' }), {
status: 500, // 또는 오류 유형에 따라 400
headers: { 'Content-Type': 'application/json' },
});
}
// 성공 응답 반환
return new Response(JSON.stringify(data), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
} catch (e) {
console.error("Server Error:", e);
return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
},
error(error) { // 서버 자체에 대한 기본 오류 핸들러 추가
return new Response(`<pre>${error}\\\\\\\\n${error.stack}</pre>`, {
headers: { "Content-Type": "text/html" },
});
},
});
console.log(`Listening on <http://localhost>:${server.port} ...`);
4. 실행:RESEND_API_KEY=your_api_key bun run index.tsx
를 사용하여 서버를 시작합니다. http://localhost:3000
에 액세스하거나 정의한 특정 라우트/메서드를 트리거하면 이메일이 전송됩니다.
Nuxt로 전송
Nuxt는 인기 있는 Vue.js 프레임워크입니다.
1. 설치:
npm install resend
# or
yarn add resend
# or
pnpm add resend
2. 서버 라우트 생성:Nuxt는 백엔드 로직에 server/
디렉토리를 사용합니다. server/api/send.post.ts
와 같은 파일을 생성합니다(.post
는 POST 요청을 처리함을 나타냅니다).
// server/api/send.post.ts
import { Resend } from 'resend';
// API 키를 안전하게 액세스합니다 (예: nuxt.config.ts의 runtimeConfig를 통해)
// 참조: <https://nuxt.com/docs/guide/going-further/runtime-config>
const config = useRuntimeConfig();
const resend = new Resend(config.resendApiKey); // 키가 런타임 구성에 설정되어 있다고 가정
export default defineEventHandler(async (event) => {
// 선택 사항: 데이터가 요청에서 오는 경우 본문 읽기
// const body = await readBody(event);
try {
const data = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'],
subject: 'Hello from Resend and Nuxt!',
html: '<strong>Nuxt works!</strong>',
// Vue 이메일 템플릿을 통합할 수 있습니다 (예: vue-email 사용)
// 참조: <https://github.com/Dave136/vue-email>
});
// Nuxt 3는 데이터를 JSON으로 반환하는 것을 자동으로 처리합니다.
return data;
} catch (error: any) { // 가능한 경우 특정 오류 유형 포착
console.error("Resend Error:", error);
// Nuxt가 처리할 수 있는 오류를 발생시켜 상태 코드를 설정합니다.
throw createError({
statusCode: 400, // 또는 500
statusMessage: 'Failed to send email',
data: error // 선택적으로 오류 세부 정보 포함
});
}
});
// nuxt.config.ts에서 runtimeConfig 정의:
// export default defineNuxtConfig({
// runtimeConfig: {
// resendApiKey: process.env.NUXT_RESEND_API_KEY, // 서버 측 전용
// public: {
// // 클라이언트 측에서 액세스 가능한 공개 키
// }
// }
// })
// 그리고 .env에 NUXT_RESEND_API_KEY 설정
3. 트리거:Nuxt 페이지 또는 구성 요소에서 $fetch
또는 useFetch
를 사용하여 /api/send
엔드포인트(POST 메서드 사용)를 호출합니다.
Vercel Functions로 전송
Vercel Functions는 Next.js와 원활하게 통합되거나 독립적으로 사용할 수 있는 서버리스 함수입니다. 위의 Next.js 예제는 이미 Vercel 환경 내에서 사용법을 보여줍니다. Next.js 없이 Vercel Functions를 사용하는 경우(예: Vercel에 배포된 정적 사이트 생성기 또는 다른 프레임워크 사용) 접근 방식은 유사합니다.
1. 함수 생성:프로젝트의 api/
디렉토리에 파일(예: api/send.ts
)을 생성합니다.
// api/send.ts (표준 Vercel Function 예제)
import type { VercelRequest, VercelResponse } from '@vercel/node';
import { Resend } from 'resend'; // resend를 설치해야 할 수 있습니다.
// RESEND_API_KEY가 Vercel 환경 변수로 설정되어 있는지 확인
const resendApiKey = process.env.RESEND_API_KEY;
if (!resendApiKey) {
console.error("RESEND_API_KEY is not set");
// 프로덕션에서 키가 누락된 경우 진행하지 마십시오.
}
const resend = new Resend(resendApiKey);
export default async function handler(
request: VercelRequest,
response: VercelResponse,
) {
// 권장: POST 메서드 확인
if (request.method !== 'POST') {
return response.status(405).json({ message: 'Method Not Allowed' });
}
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'],
subject: 'Hello from Resend & Vercel Functions!',
html: '<strong>It works on Vercel!</strong>',
// 함수가 React를 번들링하는 경우 React 템플릿을 사용할 수 있습니다.
});
if (error) {
console.error('Resend Error:', error);
return response.status(400).json(error);
}
return response.status(200).json(data);
} catch (e) {
console.error('Handler Error:', e);
return response.status(500).json({ message: 'Internal Server Error' });
}
}
2. 환경 변수 구성:Vercel 프로젝트 설정에서 RESEND_API_KEY
를 환경 변수로 추가합니다.
3. 배포:Vercel CLI(vercel
) 또는 Git 통합을 사용하여 프로젝트를 배포합니다.
4. 트리거:배포된 함수 URL(예: https://your-project.vercel.app/api/send
)에 POST 요청을 보냅니다.
Supabase Edge Functions로 전송
Supabase Edge Functions는 Deno Deploy에서 사용자 근처에서 실행됩니다. Deno 및 fetch
와 같은 표준 웹 API를 사용합니다. Resend는 아직 공식 Deno SDK가 없으므로 fetch
를 직접 사용합니다.
1. Supabase 함수 생성:Supabase CLI를 사용합니다.
supabase functions new resend-email-sender # 이름 선택
cd supabase/functions/resend-email-sender
2. 핸들러 편집:생성된 index.ts
파일을 수정합니다.
// supabase/functions/resend-email-sender/index.ts
import { serve } from "<https://deno.land/std@0.177.0/http/server.ts>"; // 적절한 std 버전 사용
// Supabase Edge Function 환경 변수를 통해 API 키를 안전하게 액세스
const RESEND_API_KEY = Deno.env.get('RESEND_API_KEY');
// 기본 요청 핸들러
const handler = async (_request: Request): Promise<Response> => {
if (!RESEND_API_KEY) {
console.error("RESEND_API_KEY environment variable not set.");
return new Response(JSON.stringify({ error: "Server configuration error" }), {
status: 500, headers: { 'Content-Type': 'application/json' }
});
}
// 선택 사항: 필요한 경우 _request 메서드, 헤더 또는 본문 확인
try {
const res = await fetch('<https://api.resend.com/emails>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${RESEND_API_KEY}` // 여기에 키 사용
},
body: JSON.stringify({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // 수신자 교체
subject: 'Hello from Resend & Supabase Edge!',
html: '<strong>It works! Edge Functions are cool.</strong>',
// 참고: React 구성 요소를 직접 보내는 것은 여기에서 불가능합니다.
// 엣지 함수에서 빌드 단계를 거쳐 HTML로 렌더링하지 않으면.
// 미리 렌더링된 HTML 또는 일반 텍스트를 보냅니다.
})
});
// Resend API의 잠재적인 비-OK 응답 처리
if (!res.ok) {
const errorData = await res.json().catch(() => ({ message: 'Failed to parse Resend error response' }));
console.error("Resend API Error:", res.status, errorData);
return new Response(JSON.stringify({ error: 'Failed to send email via Resend', details: errorData }), {
status: res.status, // Resend의 상태 코드 전달
headers: { 'Content-Type': 'application/json' },
});
}
// 성공 응답 구문 분석
const data = await res.json();
// 성공 응답 반환
return new Response(JSON.stringify(data), {
status: 200,
headers: { 'Content-Type': 'application/json' },
});
} catch (error) {
console.error("Edge Function Error:", error);
return new Response(JSON.stringify({ error: 'Internal Server Error in Edge Function' }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
};
// 서버 시작
serve(handler);
console.log("Supabase Edge Function 'resend-email-sender' is running...");
3. 환경 변수 설정:supabase secrets set RESEND_API_KEY your_actual_key
를 사용하여 로컬에서 RESEND_API_KEY
를 설정하고 배포를 위해 Supabase 프로젝트의 함수 설정에서도 설정합니다.
4. 배포 및 호출:
# 로컬 테스트 (선택 사항)
supabase functions serve resend-email-sender --no-verify-jwt
# 배포
supabase functions deploy resend-email-sender --no-verify-jwt
프런트엔드 또는 다른 백엔드 서비스의 Supabase 클라이언트 라이브러리 호출을 통해 일반적으로 URL을 사용하여 함수를 호출합니다.
Cloudflare Workers로 전송
Cloudflare Workers는 Cloudflare의 엣지 네트워크에서 실행되는 서버리스 함수입니다. Resend의 Node.js SDK는 적절한 번들링을 통해 Workers 환경에서 작동하는 경우가 많습니다.
1. Worker 프로젝트 설정:npm create cloudflare
를 사용하여 Worker 프로젝트를 초기화합니다. 모듈 및 번들링(예: Webpack 또는 esbuild와 함께 Wrangler 사용)이 설정되어 있는지 확인합니다.
2. Resend 설치:
npm install resend
# or yarn/pnpm
3. 이메일 템플릿 생성(선택 사항):React를 사용하는 경우 템플릿 파일(.tsx
)을 생성합니다.
4. Worker 스크립트 편집:기본 Worker 파일(예: src/index.ts
또는 React를 사용하는 경우 src/index.tsx
)을 수정합니다.
// src/index.tsx (React 사용 예제)
import { Resend } from 'resend';
// React 템플릿 구성 요소가 있다고 가정
import { EmailTemplate } from './emails/email-template'; // 경로 조정
// 타입 안전성을 위해 예상되는 환경 변수 정의
export interface Env {
RESEND_API_KEY: string;
}
export default {
async fetch(
request: Request,
env: Env, // 'env'를 통해 환경 변수 액세스
ctx: ExecutionContext
): Promise<Response> {
// 환경 변수의 API 키를 사용하여 Resend 인스턴스화
const resend = new Resend(env.RESEND_API_KEY);
// 선택 사항: 요청 메서드, URL 경로 등 확인
// 예제: 특정 경로에 대한 POST 요청만 허용
// const url = new URL(request.url);
// if (url.pathname !== '/send-email' || request.method !== 'POST') {
// return new Response('Not Found or Method Not Allowed', { status: 404 });
// }
try {
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // 수신자 교체
subject: 'Hello from Resend & Cloudflare Workers!',
// 해당되는 경우 React 구성 요소 사용
react: <EmailTemplate firstName="Worker User" />,
// 또는 HTML 사용
// html: '<strong>It works from the Edge!</strong>',
});
if (error) {
console.error("Resend Error:", JSON.stringify(error));
return Response.json({ error: 'Failed to send email via Resend' }, { status: 400 });
}
return Response.json(data);
} catch (e) {
console.error("Worker Error:", e);
// 가능한 경우 오류 스택 로깅
if (e instanceof Error) {
console.error(e.stack);
}
return Response.json({ error: 'Internal Server Error in Worker' }, { status: 500 });
}
},
} // satisfies ExportedHandler<Env>; // 선택 사항: 더 나은 타입 검사를 위해 satisfies 사용
5. 환경 변수 구성:Wrangler를 사용하여 Worker에 대한 비밀로 RESEND_API_KEY
를 설정합니다.
npx wrangler secret put RESEND_API_KEY
# 프롬프트가 표시되면 키 붙여넣기
6. 배포:
npx wrangler deploy # 또는 로컬 테스트를 위한 'wrangler dev'
할당된 URL을 사용하여 Worker를 호출합니다.
AWS Lambda로 전송
AWS Lambda 문서 페이지 스크랩 시간이 초과되어 이 섹션은 일반 원칙을 기반으로 합니다.
Resend를 사용하여 AWS Lambda에서 이메일을 보내는 것은 유사한 패턴을 따릅니다.
1. Lambda 함수 설정:선호하는 런타임(Node.js는 일반적이며 Resend SDK와 잘 작동함)을 사용하여 Lambda 함수를 생성합니다. Lambda에 인터넷 액세스 권한이 있는지 확인합니다(예: NAT 게이트웨이가 있는 VPC 내에 구성되거나 이그레스를 허용하는 기본 VPC 설정 사용).
2. Resend SDK 설치:함수의 배포 패키지에 resend
를 포함합니다(예: package.json
에 포함하고 압축하기 전에 npm install
실행 또는 Lambda 레이어 사용).
3. API 키 안전하게 저장:AWS Secrets Manager 또는 AWS Systems Manager Parameter Store를 사용하여 RESEND_API_KEY
를 저장합니다. Lambda 함수의 실행 역할에 이 비밀을 읽을 수 있는 권한을 부여합니다. Lambda 함수 코드에 키를 하드 코딩하지 마십시오.
4. Lambda 핸들러 코드 작성(Node.js 예제):
// lambda_function.js (Node.js 예제)
const { Resend } = require('resend');
// AWS SDK 클라이언트 (Secrets Manager/Parameter Store에서 키를 가져오는 경우)
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); // V3 SDK
let resend; // 잠재적인 재사용을 위해 핸들러 외부에서 초기화
async function getApiKey() {
// 비밀 이름/ARN 및 지역으로 교체
const secretName = "your/resend/api/key/secret";
const client = new SecretsManagerClient({ region: "your-region" });
try {
const command = new GetSecretValueCommand({ SecretId: secretName });
const response = await client.send(command);
if ('SecretString' in response) {
// 비밀이 키를 직접 저장하거나 {"apiKey": "re_..."}와 같은 JSON으로 저장한다고 가정
const secret = JSON.parse(response.SecretString);
return secret.apiKey; // 저장 방식에 따라 구문 분석 조정
}
throw new Error("API Key not found in secret string");
} catch (error) {
console.error("Error retrieving API Key from Secrets Manager:", error);
throw error; // 실패를 알리기 위해 다시 발생
}
}
exports.handler = async (event, context) => {
// 선택 사항: 필요한 경우 이벤트 데이터 구문 분석 (예: API Gateway 트리거에서)
// const body = JSON.parse(event.body || '{}');
// const recipient = body.to;
try {
if (!resend) {
const apiKey = await getApiKey();
if (!apiKey) {
return { statusCode: 500, body: JSON.stringify({ message: "API Key configuration error" }) };
}
resend = new Resend(apiKey);
}
const { data, error } = await resend.emails.send({
from: 'Your Name <you@yourverifieddomain.com>',
to: ['delivered@resend.dev'], // 이벤트 또는 고정 값에서 수신자 사용
subject: 'Hello from Resend & AWS Lambda!',
html: '<strong>Lambda email sent successfully!</strong>',
// React는 Lambda 내에서 빌드 단계 또는 서버 측 렌더링 설정이 필요합니다.
});
if (error) {
console.error('Resend Error:', error);
return {
statusCode: 400, // 또는 오류에 따라 적절한 상태
body: JSON.stringify(error),
};
}
return {
statusCode: 200,
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
};
} catch (e) {
console.error('Lambda Handler Error:', e);
return {
statusCode: 500,
body: JSON.stringify({ message: 'Internal Server Error' }),
};
}
};
5. 트리거 구성:Lambda 함수에 대한 트리거를 설정합니다(예: HTTP 요청용 API Gateway, SQS 대기열, EventBridge 이벤트).
6. 배포:Lambda 함수와 해당 종속성을 배포합니다.
Resend와 함께 React Email 사용
Resend의 주요 장점은 React Email과의 원활한 통합입니다. React Email을 사용하면 표준 React 구성 요소 및 구문을 사용하여 아름답고 반응형 이메일 템플릿을 구축할 수 있습니다.
장점:
- 구성 요소 기반: 재사용 가능한 구성 요소를 사용하여 웹 앱처럼 이메일 구조화.
- 타입 안전성: TypeScript를 사용하여 더 강력한 템플릿 생성.
- 로컬 개발: 브라우저에서 이메일 로컬 개발 및 미리 보기.
- 복잡한 템플릿 언어 없음: 독점적이거나 복잡한 이메일 템플릿 구문 사용 방지.
설정(React Email 문서 기반 - 약간 다를 수 있음):
설치: 프로젝트에 react-email
및 핵심 구성 요소를 추가합니다. Resend를 통해 보내는 경우 resend
도 필요할 수 있습니다.
npm install react-email @react-email/components resend
# or yarn/pnpm
이메일 템플릿 생성: 이메일용 .tsx
파일을 생성합니다. 일반적으로 전용 emails/
디렉토리에 생성합니다.
// emails/welcome.tsx
import { Html, Button, Text } from '@react-email/components';
import * as React from 'react';
interface WelcomeEmailProps {
name: string;
signupLink: string;
}
export const WelcomeEmail: React.FC<Readonly<WelcomeEmailProps>> = ({ name, signupLink }) => (
<Html>
<Text>Hello {name},</Text>
<Text>Welcome aboard! Click the button below to get started.</Text>
<Button href={signupLink}>Complete Signup</Button>
</Html>
);
export default WelcomeEmail; // 기본 내보내기가 종종 유용합니다.
전송 로직과 통합: 백엔드 API 라우트 또는 서버리스 함수에서 이메일 구성 요소를 가져와 Resend의 react
옵션에 전달합니다.
// Next.js API 라우트 예제 (app/api/send-welcome/route.ts)
import { Resend } from 'resend';
import WelcomeEmail from '../../../emails/welcome'; // 경로 조정
const resend = new Resend(process.env.RESEND_API_KEY);
export async function POST(request: Request) {
try {
const body = await request.json(); // 본문에 { email: '...', name: '...' }가 있다고 가정
const signupUrl = "<https://yoursite.com/signup-step2>"; // 예제 URL
const { data, error } = await resend.emails.send({
from: 'Your App <welcome@yourverifieddomain.com>',
to: [body.email],
subject: 'Welcome to Our Platform!',
// React 구성 요소 직접 전달
react: WelcomeEmail({ name: body.name, signupLink: signupUrl }),
});
if (error) {
return Response.json({ error }, { status: 400 });
}
return Response.json(data);
} catch (error) {
return Response.json({ error }, { status: 500 });
}
}
Resend(및 독립적으로 사용되는 경우 React Email의 빌드 프로세스)는 백그라운드에서 React 구성 요소를 이메일 안전 HTML로 렌더링하는 것을 처리합니다. 이를 통해 이메일 템플릿 생성 및 유지 관리에 대한 개발자 경험이 크게 향상됩니다.
결론
Resend는 이메일 전송을 위한 현대적이고 개발자 중심적인 솔루션을 제공합니다. 깔끔한 API, 뛰어난 프레임워크 통합(특히 React Email과의 통합), 전달률에 대한 집중, 테스트 이메일 및 웹훅과 같은 유용한 기능은 모든 규모의 애플리케이션에 매력적인 선택이 됩니다.
이 가이드에 설명된 단계(계정 설정, 도메인 확인, 프레임워크에 적합한 통합 방법 선택, React Email과 같은 도구 활용)를 따르면 프로젝트에 강력한 이메일 기능을 빠르고 안정적으로 통합할 수 있습니다. 항상 API 키를 안전하게 처리하고 Resend 대시보드 및 웹훅을 통해 전송 활동을 모니터링하여 최적의 전달률 및 사용자 경험을 보장하는 것을 잊지 마십시오.
개발자 팀이 최대한의 생산성으로 함께 작업할 수 있는 통합 올인원 플랫폼을 원하십니까?
Apidog는 모든 요구 사항을 충족하며 Postman을 훨씬 저렴한 가격으로 대체합니다!