현대 소프트웨어 응용 프로그램은 종종 사용자와 소통하기 위해 이메일 통신에 의존합니다. 예를 들어, 로그인 시도 중에 인증 코드를 보내거나, 마케팅 이메일이나 뉴스레터를 보낼 수 있습니다. 이는 이메일 통지가 일반적으로 사용자와의 가장 흔한 소통 수단임을 의미합니다.

이 자습서에서는 React Email를 사용하여 멋진 이메일 템플릿을 디자인하고, 강력한 이메일 API 플랫폼인 Resend을 사용하여 해당 템플릿을 보내는 방법을 배우게 됩니다.

필수 준비물

이 자습서를 최대한 활용하려면 React 또는 Next.js에 대한 기본적인 이해가 있어야 합니다.

또한 다음 도구들을 사용할 것입니다:

  • React Email: React 컴포넌트를 사용하여 아름답게 디자인된 이메일 템플릿을 생성할 수 있는 라이브러리.

  • Resend: 응용 프로그램에서 이메일을 보내기 위한 간단하고 강력한 API 플랫폼.

Next.js로 응용 프로그램 만들기 방법

이 섹션에서는 간단한 고객 지원 응용 프로그램을 만들 것입니다. 이 앱에는 사용자가 질문을 제출할 수 있는 양식이 포함되어 있으며, 이를 트리거로 지원 티켓이 생성되었음을 확인하는 이메일 통지가 발송됩니다.

시작하려면 먼저 사용자 인터페이스와 API 엔드포인트를 설정합니다.

다음 명령어를 실행하여 새로운 Next.js TypeScript 프로젝트를 생성합니다:

npx create-next-app react-email-resend

고객의 전체 이름, 이메일 주소, 티켓 주제 및 문제를 설명하는 자세한 메시지를 포함하여 고객의 세부 정보를 수집하는 양식을 렌더링하도록 app/page.tsx 파일을 업데이트합니다. 양식이 제출되면 입력 데이터가 handleSubmit 함수를 사용하여 콘솔에 기록됩니다.

"use client";
import support from "@/app/images/support.jpg";
import { useState } from "react";
import Image from "next/image";

export default function Page() {
    //👇🏻 입력 상태
    const [name, setName] = useState<string>("");
    const [email, setEmail] = useState<string>("");
    const [subject, setSubject] = useState<string>("");
    const [content, setContent] = useState<string>("");

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        //👇🏻 사용자의 입력 로그
        console.log({ name, email, subject, content });
    };
return ({/** -- UI 요소 -- */})
}

사용자의 전체 이름, 이메일 주소, 티켓 주제 및 문제를 설명하는 자세한 메시지를 수집하는 양식 UI 요소를 반환합니다.

    return (
        <main className='w-full min-h-screen flex items-center justify-between'>
                <form className='w-full' onSubmit={handleSubmit}>
                    <label htmlFor='name' className='opacity-60'>
                        Full Name
                    </label>
                    <input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='name'
                        required
                        value={name}
                        onChange={(e) => setName(e.target.value)}
                    />

                    <label htmlFor='email' className='opacity-60'>
                        Email Address
                    </label>
                    <input
                        type='email'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='email'
                        value={email}
                        onChange={(e) => setEmail(e.target.value)}
                        required
                    />

                    <label htmlFor='subject' className='opacity-60'>
                        Subject
                    </label>
                    <input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='subject'
                        value={subject}
                        onChange={(e) => setSubject(e.target.value)}
                        required
                    />

                    <label htmlFor='message' className='opacity-60'>
                        Message
                    </label>
                    <textarea
                        rows={7}
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='message'
                        required
                        value={content}
                        onChange={(e) => setContent(e.target.value)}
                    />

                    <button className='w-full bg-blue-500 py-4 px-3 rounded-md font-bold text-blue-50'>
                        SEND MESSAGE
                    </button>
                </form>
            </div>
        </main>
    );

다음은 컴포넌트에서 생성된 페이지입니다:

다음으로, 고객의 입력을 수락하는 API 엔드포인트(/api/route.ts)를 생성합니다.

cd app
mkdir api && cd api
touch route.ts

다음 코드를 api/route.ts 파일에 복사합니다. API 엔드포인트는 고객의 입력을 수신하면 콘솔에 기록합니다.

import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
    const { name, email, subject, content } = await req.json();
    //👇🏻 내용 로그
    console.log({ name, email, subject, content });
    return NextResponse.json({
        message: "Email sent successfully",
        data,
 });
}

고객의 데이터를 API 엔드포인트로 전송하고 JSON 응답을 반환하도록 handleSubmit 함수를 업데이트합니다:

const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    try {
        const response = await fetch("/api", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ name, email, subject, content }),
        });
        const data = await response.json();
        alert(data.message);
    } catch (error) {
        console.error(error);
        alert("An error occurred, please try again later");
    }
    setName("");
    setEmail("");
    setSubject("");
    setContent("");
};

축하합니다! 데이터 수집 및 제출을 설정했습니다. 다음 섹션에서는 React Email과 Resend를 사용하여 이메일 템플릿을 생성하고 전송하는 방법을 안내하겠습니다.

React Email을 사용한 이메일 템플릿 생성 방법

React Email을 사용하면 React와 TypeScript를 사용하여 이메일 구성 요소를 작성하고 전송할 수 있습니다. Gmail, Yahoo Mail, Outlook 및 Apple Mail을 포함한 여러 이메일 클라이언트를 지원합니다.

React Email은 React JSX/TSX 구성 요소를 사용하여 이메일 템플릿을 사용자 정의할 수 있는 여러 UI 구성 요소도 제공합니다.

아래의 코드 스니펫을 실행하여 React Email 패키지와 해당 구성 요소를 설치하세요:

npm install react-email -D -E
npm install @react-email/components -E

package.json 파일에 이 스크립트를 포함시킵니다. 이 스크립트는 React Email이 프로젝트 내의 이메일 템플릿 위치를 알 수 있게 합니다.

  "scripts": {
    "email": "email dev --dir src/emails"
  },

React Email의 기능 중 하나는 개발 중에 브라우저에서 이메일 템플릿을 미리보는 기능입니다. 수신자의 이메일에서 어떻게 나타날지 미리 확인할 수 있습니다.

그 다음, Next.js src 폴더 내에 emails 폴더를 만들고 TicketCreated.tsx 파일을 복사하여 다음 코드 스니펫을 파일에 붙여넣으세요:

import * as React from "react";
import {
    Body,
    Container,
    Head,
    Heading,
    Hr,
    Html,
    Link,
    Preview,
    Text,
    Tailwind,
} from "@react-email/components";

interface TicketCreatedProps {
    username: string;
    ticketID: string;
}

const baseUrl = process.env.VERCEL_URL || "http://localhost:3000";

위의 코드 스니펫에서 이메일 템플릿을 작성하는 데 필요한 구성 요소를 가져왔습니다.

그 다음, TicketCreated 컴포넌트를 파일에 추가하여 React Email 구성 요소를 사용하여 이메일 템플릿을 렌더링합니다.

export const TicketCreated = ({ username, ticketID }: TicketCreatedProps) => {
    return (
        <Html>
            <Head />
            <Preview>Support Ticket Confirmation Email 🎉</Preview>
            <Tailwind>
                <Body className='bg-white my-auto mx-auto font-sans px-2'>
                    <Container className='border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]'>
                        <Heading className='text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0'>
                            Your Ticket has been created
                        </Heading>
                        <Text className='text-black text-[14px] leading-[24px]'>
                            Hello {username},
                        </Text>
                        <Text className='text-black text-[14px] leading-[24px]'>
                            <strong>Support Ticket</strong> (
                            <Link
                                href={`${baseUrl}/ticket/${ticketID}`}
                                className='text-blue-600 no-underline'
                            >
                                {`#${ticketID}`}
                            </Link>
                            ) has been created successfully.
                        </Text>

                        <Text className='text-black text-[14px] leading-[24px]'>
                            The Support team will review your ticket and get back to you
                            shortly.
                        </Text>

                        <Hr className='border border-solid border-[#eaeaea] my-[26px] mx-0 w-full' />
                        <Text className='text-[#666666] text-[12px] leading-[24px]'>
                            This message was intended for{" "}
                            <span className='text-black'>{username}</span>. If you did not
                            create this ticket, please ignore this email.
                        </Text>
                    </Container>
                </Body>
            </Tailwind>
        </Html>
    );
};

마지막으로, props에 대한 기본값을 추가하고 내보내세요:

TicketCreated.PreviewProps = {
    username: "alanturing",
    ticketID: "9083475",
} as TicketCreatedProps;

export default TicketCreated;

터미널에서 npm run email을 실행하여 이메일 템플릿을 미리볼 수 있습니다.

이 이메일 템플릿은 고객에게 지원 티켓이 생성되었음을 알리고, 지원팀에서 누군가가 고객에게 연락할 것이라고 알려줍니다.

React Email은 다양한 미리 디자인된 이메일 템플릿을 제공하여 다양한 목적에 맞게 아름답게 스타일링된 이메일을 쉽게 작성할 수 있습니다. 가능한 데모를 확인하여 예제를 살펴보세요.

Resend를 사용하여 이메일을 보내는 방법

Resend는 소프트웨어 애플리케이션 내에서 이메일을 보낼 수 있게 해주는 간단한 이메일 API입니다. JavaScript(Next.js, Express, Node.js), Python, PHP, Go, Rust 등 다양한 프로그래밍 언어를 지원합니다.

Resend와 React Email은 쉽게 통합할 수 있습니다. 왜냐하면 Resend의 공동 창업자인 부 키노시타가 React Email의 창조자이기 때문입니다.

Resend에서 계정을 생성하세요. 로그인한 후 대시보드의 API 키 섹션으로 이동하여 API 키를 .env.local 파일에 복사하세요.

//👇🏻 .env.local file
RESEND_API_KEY=<RESEND_API_KEY>

//👇🏻 .env.local 파일

import { NextRequest, NextResponse } from "next/server";
다음과 같이 React Email 템플릿을 사용하여 이메일을 보내는 API 엔드포인트를 업데이트하세요:
import { v4 as generateID } from "uuid";
//👇🏻 티켓 ID 생성기 함수
import TicketCreated from "@/emails/TicketCreated";
//👇🏻 이메일 템플릿을 가져옵니다
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: NextRequest) {
    //👇🏻 Resend를 가져옵니다
    const { name, email, subject, content } = await req.json();
    //👇🏻 고객의 입력을 프론트엔드에서 받습니다
    console.log({ name, email, subject, content });
    //👇🏻 그들을 로깅합니다
    const { data, error } = await resend.emails.send({
        from: "Acme <[email protected]>",
        to: [email],
        subject: "Ticket Confirmation Email 🎉",
        react: TicketCreated({ username: name, ticketID: generateID() }),
    });

    if (error) {
        return NextResponse.json(
            { message: "Error sending email" },
            { status: 500 }
        );
    }

    return NextResponse.json({
        message: "Email sent successfully",
        data,
    });
}

//👇🏏 이메일 템플릿을 사용하여 이메일을 보냅니다

축하합니다!🥳 이 튜토리얼을 완료했습니다.

여기 응용 프로그램의 간단한 데모입니다:

다음 단계

이 튜토리얼에서 React Email을 사용하여 이메일 템플릿을 만들고 Resend를 사용하여 이를 보내는 방법을 배웠습니다. 두 패키지 모두 애플리케이션 내에서 이메일 통신을 쉽게 통합할 수 있도록 합니다.

간단한 이메일 알림, 뉴스레터 또는 마케팅 캠페인이든, React Email과 Resend는 귀하의 요구 사항을 충족시킬 수 있는 효율적이고 사용자 정의 가능한 솔루션을 제공합니다.

Next.js 애플리케이션에 Resend 설치하는 방법