기술 블로그 인프라 구성: Jekyll + GitHub Actions + S3 + CloudFront
기술 블로그 인프라 구성: Jekyll + GitHub Actions + S3 + CloudFront
요약
- Jekyll(Chirpy)로 정적 사이트를 만들고 GitHub Pages로 배포한다
- main 브랜치에 push하면 GitHub Actions가 빌드, 검증, 배포를 자동으로 수행한다
- 이미지는 S3 + CloudFront로
statics.jun0.dev에 분리해서 서빙한다
이렇게 구성한 이유
포트폴리오용 기술 블로그를 운영하다 보니, 글을 올릴 때마다 배포나 이미지 관리가 신경 쓰였다. 그래서 정적 사이트는 GitHub Pages로 배포하고, 이미지는 S3 + CloudFront로 분리해서 statics.jun0.dev로 서빙하는 구조로 잡았다. 글 작성은 _posts/에만 집중하고, 배포는 GitHub Actions가 처리하는 형태가 목표였다.
전체 구조
1
2
3
4
5
6
7
8
글 작성(_posts/*.md)
↓
main 브랜치에 push
↓
GitHub Actions: Jekyll 빌드 → htmlproofer 검증 → GitHub Pages 배포
↓
logs.jun0.dev (사이트)
statics.jun0.dev (이미지 CDN: S3 + CloudFront)
정적 사이트
- Jekyll + Chirpy 테마로 정적 사이트를 생성한다
- 사이트는 GitHub Pages로 배포해
logs.jun0.dev에서 제공한다
로컬에서는 Jekyll 서버로 확인하고, 실제 배포는 CI에서 빌드한 결과물을 기준으로 한다.
CI/CD: GitHub Actions
main 브랜치에 push하면 GitHub Actions가 빌드, 검증, 배포를 자동으로 처리한다. 필요하면 수동 실행도 가능하다.
여기서 정리한 포인트는 아래다.
- 빌드 결과물을 바로 배포하지 않고, 내부 링크 검증을 통과한 경우에만 배포한다
- 빌드 job과 배포 job을 분리해서, 빌드 실패 시 배포가 진행되지 않는다
- 동시 배포는 하나만 허용하고, 새 배포가 들어오면 기존 배포는 취소되도록 설정했다
아래는 현재 사용 중인 GitHub Actions 워크플로우다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
name: "Build and Deploy"
on:
push:
branches:
- main
- master
paths-ignore:
- .gitignore
- README.md
- LICENSE
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3
bundler-cache: true
- name: Build site
run: bundle exec jekyll b -d "_site$"
env:
JEKYLL_ENV: "production"
- name: Test site
run: |
bundle exec htmlproofer _site \
--disable-external \
--ignore-urls "/^http:\\/\\/127.0.0.1/,/^http:\\/\\/0.0.0.0/,/^http:\\/\\/localhost/"
- name: Upload site artifact
uses: actions/upload-pages-artifact@v3
with:
path: "_site$"
deploy:
environment:
name: github-pages
url: $
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
이미지 CDN: S3 + CloudFront
블로그에 들어가는 이미지는 statics.jun0.dev로 분리해서 서빙하고 있다.
- 저장소: AWS S3
- CDN: CloudFront
- 도메인:
statics.jun0.dev
이렇게 분리한 이유는 아래와 같다.
- 정적 사이트 저장소에 이미지까지 넣지 않아도 돼서, 저장소와 배포 흐름을 단순하게 유지할 수 있다
- CloudFront를 앞에 두면 캐시를 활용할 수 있고, 원본 S3로 가는 트래픽도 줄일 수 있다
- 트래픽 기반 과금 구조로 비용 부담이 낮다 (거의 발생 X)
글 본문에서는 https://statics.jun0.dev/... 형태로 이미지를 참조한다.
정리
- 정적 사이트는 Jekyll + Chirpy로 구성하고, GitHub Pages로 배포한다
- main push 시 GitHub Actions로 빌드, 내부 링크 검증, 배포까지 자동화했다
- 이미지는 S3 + CloudFront로 CDN을 구성해서 사이트 저장소와 분리했다
- 글은
_posts/에 쌓이고, 하단 형식을 통일해 프로젝트 맥락을 정리한다
프로젝트: 포트폴리오 블로그(logs.jun0.dev) 관련 링크
- 사이트: logs.jun0.dev
- 이미지 CDN: statics.jun0.dev
- 테마: jekyll-theme-chirpy
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.