Instruction file imported from guesung/tech-mail (
.cursor/rules/service.mdc). Copyright stays with the author.
기술 블로그 구독 서비스 개발 가이드
프로젝트 개요
RSS 피드를 활용한 기술 블로그 구독 서비스. 사용자가 관심 있는 기술 블로그를 구독하면 새 글이 올라올 때 이메일로 알림을 받는 서비스입니다.
기술 스택
- Frontend: Next.js (App Router)
- Backend: Next.js API Routes
- Database: Supabase
- Cron Job: Vercel Cron Functions
- Email: Resend 또는 Nodemailer
- RSS Parser: rss-parser 라이브러리
핵심 기능
- 기술 블로그 목록 조회 및 구독
- 이메일 주소 입력 및 구독 관리
- RSS 피드 크롤링 및 새 글 감지
- 이메일 알림 발송
코딩 스타일 가이드
TypeScript 사용 규칙
- 모든 파일은 TypeScript로 작성
- interface와 type을 명확히 정의
- any 타입 사용 금지
- 엄격한 타입 체크 적용
파일 구조
app/
├── api/
│ ├── cron/
│ │ └── check-rss/
│ ├── blogs/
│ ├── subscribe/
│ └── unsubscribe/
├── components/
├── lib/
│ ├── supabase.ts
│ ├── rss-parser.ts
│ └── email.ts
├── types/
│ ├── ...
│
├── page.tsx
├── layout.tsx
├── globals.css
├── favicon.ico
database/
└── schema.sql
vercel.json
데이터베이스 스키마
-- subscribers 테이블
CREATE TABLE subscribers (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
is_verified BOOLEAN DEFAULT false,
is_active BOOLEAN DEFAULT true,
subscribed_blog_ids TEXT[],
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- blogs 테이블
CREATE TABLE blogs (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name VARCHAR(255) NOT NULL,
rssUrl TEXT NOT NULL UNIQUE,
websiteUrl TEXT,
description TEXT,
category VARCHAR(100),
logo_url TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- articles 테이블
CREATE TABLE articles (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
blog_id UUID REFERENCES blogs(id),
title VARCHAR(500) NOT NULL,
url TEXT NOT NULL UNIQUE,
description TEXT,
author VARCHAR(255),
published_at TIMESTAMP NOT NULL,
crawled_at TIMESTAMP DEFAULT NOW()
);
개발 가이드라인
API 라우트 설계
- RESTful API 설계 원칙 준수
- 적절한 HTTP 상태 코드 사용
- 에러 처리 및 로깅 구현
- 요청/응답 타입 정의
RSS 크롤링 로직
- rss-parser 라이브러리 사용
- 중복 글 방지를 위한 URL 기반 체크
- 에러 발생 시 다음 RSS 피드로 계속 진행
- 크롤링 성능 최적화 (Promise.all 활용)
이메일 발송 로직
- HTML 템플릿 기반 이메일 작성
- 구독자별 맞춤형 콘텐츠 제공
- 이메일 발송 실패 시 재시도 로직
- 구독 취소 링크 포함
환경 변수 관리
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
# Email Service
RESEND_API_KEY=
FROM_EMAIL=
# App Config
NEXT_PUBLIC_APP_URL=
사전 정의된 블로그 목록
무신사, 네이버D2, 마켓컬리, 우아한형제들, 카카오엔터프라이즈, 데브시스터즈, 라인, 당근마켓, 토스, 직방, WATCHA, 뱅크샐러드, Hyperconnect, 쏘카, 리디, NHN Cloud 등의 RSS 피드 URL을 데이터베이스에 미리 등록
사용자 플로우 구현
- 메인 페이지에서 구독 가능한 기술 블로그 목록 표시
- 사용자가 원하는 블로그 선택
- 이메일 주소 입력 및 구독 신청
- 이메일 인증 (선택사항)
- 일일 크론잡으로 새 글 체크 후 이메일 발송
성능 최적화 가이드
- 데이터베이스 쿼리 최적화 (인덱스 활용)
- RSS 피드 크롤링 시 병렬 처리
- 이메일 발송 시 배치 처리
- 캐싱 전략 적용
에러 처리 규칙
- try-catch 블록으로 모든 비동기 작업 감싸기
- 의미 있는 에러 메시지 제공
- 로깅 시스템 구축
- 사용자 친화적인 에러 페이지
보안 고려사항
- 이메일 주소 유효성 검사
- SQL 인젝션 방지
- Rate limiting 적용
- CORS 설정
- 환경 변수 보안
테스트 가이드
- 단위 테스트 (Jest)
- API 엔드포인트 테스트
- RSS 파싱 테스트
- 이메일 발송 테스트
배포 설정
// vercel.json
{
"crons": [
{
"path": "/api/cron/check-rss",
"schedule": "0 9 * * *"
}
]
}
코드 작성 시 주의사항
- 함수명과 변수명은 명확하고 설명적으로 작성
- 주석은 복잡한 로직에만 추가
- 컴포넌트는 재사용 가능하게 설계
- 상태 관리는 필요한 경우에만 사용
- 성능을 고려한 렌더링 최적화
이 가이드라인을 따라 일관성 있고 유지보수 가능한 코드를 작성하세요.