우리 같이 하이퍼 맞춤형 뉴스 에이전트를 만들까요? 🤖📰 (함께 코딩)
Source: Dev.to
아이디어: 일반적인 뉴스레터는 이제 그만!
대부분의 테크 뉴스레터가 너무 일반적이거나 실리콘밸리에서 일어나는 일만 다루는 것을 눈치채셨나요? 저는 소프트웨어 에이전트를 만들어 맞춤형 큐레이션을 제공하려고 합니다. 그리고 여러분을 함께 코딩에 초대하고 싶어요.
이건 단순한 챗봇이 아닙니다. 자율적인 에이전트가:
- Tavily를 사용해 실시간으로 웹을 스캔합니다.
- 국가와 언어별로 필터링: 일본에서 나온 AI 뉴스를 포르투갈어로 요약하고 싶나요? 에이전트가 해결합니다.
- Gemini 1.5 Pro로 합성 – 번역, 요약, 포맷팅을 담당하는 “두뇌”.
- Resend를 통해 전달 – 자동화된 메일을 여러분의 인박스(또는 전체 구독자)로 직접 보냅니다.
주요 기능
- 실시간 검색 웹에서 (Tavily).
- 필터링 국가 및 언어별.
- 요약 및 번역 Gemini 1.5 Pro와 함께.
- 자동 이메일 전송 (Resend + MJML).
기술 스택
| 계층 | 기술 |
|---|---|
| 프레임워크 | Next.js (Vercel) |
| 인텔리전스 | Gemini SDK + Tavily API |
| 데이터베이스 & ORM | MongoDB + Prisma |
| 이메일 | Resend (확장성을 위한 Audiences) |
| 이메일 디자인 | MJML (반응형) |
로드맵 (작업)
- 아키텍처 정의 (Prisma + Mongo).
- 선호도 캡처 폼 만들기 (주제, 국가, 언어).
- 에이전트 루프 조정: 조사 → 요약 → 번역.
- Vercel에서 Cron Job 설정하여 자동 주간 전송.
어떻게 함께 할 수 있나요
- 댓글 달기: 뉴스 에이전트에 어떤 기능을 추가하고 싶나요?
- 스택 선택: 가장 관심 있는 스택을 고르세요 (프롬프트 엔지니어링, API 통합 또는 Next.js 프론트엔드).
- GitHub: 저장소가 완전한 애플리케이션과 함께 공개됩니다.
초기 목표: 프로젝트를 로컬에서 실행하고 데이터베이스를 구독자 수신 준비 상태로 만드는 것.
빠른 설정
# Next.js 애플리케이션을 생성하세요
npx create-next-app@latest ai-newsletter
의존성을 설치하세요:
npm install @prisma/client @google/generative-ai @tavily/core resend zod mjml
schema.prisma를 Subscriber 모델로 구성하세요 (아래 예시를 참고).
구현
사용자 인터페이스
- 양식:
- Input 이메일.
- Selects 국가 및 언어 선택.
- Checkboxes 관심 주제 선택.
API
/api/subscribe라우트가 Prisma를 통해 MongoDB에 구독 정보를 저장합니다.
// pages/api/subscribe.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { prisma } from '../../lib/prisma';
import { z } from 'zod';
const schema = z.object({
email: z.string().email(),
country: z.string(),
language: z.string(),
topics: z.array(z.string()),
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') return res.status(405).end();
const result = schema.safeParse(req.body);
if (!result.success) return res.status(400).json(result.error.format());
await prisma.subscriber.create({ data: result.data });
return res.status(200).json({ message: 'Inscrição salva com sucesso!' });
}
검색 및 요약 (에이전트 “마법”)
// lib/agent.ts
import { Tavily } from '@tavily/core';
import { Gemini } from '@google/generative-ai';
export async function generateNewsletter(preferences) {
const searchResults = await Tavily.search({
query: preferences.topics.join(', '),
region: preferences.country,
language: preferences.language,
});
const prompt = `
Você é um assistente que deve:
1. Resumir as notícias encontradas.
2. Traduzir o resumo para ${preferences.language}.
3. Formatar o conteúdo como e‑mail (HTML).
`;
const gemini = new Gemini({ model: 'gemini-1.5-pro' });
const response = await gemini.generate({
prompt,
documents: searchResults,
});
return response.text; // HTML pronto para MJML
}
프롬프트 엔지니어링
- 위 프롬프트는 Gemini에게 사용자의 언어에 맞게 특정 형식으로 포맷하고 MJML에 사용할 수 있는 HTML을 생성하도록 지시합니다.
MJML 통합
// lib/mjml.ts
import mjml2html from 'mjml';
export function renderEmail(htmlContent) {
const mjmlTemplate = `
<mjml>
<mj-body>
<mj-section>
<mj-column>
${htmlContent}
</mj-column>
</mj-section>
</mj-body>
</mjml>
`;
const { html } = mjml2html(mjmlTemplate);
return html;
}
배치 로직 (전송)
// pages/api/send-newsletter.ts
import { prisma } from '../../lib/prisma';
import { generateNewsletter } from '../../lib/agent';
import { renderEmail } from '../../lib/mjml';
import { resend } from '../../lib/resend';
export default async function handler(req, res) {
const subscribers = await prisma.subscriber.findMany();
for (const sub of subscribers) {
const content = await generateNewsletter(sub);
const html = renderEmail(content);
await resend.sendEmail({
from: 'news@yourdomain.com',
to: sub.email,
subject: 'Sua newsletter personalizada',
html,
});
}
res.status(200).json({ message: 'Newsletters enviadas' });
}
Vercel에서 Cron 작업
vercel.json 파일을 생성합니다:
{
"crons": [
{
"path": "/api/send-newsletter",
"schedule": "0 9 * * MON"
}
]
}
이는 매주 월요일 오전 9시에 실행을 예약합니다.
최종 테스트
- 양식을 통해 이메일을 등록합니다.
- 받은 편지함에서 뉴스레터 수신을 확인합니다.
다음 단계
- queues(예: BullMQ)를 사용하여 오케스트레이션을 리팩터링합니다.
- Resend에서 다중 청중 지원을 추가합니다.
- 비용을 절감하기 위해 검색 결과 cache를 구현합니다.
ChatGPT에게 “안녕”만 하는 걸 그만하고 실제로 가치를 자동으로 제공하는 도구를 만들자. 🚀