AWS ECS Fargate와 EventBridge를 사용하여 Notion에서 SvelteKit 정적 블로그로 매일 자동 동기화합니다.
Notion API → ECS Fargate (매일 자정 KST)
↓
1. 페이지 가져오기 (Go)
2. 이미지 다운로드 (Go)
3. .svelte 파일 생성 (Go)
↓
4. Git 동기화 (Bash 스크립트)
- 저장소 클론
- 파일 복사
- 'posts' 브랜치에 푸시
↓
GitHub Actions (자동 트리거)
- npm ci
- npm run build
- GitHub Pages에 배포
↓
블로그 업데이트 완료! ✨
master: 개발용 (코드 수정, PR, 인프라)posts: 프로덕션 (블로그 포스트만, 배포 트리거)월 ~$0.10 💰
repo 권한 필요)이 프로젝트는 사용자/조직 사이트 형식의 GitHub Pages를 사용합니다:
<username>.github.iohttps://<username>.github.io/johndoe라면 johndoe.github.io 저장소를 생성하세요# GitHub.com에서 새 퍼블릭 저장소 생성:
# <your-username>.github.io
# 이 템플릿 클론
git clone https://github.com/jhseoeo/notion-blog.git
cd notion-blog
# 원격 저장소를 본인 저장소로 변경
git remote set-url origin https://github.com/<your-username>/<your-username>.github.io.git
git push -u origin master
terraform/terraform.tfvars 파일 수정:
project_name = "notion-blog-sync"
aws_region = "ap-northeast-2"
# Notion Integration 페이지에서 가져오기
notion_secret = "ntn_xxxxxxxxxxxxx"
notion_db_id = "your-database-id"
# GitHub PAT 생성 ('repo' 권한 필요)
github_token = "ghp_xxxxxxxxxxxxx"
github_repo = "https://github.com/<YOUR_USERNAME>/<YOUR_USERNAME>.github.io.git"
git_user_name = "Notion Blog Sync Bot"
git_user_email = "your-email@example.com"
# 매일 자정 KST (15:00 UTC)
schedule_expression = "cron(0 15 * * ? *)"
중요: terraform.tfvars는 절대 커밋하지 마세요 (이미 .gitignore에 포함됨)
참고: posts 브랜치는 워크플로우가 처음 실행될 때 자동으로 생성됩니다. 수동으로 만들 필요가 없습니다.
cd terraform
# Terraform 초기화
terraform init
# 변경사항 검토
terraform plan
# 인프라 배포 (yes 입력)
terraform apply
# 다음 단계를 위해 출력값 저장
terraform output ecr_repository_url
gh-pages/ (root)블로그 접근 URL: https://<your-username>.github.io/
참고: gh-pages 브랜치는 posts 브랜치에 푸시할 때 GitHub Actions 워크플로우가 자동으로 생성합니다.
cd ../workflow
# Terraform output에서 ECR 저장소 URL 가져오기
ECR_REPO=$(cd ../terraform && terraform output -raw ecr_repository_url)
# ECR 로그인
aws ecr get-login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin $ECR_REPO
# Docker 이미지 빌드
docker build -t notion-blog-sync .
# 태그 및 푸시
docker tag notion-blog-sync:latest $ECR_REPO:latest
docker push $ECR_REPO:latest
# ECS 태스크 수동 트리거
cd ../terraform
aws ecs run-task \
--cluster notion-blog-sync-cluster \
--task-definition notion-blog-sync \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[$(terraform output -json subnet_ids | jq -r '.[0]')],securityGroups=[$(terraform output -raw security_group_id)],assignPublicIp=ENABLED}" \
--region ap-northeast-2
# 로그 확인
aws logs tail /ecs/notion-blog-sync --follow
목적: Workflow 코드 변경 시 Docker 이미지 자동 재빌드
이미 설정된 두 워크플로우:
deploy-workflow.yml - master 브랜치에서 Docker 이미지 재빌드
master의 workflow/** 푸시deploy-pages.yml - posts 브랜치에서 블로그 배포
posts 브랜치의 모든 푸시설정:
AWS_ROLE_ARN - OIDC 인증용AWS_ACCESS_KEY_ID와 AWS_SECRET_ACCESS_KEY# AWS에서 OIDC 프로바이더 및 IAM 역할 생성
# 참고: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
.github/workflows/deploy-workflow.yml):
이제:
master에 workflow 변경 푸시 → Docker 이미지 재빌드posts에 푸시 → 블로그 자동 배포# 실시간 로그 확인
aws logs tail /ecs/notion-blog-sync --follow
# 에러 필터링
aws logs filter-log-events \
--log-group-name /ecs/notion-blog-sync \
--filter-pattern "ERROR"
# 예약된 태스크 목록
aws events list-rules --name-prefix notion-blog-sync
# 규칙 상세 정보
aws events describe-rule --name notion-blog-sync-daily
# 최근 태스크 목록
aws ecs list-tasks --cluster notion-blog-sync-cluster
# 특정 태스크 상세 정보
aws ecs describe-tasks \
--cluster notion-blog-sync-cluster \
--tasks <task-id>
또는 AWS Console 사용:
cd workflow
cp .env.example .env # 자격 증명으로 수정
go run main.go
repo 권한이 있는지 확인terraform.tfvars에서 저장소 URL이 올바른지 확인Notion 콘텐츠가 변경되지 않았다면 정상입니다. 로그 확인:
No changes to commit
gh-pages / (root)deploy-pages.yml 워크플로우 확인브라우저 콘솔에서 에셋 404 에러를 확인하세요:
notion-blog/
├── .github/
│ └── workflows/
│ ├── deploy-workflow.yml # master에서 Docker 빌드
│ └── deploy-pages.yml # posts에서 블로그 배포
├── workflow/ # Go 애플리케이션
│ ├── main.go # 진입점 (Notion 동기화만)
│ ├── sync.sh # Git 동기화 스크립트
│ ├── Dockerfile # 컨테이너 정의
│ ├── notion/ # Notion API 클라이언트
│ ├── post/ # 포스트 내보내기 로직
│ └── model/ # 데이터 구조
├── terraform/ # Infrastructure as Code
│ ├── vpc.tf # VPC & 서브넷
│ ├── ecs.tf # 컨테이너 오케스트레이션
│ ├── eventbridge.tf # 스케줄링
│ ├── secrets.tf # SSM Parameter Store
│ ├── iam.tf # IAM 역할 & 정책
│ └── ...
└── blog/ # SvelteKit 블로그
└── src/
└── posts/ # 생성된 포스트 (posts 브랜치)
git checkout master
cd workflow
# 코드 변경
git add .
git commit -m "워크플로우 업데이트"
git push
# GitHub Actions가 설정되어 있으면 이미지가 자동 배포됨
# 아니면 수동으로 재빌드 및 푸시 (6단계 참고)
git checkout master
cd blog
# 변경 (컴포넌트, 스타일 등)
git add .
git commit -m "블로그 디자인 업데이트"
git push
# 변경사항은 배포되지 않음 (posts 브랜치에서만 배포)
git checkout posts
cd blog/src/posts
# .svelte 파일 생성 또는 수정
git add .
git commit -m "새 글 추가"
git push
# 자동으로 블로그 배포 트리거!
git checkout master
cd terraform
# .tf 파일 수정
terraform plan
terraform apply
terraform/terraform.tfvars 수정:
# 오전 9시 KST 실행 (자정 UTC)
schedule_expression = "cron(0 0 * * ? *)"
# 하루 2회 실행 (자정, 정오 KST)
# 자정 KST: cron(0 15 * * ? *)
# 정오 KST: cron(0 3 * * ? *)
그 다음 적용:
cd terraform
terraform apply
# 블로그 코드 변경사항을 posts 브랜치에 동기화하려면
git checkout posts
git merge master
git push
모든 인프라를 삭제하려면:
cd terraform
terraform destroy
경고: 로그 및 ECR 이미지를 포함한 모든 리소스가 삭제됩니다.
이슈 및 질문: