CI / CD 자동화
🎯 핵심 질문
로컬에서 잘 돌아가는 코드, 어떻게 전 세계 사람들이 접속할 수 있게 할까?
1. 왜 "서비스 배포"가 필요한가?
상상해 보세요. 집에서 진수성찬을 차렸는데, 맛있는 건 가족만 먹을 수 있고 이웃이나 지나가는 사람은 맛볼 수 없습니다.
어떻게 해야 할까요? 음식을 식당에 내놓아야 합니다. 이게 바로 "서비스 배포"가 하는 일입니다 — 여러분이 작성한 코드를 개인 컴퓨터에서 7x24시간 항상 켜져 있는 "공용 컴퓨터"로 옮기는 것입니다. 그러면 인터넷만 가능하면 누구나 웹사이트에 접속할 수 있습니다.
서비스 배포는 많은 단계가 포함됩니다. 식당을 여는 게 단순히 요리를 내놓는 것만이 아닌 것처럼, 가게 임대, 인테리어, 허가증 발급, 직원 고용 등이 필요하죠. 웹사이트 개발도 마찬가지입니다. 코드에서 사용자가 접속할 수 있는 웹사이트가 되기까지 많은 단계를 거쳐야 합니다. 빌드, 배포, 네트워크 설정, 보안 확보 등을 단계별로 완료해야 합니다.
아래에서 전체 과정을 하나씩 자세히 설명하겠습니다. 각 단계를 아주 세밀하게 풀어 설명할 테니, 완전 초보자도 이해할 수 있을 것입니다.
2. 빌드: 코드를 "실행 가능한 패키지"로 변환하기
2.1 왜 빌드가 필요한가?
초보자들이 자주 묻는 질문: 코드를 다 작성했는데, 왜 서버에 올려서 바로 사용자에게 제공할 수 없나요?
이 질문에 답하려면, 여러분이 작성한 코드가 어떤 형식인지 먼저 이해해야 합니다. Vue, React, Express, Koa 등의 프레임워크를 사용했을 것입니다. 이 프레임워크들의 공통점은: 브라우저나 서버가 직접 사용할 수 있는 형식이 아니라는 것입니다.
예를 들어, Vue 코드를 작성할 때 <template>, <script setup> 같은 태그를 사용하죠? 이 문법은 Vue만 이해할 수 있습니다. 브라우저는 전혀 이해하지 못합니다. 브라우저가 이해하는 언어는 세 가지뿐입니다: HTML(웹페이지 구조), CSS(웹페이지 스타일), JavaScript(웹페이지 로직). Vue 컴포넌트 문법은 브라우저에게 천서와 같아서 전혀 해석할 수 없습니다.
그래서 코드를 서버에 올리기 전에 반드시 해야 할 중요한 일이 있습니다: 브라우저가 이해할 수 있는 언어로 번역하는 것. 이 번역 과정을 "빌드(Build)"라고 합니다.
2.2 빌드는 구체적으로 무엇을 하나요?
빌드는 단순한 번역이 아닙니다. 웹사이트를 더 빠르고 가볍게 만드는 많은 최적화도 수행합니다. 구체적으로 어떤 작업을 하는지 자세히 살펴보겠습니다:
첫 번째: 의존성 분석
코드를 작성할 때 다양한 서드파티 라이브러리를 사용합니다. 예를 들어 Vue, Vue Router, Axios, Vite 등. 이 라이브러리를 매번 사용자가 npm에서 다운로드하게 할 수는 없습니다. 너무 느리니까요. 빌드 도구는 코드를 분석하여 모든 의존성을 찾아내고, 이를 하나로 "패키징"합니다.
두 번째: 컴파일 및 변환
가장 핵심적인 단계입니다. Vue 컴포넌트를 HTML과 JavaScript로 컴파일합니다. SASS/LESS를 CSS로 컴파일합니다. ES6+의 새로운 문법을 호환성이 더 좋은 ES5 코드로 변환합니다. 이 단계가 완료되면 코드는 "개발자가 이해할 수 있는 형식"에서 "기계가 실행할 수 있는 형식"으로 변환됩니다.
세 번째: 압축 및 난독화
압축은 모든 공백, 줄바꿈, 주석을 제거하는 것입니다. 변수명을 영어 단어에서 한 글자로 변경합니다. 예를 들어 userName은 a가 되고, calculateTotalPrice는 b가 됩니다. 이렇게 하면 파일 크기가 크게 줄어들어 사용자 다운로드가 빨라집니다. 난독화된 코드는 사람이 거의 이해할 수 없어, 약간의 "코드 보호" 효과도 있습니다.
네 번째: 코드 분할
10개의 페이지를 작성했을 수 있습니다. 각 페이지에는 고유한 코드가 있습니다. 하지만 사용자는 그 중 하나의 페이지만 방문할 수도 있습니다. 왜 나머지 9개 페이지의 코드를 다운로드해야 할까요? 빌드 도구는 코드를 여러 작은 청크로 분할합니다. 사용자가 어떤 페이지를 방문하면 해당 페이지의 코드만 다운로드합니다. 이것이 바로 "지연 로딩(Lazy Loading)"입니다. 첫 방문 속도를 크게 향상시킬 수 있습니다.
다섯 번째: 해시 생성
매우 중요하지만 많은 사람이 간과하는 단계입니다. 빌드가 완료되면 파일명이 app.abc123.js, vendor.def456.css와 같은 형식이 됩니다. 뒤에 붙은 문자와 숫자의 조합을 "해시"라고 합니다.
해시의 역할은: 코드에 어떤 변경이 있으면 해시값이 변경됩니다. 브라우저는 "이 파일이 변경되었으니 다시 다운로드해야 한다"는 것을 알게 됩니다. 변경되지 않은 파일은 브라우저가 계속 캐시를 사용합니다. 다시 다운로드할 필요가 없습니다. 이렇게 하면 사용자가 항상 최신 코드를 볼 수 있으면서도 캐시를 충분히 활용하여 속도를 높일 수 있습니다.
2.3 빌드는 어떻게 실행하나요?
대부분의 현대 프론트엔드 프로젝트는 이미 빌드 도구가 설정되어 있습니다. 하나의 명령만 기억하면 됩니다:
# npm을 사용하는 경우
npm run build
# yarn을 사용하는 경우
yarn build
# pnpm을 사용하는 경우
pnpm build실행 후 프로젝트 루트 디렉토리에서 dist라는 폴더(때로는 build 또는 .output이라고도 함)를 찾으세요. 여기에 빌드된 모든 파일이 있습니다. 이 파일들이 서버에 업로드할 최종 산출물입니다. 더 이상 수정할 필요가 없습니다. 서버에 그대로 복사하면 됩니다.
2.4 빌드 산출물에는 무엇이 있나요?
dist 폴더를 열어보면 주로 세 가지 유형의 파일이 있습니다:
- HTML 파일: 보통
index.html이라고 합니다. 이것이 진입점 파일입니다. 브라우저가 가장 먼저 로드하는 파일입니다. - JS 파일: 모든 JavaScript 코드. 1개일 수도 있고 여러 개일 수도 있습니다.
- CSS 파일: 모든 스타일 코드. HTML에 인라인되어 있을 수도 있고, 독립적인 CSS 파일일 수도 있습니다.
비교적 복잡한 백엔드 프로젝트(예: Node.js)의 경우, 빌드 산출물은 실행 파일이나 Docker 이미지일 수 있습니다. 하지만 원리는 같습니다: 코드를 서버가 직접 실행할 수 있는 형태로 변환하는 것입니다.
3. 서버: 절대 문을 닫지 않는 "집" 찾기
3.1 서버란 무엇인가?
많은 사람이 "서버"라는 말을 처음 들으면 뭔가 대단한 신비로운 장비라고 생각합니다. 사실 그렇게 복잡하지 않습니다. 서버는 컴퓨터입니다. 절대 전원을 끄지 않고, 항상 인터넷에 연결된 컴퓨터입니다.
누군가 물을 수 있습니다: 집에 컴퓨터가 있는데 왜 추가로 서버를 빌려야 하나요?
좋은 질문입니다. 분석해 드리겠습니다:
첫째, 집의 컴퓨터는 24시간 켜둘 수 없습니다. 외출해야 하고, 잠도 자야 하고, 가끔 멈추고 재부팅해야 합니다. 하지만 서버는 다릅니다. 이 일만 하도록 만들어졌습니다. 365일 쉬지 않고 실행할 수 있습니다. 웹사이트에 언제든 접속할 수 있습니다.
둘째, 집의 인터넷도 안 됩니다. 가정용 브로드밴드의 업로드 속도는 보통 매우 느립니다. 그리고 가정용 브로드밴드의 IP는 동적으로 변합니다. 오늘 이 IP였다가 내일은 다른 IP가 될 수 있습니다. 웹사이트 서버로 사용할 수 없습니다. 서버는 데이터 센터의 고속 네트워크를 사용합니다. IP가 고정되어 있고 속도가 매우 빠릅니다.
셋째, 집의 컴퓨터에는 "공인 IP"가 없습니다. 공인 IP가 무엇일까요? 전 세계에서 유일한 주소입니다. 이 주소가 있어야 다른 사람이 인터넷에서 여러분의 컴퓨터를 찾을 수 있습니다. 집 컴퓨터의 IP는 보통 집의 로컬 네트워크에서만 사용할 수 있습니다. 외부에서는 전혀 찾을 수 없습니다. 서버는 다릅니다. 고정된 공인 IP가 있습니다. 전 세계 사람이 이 IP를 통해 서버를 찾을 수 있습니다.
3.2 서버는 어떻게 선택하나요?
서버를 선택할 때 주로 세 가지 지표를 봅니다: CPU 코어 수, 메모리 크기, 디스크 공간. 이 세 가지 지표가 높을수록 서버 성능이 좋고 가격도 비쌉니다.
입문자에게 비싼 구성을 살 필요는 전혀 없습니다. 간단한 선택 방법을 기억하세요:
- 개인 프로젝트, 학습용: 1코어 2GB 메모리면 충분합니다. 한 달에 수십 위안 정도.
- 소형 상업 프로젝트: 2코어 4GB 메모리. 하루 수천에서 수만 방문을 감당할 수 있습니다.
- 중형 프로젝트: 4코어 8GB 이상. 전문 팀의 운영이 필요합니다.
또 하나 고려할 점: 지역. 사용자가 주로 한국에 있다면 국내 서버(네이버 클라우드, 카카오 i 클라우드, AWS 한국 리전)를 구매하면 접속 속도가 빠릅니다. 사용자가 주로 해외에 있다면 해외 서버(AWS, Google Cloud, DigitalOcean)를 구매하거나 홍콩 서버를 구매하면 됩니다. 속도가 빠르고 ICP备案(중국 웹사이트 등록)도 필요 없습니다.
3.3 국내 서버인가, 해외 서버인가?
매우 중요한 질문입니다. 많은 사람이 처음에 제대로 생각하지 않아 나중에 문제가 발생합니다.
국내 서버의 장점은 속도가 빠르고 지연이 낮다는 것입니다. 단점은 비안(备案, 웹사이트 등록)이 필요하다는 것입니다. 보통 1주일에서 1개월을 기다려야 합니다. 그리고 국내 서버 가격이 상대적으로 비쌉니다.
해외 서버의 장점은 비안이 필요 없다는 것입니다. 구매하면 바로 사용할 수 있습니다. 가격도 더 저렴할 수 있습니다. 단점은 중국 대륙 사용자의 접속 속도가 느릴 수 있다는 것입니다. 홍콩이나 싱가포르 데이터 센터라면 훨씬 나을 것입니다.
권장 사항: 개인 프로젝트, 학습용 웹사이트라면 홍콩이나 해외 서버를 구매하세요. 비안의 번거로움을 피할 수 있습니다. 정식 상업 프로젝트로 장기 운영이 필요하다면 국내 서버를 구매하세요. 비안을 제대로 완료하면 나중에 많은 문제를 피할 수 있습니다.
3.4 주요 클라우드 서비스 비교
| 서비스 | 적합 대상 | 특징 | 신규 사용자 가격 |
|---|---|---|---|
| 알리바바 클라우드 | 중국 내 비즈니스 | 시장 점유율 1위, 생태계 완비 | 첫 해 수십~백여 위안 |
| 텐센트 클라우드 | 미니프로그램, 게임 | 미니프로그램 클라우드 개발 지원 우수 | 첫 해 할인 폭이 큼 |
| 화웨이 클라우드 | 기업 사용자 | 정부, 공공 프로젝트 우선 | 가격이 상대적으로 높음 |
| DigitalOcean | 개발자 | 간단하고 사용하기 쉬움, 가격 투명 | $4/월부터 |
| Vercel | 프론트엔드 프로젝트 | 제로 설정, 푸시만 하면 배포 완료 | 무료 한도로 충분 |
초보자에게 가장 추천하는 것은 알리바바 클라우드나 텐센트 클라우드의 학생/신규 사용자 할인 서버입니다. 보통 1년에 수십 위안이면 됩니다. 가성비가 매우 높습니다. 순수 프론트엔드 프로젝트로 번거로움을 피하고 싶다면 Vercel이나 Netlify를 직접 사용할 수도 있습니다. 서버를 구매할 필요도 없습니다. 코드를 푸시하면 자동으로 배포됩니다.
3.5 서버를 받은 후 무엇을 해야 하나요?
서버를 구매하면 이메일을 받게 됩니다. 여기에는 몇 가지 중요한 정보가 포함되어 있습니다:
- IP 주소:
123.45.67.89와 같은 숫자입니다. 서버가 인터넷에서의 주소입니다. - 로그인 사용자 이름: 보통
root(관리자 계정)입니다. - 로그인 비밀번호: 초기 비밀번호, 또는 비밀번호 설정 링크입니다.
이 정보가 있으면 SSH(Secure Shell)를 사용하여 서버에 원격으로 로그인할 수 있습니다. 서버를 원격으로 제어하는 암호화된 명령이라고 생각하면 됩니다. 내 컴퓨터에서 멀리 있는 서버를 조작할 수 있습니다.
로그인 명령은 다음과 같습니다:
ssh root@123.45.67.89
# Enter를 누르면 비밀번호를 입력하라는 메시지가 나옵니다. 올바른 비밀번호를 입력하면 로그인에 성공합니다.로그인에 성공하면 서버의 명령줄 인터페이스로 들어갑니다. 내 컴퓨터에서 터미널 창을 연 것과 비슷해 보입니다. 여기서 소프트웨어를 설치하고, 폴더를 만들고, 설정을 수정할 수 있습니다. 모든 작업이 로컬 컴퓨터와 같습니다.
4. 배포: 코드를 "집"으로 옮기기
4.1 배포란 무엇인가?
배포는 서버(집)를 빌린 후 코드(짐과 가구)를 옮기고, 문을 열어 영업을 시작하는 과정입니다.
구체적으로 배포는 다음 단계를 포함합니다:
- 코드를 서버에 업로드: 빌드 산출물을 로컬 컴퓨터에서 서버로 전송합니다.
- 의존성 설치: 서버에 프로젝트에 필요한 다양한 패키지가 없을 수 있습니다. 설치가 필요합니다.
- 환경 변수 설정: 데이터베이스 비밀번호, API 키 등 민감한 정보를 설정합니다.
- 서비스 시작: 애플리케이션을 실행합니다. 사용자의 요청을 받기 시작합니다.
이 네 단계가 복잡해 보이지만, 사실 그렇게 어렵지 않습니다. 아래에서 각 단계를 자세히 설명하겠습니다.
4.2 코드를 서버에 업로드하는 방법?
방법 1: FTP/SFTP 업로드
가장 직관적인 방법입니다. 클라우드 스토리지를 사용하는 것처럼 파일을 서버에 끌어다 놓습니다. FileZilla라는 무료 소프트웨어를 다운로드할 수 있습니다. 서버의 IP, 사용자 이름, 비밀번호를 입력하면 로컬 파일을 관리하듯 서버의 파일을 관리할 수 있습니다.
방법 2: Git 풀
더 권장되는 방법입니다. 먼저 GitHub, GitLab 또는 Gitee에 코드 저장소를 만듭니다. 코드를 클라우드에 푸시합니다. 그런 다음 서버에서 git clone 명령으로 코드를 가져옵니다.
이 방법의 장점은: 코드를 업데이트할 때 서버에서 git pull 명령만 실행하면 된다는 것입니다. 매번 수동으로 업로드할 필요가 없습니다. 그리고 코드가 클라우드에 저장되어 안전합니다. 서버를 다시 설치해도 괜찮습니다.
방법 3: CI/CD 자동 배포
가장 전문적인 방법이며 강력히 권장하는 방법입니다. CI/CD(지속적 통합/지속적 배포)를 구성하면, 코드를 GitHub에 푸시하기만 하면 됩니다. CI/CD 시스템이 자동으로 코드 풀 → 의존성 설치 → 빌드 → 배포의 전체 과정을 완료합니다. 서버에 로그인할 필요도 없습니다. 모든 것이 자동으로 완료됩니다.
4.3 배포의 구체적인 단계
가장 간단한 방법인 Git 수동 배포를 사용하여 전체 과정을 시연하겠습니다:
첫 번째 단계: 서버에 연결
ssh root@123.45.67.89두 번째 단계: 필요한 소프트웨어 설치
Node.js 프로젝트인 경우 먼저 Node.js를 설치해야 합니다:
# Ubuntu 시스템을 예로 들면
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs세 번째 단계: 코드 가져오기
# 웹사이트를 저장할 디렉토리 생성
mkdir -p /var/www/my-website
cd /var/www/my-website
# 코드 저장소 클론 (먼저 GitHub에 저장소를 만들어야 함)
git clone https://github.com/사용자이름/저장소이름.git .네 번째 단계: 의존성 설치 및 빌드
# 프로젝트 의존성 설치
npm install
# 프로젝트 빌드 (dist 디렉토리 생성)
npm run build다섯 번째 단계: PM2로 서비스 시작
왜 PM2를 사용할까요? PM2는 프로세스 관리 도구입니다. 웹사이트를 백그라운드에서 계속 실행할 수 있게 합니다. 서버가 재시작되어도 자동으로 시작됩니다.
# PM2 전역 설치
sudo npm install -g pm2
# 웹사이트 시작 (진입점 파일이 index.js라고 가정)
pm2 start index.js
# 부팅 시 자동 시작 설정
pm2 startup
pm2 save여섯 번째 단계: Nginx 리버스 프록시 설정
Node.js 애플리케이션은 보통 3000이나 8080 포트에서 실행됩니다. 하지만 사용자가 접속하는 것은 80 포트(HTTP 기본 포트)입니다. Nginx를 사용하여 80 포트의 요청을 애플리케이션 포트로 전달해야 합니다.
# Nginx 설치
sudo apt install -y nginx
# Nginx 설정 파일 생성
sudo nano /etc/nginx/sites-available/my-website열린 편집기에 다음 설정을 입력합니다:
server {
listen 80;
server_name example.com www.example.com;
# 정적 파일 (빌드 산출물) 직접 반환
location / {
root /var/www/my-website/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
# API 요청을 Node.js 백엔드로 전달
location /api/ {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}저장하고 나간 후 이 설정을 활성화합니다:
# 설정 활성화
sudo ln -s /etc/nginx/sites-available/my-website /etc/nginx/sites-enabled/
# 설정에 오류가 없는지 테스트
sudo nginx -t
# Nginx 재시작
sudo systemctl restart nginx이제 http://example.com에 접속하면 (도메인이 이 서버 IP를 가리키도록 DNS를 먼저 설정해야 함) 웹사이트를 볼 수 있습니다!
5. 도메인과 DNS: 웹사이트에 좋은 이름 짓기
5.1 왜 도메인을 구매해야 하나요?
서버 IP가 있는데 왜 도메인을 구매해야 할까요?
생각해 보세요. 123.45.67.89라는 숫자를 기억하는 게 쉽나요? 틀리기 쉽지 않나요? 하지만 google.com, naver.com 같은 이름은 훨씬 기억하기 쉽습니다.
도메인은 웹사이트의 이름입니다. 기억하기 쉽고 전문적입니다. 브랜드 이미지도 보여줄 수 있습니다. 상상해 보세요. "내가 만든 웹사이트에 접속해, IP는 123.45.67.89야"라고 말하는 것과 "woshishuaige.com에 접속해"라고 말하는 것 중 어느 것이 더 그럴듯해 보이나요?
example.com → 192.168.1.15.2 DNS란 무엇인가?
좋습니다. 이제 도메인을 하나 구매했습니다. 예를 들어 my-awesome-website.com이라고 합시다. 하지만 문제가 있습니다: 컴퓨터는 IP 주소만 이해합니다. "my-awesome-website.com" 같은 사람의 언어는 이해하지 못합니다.
이때 DNS가 등장합니다. DNS의 전체 이름은 "Domain Name System"입니다. 거대한 "전화번호부"라고 이해하면 됩니다. 사람이 기억하기 쉬운 도메인을 컴퓨터가 이해할 수 있는 IP 주소로 번역하는 역할을 합니다.
브라우저에서 my-awesome-website.com을 입력하고 Enter를 누르면, 배경에서 다음과 같은 일이 발생합니다:
- 브라우저가 DNS에 묻습니다: "hey, my-awesome-website.com의 IP 주소가 뭐야?"
- DNS가 "전화번호부"를 조회하여 브라우저에 알려줍니다: "IP는 123.45.67.89야"
- 브라우저가 이 IP 주소를 기반으로 서버를 찾아 요청을 보냅니다
전체 과정은 보통 수십 밀리초밖에 걸리지 않아 사용자가 전혀 인지하지 못합니다.
5.3 DNS는 어떻게 설정하나요?
DNS 설정은 보통 두 곳에서 할 수 있습니다:
방법 1: 도메인 구매처에서 설정
도메인을 구매한 곳에서 DNS 레코드를 설정합니다. 가장 일반적인 레코드 유형은 A 레코드입니다:
- 레코드 유형: A
- 호스트 레코드: 보통
@(도메인 자체, 예: my-awesome-website.com) 또는www(www.my-awesome-website.com) - 레코드 값: 서버 IP 주소, 예:
123.45.67.89
방법 2: 서드파티 DNS 서비스 사용
많은 전문가들이 도메인 등록기관의 기본 DNS를 사용하지 않고 Cloudflare, 알리바바 클라우드 DNSPod, 텐센트 클라우드 DNS 같은 전문 DNS 서비스를 사용합니다. 이 서비스는 보통 더 안정적이고 해석 속도가 빠릅니다. CDN, DDoS 방어 같은 부가 기능도 제공합니다.
5.4 DNS 설정은 얼마나 걸리나요?
많은 사람이 궁금해하는 질문입니다. 답은: 일정하지 않습니다. 보통 몇 분에서 24시간입니다.
DNS가 수정되면 전 세계의 모든 DNS 서버가 이 변경을 동기화해야 합니다. 바다에 돌멩이를 던지면 파도가 멀리까지 퍼져나가는 데 시간이 걸리는 것과 같습니다. 어떤 DNS 서버는 업데이트가 빨라 몇 분이면 적용됩니다. 어떤 서버는 느려 오래 기다려야 할 수 있습니다.
다음 명령으로 DNS가 적용되었는지 확인할 수 있습니다:
# Windows
ping 도메인이름
# Mac/Linux
ping 도메인이름ping이 성공하고 서버의 IP가 표시되면 DNS가 적용된 것입니다.
6. HTTPS: 웹사이트에 "자물쇠" 채우기
6.1 HTTP와 HTTPS의 차이
웹사이트 주소가 http://로 시작하는 것과 https://로 시작하는 것을 보셨을 것입니다. 이 "s"는 매우 중요합니다. "보안(Secure)"을 의미합니다.
HTTP(HyperText Transfer Protocol)은 웹페이지를 전송하는 프로토콜입니다. 데이터를 운반하는 트럭이라고 생각할 수 있습니다. 하지만 이 트럭은 투명합니다. 안에 담긴 것을 모든 사람이 볼 수 있습니다. HTTP 웹사이트에서 입력한 비밀번호, 개인정보는 전송 과정에서 중간에 있는 누구나 엿볼 수 있습니다.
HTTPS(HTTP Secure)는 이 트럭에 밀봉된 컨테이너를 추가한 것입니다. 열쇠도 함께 제공됩니다. 발신자와 수신자만 열쇠를 가지고 있습니다. 중간에 있는 사람이 가로채도 안에 무엇이 들었는지 알 수 없습니다. 이것이 암호화 전송입니다.
6.2 왜 HTTPS가 필요한가?
첫 번째 이유: 보안. HTTPS가 없으면 사용자가 웹사이트에서 입력한 비밀번호가 평문으로 전송됩니다. 약간의 기술이 있는 사람이면 누구나 가로챌 수 있습니다. 요즘 세상에 HTTPS가 없는 웹사이트를 사용하는 사람이 있을까요?
두 번째 이유: 브라우저 경고. Chrome, Edge 등 주요 브라우저는 HTTPS가 없는 웹사이트에 "안전하지 않음" 경고를 표시합니다. 사용자가 경고 아이콘을 보면 도망가기 바쁩니다. 가입이나 결제는 더더욱 하지 않을 것입니다.
세 번째 이유: SEO. Google, 네이버 같은 검색 엔진은 HTTPS 웹사이트를 우선적으로 인덱싱합니다. SEO 효과가 더 좋습니다.
6.3 HTTPS 인증서는 어떻게 얻나요?
예전에는 HTTPS 인증서가 비쌌습니다. 매년 수백에서 수천 위안을 내야 했습니다. 이제는 Let's Encrypt라는 단체가 나타나 완전 무료인 SSL/TLS 인증서를 제공합니다. 그리고 커뮤니티에 자동화 도구가 많아 설치와 갱신이 쉽습니다.
방법 1: Certbot 사용 (권장)
Certbot은 Let's Encrypt 인증서를 자동으로 신청하고 설정하는 도구입니다. 매우 간단합니다:
# Certbot 설치
sudo apt install -y certbot python3-certbot-nginx
# 인증서 자동 신청 및 Nginx 설정
sudo certbot --nginx -d example.com -d www.example.com실행 과정에서 몇 가지 질문을 합니다. 예를 들어 이메일(인증서 만료 알림용) 등. 답변을 완료하면 인증서가 자동으로 설정됩니다. 웹사이트에 접속하면 주소창에 자물쇠 아이콘이 추가된 것을 볼 수 있습니다.
인증서 유효기간은 90일입니다. 하지만 Certbot이 자동 갱신을 위한 스케줄을 설정해 줍니다. 거의 신경 쓸 필요가 없습니다.
방법 2: Cloudflare 사용
Cloudflare의 DNS 서비스를 사용하고 있다면 HTTPS 인증서를 직접 설정할 필요가 없습니다. Cloudflare가 자동으로 도메인에 HTTPS를 제공합니다. 90일 갱신 문제도 해결해 줍니다.
6.4 HTTPS 설정 후 어떤 변화가 있나요?
HTTPS를 설정하면 사용자 접속이 기존 http://example.com에서 https://example.com으로 변경됩니다. 이 변화는 다음과 같은 보안 보장을 가져옵니다:
- 암호화 전송: 사용자와 서버 간의 모든 통신이 암호화됩니다.
- 신원 확인: 인증서는 "이 웹사이트가 정말 이 웹사이트가 맞다"는 것을 증명합니다. 피싱 사이트를 방지합니다.
- 데이터 무결성: 데이터가 변조되었는지 감지할 수 있습니다.
7. CI/CD: 로봇이 대신 일하게 하기
7.1 CI/CD란 무엇인가?
CI/CD는 두 단어의 약자입니다: Continuous Integration(지속적 통합)과 Continuous Deployment(지속적 배포). 자동으로 작업을 수행하는 로봇 시스템이라고 이해하면 됩니다.
CI/CD가 없을 때 새로운 기능을 배포하려면 매번 다음 과정을 거쳐야 했습니다:
- 컴퓨터를 켜고 GitHub에 로그인
- 최신 코드를 풀
- 테스트를 실행하여 버그가 있는지 확인
- 프로젝트를 수동으로 빌드
- 서버에 로그인
- 최신 코드를 풀
- 의존성 설치
- 프로젝트 빌드
- 서비스 재시작
이 9단계를 매번 배포할 때마다 수동으로 해야 합니다. 귀찮지 않나요? 그리고 어떤 단계를 빼먹기 쉽습니다. 예를 들어 테스트 실행을 잊거나, 서비스 재시작을 잊는 등.
CI/CD가 있으면 과정이 이렇게 바뀝니다:
- 코드를 GitHub에 푸시
- 차를 마시며 기다림
- (로봇이 자동으로 위 9단계를 완료)
- 웹사이트가 자동으로 업데이트됨
이것이 CI/CD의 매력입니다: 코드만 푸시하면 나머지는 모두 자동으로 완료됩니다.
7.2 CI/CD의 작업 흐름
전형적인 CI/CD 흐름은 다음과 같습니다:
첫 번째 단계: 코드 제출(Push)
새로운 기능 개발을 완료하고 코드를 GitHub에 푸시합니다.
두 번째 단계: CI(지속적 통합) 트리거
GitHub이 코드 변경을 감지하고 CI 시스템(GitHub Actions, GitLab CI 등)에 작업을 시작하라고 알립니다.
세 번째 단계: 의존성 설치 및 테스트
CI 시스템이 가상 컴퓨터를 시작하고 그 위에서:
- 프로젝트에 필요한 다양한 의존성을 설치
- 테스트 코드를 실행하여 버그가 없는지 확인
- 프로젝트를 빌드하여 산출물을 생성
테스트가 실패하면 CI가 이메일로 알려줍니다. 이번 배포는 중단됩니다. 문제가 있는 코드가 프로덕션 환경에 배포되지 않습니다.
네 번째 단계: CD(지속적 배포) 실행
테스트가 모두 통과하면 CI 시스템이:
- SSH로 서버에 연결
- 최신 코드를 풀
- 의존성 설치
- 프로젝트 빌드
- 서비스 재시작
전체 과정은 몇 분밖에 걸리지 않을 수 있습니다. 모두 자동으로 완료됩니다.
7.3 GitHub Actions는 어떻게 설정하나요?
GitHub Actions는 GitHub에 내장된 CI/CD 기능입니다. 추가 요금이 필요하지 않습니다(무료 한도는 개인 프로젝트에 충분함). 설정도 매우 간단합니다.
프로젝트 루트 디렉토리에 .github/workflows/deploy.yml 파일을 만들고 다음 설정을 작성합니다:
name: Deploy to Production
# 트리거 조건: main 브랜치에 코드가 푸시될 때마다
on:
push:
branches: [main]
# 작업 목록
jobs:
# 배포 작업
deploy:
# 어떤 시스템에서 실행할지
runs-on: ubuntu-latest
# 구체적인 단계
steps:
# 1. 코드 체크아웃
- name: Checkout code
uses: actions/checkout@v3
# 2. Node.js 환경 설정
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
# 3. 의존성 설치 및 빌드
- name: Install and Build
run: |
npm ci
npm run build
# 4. 서버에 배포
- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/my-website
git pull origin main
npm install
npm run build
pm2 restart all이 설정 파일은 GitHub Actions에게 다음을 알려줍니다:
- main 브랜치에 새 코드가 있을 때 트리거
- Ubuntu 컴퓨터에서 작업 실행
- 먼저 Node.js 18 설치
- 그런 다음 의존성 설치 및 프로젝트 빌드
- 마지막으로 SSH로 서버에 연결하여 일련의 배포 명령 실행
설정이 완료되면 매번 git push origin main을 실행할 때마다 GitHub가 자동으로 배포를 시작합니다. 매우 편리합니다.
8. 모니터링과 로그: 웹사이트의 "야간 경비"
8.1 왜 모니터링이 필요한가?
웹사이트가 온라인이 되면 이론적으로 7x24시간 끊임없이 실행되어야 합니다. 하지만 현실은 그렇게 아름답지 않습니다. 서버가 다운될 수 있고, 네트워크가 불안정할 수 있고, 코드에 버그가 있을 수 있습니다. 실제 프로덕션 환경에서는 모든 종류의 예상치 못한 상황이 발생할 수 있습니다.
모니터링이 없으면 사용자가 전화해서 "웹사이트가 안 열려요"라고 알려줄 때까지 기다려야 합니다. 이때는 이미 늦었을 가능성이 높습니다. 사용자가 이미 이탈했을 수 있습니다.
모니터링이 있으면:
- 문제를 조기 발견: CPU 사용률이 90%입니다. 서버를 미리 업그레이드하세요.
- 문제를 빠르게 파악: 웹사이트가 느려졌어요. 모니터링을 보고 어디가 병목인지 확인.
- 현황 파악: 매일 몇 명이 방문하는지, 언제 방문이 가장 많은지.
8.2 어떤 지표를 모니터링해야 하나요?
가장 중요한 모니터링 지표는 다음 몇 가지입니다:
| 지표 | 정상 범위 | 초과 시 대응 |
|---|---|---|
| CPU 사용률 | < 70% | 서버 설정 업그레이드 또는 코드 최적화 |
| 메모리 사용률 | < 80% | 메모리 누수가 있는지 확인 |
| 디스크 사용률 | < 80% | 로그나 불필요한 파일 정리 |
| 웹사이트 접근성 | 100% | 서비스가 정상적으로 실행 중인지 확인 |
| 응답 시간 | < 2초 | 데이터베이스 쿼리 최적화 또는 캐시 추가 |
| 에러율 | < 1% | 에러 로그를 확인하여 문제 파악 |
8.3 모니터링은 어떻게 설정하나요?
가장 간단한 방법: Uptime Robot
uptimerobot.com에 가입하세요. 웹사이트 URL을 추가합니다. 5분마다 자동으로 웹사이트가 정상인지 확인합니다. 웹사이트가 다운되면 이메일로 알려줍니다. 무료 버전은 50개의 웹사이트를 모니터링할 수 있습니다. 개인 프로젝트에 충분합니다.
중급 방법: 클라우드 서비스 모니터링
서버가 알리바바 클라우드나 텐센트 클라우드에 있다면 자체 모니터링 기능이 있습니다. 임계값 알림을 설정하면 됩니다.
전문적인 방법: Prometheus + Grafana
이 두 가지는 모니터링 분야의 "스위스 아미 나이프"입니다. 기능이 매우 강력합니다. 생각할 수 있는 모든 지표를 모니터링할 수 있고 아름다운 시각화 차트도 만들 수 있습니다. 하지만 설정이 비교적 복잡합니다. 경험이 있는 개발자에게 적합합니다.
8.4 로그: 문제가 발생했을 때 어떻게 확인하나요?
모니터링은 "웹사이트에 문제가 있다"고 알려줍니다. 하지만 구체적으로 어떤 문제인지, 왜 발생했는지는 로그를 통해 파악해야 합니다.
로그는 프로그램이 실행되는 동안의 "일기장"입니다. 프로그램 실행 중의 모든 세부 사항을 기록합니다:
- 어떤 사용자가 언제 어떤 페이지에 접속했는지
- 데이터베이스 쿼리에 얼마나 걸렸는지
- 에러가 있는지, 에러 메시지는 무엇인지
가장 기본적인 로그 사용법
서버에서 애플리케이션 로그 확인:
# PM2 로그 확인
pm2 logs
# Nginx 접근 로그 확인
tail -f /var/log/nginx/access.log
# Nginx 에러 로그 확인
tail -f /var/log/nginx/error.log고급 로그 솔루션
프로젝트가 비교적 복잡하다면 전문적인 로그 수집 도구를 사용하는 것을 권장합니다:
- Loki: 무료 오픈소스. Prometheus와 같은 계열.
- ELK(Elasticsearch + Logstash + Kibana): 기능이 강력하지만 설정이 복잡함.
- Sentry: 애플리케이션 에러 수집 전용 도구. 에러 정보를 자동으로 수집합니다.
8.5 알림: 문제가 발생하면 즉시 알 수 있는 방법은?
모니터링은 문제가 있다고 알려주지만, 모니터링 대시보드를 계속 보고 있지 않으면 어떻게 할까요? 이때 알림이 필요합니다.
알림은 모니터링 시스템이 이상을 감지했을 때 자동으로 SMS, WeChat, DingTalk, 이메일 등의 방법으로 알려주는 것입니다. 다양한 알림 레벨을 설정할 수 있습니다:
- 긴급 (웹사이트 완전 다운): SMS + 전화. 즉시 알아야 함.
- 심각 (에러율 급증): DingTalk/WeChat 메시지. 보는 즉시 처리.
- 일반 (CPU 높음): 이메일 요약. 하루에 한 번 확인.
알림 설정의 핵심 원칙은: 레벨별 알림, 너무 자주 알림하지 않기입니다. 사소한 일에도 SMS를 보내면 오래지 않아 알림을 꺼버릴 것입니다.
9. 자주 발생하는 문제 빠른 참조표
| 문제 현상 | 가능한 원인 | 해결 방법 |
|---|---|---|
| 웹사이트가 열리지 않음 | 도메인이 해석되지 않음 / 서버 다운 / Nginx가 시작되지 않음 | ping 도메인으로 연결 확인; pm2 list로 서비스 상태 확인; systemctl status nginx로 Nginx 확인 |
| 빈 페이지가 표시됨 | 빌드 산출물 경로 오류 / 정적 파일이 올바르게 설정되지 않음 | Nginx의 root 경로가 dist 디렉토리를 가리키는지 확인 |
| 404 페이지를 찾을 수 없음 | 라우팅이 올바르게 설정되지 않음 / 경로 오타 | Nginx 설정에 try_files $uri $uri/ /index.html 추가 |
| 502 Bad Gateway | 백엔드 서비스 다운 / 포트가 열리지 않음 | pm2 list로 프로세스가 실행 중인지 확인; 포트가 올바른지 확인 |
| 403 Forbidden | 권한 오류 / 인덱스 디렉토리가 활성화되지 않음 | 파일 권한 확인 chmod -R 755; Nginx 설정에 autoindex on 추가 |
| HTTPS 인증서 만료 | 인증서가 만료되어 갱신되지 않음 | certbot renew로 수동 갱신; 자동 갱신 스케줄 확인 |
| 업데이트 후 변화가 보이지 않음 | 브라우저 캐시 / CDN 캐시 | Ctrl+Shift+R로 강력 새로고침; CDN 콘솔에서 "캐시 새로고침" |
| 웹사이트가 느림 | 대역폭 부족 / 캐시 미사용 / CDN 미설정 | 서버 대역폭 업그레이드; Redis 캐시 설정; CDN 연결 |
| 데이터베이스 연결 불가 | 데이터베이스가 시작되지 않음 / 비밀번호 오류 / 권한 문제 | 데이터베이스 서비스 상태 확인; 설정의 연결 정보 확인 |
요약
서비스 배포는 체계적인 대공정입니다. 코드 빌드부터 서버 배포, 네트워크 설정부터 보안 방어, 모니터링 알림부터 로그 분석까지 다방면을 포괄합니다. 초보자에게는 처음부터 완벽을 추구할 필요가 없습니다. 먼저 최소 기능 버전(MVP)을 실행시키고, 그 위에 점진적으로 개선해 나가면 됩니다.
전체 과정의 핵심 포인트는 다음과 같이 요약할 수 있습니다:
핵심 프로세스
- 빌드 →
npm run build로 코드를 브라우저가 이해할 수 있는 HTML/CSS/JS로 변환 - 배포 → 빌드 산출물을 서버에 업로드. Nginx로 리버스 프록시 설정.
- 도메인 → 도메인을 구매하고 DNS 해석을 서버 IP로 설정
- HTTPS → Let's Encrypt로 무료 인증서를 신청. 데이터 전송 보안 강화.
- CI/CD → 자동 배포 설정. 코드 푸시 후 자동으로 온라인.
- 모니터링 → 모니터링과 알림 설정. 문제 발생 시 즉시 인지.
학습 로드맵 추천
- 1일차: Vercel/Netlify로 정적 웹페이지 배포. "코드가 웹사이트가 되는" 경험 하기.
- 1주차: 클라우드 서버를 빌리고 Node.js 프로젝트를 수동으로 배포. 도메인과 HTTPS 설정.
- 2-4주차: 완전한 CI/CD 프로세스 설정. 모니터링과 알림 시스템 구축.
- 지속적 학습: Docker 컨테이너화 학습, Kubernetes 클러스터 학습, 마이크로서비스 아키텍처 학습.
용어 빠른 참조표
| 용어 | 영어 | 쉬운 설명 |
|---|---|---|
| 빌드 | Build | 소스코드를 브라우저가 실행할 수 있는 형식으로 번역하고 패키징 |
| 배포 | Deploy | 코드를 서버에 올려 사용자가 접속할 수 있게 함 |
| 서버 | Server | 7x24시간 전원이 켜져 있고 인터넷에 연결된 컴퓨터 |
| 도메인 | Domain | 웹사이트의 기억하기 쉬운 이름 (예: naver.com) |
| DNS | Domain Name System | 도메인을 IP 주소로 번역하는 "전화번호부" |
| HTTP | HyperText Transfer Protocol | 웹페이지 전송 프로토콜 (안전하지 않음, 평문 전송) |
| HTTPS | HTTP Secure | 암호화 전송 웹 프로토콜 (안전함) |
| Nginx | Engine X | 고성능 웹 서버. 리버스 프록시 역할. |
| 리버스 프록시 | Reverse Proxy | 문 앞에 서 있는 점원. 요청을 백엔드로 전달. |
| SSH | Secure Shell | 서버에 원격 로그인하는 암호화 도구 |
| CDN | Content Delivery Network | 전 세계에 분산된 서버 네트워크. 접속 속도 향상. |
| CI/CD | Continuous Integration/Deployment | 자동화 파이프라인. 코드 푸시 후 자동 테스트 및 배포. |
| SSL/TLS | Secure Sockets Layer / Transport Layer Security | 암호화 프로토콜. HTTPS에 보안을 제공. |
| PM2 | Process Manager 2 | Node.js 프로세스 관리자. 애플리케이션이 계속 실행되도록 함. |