본문 바로가기

Vite 기반 프론트엔드 서비스 Dev 서버와 운영 배포 환경 분리의 아키텍처

728x90

Vite dev 모드 vs prod(운영) 환경을 “동작 원리 → 구성/배포 → 보안 관점 → 점검 체크리스트 → 예시”까지 정리합니다.
(React+TSX 기준으로 설명하지만 Vue/Svelte도 핵심은 동일합니다.)

Vite가 “서비스”하는 대상은 뭔가요?

개발 소스(원본)

  • src/**/*.ts, src/**/*.tsx
  • src/main.tsx, src/App.tsx, components/*

Vite가 브라우저에 제공하는 방식은 “모드”에 따라 다릅니다

  • dev 모드: 원본 구조를 유지한 채 모듈(ESM) 단위로 실시간 변환해서 제공
  • prod 모드(build): 원본을 번들/압축/최적화해서 dist/ 정적 파일로 생성 후 제공

Vite Dev 모드 (개발 서버) – 동작 원리

핵심 컨셉: “번들링 없이 ESM로 바로 제공”

Vite dev는 “번들”을 거의 하지 않고, 브라우저가 모듈을 import로 요청하면 그때그때 변환해서 돌려줍니다.

dev 모드에서 실제로 일어나는 일

  1. 브라우저가 index.html 요청
  2. index.html 안의 <script type="module" src="/src/main.tsx"> 실행
  3. 브라우저가 /src/main.tsx 요청
  4. Vite가 TSX → JS로 변환해서 응답
  5. main.tsx가 import한 /src/App.tsx도 브라우저가 또 요청
  6. 이런 식으로 모듈 단위로 계속 요청/응답

네트워크에서 보이는 흔한 요청 예

  • GET /src/main.tsx
  • GET /src/App.tsx
  • GET /src/components/Header.tsx
  • GET /@vite/client (HMR 클라이언트)
  • GET /node_modules/.vite/deps/react.js?... (의존성 pre-bundle)
300x250

👉 그래서 질문하신 것처럼 브라우저에서 TSX 파일이 “다운로드되는 것처럼” 보이는 게 정상입니다.
(엄밀히는 “TSX 원본 그대로”가 아니라, 요청 경로는 .tsx지만 응답은 JS로 변환된 코드인 경우가 많습니다.)

dev 모드의 강점

  • 매우 빠른 스타트/리로드
  • HMR(Hot Module Replacement)로 화면 즉시 반영
  • 의존성은 미리 pre-bundle해서 빠르게 제공

dev 모드의 리스크(보안/운영 관점)

  • src/ 경로와 모듈 구조가 노출됨
  • 내부 라우팅, 화면 흐름, API 호출 패턴이 그대로 보임
  • HMR/디버깅 기능이 포함되므로 운영에 부적합

Prod (운영) – Build 결과물의 구조와 원리

build의 목표

  • TS/TSX 원본을 “배포 가능한 정적 파일”로 변환
  • 번들링/압축/캐싱 최적화
  • 코드 스플리팅(필요할 때만 로드)

build 결과 예시

dist/
 ├─ index.html
 ├─ assets/
 │   ├─ index-7c1a9f0d.js
 │   ├─ vendor-3b2c1aa1.js
 │   ├─ index-11a2.css
 │   └─ logo-9d3.png
  • .tsx 파일은 없음
  • 파일명에 해시가 붙어서 캐시 무효화가 쉬움
  • 브라우저는 /assets/index-xxxx.js만 받음

운영에서 코드가 “보이지 않는가?”의 현실

  • 원본 TSX는 제공되지 않음
  • 하지만 JS 번들 자체는 당연히 브라우저에 내려가므로 분석은 가능
  • “소스 파일”은 없지만 “로직”은 남아있음

“빌드 결과물로 소스코드를 만들 수 있나?” (현실적인 결론)

✅ 가능한 것

  • 화면/로직 흐름 분석
  • API 엔드포인트 추출
  • 권한 분기 추정(특히 프론트에서 권한 판단하면 거의 다 보임)
  • 피처플래그/상수/문자열/에러메시지/라우트 추출

❌ 어려운 것

  • 타입 정보(TypeScript 타입)
  • 원래 파일 단위 구조 정확히 복원
  • 주석/의도/변수명(압축 시 많이 사라짐)

단, SourceMap이 있으면 거의 “복원 가능”

*.map이 외부에서 접근 가능하면

  • 원래 파일 경로(src/pages/Admin.tsx)
  • 원래 코드(상당량)
  • 주석까지 노출될 수 있음

Dev vs Prod 운영에서 반드시 지켜야 할 기준

원칙 1: Dev 서버는 “개발망/로컬 전용”

  • dev 서버를 외부에 노출하면 사실상 소스 구조 공개
권장 설정 예
// vite.config.ts
export default {
  server: {
    host: "127.0.0.1",
    port: 5173,
    strictPort: true,
  }
}

내부 개발망 공유가 필요하면(최소한)

  • VPN 내부에서만
  • 방화벽으로 접근 제한
  • IP allowlist
  • Basic Auth / SSO reverse proxy(가능하면)

원칙 2: 운영은 반드시 build 결과물만 서비스

  • npm run builddist/ 생성
  • Nginx/Apache/CDN/오브젝트 스토리지로 정적 배포
Nginx 기본 예시
server {
  listen 80;
  server_name example.com;

  root /var/www/app/dist;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}

원칙 3: 프론트엔드는 “노출되어도 안전”해야 함

프론트에서 하면 안 되는 것들

  • 권한 결정 (관리자 여부 등)
  • 데이터 접근 통제
  • 핵심 검증 로직(가격/할인/승인 등)
  • 민감 키/토큰/비밀값 포함

👉 “프론트는 UI”, “서버가 결정권자”가 보안의 정석입니다.

원칙 4: SourceMap 운영 정책

운영에서 .map을 그냥 공개하면 위험합니다.

권장
  • prod: sourcemap: false
  • 또는 오류 추적 도구(Sentry 등)에만 업로드하고 외부 제공 금지
// vite.config.ts
export default {
  build: {
    sourcemap: false,
    minify: "esbuild",
  }
}

예시로 보는 차이 (dev vs prod)

dev 모드에서의 import 체인

main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";

ReactDOM.createRoot(document.getElementById("root")!).render(<App />);

브라우저 요청

  • /src/main.tsx
  • /src/App.tsx
  • /src/components/...

👉 소스 구조가 그대로 노출되는 느낌이 나는 이유입니다.

prod 모드에서는 이렇게 바뀜

브라우저 요청

  • /assets/index-7c1a9f0d.js
  • /assets/vendor-3b2c1aa1.js

👉 파일명/구조가 해시로 숨겨지고 최적화됩니다.
하지만 JS 번들 내부 로직은 분석 가능합니다.

실무 점검 체크리스트 (보안팀/운영팀 공통)

A) Dev 서버 노출 여부

  • vite dev 서버가 외부(인터넷)에서 접근 가능한가?
  • --host 0.0.0.0로 열어둔 적이 있는가?
  • Reverse proxy 없이 5173/3000 포트가 열려있는가?

B) 운영 배포 방식

  • 운영 서버가 dist/ 정적 파일만 서비스하는가?
  • src/ 경로가 운영에서 접근 가능한가? (있으면 비정상)

C) SourceMap 노출

  • 운영 환경에서 *.map URL이 200으로 접근되는가?
  • CDN/오브젝트 스토리지에 .map이 올라가 있는가?
  • Content-Type이 map로 내려가며 DevTools에서 소스가 보이는가?

D) 프론트 로직 보안(설계 점검)

  • 권한 체크가 프론트에서만 이뤄지지 않는가?
  • 민감 API가 인증 없이 호출 가능한가?
  • 관리자 기능이 라우트만 숨긴 상태인가? (서버 검증 필수)
  • API base URL/키/토큰이 프론트에 하드코딩되어 있지 않은가?

운영 환경에서 자주 쓰는 배포 패턴

패턴 1: Nginx 정적 서빙 + API는 별도

  • / → dist 정적 파일
  • /api/ → 백엔드로 프록시

패턴 2: CDN + Object Storage (S3류)

  • dist를 버전 단위로 업로드
  • 캐시 정책 최적화
  • .map은 업로드 제외 또는 접근 제한

최종 정리 (한 눈에)

Dev 모드

  • 브라우저가 /src/*.tsx를 직접 요청하는 구조
  • 실시간 변환 + HMR
  • 소스 구조 노출이 “정상”
  • 운영에 쓰면 위험

Prod 모드

  • dist 정적 파일만 제공
  • TSX 원본은 없음
  • 하지만 JS 분석으로 로직 추론은 가능
  • SourceMap 노출 시 사실상 소스 공개

사내 보안 가이드 문서 형태

  • “Vite Dev 서버 운영 금지 기준” 문구 템플릿
  • “운영 배포 점검 표준 체크리스트(감사/ITGC 스타일)”
  • “Sourcemap 정책(개발/스테이징/운영) 표준안”
728x90
그리드형(광고전용)

댓글