Dokcer, AWS, Cloudflare๋ฅผ ๋น๊ตํด์ ๋ฐฐํฌํด๋ณด๊ณ Cloudflare๋ก ๋ฐฐํฌํ๊ฒ๋ ์ด์ผ๊ธฐ์ ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ์ฐ๋ฆฌ NDD ํ์ Cloudflare๋ฅผ ์ฌ์ฉํด์ React ํ์ด์ง๋ฅผ ๋ฐฐํฌํ๊ฒ ๋์์ต๋๋ค. ์ด ๊ธ์ ์ ์๋ง์ ์ ํ์ง์ค์ Cloudflare๋ฅผ ์ฌ์ฉํด์ ๋ฐฐํฌํ๊ฒ ๋์๋์ง์ ๋ํ ๊ณผ์ ์ด ๋ด๊ฒจ์์ต๋๋ค.
์ฌ๋ฌ๊ฐ์ง ๋ฐฐํฌ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ธฐ ์ ์ ๋จผ์ React ๋ฐฐํฌ ํ๋ก์ธ์ค์ ๋ํด ๊ฐ๋จํ๊ฒ ์ง๊ณ ๋์ด๊ฐ๊ฒ ์ต๋๋ค.
๋น๋
: React ์ ํ๋ฆฌ์ผ์ด์
์ด ๋ฒ๋ค๋ฌ(Webpack, Vite ๋ฑ)์ ํตํด ๋น๋๋์ด ์ ์ ํ์ผ๋ก ๋ณํ๋ฉ๋๋ค.ํ์ผ ์
๋ก๋
: ๋น๋๋ ์ ์ ํ์ผ์ด ์๋ฒ์ ์
๋ก๋๋ฉ๋๋ค. ์๋ฒ์ ์
๋ก๋๋ ํ์ผ์ ์ธํฐ๋ท์ ํตํด ์ ๊ทผ ๊ฐ๋ฅํ๊ณ ํด๋ผ์ด์ธํธ๊ฐ ํด๋น ์ฃผ์๋ก ์ ์ ์ ๋ฒ๋ค๋ง๋ ์ ์ ํ์ผ์ ์ ๊ณตํด์ค๋๋ค.์ฌ์ฉ์ ๋์
: ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ )๋ ์๋ฒ๋ก๋ถํฐ ๋ฐ์์จ ์ ์ ํ์ผ์ ๋ค์ด๋ก๋๋ฐ์ ์น ํ์ด์ง๋ฅผ ๋๋๋งํฉ๋๋ค.์ ๊ณผ์ ์ ๊ฑฐ์น๋ฉฐ ์ ์ ํ์ด์ง๊ฐ ๋ฐฐํฌ๋๋๋ฐ์. ์ฌ๊ธฐ์ ์ฃผ์ํด์ผ ํ ์ ์ React๋ SPA๊ตฌ์กฐ๋ก ๋์ด์์ด ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ root(/) ๊ฒฝ๋ก์์ /user๋ฑ์ ๊ฒฝ๋ก๋ก ์ด๋ํด๋ ์ค์ ๋ก๋ index.html ํ ํ์ผ ๋ด์์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ๋๋ฌธ์ ์ด์ ๋ํ ์๋ฒ ์ค์ ์ ๋ณ๋๋ก ํ์ง ์์ผ๋ฉด /user ๊ฒฝ๋ก๋ก ์ด๋์ 404ํ์ด์ง๊ฐ ๋ฐํ๋ฉ๋๋ค. ๋ฐ๋ผ์ Nginx๋ฑ์ ์น ์๋ฒ์ ํจ๊ป ๋ฐฐํฌํด์ ๋ชจ๋ ๊ฒฝ๋ก ์์ฒญ์ index.html๋ก ๋ฆฌ๋ค์ด๋์ ํ๋ ๋ก์ง์ ๊ตฌํํด์ผ ํฉ๋๋ค.
์ฌ์ค React๋ ์ ์ ์ฌ์ดํธ๋ผ์ Docker๋ฅผ ์ฌ์ฉํด์ ๋ฐฐํฌํ์ ๋ ์ป์ ์ ์๋ ์ฅ์ ์ด ๊ฑฐ์ ์์ต๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ ๊ฐ ์ด ์ ํ์ง๋ฅผ ๊ณ ๋ คํ๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์์ ๊ฐ์ ์ด์ ๋ค์ด ์์์ง๋ง ์ฐ๋ฆฌ ํ์ Docker๋ฅผ ์ ํํ์ง ์์์ต๋๋ค. ๊ทธ ์ด์ ๋ ์ฐ๋ฆฌ๊ฐ NCP๋ฅผ ์ฌ์ฉํ์ง ์๊ธฐ๋ก ๊ฒฐ์ ํด์ ํธ์คํ ์๋ฒ๋ฅผ ๋ณ๊ฒฝํ ์ผ๋ ์์๊ณ , ๋ชจ๋ ธ๋ ํฌ๋ผ๊ณ ํด์ ๊ผญ ํ ์๋ฒ์ ์ ๋ก๋ํ ํ์๋ ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ฐ๋ฆฌ ํ์ NCP ๋์ AWS EC2๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๊ณ , ํด๋ผ์ด์ธํธ์ ์๋ฒ๋ฅผ ํ ๊ณณ์ ์ ๋ก๋ํ๋ ๊ฒ์ ์คํ๋ ค EC2์ ๋น์ฉ๋ง ์ฆ๊ฐ์ํค๋ ์ผ์ด๊ธฐ ๋๋ฌธ์ ์ด ์ ํ์ง๋ ๊ธฐ๊ฐ๋์์ต๋๋ค.
์๊น ์ ๊ฐ Docker ๋์ ์ ์ผ๋ํ๋ ํฐ ์ด์ ์ค ํ๋๋ ์ด์ ์ Docker๋ฅผ ํตํด ๋ฐฐํฌํ๋ ๊ฒฝํ์ด ์์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ทธ ๋๋ ๋ฐฐํฌ ๋ฐฉ์์ ๋ํด ํฐ ๊ณ ๋ฏผ์ ํ์ง ์๊ณ ๋ฐ๋ก Docker๋ฅผ ์ฌ์ฉํ์๋๋ฐ์. ๊ทธ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์์ต๋๋ค.
name: Docker CD
on:
push:
branches:
- 'production'
tags:
- 'v*'
pull_request:
branches:
- 'production'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'
- name: Make env
run: |
touch ./.env
echo "${{ secrets.ENV }}" > ./.env
echo .env
shell: sh
- name: Install dependencies
run: yarn
- name: Build Project
run: yarn build
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: |
${{ secrets.DOCKER_USERNAME }}/home-appcenter
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
- name: Deploy
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
script: |
docker stop inu-hompage
docker rm inu-hompage
docker pull ${{ secrets.DOCKER_USERNAME }}/home-appcenter:production
docker run -d --name inu-hompage -p 3000:3000 ${{ secrets.DOCKER_USERNAME }}/home-appcenter:production
docker image prune -f
AWS๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ ํ S3๋ผ๋ ์ ํ์ง๊ฐ ์๊ฒผ์ต๋๋ค! S3๋ AWS์์ ์ ๊ณตํด์ฃผ๋ ๊ฐ์ฒด ์คํ ๋ฆฌ์ง ์๋น์ค์ ๋๋ค. React๋ ์ ์ ์ฌ์ดํธ์ด๋ฏ๋ก ์คํ ๋ฆฌ์ง์ ๋ฒ๋ค๋ง๋ ํ์ผ์ ์ฌ๋ ค๋๋ ๋ฐฉ์์ผ๋ก๋ ๋ฐฐํฌํ ์ ์์ต๋๋ค. S3๋ฅผ ์ฌ์ฉํด์ ๋ฐฐํฌํ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ๋ค์ ์ป์ ์ ์์ต๋๋ค.
IAM ์๋น์ค๋ก ์ด๋ํด์ ์ฌ์ฉ์ ์์ฑ ๋ฒํผ์ ํด๋ฆญํฉ๋๋ค.
IAM ์ฌ์ฉ์์๊ฒ ๋ค์ ๊ถํ์ ๋ถ์ฌํฉ๋๋ค.
์ฌ์ฉ์๋ฅผ ์์ฑํฉ๋๋ค.
์ก์ธ์คํค๋ฅผ ์์ฑํ๊ณ ์ ์ฅํด๋ก๋๋ค. (๋ค์ ๋ณผ ์ ์์ผ๋ ๊ผญ!! ์ ์ฅํด๋์ ์ผ ํฉ๋๋ค.)
๋ฒํท์ ์ ๋นํ ์ด๋ฆ๊ณผ ๋ฆฌ์ ์ ์ ํํฉ๋๋ค.
ํผ๋ธ๋ฆญ ์ก์ธ์ค ์ฐจ๋จ์ ์ฒดํฌ๋ฐ์ค ํด์ ๋ฅผ ํด์ค์๋ค.
๋๋จธ์ง ์ต์ ์ ๊ทธ๋๋ก ๋์ฑ๋ก ๋ฒํท์ ์์ฑํฉ๋๋ค.
์์ฑ๋ ๋ฒํท์ ์์ฑ ํญ์ผ๋ก ์ด๋ํด์ ๋งจ ์๋๋ก ์คํฌ๋กค์ ๋ด๋ ค์ ์ ์ ์น ์ฌ์ดํธ ํธ์คํ ์ค์ ์ ๋ค์ด๊ฐ๋๋ค.
์ ์ ์น ์ฌ์ดํธ ํธ์คํ ์ต์ ์ ํ์ฑํ๋ก ๋ฐ๊ฟ์ค ํ ์ธ๋ฑ์ค ๋ฌธ์์ ์ค๋ฅ ๋ฌธ์์ ํ์ผ๋ช ์ index.html๋ก ๋ณ๊ฒฝํด์ค๋๋ค.
๋ฒํท์ ๊ถํ ํญ์ผ๋ก ์ด๋ํด์ ๋ฒํท ์ ์ฑ ์ ํธ์งํฉ๋๋ค.
๋ฒํท ARN์ ๋ณต์ฌํ ํ ์ ์ฑ ์์ฑ๊ธฐ๋ก ์ด๋ํฉ๋๋ค.
์๋์ ๊ฐ์ด ์ ์ฑ ์ ์ค์ ํฉ๋๋ค.
GetObject
๋ฅผ ์ ํํฉ๋๋ค./*
๋ฅผ ๋ถ์ฌ์ค๋๋ค.Generate Policy๋ฅผ ๋๋ฌ์ ์์ฑ๋ ์ ์ฑ ์ ๋ณต์ฌํฉ๋๋ค.
์์ฑ๋ ์ ์ฑ ์ ์ถ๊ฐํฉ๋๋ค.
name: Deploy React App to Amazon S3
on:
push:
branches:
- dev
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Change to FE directory
run: cd ./FE
- name: Install Dependencies
run: yarn install
working-directory: ./FE
- name: Build
run: yarn build
working-directory: ./FE
- name: Deploy to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
aws s3 sync ./FE/dist/ s3://${{ secrets.AWS_S3_BUCKET }} --region ap-northeast-2 --delete
์ฐ๋ฆฌํ์ ๋ ํฌ์งํ ๋ฆฌ๋ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ก ์ฌ๋ผ๊ฐ์์๊ธฐ ๋๋ฌธ์ FE ๋๋ ํฐ๋ฆฌ๋ก ์ด๋ํ๋ ๊ณผ์ ์ ์คํฌ๋ฆฝํธ์ ์ถ๊ฐ๋ก ์์ฑํ์ต๋๋ค.
โโโ BE
โโโ FE
โโโ README.md
์ด ์ก์ ํ์ผ์ ํ์ํ ํ๊ฒฝ๋ณ์๋ ์๋์ ๊ฐ์ต๋๋ค.
AWS_ACCESS_KEY_ID
: ์์์ ์์ฑํ IAM ์ฌ์ฉ์์ ์์ธ์ค ํค ID
AWS_SECRET_ACCESS_KEY
: IAM ์ฌ์ฉ์์ ์์ธ์ค ํค๋ฅผ ์ฒ์ ๋ฐ๊ธ๋ฐ์ ๋ ๋ฐ์๋ ์ํฌ๋ฆฟ ํคAWS_S3_BUCKET
: S3 ๋ฒํท์ ์ด๋ฆ์์ ๊ฐ์ ๊ณผ์ ์ ๊ฑฐ์น๊ณ Github Action์ด ์ํ๋๊ณ ๋๋ฉด ์๋์ ๊ฐ์ด S3 ๋ฒํท์ ๋น๋๋ ํ์ผ์ด ์ฌ๋ผ๊ฐ๋๋ค.
ํ์ง๋ง index.html์ ์ ๊ทผํด๋ณด๋ฉด ์ฐ๋ฆฌ์ ํ์ด์ง๋ ๋ณด์ด์ง ์๊ณ 404์๋ฌ ๋ฉ์์ง๋ง ๋ํ๋๊ฒ ๋ฉ๋๋ค.
๋ค๋ฅธ ํ์ ๊ฒฝ๋ก๋ก ์ ์ํด๋ณด๋ฉด 403 ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค. ์๋ํ๋ฉด S3 ๋ฒํท์์ ํผ๋ธ๋ฆญ ์ ๊ทผ์ index.html๋ง ํ์ฉ๋์ด ์๊ธฐ ๋๋ฌธ์ด์ฃ .
์ด๋ฌํ ๋ฌธ์ ์ ์ ์ปค์คํ ์๋ฌ ์๋ต์ ์ค์ ํด์ ํด๊ฒฐํ ์ ์์ต๋๋ค. ๊ธ ์ด๋ฐ๋ถ์์ ์ค๋ช ํ๋ฏ์ด SPA์์ ๋ผ์ฐํฐ๊ฐ ์ ์์ ์ผ๋ก ๋์ํ๊ธฐ ์ํด์๋ ์น์๋ฒ ๋ฑ์์ ๋ฆฌ๋ค์ด๋์ ํ๋ ๊ณผ์ ์ด ํ์ํ๋ฐ์. CloundFront์์ ์๋ฌ ํ์ด์ง๋ฅผ index.html๋ก ์ปค์คํ ํ๋ฉด ์ด ๋์์ ๊ตฌํํ ์ ์์ต๋๋ค.
CloudFront ๋ฐฐํฌ ์์ฑํ๊ธฐ AWS CloudFront ์๋น์ค์ ๋ค์ด๊ฐ์ S3๋ก ๋ฐฐํฌ๋ ์น์ฌ์ดํธ์ ๋๋ฉ์ธ์ ์ ๋ ฅํฉ๋๋ค.
์น ์ ํ๋ฆฌ์ผ์ด์ ๋ฐฉํ๋ฒฝ์ ๋นํ์ฑํ ํ ํ ๋ฐฐํฌ๋ฅผ ์์ฑํฉ๋๋ค. (๋ฐฉํ๋ฒฝ ํ์ฑํํ๋ฉด ๋๋ค์ด์!)
์์ฑ๋ ๋ฐฐํฌ์์ ์ฌ์ฉ์ ์ ์ ์ค๋ฅ ์๋ต ์์ฑ ๋ฒํผ์ ํด๋ฆญํฉ๋๋ค.
์๋์ ๊ฐ์ด 404 ์๋ฌ์ ๋ํด index.html๋ก ๋ฆฌ๋ค์ด๋์ ์์ผ์ฃผ๊ณ 200 ์๋ต์ ๋ด๋ ค์ฃผ๋ ์ปค์คํ ์๋ต์ ์์ฑํฉ๋๋ค.
403 ์๋ฌ์ ๋ํด์๋ ๋์ผํ ์ฒ๋ฆฌ๋ฅผ ํด์ค๋๋ค.
CloudFront์ ๋ฐฐํฌ ๋๋ฉ์ธ์ผ๋ก ์ ์ํ๋ฉด ํ์ด์ง๊ฐ ์ ์์ ์ผ๋ก ํ์๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
์์ ๊ณผ์ ์ฒ๋ผ S3์ CloudFront์ ๋ํด ํ์ตํ๊ณ ๋ฐฐํฌํ๋ ๊ณผ์ ๋ ์ง์ ์ํํ์ง๋ง ์ด ๋ฐฉ๋ฒ์ ์ ํํ์ง ์์์ต๋๋ค. ์๋ํ๋ฉด ๋ฒ์ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ด Cloudflare์ ๋นํด ๋น์ฝํ๊ธฐ ๋๋ฌธ์ธ๋ฐ์. Cloudflare์์๋ ๋ฉ์ธ ๋ธ๋์น๋ก PR์ด ๋จธ์ง๋ ๋ ๋ง๋ค ํด๋น ๋ฒ์ ์ ๋ํ preview URL์ ์์ฑํด์ฃผ๋ ๊ธฐ๋ฅ์ ์ง์ํด์ค๋๋ค. ์ด ๋ฐ์๋ S3์ CloudFront์์ ํ ์ ์๋ ์ผ๋ค์ ์์ ํธํ๋๋ ์์ ์๋ค Cloudflare์์ ์ํํ ์ ์์๊ธฐ ๋๋ฌธ์ S3์ CloudFront ๋์ Cloudflare๋ฅผ ์ ํํ์ต๋๋ค.
์ฐ๋ฆฌํ์ ์ต์ข ์ ์ผ๋ก Cloudflare๋ฅผ ์ฌ์ฉํ ๋ฐฐํฌ ๋ฐฉ์์ ์ฑํํ์ต๋๋ค. ์๋ํ๋ฉด ์๋์ ๊ฐ์ ์ฅ์ ๋ค์ด ์์๊ธฐ ๋๋ฌธ์ ๋๋ค.
Cloudflare์์ Workers & Pages ํญ์ ๋ค์ด๊ฐ๋๋ค.
Pages ํญ์์ Connect to Git
๋ฒํผ์ ๋๋ฌ ๋ ํฌ์งํ ๋ฆฌ ์ ์ฅ์์ ์ฐ๊ฒฐํฉ๋๋ค.
Connect Github๋ฅผ ํตํด ๊นํ๋ธ์ ์ฐ๋ํฉ๋๋ค.
์ฐ๊ฒฐํ๊ณ ์ถ์ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์ ํํ ํ ์ค์ ์ ๋ง์นฉ๋๋ค.
ํ๋ก์ ํธ์ ๋น๋ ์์ ์ ๋ง๊ฒ ์๋ ๊ฐ๋ค์ ์ค์ ํด์ค๋๋ค.
Save and Deploy๋ฅผ ๋๋ฌ์ฃผ๋ฉด ๋น๋ ์ค์ ์ด ์๋ฃ๋ฉ๋๋ค~!
Docker, S3์ CloudFront, Cloudflare๋ฅผ ํตํด React ์น์ฌ์ดํธ๋ฅผ ๋ฐฐํฌํด๋ณธ ๊ฒฐ๊ณผ Cloudflare๋ฅผ ์ฌ์ฉํด์ ๋ฐฐํฌํ๋ ๋ฐฉ์์ ์ฑํํ์ต๋๋ค. ์ง๊ธ๊น์ง ๋ฐฐํฌ ์ ๋ฌด๋ฅผ ์งํํ ๋๋ ํฐ ํ์ต ์์ด "์ฌ๋ฆฌ๊ธฐ๋ง ํ๋ฉด ๋๋ค!" ๋ผ๋ ์๊ฐ์ ๊ฐ๊ณ ์์๋๋ฐ์. ์ด๋ฒ ๊ธฐํ์ ๋ค์ํ ๋ฐฐํฌ ๋ฐฉ์์ ๋ํด ํ์ต ํด๋ณผ ์ ์๊ฒ ๋์ด ์ ์ตํ์ต๋๋ค.๐ ํ์ตํ ๋ด์ฉ์ ๋นํด Cloudflare์์ ๋๋ฌด ์ฝ๊ฒ ๋ฐฐํฌ๋ฅผ ์งํํ ์ ์์ด์ ํ๋ฌดํ๊ธฐ๋ ํ์ต๋๋ค. (~~๋ก๋ด์๊ฒ ์ผ์๋ฆฌ๋ฅผ ๋บ๊ธด ๋ ธ๋์๊ฐ ๋ ๊ธฐ๋ถ~~) ์์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ Cloudflare์ ๋ค์ํ ๊ธฐ๋ฅ์ ๋ํด ์๊ฒ๋๋ค๋ฉด ์ถ๊ฐ๋ก ํฌ์คํ ํ๊ฒ ์ต๋๋คใ ใ