다크 모드
Appendix A. 사내 실무 환경설정 및 Docker/Nginx 배포 가이드
"로컬에서만 잘 돌아가는 코드는 아무런 가치가 없다. 개발, 검증, 운영 환경을 안전하게 분기하고, Docker와 Nginx로 프로덕션에 배포하는 엔터프라이즈 실무 표준을 정립한다."
A.1 환경변수 분기 전략 (.env)
사내 시스템은 보통 로컬(Local), 개발/검증(Dev/Stage), 운영(Prod) 환경으로 나뉩니다.
API 서버의 도메인이 환경마다 달라지는데, 코드 안에 http://localhost:8080을 하드코딩해서는 안 됩니다.
Vite는 접두사 **VITE_**로 시작하는 환경변수를 빌드 시점에 코드 내부로 주입해 줍니다.
[설정 A-1] 로컬 개발 환경 (.env.development)
ini
# 로컬 개발 환경: Vite의 리버스 프록시(/api)를 타도록 상대 경로 지정
VITE_API_BASE_URL=
VITE_ENV_NAME=local[설정 A-2] 사내 운영 환경 (.env.production)
ini
# 운영 배포 환경: 실제 사내 API 게이트웨이 또는 도메인 주소 지정
VITE_API_BASE_URL=https://board-api.company.com
VITE_ENV_NAME=production코드 내부에서는 TypeScript의 타입 가호를 받으며 다음과 같이 참조합니다:
typescript
// src/api/httpClient.ts
export const httpClient = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || '',
timeout: 10000
});A.2 프로덕션 배포를 위한 멀티 스테이지 Dockerfile
Vue 3 SPA는 빌드하고 나면 순수한 HTML, CSS, JavaScript 정적 파일(dist/ 폴더)만 남습니다.
Node.js 런타임을 운영 서버에 통째로 띄울 필요 없이, 초경량 Nginx 컨테이너로 서빙하는 것이 엔터프라이즈의 표준입니다.
[코드 A-1] 멀티 스테이지 빌드 (frontend/Dockerfile)
dockerfile
# ==========================================
# 1단계: 빌드 스테이지 (Node.js 환경)
# ==========================================
FROM node:20-alpine AS builder
WORKDIR /app
# 캐시 효율을 위해 package.json 먼저 복사
COPY package*.json ./
RUN npm ci
# 소스 복사 및 프로덕션 빌드 실행
COPY . .
RUN npm run build
# ==========================================
# 2단계: 서빙 스테이지 (경량 Nginx 알파인 환경)
# ==========================================
FROM nginx:alpine
# 빌드된 dist 폴더만 Nginx 루트로 복사 (이미지 용량: 30MB 이하로 극단적 경량화)
COPY --from=builder /app/dist /usr/share/nginx/html
# SPA 라우팅을 위한 커스텀 Nginx 설정 파일 주입
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]A.3 SPA 히스토리 모드를 위한 Nginx 라우팅 설정 (nginx.conf)
Vue Router의 createWebHistory()를 사용할 때 가장 흔히 터지는 운영 장애가 있습니다:
메인(/)에서는 잘 동작하는데, 사용자가 특정 상세 URL(예: /post/10)에서 **브라우저 새로고침(F5)**을 누르면 Nginx가 실제 물리 파일인 /post/10을 찾다가 404 Not Found 에러를 뿜어내는 현상입니다.
이를 방지하기 위해 모든 URL 요청을 Vue의 index.html로 폴백(Fallback)시켜 주어야 합니다.
[코드 A-2] frontend/nginx.conf
nginx
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gzip 압축 전송 설정 (초기 로딩 속도 극대화)
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
location / {
# 🌟 핵심: 요청한 파일($uri)이나 디렉토리($uri/)가 없으면 index.html로 토스!
try_files $uri $uri/ /index.html;
}
# 정적 에셋(JS, CSS, 이미지)의 브라우저 캐시 정책 (1년 캐싱)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, no-transform";
}
# 500 등 서버 장애 시 에러 페이지
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}A.4 사내 원클릭 빌드 및 배포 명령어
bash
# 1. Docker 이미지 빌드
docker build -t company-board-fe:latest .
# 2. 컨테이너 기동 (포트 80 매핑)
docker run -d -p 80:80 --name board-frontend company-board-fe:latest이 설정이 갖춰지면, 사내 GitLab CI나 Jenkins 파이프라인에서 커밋 푸시 한 번으로 운영 서버에 무중단으로 컨테이너가 배포되는 완벽한 DevOps 파이프라인이 완성됩니다.