AI를 활용한 재밌는 것들을 개발합니다

2026년 4월 27일 월요일

Python으로 분석 결과 자동 이메일 발송하기 [Claude Code · 유튜브분석기 · 3편]

Gemini API PDF 생성 Gmail 자동 발송

Python으로 분석 결과
자동 이메일 발송하기

AI 분석 → 한글 PDF 생성 → Gmail 자동 발송. 삽질 과정까지 전부 공개합니다.

📌 시리즈 3편입니다
2편에서 YouTube 데이터 수집 코드를 공개했습니다. 이번 편은 수집된 데이터를 AI가 분석하고, PDF로 만들어 이메일로 보내는 과정입니다.

전체 흐름 요약

YouTube 데이터
    │
    ▼
Gemini AI 분석  ← "이번 주 트렌드 요약 + 주제 3개 추천해줘"
    │
    ▼
PDF 리포트 생성  ← 차트 3개 + 한글 내용
    │
    ▼
Gmail 자동 발송  ← 매주 일요일 20:00

1단계: Gemini AI 트렌드 분석

왜 Claude API 대신 Gemini를 썼나?

처음에는 Claude API(Anthropic)로 분석하려 했습니다. 그런데 이 시스템은 매주 자동으로 돌아가야 하는데, Claude API는 유료입니다. 반면 Gemini API는 무료 티어가 있어서 교체했습니다.

Gemini API 키 발급
aistudio.google.com → "Get API Key" → "Create API key in new project"
⚠️ Google Cloud Console에서 발급한 키와 다릅니다. 반드시 AI Studio에서 발급받으세요.

실제 분석 코드

# tools/analysis_tools.py
from google import genai
import json

def generate_recommendations(niche_data, analysis) -> dict:
    client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])

    summary = "\n".join(
        f"[{niche}] 인기 영상:\n" +
        "\n".join(f"- {v['title']} (조회수: {v['view_count']:,})"
                  for v in videos[:5])
        for niche, videos in niche_data.items()
    )

    prompt = f"""당신은 YouTube 콘텐츠 전략 전문가입니다.
아래 인기 영상 데이터를 분석해 JSON으로만 답변해주세요.

{summary}

다음 JSON 형식으로 답변:
{{
  "trend_summary": "이번 주 트렌드 2-3줄 요약",
  "recommended_topics": [
    {{"title": "추천 주제", "reason": "추천 이유", "format": "권장 포맷"}}
  ],
  "hot_keywords": ["키워드1", "키워드2"]
}}
추천 주제 3개, hot_keywords 5개."""

    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=prompt,
    )
    text = response.text
    return json.loads(text[text.find("{"):text.rfind("}")+1])

2단계: 한글 PDF 리포트 생성

가장 많이 삽질한 부분입니다 😅

🔴 문제 1: weasyprint 설치 실패
Windows에서 GTK 라이브러리 의존성 문제로 설치 자체가 안 됨.
🔴 문제 2: xhtml2pdf 한글 깨짐
설치는 됐지만 한글이 전부 □□□로 출력됨. @font-face 설정해도 Windows 임시 파일 권한 에러 발생.
✅ 해결: fpdf2 + 맑은 고딕 TTF 직접 삽입
C:\Windows\Fonts 에서 malgun.ttf(맑은 고딕)를 프로젝트 fonts/ 폴더로 복사하고, fpdf2에 직접 등록.

한글 PDF 코드

# tools/pdf_tools.py
from fpdf import FPDF
from pathlib import Path

FONTS_DIR = Path(__file__).parent.parent / "fonts"

class ReportPDF(FPDF):
    def __init__(self):
        super().__init__()
        # 맑은 고딕 폰트 등록 (한글 지원)
        self.add_font("Malgun", "",  str(FONTS_DIR / "malgun.ttf"))
        self.add_font("Malgun", "B", str(FONTS_DIR / "malgunbd.ttf"))
        self.set_auto_page_break(auto=True, margin=20)

    def cover(self, generated_at: str):
        self.add_page()
        self.set_fill_color(48, 43, 99)   # 브랜드 컬러 #302b63
        self.rect(0, 0, 210, 70, "F")
        self.set_text_color(255, 255, 255)
        self.set_font("Malgun", "B", 22)
        self.set_y(18)
        self.cell(0, 10, "YouTube 콘텐츠 트렌드 리포트", align="C",
                  new_x="LMARGIN", new_y="NEXT")

차트는 matplotlib으로 따로 생성한 뒤 PNG로 저장하고, PDF에 이미지로 삽입합니다.


3단계: Gmail 자동 발송

Gmail OAuth2 credentials.json 발급

1
Google Cloud Console → API 및 서비스 → Gmail API 사용 설정
2
OAuth 동의 화면 → 외부 선택 → 앱 이름 입력 → 테스트 사용자에 본인 Gmail 추가
3
사용자 인증 정보 → OAuth 2.0 클라이언트 ID 만들기 → 데스크톱 앱 → JSON 다운로드
4
다운로드한 파일을 프로젝트 루트에 credentials.json으로 저장

Gmail 발송 코드

# tools/gmail_tools.py
import base64, os
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
from pathlib import Path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import pickle

SCOPES = ["https://www.googleapis.com/auth/gmail.send"]

def _get_gmail_service():
    creds = None
    token_path = Path("token.pickle")
    if token_path.exists():
        with open(token_path, "rb") as f:
            creds = pickle.load(f)
    if not creds or not creds.valid:
        if creds and creds.expired:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                os.environ["GMAIL_CREDENTIALS_PATH"], SCOPES)
            creds = flow.run_local_server(port=0)
        with open(token_path, "wb") as f:
            pickle.dump(creds, f)
    return build("gmail", "v1", credentials=creds)

def send_gmail(pdf_path: Path):
    service = _get_gmail_service()
    msg = MIMEMultipart()
    msg["To"]      = os.environ["REPORT_RECIPIENT_EMAIL"]
    msg["Subject"] = "📊 이번 주 YouTube 트렌드 리포트"
    msg.attach(MIMEText("안녕하세요. 이번 주 리포트를 보내드립니다.", "plain", "utf-8"))

    with open(pdf_path, "rb") as f:
        part = MIMEBase("application", "octet-stream")
        part.set_payload(f.read())
    encoders.encode_base64(part)
    part.add_header("Content-Disposition", f'attachment; filename="{pdf_path.name}"')
    msg.attach(part)

    raw = base64.urlsafe_b64encode(msg.as_bytes()).decode()
    service.users().messages().send(userId="me", body={"raw": raw}).execute()
    print(f"✅ 메일 발송 완료: {os.environ['REPORT_RECIPIENT_EMAIL']}")

4단계: 매주 자동 실행 스케줄러

# main.py 핵심 부분
import schedule, time

schedule.every().sunday.at("20:00").do(run)

print("스케줄러 시작: 매주 일요일 20:00 자동 실행")
while True:
    schedule.run_pending()
    time.sleep(30)

실행 방법:

# 즉시 한 번 실행 (테스트용)
python main.py --run-now

# 스케줄러 시작 (매주 자동 실행)
python main.py --schedule

다음 편 예고

4편에서는 실제로 받은 PDF 리포트와, 무료 로컬 AI(Ollama)로 Gemini를 대체하려다 겪은 웃픈 경험을 공유합니다.

댓글 없음:

댓글 쓰기

가장 많이 본 글