Architectural Improvements 3
2025.07.21 · 나만무

도메인을 직접 구입했으니 이제는 “집 주소만 있고 초인종도 없는” 상태에서 벗어나야 했다. 조금 전 한 일은 세 가지다.
- klicklab.co.kr을 EC2 퍼블릭 IP에 매핑하는 도메인 연결
- 무료 SSL(Let’s Encrypt)로 HTTPS 적용
- **PM2**로 프론트·백엔드 프로세스를 영구 데몬화
이 세 단계만으로 “주소 → 보안문 설치 → 집주인 자동 출근”까지 끝냈다. 이제 클릭랩은 한층 더 실제 서비스같은 면모를 갖춰 나가고 있다.
1. 도메인 & DNS 두 개의 A 레코드
| 레코드 | 값 | TTL① |
|---|---|---|
A @ (root) | 15.165.249.173 | 600 |
A www | 15.165.249.173 | 600 |
① TTL(Time To Live) — DNS 캐시 유지 시간(초). 600이면 10분마다 갱신된다.
왜 이중 레코드가 필요하냐면…
- 사용자가 www 붙여서 접속할 수도, 생략 할 수도 있다.
- 두 레코드를 모두 IP에 매핑해야 **트래픽·SEO 지표가 한 URL로 집중**돼 검색 순위 하락(중복 페이지 패널티)을 막는다.
얻은 이점
- 운영자가 로그·분석 대시보드를 볼 때 “www”와 “non-www”를 합쳐 계산할 필요가 없다.
- 외부에 배포하는 자료(발표 자료·SNS)에서도 도메인을 한 형태로만 쓰면 된다.
2. Nginx 상세 설정
# ① www → non-www 강제 이동
server {
listen 80;
server_name www.klicklab.co.kr; # 요청 호스트가 www일 때
return 301 http://klicklab.co.kr$request_uri; # 301 Moved Permanently
}
# ② 애플리케이션 프록시
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name klicklab.co.kr; # non-www
location / {
proxy_pass http://localhost:5173; # Vite dev 서버
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade'; # WebSocket 지원
}
}
| 구성 | 왜 필요한가 | 이점 |
|---|---|---|
| www 리디렉션 | URL 통일, 쿠키·세션 혼란 제거 | 브라우저 캐시 중복·SEO 패널티 해결 |
| 리버스 프록시 | Node(Vite) 서버를 5173 포트에 숨김 | 직접 노출 안 돼 공격 벡터 축소 |
proxy_set_header | WebSocket·Header 전달 | Vite HMR(Hot Module Reload) 정상 동작 |
nginx -t으로 문법 검증하고 warning 없으면systemctl reload nginx.
3. Node 런타임 & PM2(Process Manager 2)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g pm2 # sudo 필수, 전역 설치
| 용어 | 설명 |
|---|---|
| Node.js | JavaScript 백엔드 런타임. 싱글 스레드 이벤트 루프 구조 |
| PM2 | Node 프로세스를 포크·클러스터 모드로 데몬 관리, 로그·오토 리로드 지원 |
이걸 왜 해야 하냐면
node index.js만 사용하면 터미널이 끊길 때 서버도 같이 죽는다.- PM2는 크래시 감지 후 재시작, 메모리 누수 감시, 시스템 재부팅 후 자동 복구 기능을 제공. 이점 — 운영자가 SSH 세션을 종료해도 서비스 지속, 장애 MTTR② 대폭 감소. (② Mean Time To Recovery — 복구 평균 시간)
4. 애플리케이션 등록
4-1. 프로젝트 구조
~/KlickLab
├─ backend/ # Node(Express) ▶ index.js
└─ frontend/ # Vite + React ▶ vite.config.ts
4-2. Vite 설정(외부 호스트 허용)
server: {
host: '0.0.0.0', // 모든 인터페이스 바인딩
port: 5173,
allowedHosts: ['klicklab.co.kr','www.klicklab.co.kr'], // 도메인 화이트리스트
proxy: { '/api': 'http://localhost:4000' } // 백엔드 프록시
}
- Blocked request 오류(Vite의 호스트 검증)를 제거.
/api요청은 자동으로 백엔드로 분기.
4-3. PM2로 서비스 등록
# 프런트
cd ~/KlickLab/frontend
pm2 start "npx vite --host 0.0.0.0 --port 5173" --name klicklab-frontend
# 백엔드
cd ~/KlickLab/backend
pm2 start index.js --name klicklab-backend
pm2 save # 현재 프로세스 스냅샷 저장
pm2 startup # systemd에 서비스 등록

pm2 startup출력에 나온sudo env PATH=… pm2 startup systemd …한 줄을 복사-실행해 systemd 서비스 파일을 생성.
| 이점 | 설명 |
|---|---|
| 자동 부활 | 서버 재부팅 후 pm2 resurrect 가 dump 파일을 읽어 자동 실행 |
| 로그 관리 | ~/.pm2/logs/*.log 파일로 stdout/stderr 분리 저장 |
| 리소스 모니터 | pm2 monit 한눈에 CPU·메모리 확인 |
5. HTTPS 적용 (Let’s Encrypt)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d klicklab.co.kr -d www.klicklab.co.kr
| 용어 | 설명 |
|---|---|
| Certbot | Let’s Encrypt가 제공하는 무료 SSL 자동 발급·갱신 클라이언트 |
| ACME | Automatic Certificate Management Environment, SSL 자동화 프로토콜 |
- 설치 중 옵션 2 “Redirect” 선택 → 모든 HTTP 요청 301 → HTTPS
- 만료 30 일 전에
certbot.timer(systemd)가 자동 갱신 - 인증서 경로:
/etc/letsencrypt/live/klicklab.co.kr/


이걸 하면 좋은 점
- 브라우저 ‘Not Secure’ 경고 제거, 사용자 신뢰도 향상
- 비용이 공짜다. 안쓸 이유가 없음
6. 최종 효과 정리
| 카테고리 | 개선 전 | 개선 후 |
|---|---|---|
| 접근 URL | 다중(www/non-www/HTTP/HTTPS) | HTTPS + non-www 로 통일 |
| 보안 | 평문 HTTP | TLS 1.3 암호화, 무료 SSL |
| 가용성 | 터미널 종료 시 서비스 중단 | PM2 재시작, 크래시 자동 복구 |
| 운영 비용 | 유료 CA 발급 | Let’s Encrypt(무료) |
| 데브 UX | 로컬 5173 직접 노출 | Nginx 프록시 → HMR 유지 |