์์ ๋ ํธ๊น์ง๋ ์ ๋ถ ์๋ ๋ฐฐํฌ์๋ค.
์ด์ ๋ถํฐ๋ ์ง์ง ๊ฐ๋ฐ์๋ค์ด(?) CI/CD ์ด์ผ๊ธฐ๋ฅผ ์ ์ด๋ณด๋ ค ํ๋ค.
๋ด๊ฐ ์ค๊ณํ ํ๋ฆ์ ์ด๋ ๋ค.
git fetch / resetnpm install --omit=devnpm run buildpm2 restart onfit ์ ์๋์ผ๋ก ์ํ์ฆ,
PR = CI (๊ฒ์ฆ)
Merge = CD (๋ฐฐํฌ)
๊ฐ ๋๋๋ก ๋ง๋ ๊ฒ์ด๋ค.
๋จผ์ GitHub ๋ ํฌ ์ค์ ์์ Actions Secrets๋ฅผ ๋ง๋ค์๋ค.
Settings โ Secrets and variables โ Actions โ New repository secret๋ด๊ฐ ๋ง๋ ์ฃผ์ ์ํฌ๋ฆฟ๋ค์:
EC2_HOST : 35.74.238.231 (EC2 ํผ๋ธ๋ฆญ IP)EC2_KEY : onfit.pem ํ์ผ ๋ด์ฉ์ ๊ทธ๋๋ก ๋ณต๋ถํ ๊ฐEC2_KEY๋ ๋งฅ์์:
cat ~/Downloads/onfit.pem
๋ก ๋ด์ฉ์ ์ถ๋ ฅํด์ ๊ทธ๋๋ก ๋ณต์ฌ + GitHub Secret์ ๋ถ์ฌ ๋ฃ์๋ค.
(์ด๋ Keychain์ด ์ด๋ฆฌ๋ ค๊ณ ํ ๋๋ง๋ค ์ทจ์ํ๊ณ , ๊ทธ๋ฅ ํ ์คํธ๋ก ๋ณต์ฌํ๋ ๊ฒ ํฌ์ธํธ.)
๋ ํฌ ๋ฃจํธ์์:
.github/workflows/deploy.yml
์ ๋ง๋ค๊ณ ์๋ ๋ด์ฉ์ ์์ฑํ๋ค.
name: Deploy to EC2
on:
push:
branches:
- main # main์ push๋ ๋๋ง๋ค ์คํ
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Deploy on EC2 via SSH
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_KEY }}
script: |
cd /home/ubuntu/on-fit/on-fit-next
echo "[DEPLOY] git fetch & reset to origin/main..."
git fetch origin
git reset --hard origin/main
echo "[DEPLOY] install dependencies..."
npm install --omit=dev
echo "[DEPLOY] build..."
npm run build
echo "[DEPLOY] restart pm2..."
pm2 restart onfit || pm2 start npm --name "onfit" -- start
echo "[DEPLOY] done."
์ฌ๊ธฐ์ ๊ฒฝ๋ก๋ ์ค์ EC2 ์์์์ ํ๋ก์ ํธ ์์น์ ๋ง์ถฐ์ผ ํ๋ค.
/home/ubuntu/on-fit/on-fit-next
์ด๊ธฐ์๋ SSH ํ์์์(i/o timeout) ์๋ฌ๋ ๋ฌ์๋๋ฐ, ๊ทธ๊ฑด ๋ณด์ ๊ทธ๋ฃน์์ 22๋ฒ ํฌํธ๋ฅผ GitHub Actions์์ ์ ๊ทผ ๊ฐ๋ฅํ๊ฒ ์ด์ด์ฃผ๋ฉด์ ํด๊ฒฐํ๋ค.
์ด์ main์ ์ด๋ค ์ปค๋ฐ์ด ํธ์๋๋ฉด Actions ํญ์์ ์ด๋ ๊ฒ ๋ก๊ทธ๊ฐ ๋์จ๋ค.
๊ทธ ํ https://onfit.today์ ์ ์ํ๋ฉด ๊ณง๋ฐ๋ก ์ต์ ์ฝ๋๊ฐ ๋ฐ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
CD๊น์ง ๊ตฌ์ถํ๊ณ ๋๋, ํ ๊ฐ์ง ๊ฑฑ์ ์ด ๋จ์๋ค.
โ๋ง์ฝ ๋น๋๊ฐ ๊นจ์ง๋ ์ฝ๋๋ฅผ main์ mergeํ๋ฉด?
EC2 ๋ฐฐํฌ ๋จ๊ณ์์ ๋ฐ๋ก ํฐ์ง๋ ๊ฑฐ ์๋๊ฐโฆ?โ
๊ทธ๋์ main์ ๋ค์ด๊ฐ๊ธฐ ์ ์ ๋ฌด์กฐ๊ฑด ๋น๋๊ฐ ์ฑ๊ณตํ๋์ง ํ์ธํ๋ CI๋ฅผ ์ถ๊ฐํ๋ค.
on-fit-next ํ๋ก์ ํธ๊ฐ on-fit ๋ ํฌ ์์ชฝ์ ์์ผ๋ฏ๋ก,
working directory๋ฅผ ./on-fit-next๋ก ์ง์ ํ๋ ๊ฒ ์ค์ํ๋ค.
.github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [ main ] # dev -> main PR
push:
branches: [ dev ] # dev์ pushํ ๋๋ ์ฒดํฌ
jobs:
build:
runs-on: ubuntu-latest
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.NEXT_PUBLIC_SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }}
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
working-directory: ./on-fit-next
run: npm install
- name: Build project
working-directory: ./on-fit-next
run: npm run build
์ฌ๊ธฐ์ ์ค์ํ ํฌ์ธํธ๋ ๋ ๊ฐ์ง์๋ค.
working-directory ๋ฅผ ๊ผญ ./on-fit-next๋ก ์ค์
โ ๋ฃจํธ(on-fit)์๋ package.json์ด ์์ด์, ์ฒ์์ ENOENT ์๋ฌ๊ฐ ๋ฌ์๋ค.
Supabase ํ๊ฒฝ๋ณ์ ๋ฅผ secrets์ ๋ฃ๊ณ env๋ก ์ฃผ์
โ CI ํ๊ฒฝ์ .env ํ์ผ์ด ์์ด์, supabaseUrl is required ์๋ฌ๊ฐ ๋ด๋ค.
โ NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY ๋ฑ์ Secrets์ ๋ฃ๊ณ env๋ก ๋๊ธฐ๋ ํด๊ฒฐ.
CI๋ฅผ ๋๋ฆฌ๋ฉด์ ๋ช ๊ฐ์ง ๋ฌธ์ ๋ฅผ ์ฌ์ ์ ์ก์ ์ ์์๋ค.
@radix-ui/react-dialogDialog ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋ @radix-ui/react-dialog๋ฅผ ์ฌ์ฉํ๋๋ฐ,
๋ก์ปฌ์ ์ค์น๋์ด ์์ง๋ง package.json์ ๋ฐ์์ด ์ ๋ผ ์์ด์ CI์์ ์ด๋ฐ ์๋ฌ๊ฐ ๋ฌ๋ค.
Module not found: Can't resolve '@radix-ui/react-dialog'
ํด๊ฒฐ:
cd on-fit-next
npm install @radix-ui/react-dialog
git add package.json package-lock.json
git commit -m "fix: add radix dialog dependency"
์๋ฅผ ๋ค์ด ์ด๋ฐ ํ์ ์๋ฌ๊ฐ ์์๋ค.
Type error: Type 'string | undefined' is not assignable to type 'string'.
PostInfo โ ReportModal๋ก ๋๊ธฐ๋ props์์:
<ReportModal
...
postTitle={data?.title ?? ""}
targetUserId={data?.profile?.id}
/>
targetUserId๊ฐ string | undefined๋ผ์ ์๋ฌ.
CI๊ฐ ์๋ค๋ฉด ์ค์ ๋ฐฐํฌํ ๋๊น์ง ๋ชฐ๋์ ์ด์์๋ค.
์์ :
<ReportModal
...
postTitle={data?.title ?? ""}
targetUserId={data?.profile?.id ?? ""}
/>
๋ํ useSearchParams๋ฅผ ์ฌ์ฉํ๋ /auth ํ์ด์ง์์
Next.js 16์ โCSR bail-out + Suspenseโ ๊ด๋ จ ๊ฒฝ๊ณ /์๋ฌ๋ ์ก์ผ๋ฉด์,
์๋ฒ ์ปดํฌ๋ํธ์ ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉํฅ์ผ๋ก ๋ฆฌํฉํฐ๋ง๊น์ง ์งํํ๋ค.
CI๊น์ง ๋ง๋ค๊ณ ๋์ ๋ง์ง๋ง์ผ๋ก ํ ๋จ๊ณ ๋:
โCI๊ฐ ์คํจํ๋ฉด ์์ main์ ๋จธ์ง ์์ฒด๊ฐ ์ ๋๊ฒ ๋ง๋ค์.โ
GitHub์์:
main์ ๋ํด Add branch protection ruleBranch name pattern: mainCI ์ํฌํ๋ก์ฐ ์ ํ์ด๋ ๊ฒ ์ค์ ํ๋ฉด:
์ฆ, โ๋น๋ ์ ๋๋ ์ฝ๋๋ main์ ๋ค์ด๊ฐ ์ ์๋คโ๋ ๊ท์น์ด ๊ฐ์ ๋๋ค.
์ด์ ์จํ์ ๊ธฐ๋ณธ ๊ฐ๋ฐ/๋ฐฐํฌ ํ๋ก์ฐ๋ ์ด๋ ๊ฒ ๋์๊ฐ๋ค.
๊ฐ๋ฐ์๋ dev ๋ธ๋์น์์ ์์
npm run build ๋ก์ปฌ ํ์ธdev์ push
โ GitHub Actions CI๊ฐ ์๋์ผ๋ก ๋น๋ ๋๋ฆผ
dev โ main PR ์์ฑ
Merge pull request ๋ฒํผ ํด๋ฆญ
Deploy to EC2 ์ํฌํ๋ก์ฐ ์คํ๋ฐฐํฌ ์ํฌํ๋ก์ฐ (CD) ์ํ
git reset --hard origin/mainnpm install --omit=devnpm run buildpm2 restart onfit์ฌ์ฉ์ ๋ธ๋ผ์ฐ์
https://onfit.today ์ ์์ด๋ฒ ์จํ ํ๋ก์ ํธ ๋ฐฐํฌ๋ฅผ ์ค๋นํ๋ฉด์:
์ด๋ผ๋ ์ ์ฒด ํ๋ฆ์ ์ฒ์๋ถํฐ ๋๊น์ง ์ง์ ๊ฒช์ด๋ดค๋ค.
๊ฐ์ฅ ํฌ๊ฒ ๋๋ ๋ ๊ฐ์ง๋:
์ด์ ์จํ์์ ๊ธฐ๋ฅ์ ํ๋ ์ถ๊ฐํ ๋๋ง๋ค:
dev์ ์ฝ๋๋ฅผ ์ฌ๋ฆฌ๊ณ ,
PR์์ CI ์ด๋ก๋ถ ํ์ธํ๊ณ ,
Merge โ ์๋ ๋ฐฐํฌ โ onfit.today์์ ๋ฐ๋ก ํ์ธ.
์ด ๋ฃจํด์ด ๋๊ฐ์ด ๋ฐ๋ณต๋๋ค.