다음과 같은 명령어를 통해 빌드 단계를 수행할 수 있다.
npm run build # vite build

빌드 과정에서는 번들링을 통해 .jsx, .html, .css와 같이 개발자가 작성한 코드 파일들이 브라우저가 이해할 수 있는 단일 .html, .css, .js 파일로 압축된다.
번들링이란, 여러 개의 JS 파일을 하나의 파일로 묶어, 브라우저에서 효율적으로 로딩하고 실행될 수 있도록 최적화하는 과정이다.
Vite에서는 Rollup.js를 이용하여 번들링을 수행하고, 다음과 같은 기능을 제공한다.
Nginx는 Nginx 웹 서버로의 모든 클라이언트의 요청에 대해 로그를 남긴다.
acccess.log
127.0.0.1 - - [19/Jan/2026:12:11:17 +0900] "GET / HTTP/1.1" 200 408 "-" "curl/8.17.0"
127.0.0.1 - - [19/Jan/2026:12:11:53 +0900] "GET /not HTTP/1.1" 404 153 "-" "curl/8.17.0"
error.log
2026/01/19 12:11:53 [error] 23364#10364: *29 CreateFile() "C:\woori-workspace\00.sw\nginx-1.28.1\nginx-1.28.1/nginx-practice/not" failed (2: The system cannot find the file specified), client: 127.0.0.1, server: localhost, request: "GET /not HTTP/1.1", host: "localhost"
모든 요청에 대해 로깅을 수행할 경우, 로그 파일의 용량이 커지게 되고, 매번 로그 처리 연산을 수행하느라 서버의 부하에 영향을 미칠 수 있다.
또한, 서로 관련 있는 요청별로 로그 파일을 구분하여 모아두는 것이 유지보수에 편하기 때문에 적절히 분리하는 게 좋다.
nginx.config
events {} # 연결 처리 설정 (기본값 사용)
http { # HTTP 요청 처리 설정 시작
include mime.types;
server { # 서버 블록 시작
listen 80; # 80 포트에서 HTTP 요청 대기
server_name localhost; # 'localhost' 도메인에 대해 응답
root nginx-practice; # 정적 파일들이 위치한 루트 디렉토리
index index.html; # 기본 인덱스 파일 설정
location /custom {
access_log logs/custom.access.log;
return 200 'custom route';
}
} # 서버 블록 종료
} # HTTP 블록 종료
다음과 같이 /custom 으로의 새 분기를 추가하고, access_log에 해당 분기로 접근했을 때의 로그를 관리할 파일을 적어준다.
curl localhost/custom
으로 확인하면, 새로 추가한 custom.access.log 파일에 새 로그가 찍히는 걸 확인할 수 있다.
access_log에 로그 파일 대신 ‘off’ 옵션을 넣어주면 해당 페이지에 접근해도 로그가 찍히지 않게 할 수 있는데, 로그를 기록해야 하므로 보통은 잘 사용하지 않는다.
사용자가 서비스를 언제든지 이용할 수 있도록 하기 위해서는 서버가 높은 가용성을 가져야 한다. 일반적으로 같은 서버 인스턴스를 최소 2대 이상 가동해, 클라이언트의 요청 트래픽을 각각의 서버로 분산할 수 있다.

다음과 같은 로드 밸런서를 통해 여러 서버로 트래픽이 분산 될 수 있다.

npm run preview

개발 환경(npm run dev)에서는 5173 포트로 실행했지만, 빌드 환경 미리보기로 하면 4173 포트로 실행된다.
대표적인 상용 웹 서버다.
nginx.config
events {} # 연결 처리 설정 (기본값 사용)
http { # HTTP 요청 처리 설정 시작
server { # 서버 블록 시작
listen 80; # 80 포트에서 HTTP 요청 대기
server_name localhost; # 'localhost' 도메인에 대해 응답
root nginx-practice; # 정적 파일들이 위치한 루트 디렉토리
index index.html; # 기본 인덱스 파일 설정
} # 서버 블록 종료
} # HTTP 블록 종료
nginx.config 가 유효한지 검사하는 명령어
nginx -t

작성한 파일 내용으로 리로드 하는 명령어
(서버를 껐다 켜지 않고도 바뀐 config 내용을 적용할 수 있다)
nginx -s reload
curl을 통해 style.css가 잘 적용되었는지 본다.
curl -I localhost/style.css

nginx.config
location /hello {
return 200 '/hello requested';
}
server 설정 안에 해당 블록을 넣어주면, 다음과 같이 localhost/hello에서 해당 문구를 보여준다.

초기 세팅 과정은 다음과 같다.
server_a.js
const http = require('http');
const port = 3001;
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
console.log("Server A");
res.end('Node.js Server A\n');
});
server.listen(port, () => {
console.log(`Server A running on http://localhost:${port}\n`);
});
nginx.config
location / {
proxy_pass 'http://localhost:3001/';
}
서버 안에 해당 코드를 넣어주면 localhost로 접근해도 server_a로 이동한다.
upstream node_servers {
server localhost:3001 weight=1;
server localhost:3002 weight=2; # 3001보다 더 많은 요청을 처리
}

서버 A를 끄면 B, C에서만 분산되어 응답한다. A를 다시 켜주면 잠시 후 A, B, C가 순차적으로 응답하며 부하가 분산된다.
upstream node_servers {
least_conn; # 리스트 커넥션 알고리즘 적용
server localhost:3001
server localhost:3002
}+) 현업에서는 nginx를 많이 쓴다. 대체 프로그램으로 haproxy가 있음!
일정 시간 동안 허용되는 요청의 수를 제한한다. 특정 사용자의 IP에 대해 요청 비율을 제한하도록 적용한다.
비정상적인 대량의 요청을 차단한다.
API 남용을 방지하고, 서버의 리소스를 보호한다.
Nginx의 디렉티브
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;


예를 들어 burst=5 이고 rate=1r/s이면, 한 요청당 1L의 물이 들고 최대 5L까지 바구니에 들어갈 수 있다.
5L를 넘는 요청에 대해서는 에러를 발생시키고, 1초마다 1L의 물이 비워진다(샌다.)


전체 요청에 대해서 3개를 허용하는 거였다!