"자동화는 귀찮음을 줄이기 위한 고도의 귀찮음이다.”
단순한 스크립트 한 줄부터, nginx의 루트 경로, docker volume 마운트, 그리고 마지막 curl 헬스 체크까지
작은 시행착오 속에서 쌓아올린 CI/CD 구축기를 공유해보겠습니다.
요즘은 많은 프론트엔드 개발자 분들이 Vercel을 활용해 배포하는 것이 일반적입니다. 배포가 편리하고 깃헙 연동이 쉽다는 장점 때문에 다들 많이 채택하고 있는 것 같아요. 저희 팀은 익숙하고 손쉬운 기술을 계속 사용하는 것에 그치지 말고 다른 기술들을 경험해보고 성장해보자는 의견이 많았습니다. 그런 고민 끝에, Vercel 이 정말 장점만 있을까 좀 더 톺아보았어요.
Vercel은 호스팅 인프라가 퍼블릭 클라우드에 위치하기 때문에 망 분리된 내부 환경에서는 배포가 어렵습니다. 민감 데이터나 사내 시스템과 연동할 경우 망 분리된 환경에서 운영해야 하는데, Vercel 은 이러한 환경을 지원하지 않습니다.
특히 보험 서비스라는 도메인 특성상, 법적·보안적 규제 요건을 충족하기 위한 배포 구조가 필요했기에, Vercel의 사용이 장기적으로는 적합하지 않을 수 있다는 판단이 들었습니다.
그러다 Nginx와 Jenkins 배포를 시도해보자는 의견으로 좁혀졌고 저희 팀은 향후 스프린트에서 실제 유저 데이터를 다룰 가능성을 고려하여 이 방식을 시도해보기로 했습니다. 물론 이 방식이 무조건 보안적으로 우월하다고 단언할 수는 없지만, 모두가 편리한 Vercel에 익숙해진 이 환경 속에서 과거의 방식이자 다소 번거로운 배포 방식을 직접 구성해본 경험은 기술적 성장과 시스템에 대한 깊은 이해라는 측면에서 충분히 의미 있는 도전이었다고 생각합니다.
소개 (CI/CD와 Jenkins, Docker, Nginx 개요)
CI/CD란 지속적 통합(Continuous Integration)과 지속적 배포(Continuous Delivery/Deployment)의 줄임말입니다. 개발자가 코드를 변경해 저장소에 푸시하면 자동으로 빌드와 테스트를 수행하고, 이상이 없다면 배포까지 진행하는 파이프라인을 의미합니다 . 이러한 자동화는 개발과 배포 사이의 과정을 효율화하여 더 빠르고 안정적인 업데이트를 가능하게 합니다.
이 글에서는 프론트엔드 프로젝트에 CI/CD 파이프라인을 구축한 과정을 다룹니다. 사용된 주요 도구들은 다음과 같습니다.
Jenkins
- Jenkins는 오픈소스 기반의 자동화 서버
- 코드 변경 시 테스트 및 배포 파이프라인을 자동으로 실행할 수 있습니다.
- GitHub와 연동하여 push 이벤트가 발생하면 즉시 빌드 및 배포 작업을 트리거할 수 있습니다.
- Pipeline Script (Jenkinsfile) 기반 빌드/배포
- 오픈소스 자동화 서버
- 주요 특징:
- 다양한 빌드/배포 스크립트 구성 가능 (Pipeline)
- GitHub push → Docker build → 컨테이너 재시작까지 자동화 /배경
- 이번 프로젝트에서는:
- init/cicd-deploy 브랜치 push 시 자동 빌드
- Dockerfile, docker-compose-dev.yml 등을 조합하여 client 배포
Docker & Docker Compose
- Docker: 애플리케이션을 컨테이너화하여 환경에 상관없이 동일하게 실행되도록 도와줍니다.
- Docker Compose: 여러 개의 Docker 컨테이너 서비스를 정의하고 실행할 수 있는 YAML 기반 도구입니다. 프론트(client), 백엔드(blue/green), Nginx, Certbot, Jenkins 등을 하나의 네트워크로 관리합니다.
Nginx
- 가볍고 고성능인 웹 서버입니다. 정적 파일(HTML, CSS, JS)을 클라이언트 요청에 맞춰 제공하는 HTTP 웹 서버
- 정적 파일 서비스, SSL 적용, 백엔드 연결 등을 담당
- docker-compose-dev.yml에서 Nginx 컨테이너 설정
- nginx.conf, api.bofit.conf, service-env.inc 등 직접 구성
- 이번 구축에서는 Nginx가 정적 프론트엔드 파일을 서비스하고, 동시에 API 서버와 Jenkins로의 프록시 역할도 담당합니다.
📌 nginx.conf에서 client:80 같은 컨테이너 네이밍 사용 시, docker network 명시 필요
시스템 아키텍쳐

전체 시스템은 AWS EC2 서버 한 대에서 동작하도록 구성했습니다.
- 각 서비스는 도커 컨테이너로 분리되어 관리한다.
- https://bofit.co.kr 도메인 하나로 서비스, API, Jenkins UI를 모두 제공
| 구성 요소 | URL | 설명 |
| 프론트엔드 서비스 | https://bofit.co.kr | 웹 애플리케이션 |
| 백엔드 API | https://bofit.co.kr/api/v2/ | RESTful API |
| Jenkins | https://bofit.co.kr/jenkins | CI/CD 관리 UI |
Nginx 를 통해 외부 요청을 라우팅합니다. 개발자가 소스 코드를 GitHub에 푸시하면 GitHub Webhook이 Jenkins에 통지하여 파이프라인이 시작되고, 최종적으로 빌드 결과물이 Nginx를 통해 배포됩니다.
- EC2 서버: Ubuntu 기반의 클라우드 서버 한 대를 사용했습니다. Jenkins와 Nginx 모두 이 서버에서 동작하며, Jenkins는 Docker 컨테이너로 띄웠습니다
- Jenkins (CI 서버): Webhook을 받아 빌드/배포 파이프라인을 실행합니다. Jenkins 컨테이너 내부에서 프론트엔드 빌드를 수행하며, 결과물(dist 디렉터리)을 준비합니다. Nginx를 통해 접근 가능하도록 설정하여, Jenkins 대시보드는 https://bofit.co.kr/jenkins 경로로 접속할 수 있게 만들었습니다.
- Nginx (웹 서버): EC2 서버에 설치된 웹 서버로 80포트(HTTPS 설정 시 443포트)를 사용합니다. 하나의 도메인(bofit.co.kr 예시)을 통해 여러 서비스에 접근하기 위해 경로 기반 라우팅을 설정했습니다.
- /jenkins 경로로 들어오는 요청 → Jenkins 컨테이너로 프록시(Mirror Jenkins의 8080포트).
- /api/v2 경로로 들어오는 요청 → 백엔드 API 서버로 프록시
- / (루트 경로) 요청 → Nginx가 로컬 디렉토리에 있는 프론트엔드 정적 파일을 직접 제공. 사용자가 별도 경로 없이 도메인에 접속하면 빌드된 index.html 파일이 반환됩니다.
이 아키텍처를 통해 하나의 서버/도메인에서 jenkins 대시보드, API 프론트엔드 서비스를 모두 이용할 수 있습니다.
FE CD/CD 동작 흐름
제가 의도한 액션 흐름은 Github main 브랜치에 PR 이 머지가 되면, 바로 서비스 배포가 되도록 구현하고자 했습니다.
어떻게 gitHub 에서 jenkins 를 거쳐 배포되는지 흐름을 톺아보겠습니다. 3 차례 흐름을 엎고 다시 만들었고, 그 중 최종 본 기준으로 설명하겠습니다.
- GitHub main 브랜치 푸시
FE 레포 원격 저장소 main 브랜치에 push (PR merge) 되면 이벤트가 발생합니다. jenkins 와 연동하기 위해 GitHub Webhook을 설정하여 push 이벤트를 Jenkins에 알려주도록 했습니다. - Jenkins 빌드 트리거
Webhook을 받은 Jenkins는 해당 저장소의 파이프라인 Job을 실행시킵니다. 이때 Jenkins가 GitHub으로부터 소스 코드를 가져와 (git clone) 워크스페이스에 최신 소스를 준비합니다. - 의존성 설치 & 프론트 코드 빌드
jenkins 는 미리 정의 된 Pipeline 스크립트에 따라 npm 설치 및 빌드 작업을 진행합니다. Jenkins 환경에 Node.js가 기본 설치되어 있지 않으므로, NodeJS 플러그인을 사용해 빌드 시 필요한 Node 버전을 세팅했습니다 . 빌드가 성공하면 dist/ 폴더 등에 최종 정적 리소스들이 생성됩니다. - 배포 스크립트 실행
Jenkins는 빌드 산출물(dist 폴더)을 준비한 뒤 배포 단계를 진행합니다. 배포 단계에서는 미리 작성된 쉘 스크립트(deploy-front.sh)를 실행하여 Nginx 웹 서버에 새로운 정적 파일들을 배치합니다. 이 스크립트는 기존 배포 파일을 제거하고 새로운 파일로 교체한 다음 Nginx를 재시작/재로드하여 변경된 파일을 제공하도록 합니다. - 배포 완료
Nginx reload는 연결을 끊지 않고 구성만 재적용하므로 서비스 중단 없이 바로 웹사이트 접속이 가능합니다.
이 동작 흐름을 적용시키기 위해 총 두 가지의 코드를 작성해야합니다.
1. Jenkins 파이프라인 설정
2. 배포 스크립트 (deploy-front.sh) 구현
이 중 jenkins 파이프라인 설정은 jenkins ui 에서 세팅이 가능하고, 배포 스크립트 구현은 .pem 키를 사용하여 ssh 접속해서 파일을 내부에 생성해야합니다.
-> 참고차 말씀 드린 것이고, 어떻게 jenkins 를 세팅했으며 어떻게 배포 스크립트 파일을 ssh 에 접속해서 생성했는지 과정은 하단에서 작성하겠습니다.
초기 세팅
Jenkins 설치
1. Jenkins 로컬에 설치
해당 사이트에 나와있는 대로 Jenkins 를 맥북에 설치합니다.
macOS Installer for Jenkins LTS
Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software
www.jenkins.io

2. jenkins Start
젠킨스 서비스를 Start 명령어를 실행하면, http://localhost:8080 에 접속할 수 있습니다.
여기 접속하면 해당 페이지가 뜨게 됩니다.

터미널에 해당 명어를 치면 어드민 password 가 나옵니다.
cat /Users/violet/.jenkins/secrets/initialAdminPassword
b8734ee1f8b14daf9572fa2868ea3e1e
3. 토큰 넣고 start

여기까지는 로컬 테스트를 위한 Jenkins 설치 였구요.여기까지는 로컬 테스트를 위한 Jenkins 설치 였습니다.
이제 이 8080 포트를 nginx conf 파일을 열어 저희가 지정한 https://bofit.co.kr/jenkins url 로 proxy_pass 세팅을 해주어야 접근이 가능합니다.
저희 bofit 의 환경은 사실 서버 개발자분들이 배포 환경에 jenkins 를 띄워둔 상태라서 https://bofit.co.kr/jenkins 접근이 이미 가능한 상태였습니다.
그래서 로컬은 그냥 연습해봤다고 생각하고, 해당 url 을 접속해서 세팅하기 시작했어요.
jenkins url proxy_pass 세팅하려면?
.pem 키를 가지고 ssh 에 접속해서 nginx/conf/{서비스에서 설정한 파일명}.conf 을 접속해서 세팅이 필요합니다.
1. upstream 설정 – Blue/Green & Jenkins & Client
upstream jenkins {
# server 172.31.129.114:9090;
server jenkins:8080;
keepalive 10; # keepalive 갯수
keepalive_timeout 30; # keepalive의 생존 시간 (초)
}
Nginx가 프록시할 Jenkins 서버를 정의합니다.
현재는 Docker 컨테이너 내부의 DNS를 활용해 jenkins:8080으로 접근하고 있습니다.
즉, nginx와 jenkins가 같은 도커 네트워크 내부에 있다는 전제입니다.
🌐 2. location /jenkins/블록 분석
server{
location /jenkins/ {
proxy_pass http://jenkins;
#rewrite ^/jenkins(/.*)$ $1 break; # /jenkins/ 접두어 제거
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
클라이언트가 /jenkins/ 경로로 접근하면 nginx가 내부의 Jenkins 서버(jenkins:8080)로 요청을 프록시합니다.
proxy_set_header는 리버스 프록시 환경에서도 요청 정보가 손실되지 않도록 원 IP, 호스트, 프로토콜 등을 전달합니다.
환경 세팅 - jenkins
1. 플러그인 설치
bofit 배포를 위해 5개의 플러그인을 설치했습니다.
https://plugins.jenkins.io/nodejs/
Jenkins에서 Node.js 및 npm, pnpm을 사용할 수 있도록 해주는 플러그인 입니다.
https://plugins.jenkins.io/gitlab-plugin/
GitLab과 Jenkins를 연동하여 Webhook 기반 자동 빌드 트리거, Merge Request 상태 반영 등을 지원합니다.
https://plugins.jenkins.io/generic-webhook-trigger/
GitHub/GitLab 등에서 오는 Webhook 요청을 받아 Jenkins Job을 트리거할 수 있도록 하는 범용 트리거 플러그인 입니다.
https://plugins.jenkins.io/docker-build-step/
Jenkins에서 도커 컨테이너를 직접 빌드, 실행, 정지 등 제어할 수 있게 해주는 플러그인 입니다
https://plugins.jenkins.io/ssh-agent/
빌드 중 SSH credentials를 사용해 원격 서버에 안전하게 접속할 수 있도록 도와주는 플러그인 입니다 원격 배포에 자주 사용됩니다
https://plugins.jenkins.io/pipeline-stage-view/
https://plugins.jenkins.io/github-pullrequest/


2. 서비스만을 위한 github token 생성
권한은 repo 와 webhook 만 주었습니다.
3. Global Credentials 설정
[Jenkins 관리] → [Credentials] → [System] → [Global credentials]
Username에 GITHUB ID(아무거나 써도 상관 x), Password에 위에서 생성된 토큰 정보를 모두 복붙한다.
ID는 pipeline에서 쉽게 알아볼 수 있도록 github-token으로 설정한다.

이렇게 글로벌 크레덴셜 확인해줍니다.

환경 세팅 - github
Webhooks 세팅

이렇게 서비스 레포지토리 권한을 관리자로 받고
setting > webhook 에 접속하여 세팅을 합니다.
preload-url 을 세팅해두었어요.
환경 세팅 - ssh 접속
1. pem 키 세팅
서버 개발자로부터 pem 키를 받아서, 데스크탑에 폴더를 하나 생성 후 .pem 키를 넣어두고 이 폴더 내부에서 터미널을 열었어요.

그리고 권한을 설정해줍니다.
chmod 400 bofit.pem

2. AWS AMI 이름 체크

우리 별별 DB 에 있는 AWS 에 접속해서 저희가 쓰고자 했던 bofit-front-ec2 인스턴스에 들어갑니다.
그러면이렇게 AMI 를 볼 수가 있는데 우리는 ubuntu 인 것을 확인할 수 있죠.
→ 기본 계정 : ubuntu
근데 만약에 AMI 를 봤는데 이름이 “amzn2-ami-hvm-2.0.2023...” 이면,
→ 기본 계정 : ec2-user
입니다. 이 정보를 확인해주세요.
3. ssh 접속 테스트
이제 ssh 에 접속할 거에요. 저희 bofit.pem 키를 사용해서 해당 코드를 .pem 키가 있는 폴더 내부에서 터미널을 켜서 입력해주세요.
bofit.pem 이라고 작성되어 있는데, 이것은 각자 서비스의 pem 키 파일 명을 작성해주시면 됩니다.
ssh -i bofit.pem ubuntu@43.200.142.40

-> 이렇게 ubuntu 환경에 접속해줍니다.
Jenkins Item 구축
1. 새로운 Item 등록

2. New item 세팅
저는 pipeline 으로 명령을 내릴 예정이라 파이프라인을 채택했습니다.
명은 자유롭게 작성했습니다! 저는 서버 명과 비슷하게 갔어요

3. General Github 세팅
이렇게 제너럴에 깃헙 세팅을 했습니다.

4. Build Trigger 세팅
GitHub hook trigger을 체크해서 GitHub에서 받은 Webhook 이벤트를 기반으로 변경 사항을 감지해 빌드를 시작합니다.

5. pipeline script 세팅
사진 보시면 보여지는 페이지가 파이프라인 스크립트 작성란입니다.
jenkins 는 이 파이프라인을 기반으로 코드를 돌려요.
그래서 여기에는 저희 서비스 배포를 위한 파이프라인을 작성할 거고, 설계 계획은 다음과 같습니다.
- 우리가 구현한 코드가 있는 git 을 클론 받을 수 있어야 하고
- 그 클론 받은 코드를 build 해서 테스트를 하고
- 그렇게 해서 나온 산출물인 .dist 파일 압축하고
- 이를 ssh 에 연결해서 보낸 후에
- 이 압축 파일을 ssh 에서 받아서 압축을 풀고
- 이 코드를 기반으로 nginx 를 돌려서 저희 배포 사이트와 연결하는 작업을 모두 담당하게 됩니다.

제가 설계한 아키텍쳐는 간단히 다음과 같아요. 해당 내용이 프로젝트 배포 방법의 축약 입니다.
1. GitHub main 브랜치 PR Merge
- GitHub Webhook → Jenkins가 트리거
2. Jenkins 파이프라인 실행.
├── git clone
├── pnpm install
├── pnpm build
└── 생성된 /dist 파일을 찾아 압축
3. 원격 배포 단계
- EC2에 SSH 접속
- 압축한 /dist 파일 EC2 로 전송
- deploy-front.sh 배포 스크립트 실행
├── /home/ubuntu/client-dist → 전송 받은 dist 파일 압축 해제
├── docker-compose up
└── nginx restart
해당 아키텍쳐가 잘 이루어지기 위해 jenkins pipeline / deploy-front.sh 를 잘 작성해야합니다.
Jenkins 파이프라인
위의 단계를 함께 보며 해당 파이프라인을 따라가보면 됩니다!
하단 코드 정리
1. Git Clone
2. pnpm install & Build
3. package.json 파일이 있는 폴더 내의 .dist 파일 찾아서 압축
4. ssh 접속 후 .dist 압축 파일 EC2로 전송
5. ssh 접속 후 deploy-front.sh 원격 실행
CI (jenkins) ↔ CD (EC2) 명확히 분리'
pipeline {
agent any
tools {
nodejs 'node23' // Jenkins에서 등록한 NodeJS 버전명
}
environment {
GIT_REPO = 'https://github.com/team-bofit/bofit-client.git'
GIT_BRANCH = 'develop'
SSH_CREDENTIALS_ID = 'bofit-front-ec2-key'
}
stages {
stage('📦 Git Clone') {
steps {
git branch: "${GIT_BRANCH}", credentialsId: 'github-token', url: "${GIT_REPO}"
}
}
stage('🧱 Build with pnpm') {
steps {
sh '''
corepack enable
corepack prepare pnpm@latest --activate
pnpm install
pnpm build
'''
}
}
stage('📦 Create Tarball') {
steps {
sh '''
mkdir -p packaged
tar -czvf packaged/client-dist.tar \
./apps/client/dist \
./packages/*/dist || echo "[INFO] 일부 패키지에 dist가 없을 수 있습니다"
echo "[INFO] ✅ dist 압축 완료"
ls -lh packaged/client-dist.tar
'''
}
}
stage('📤 파일 EC2로 전송') {
steps {
sshagent(credentials: ['bofit-front-ec2-key']) {
sh '''
echo "[INFO] ▶ EC2로 client-dist.tar 전송"
scp -o StrictHostKeyChecking=no \
packaged/client-dist.tar \
ubuntu@43.200.142.40:/home/ubuntu/Frontend/
echo "[DEBUG] 현재 디렉토리:"
pwd
echo "[DEBUG] packaged 폴더 내용:"
ls -lh packaged
'''
}
}
}
stage('🚀 배포 스크립트 실행') {
steps {
sshagent(credentials: ['bofit-front-ec2-key']) {
sh '''
echo "[INFO] ▶ EC2에서 배포 스크립트 실행"
ssh -o StrictHostKeyChecking=no ubuntu@43.200.142.40 'bash /home/ubuntu/script/deploy-front.sh'
'''
}
}
}
}
post {
success {
echo '[✅] 빌드 및 배포 성공'
}
failure {
echo '[❌] 실패 - 로그 확인 필요'
}
}
}
배포 스크립트 (deploy-front.sh)
이것이 EC2 접속 후 .dist 파일을 찾은 후 배포 스크립트를 돌리기 위한 코드 입니다.
해당 파일(deploy-front.sh)은 EC2 환경에 위치해야합니다!!
하단 코드 정리
1. jenkins pipeline 으로 받은 .dist 압축 파일 압축 해제 ( 원래 있었다면 제거 )
2. docker compose 재시작 nginx
정적 파일만 전달해 빠름 (dist)
#!/bin/bash
set -e
echo "[DEPLOY] ▶ 프론트 배포 시작"
echo "--------------------------------------------------"
cd /home/ubuntu
DIST_TAR="/home/ubuntu/Frontend/client-dist.tar"
DIST_DIR="/home/ubuntu/Frontend/dist"
TEMP_DIR="/home/ubuntu/Frontend/temp"
echo "[INFO] 📂 기존 dist 폴더 삭제"
rm -rf "$DIST_DIR"
echo "[INFO] 📦 dist 압축 해제"
if [ ! -f "$DIST_TAR" ]; then
echo "❌ dist tar 파일이 존재하지 않습니다: $DIST_TAR"
exit 2
fi
mkdir -p "$TEMP_DIR"
tar -xvf "$DIST_TAR" -C "$TEMP_DIR"
echo "[INFO] ✅ 압축 해제 성공, dist로 이동"
mkdir -p "$DIST_DIR"
mv "$TEMP_DIR"/apps/client/dist/* "$DIST_DIR"
rm -rf "$TEMP_DIR"
echo "[INFO] 🔁 nginx 재시작"
sudo docker compose -f /home/ubuntu/docker-compose-dev.yml restart nginx
echo "[INFO] 🩺 헬스 체크"
curl -I https://bofit.co.kr || {
echo "❌ curl 헬스 체크 실패"
}
echo "--------------------------------------------------"
echo "[DEPLOY] ✅ 프론트 배포 완료"
저는 여기서 의문이 하나 들었었는데요.

그쵸.. 말이 안 됩니다.
이는 nginx 세팅을 해주어야 하는데요. 이 세팅이 빠지면 배포가 안 됩니다
저는 서버 개발자 친구들이 세팅해준 .conf 파일에서 client 만 따로 추가 했습니다!
다시 EC2 에 접속해줍니다.
ssh -i bofit.pem ubuntu@43.200.142.40
여기서 nginx 세팅 파일을 찾습니다.
./nginx/conf/api.bofit.conf
요건 저희 서비스 nginx conf 파일이고, 네이밍은 자유롭게 개발자분들이 만들어주시면 됩니다. (저희 서비스는 백엔드 친구들이 만들어주어서 저렇게 네이밍이 되었어요.
upstream client {
server client:80;
keepalive 20;
keepalive_timeout 30;
}
server {
listen 80;
listen [::]:80;
server_name bofit.co.kr *.bofit.co.kr;
# HTTP 요청을 HTTPS로 리디렉션
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name bofit.co.kr *.bofit.co.kr;
include /etc/nginx/conf.d/service-env.inc;
# SSL 인증서 설정
ssl_certificate /etc/letsencrypt/live/bofit.co.kr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bofit.co.kr/privkey.pem;
location / { # 'bofit.co.kr/' 로 접근시
root /usr/share/nginx/html; # ".dist 파일이 압축 해제되는 장소
index index.html; # 해당 경로에서 index.html 을 보여주도록 세팅
try_files $uri $uri/ /index.html;
}
}
.dist 파일을 압축 해제한 후 어떻게 실제 배포로 이어지는지 궁금하다면, 해당 코드의 location 블록을 살펴보면 됩니다.
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
이 설정은 /usr/share/nginx/html 폴더 안의 index.html 파일과 정적 리소스를 브라우저에 서빙하도록 구성되어 있습니다.
즉, 이 경로에 .dist 파일을 압축 해제하여 넣어두면, 사용자가 브라우저에서 https://bofit.co.kr에 접속했을 때 자동으로 해당 파일들이 보여지게 되는 것입니다.
마지막으로 최종 정리를 해보자면,, 순서는 다음과 같고,
1. GitHub main 브랜치 PR Merge
- GitHub Webhook → Jenkins가 트리거
2. Jenkins 파이프라인 실행.
├── git clone
├── pnpm install
├── pnpm build
└── 생성된 .dist 파일(빌드 후 정적 파일 번들)을 찾아 압축
3. 원격 배포 단계
- EC2에 SSH 접속
- 압축한 .dist 파일 EC2 로 전송
- [deploy-front.sh](http://deploy-front.sh/) 배포 스크립트 실행
├── /home/ubuntu/client-dist 경로로 전송 받은 .dist 파일 압축 해제
├── docker-compose up
└── nginx restart
4. nginx 재시동 → 정적 파일 배포 완료
++ 내부적으로 배포가 완료 되었을 때 nginx 가 어떻게 돌아가는지 사용자 경험을 예로 설명을 해보자면,
1. 사용자가 웹사이트 접속
- 클라이언트 요청이 EC2 의 443 포트로 전달
- 이 요청을 nginx 가 받고, SSL 서버 블록에 진입하게 된다.
2. nginx 는 /usr/share/nginx/html 디렉토리로 이동
- 해당 경로는 .dist 파일이 Jenkins 파이프라인을 통해 배포된 프론트 정적 파일이 서빙된 위치입니다.
- index.html 파일을 시작점으로 React 앱이 구동됩니다.
이렇게 배포가 완료되는 것입니다.
헷갈리지 말아야 하는 것은 jenkins 가 배포를 하는 게 아니라, jenkins 는 배포를 도와주는 역할이며 배포를 위한 사용자 친화적인 UI 를 그려주는 것이다.
그리고 우리가 편하게 사용하던 Vercel 은 내부적으로 이런 과정이 모두 구현이 되어 있기 때문에 간편하다는 사실..
그 모든 것을 편리하게 만들기 위해 많은 개발자들이 자동화에 힘쓰고 있는 것을 잊지말고.. 거기에 편해지면 안될 것이고 그 안에 내부 구현을 항상 궁금해 하는 개발자가 되어야겠다라고 또 다시 다짐했습니다.
'WEB' 카테고리의 다른 글
| [Architecture] 모놀리식 아키텍쳐 vs 마이크로서비스 (0) | 2025.04.03 |
|---|---|
| [Next.js] Vite 프로젝트 Next.js 로 마이그레이션 (0) | 2025.03.04 |
| [WebApp] Dart package 오류 (0) | 2025.03.01 |
| [WEB] CSR vs SSR 차이 및 특징 ( + SPA, MPA ) (1) | 2025.02.15 |
| [WEB] React-Query Mutation, invalidateQueries (0) | 2025.02.14 |