본문 바로가기
프로그램 (PHP,Python)

Python FastAPI 뉴스레터 예제 프로그램 제작 및 배포 과정

by 날으는물고기 2024. 1. 15.

Python FastAPI 뉴스레터 예제 프로그램 제작 및 배포 과정

How to build a newsletter using Python and FastAPI

파이썬과 FastAPI를 사용하여 뉴스레터를 만드는 과정입니다.

  1. FastAPI 소개
    • FastAPI는 빠르고 현대적인 웹 프레임워크로, 파이썬을 기반으로 하는 비동기 웹 어플리케이션을 쉽게 작성할 수 있도록 지원합니다.
  2. 프로젝트 설정
    • FastAPI를 설치하고 새로운 프로젝트를 초기화합니다. 이때, Pydantic을 사용하여 데이터 모델을 정의합니다.
  3. 이메일 전송 설정
    • 뉴스레터를 보낼 때 사용할 이메일 전송 서비스를 설정합니다. 보통은 SMTP 서버를 사용하는데, 이를 위해 smtplib를 사용할 수 있습니다.
  4. 데이터베이스 설정
    • 사용자 정보와 뉴스레터 구독 정보를 저장하기 위해 데이터베이스를 설정합니다. 이때, SQLAlchemyORM을 활용하여 데이터 모델을 정의하고 데이터베이스에 연결합니다.
  5. API 엔드포인트 구현
    • FastAPI를 사용하여 구독자 추가, 삭제, 뉴스레터 전송 등을 처리하는 API 엔드포인트를 구현합니다.
  6. 이메일 발송
    • 이메일을 발송하는 부분에서는 SMTP 서버를 이용하여 사용자에게 뉴스레터를 전송합니다. 여기서는 smtplib를 사용하여 이 작업을 처리합니다.
  7. 프로젝트 실행 및 테스트
    • 프로젝트를 실행하고 API 엔드포인트를 테스트하여 정상적으로 동작하는지 확인합니다.
  8. 추가 기능 (선택 사항)
    • 필요에 따라 구독자 관리 기능, 이메일 템플릿 설정, 예약 발송 기능 등을 추가로 구현할 수 있습니다.

Python과 FastAPI에 대한 기본적인 이해가 필요하며, Kindle에서 추출한 하이라이트를 저장하고, 주기적으로 하이라이트 중 하나를 이메일로 받아볼 수 있는 뉴스레터 서비스를 구축합니다. 아래는 프로젝트의 핵심 부분을 단계별로 설명한 것입니다.

FastAPI를 사용한 웹 앱 설정

  • FastAPI는 빠르고 비동기 처리가 가능한 웹 애플리케이션 프레임워크입니다.
  • 네 가지 간단한 엔드포인트를 가진 웹 앱을 만듭니다.
    1. 홈 페이지: 뉴스레터 가입 폼을 표시합니다.
    2. 사용자로부터 제출된 폼 데이터를 처리하는 엔드포인트.
    3. 뉴스레터 구독 확인을 위한 엔드포인트.
    4. 뉴스레터 구독 취소를 위한 엔드포인트.

비동기 처리 및 백그라운드 작업

  • FastAPI의 비동기 및 백그라운드 작업을 활용하여 이메일 전송, 사용자 등록 및 하이라이트 업로드를 비동기적으로 처리합니다.
  • asyncbackground_tasks를 사용한 예제 코드를 통해 이를 구현합니다.

데이터베이스 설정

  • PynamoDB를 사용하여 DynamoDB와 상호 작용하는 모델을 정의합니다.
  • HighlightModel은 Kindle에서 추출한 각 하이라이트의 데이터 모델을 나타냅니다.

AWS Elastic Beanstalk을 이용한 배포

  • AWS Elastic Beanstalk를 사용하여 Docker 기반 애플리케이션을 배포합니다.
  • GitHub Actions를 활용하여 자동 업데이트 및 배포를 구성합니다.

이메일 발송 설정

  • Amazon SES를 사용하여 이메일을 전송합니다.
  • 주기적인 작업으로 매주 금요일에 이메일을 전송하기 위해 GitHub Actions를 사용합니다.
  • send_email.py 스크립트를 사용하여 사용자에게 주간 하이라이트를 이메일로 보냅니다.

GitHub Actions를 통한 CI/CD 설정

  • GitHub Actions를 사용하여 두 가지 중요한 작업을 자동화합니다.
    1. 매번 마스터 브랜치에 커밋이 발생하면 Elastic Beanstalk에 자동으로 애플리케이션을 업데이트하고 재배포합니다.
    2. 매주 금요일에 send_email.py 스크립트를 실행하여 뉴스레터를 사용자에게 자동으로 전송합니다.

마무리

  • 전체 프로세스를 통해 새로운 기술들을 배우고, 뉴스레터 서비스를 직접 구축하는 경험을 통해 다양한 기술에 대한 존경을 얻었습니다.
  • 최종 결과물은 Kindle-highlights.email이라는 무료 오픈소스 프로젝트로, 사용자는 하이라이트 파일을 업로드하고 매주 금요일에 강조된 구절을 이메일로 받을 수 있습니다.

 

이제 프로젝트의 핵심 부분에서 사용된 코드를 추가하여 단계별로 자세하게 설명하겠습니다.

FastAPI를 사용한 웹 앱 설정

# main.py
from fastapi import FastAPI, BackgroundTasks, File, Form, Request, UploadFile
from fastapi.responses import FileResponse
from app.utils import (
    parse_highlights_file,
    email_is_valid,
    check_user_subscribed,
    register_user,
    send_confirmation_to,
    upload_highlights,
)
from fastapi.templating import Jinja2Templates

app = FastAPI()
templates = Jinja2Templates(directory="templates")

@app.post("/")
async def sign_up(
    request: Request,
    background_tasks: BackgroundTasks,
    file: UploadFile = File(...),
    email: str = Form(...),
):
    highlights = await parse_highlights_file(file)
    email_valid = await email_is_valid(email)

    if not highlights or email_valid is False:
        return FileResponse("static/error.html")

    subscribed_status = await check_user_subscribed(email)

    if subscribed_status is False:
        background_tasks.add_task(register_user, email)
        background_tasks.add_task(send_confirmation_to, email)
        background_tasks.add_task(upload_highlights, highlights, email)
        return templates.TemplateResponse("sign_up.html", {"request": request})
    else:
        return templates.TemplateResponse("success.html", {"request": request})

데이터베이스 설정

# models.py
from pynamodb.models import Model
from pynamodb.attributes import (
    UnicodeAttribute,
    UTCDateTimeAttribute,
    BooleanAttribute,
    NumberAttribute,
)

class HighlightModel(Model):
    class Meta:
        table_name = "kindle-highlights-contents"
        region = "eu-west-1"

    email = UnicodeAttribute(hash_key=True, null=False)
    author = UnicodeAttribute(null=False)
    book = UnicodeAttribute(null=False)
    content = UnicodeAttribute(null=False)
    date_string = UnicodeAttribute(null=False)
    highlight_index = NumberAttribute(range_key=True, null=False)

AWS Elastic Beanstalk을 이용한 배포

  1. Dockerfile
# Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.8

COPY ./app /app
  1. docker-compose.yml
# docker-compose.yml
version: "3"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - MODULE_NAME=main
      - VARIABLE_NAME=app
    ports:
      - "80:80"
    depends_on:
      - dynamodb

  dynamodb:
    image: amazon/dynamodb-local
    ports:
      - "8000:8000"

CI/CD: GitHub - (ab)using GitHub actions

  1. 업데이트 및 배포
# .github/workflows/deploy.yml
name: Deploy to AWS Elastic Beanstalk

on:
  push:
    branches:
      - master

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: 3.8

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt

    - name: Deploy to Elastic Beanstalk
      run: eb deploy
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  1. 주간 뉴스레터 발송
# .github/workflows/send_newsletter.yml
name: Send Weekly Newsletter

on:
  schedule:
    - cron: "0 8 * * 5"  # Every Friday at 8 AM

jobs:
  send_newsletter:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2

    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: 3.8

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt

    - name: Run send_email.py script
      run: python app/send_email.py
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

이러한 코드와 설정을 통해 Kindle 하이라이트 뉴스레터 서비스를 개발하고, AWS Elastic Beanstalk 및 GitHub Actions를 사용하여 배포 및 자동화를 구현할 수 있습니다.

728x90

댓글