목차
- 개요
- nginx.conf 생성
- Dockerfile 생성
- Docker image 생성
- Docker Container 실행
개요
폐쇄망에서 react 프론트 프로젝트를 nginx와 함께 구축해서 배포
spring boot의 경우 배포할때 profiles 설정, 필요 환경변수과 함께 jar(executable jar)파일 생성 후 도커 이미지를 container로 실행만하면 웹 서버가 쉽게 구성이 됩니다.(spring boot의 장점 중 하나인 내장 tomcat)
하지만 react의 경우 node.js와 express 모듈을 이용해 웹 서버를 구성할 수있지만, 로드밸런싱, 캐싱 등의 안정적이고 효율적인 웹 서버이자 리버스 프록시 서버인 nginx를 함께 구성해주는것이 좋습니다.

react를 이용한 프론트를 웹 서버인 nginx와 함께 구성하여 프론트 웹 서버 구성하는 방법을 알아보겠습니다.
환경
- react - 18.3.1
- nginx - 1.29
- vite - 5.4.19
- harbor(개인 이미지 저장소) - 폐쇄망으로 인해 docker hub 대체로 사용
nginx.conf 생성
react와 nginx를 nginx의 설정파일인 nginx.conf를 생성합니다.
생성 위치는 프로젝트의 루트 디렉터리입니다.
//nginx.conf
server {
listen 21000;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
# root를 /usr/share/nginx/html 을 바라보게 했으므로(Dockerfile 참고)
# 해당 경로 아래에 배포해주면 됨
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
nginx.conf 요소의 목적 및 역할
server {...}
nginx에서 하나의 웹사이트 또는 가상 호스트를 정의하는 블록입니다.
이 블록 내의 모든 설정은 이 nginx서버를 통해 들어오는 요청에 적용됩니다.
- listen
- nginx가 외부로부터 연결 요청을 수신할 TCP포트 번호
- nginx의 기본 포트는 80
- listen 21000; 설정시 이 서버는 21000포트를 통해 접근 가능
- access_log & error_log
- 해당 서버로 들어오는 모든 요청 및 에러 기록을 저장할 파일 경로를 지정
- 서버의 트래픽 분석 및 모니터링에 사용
location / {...}
해당 서버로 들어오는 모든 URL 경로(http://ip:21000/ 뒤의 모든 경로)에 대해 nginx가 어떻게 응답할지를 정의합니다.
- root
- nginx가 정적파일을 찾는 최상위 디렉터리(문서 루트) 지정
- react 빌드 결과물(index.html, .js, .css파일 등)이 해당 경로에 있어야 합니다.
- 예시의 경우 vite의 빌드 파일인 dist파일 정보를 해당 경로(/usr/share/nginx/html)로 이동시킵니다.
- ex) root /usr/share/nginx/html;
- index
- 사용자가 기본 경로(http://ip:21000)만 입력했을 때 기본으로 제공할 파일 이름을 지정
- ex) index index.html index.html
- try_files $uri $uri /index.html
- SPA(Single Page Application) 라우팅을 위한 핵심 설정
[try_files $uri $uri /index.html 동작원리]
해당 설정은 브라우저의 요청을 처리하는 우선순위를 정의합니다.
1. $uri (첫번째 시도)
요청된 경로에 해당하는 정확한 파일이 root 디렉터리(index.html 이나 .js파일 등)에 있는지 확인합니다.
2. $uri/ (두번째 시도)
요청된 경로에 해당하는 디렉터리가 있는지 확인하고, 있다면 index설정에 따라 디렉터리 내의 index.htm파일을 찾습니다.
3. /index.html (최종 대체)
위 두가지 모두 실패했을때 무조건 /index.html 파일을 제공하도록 합니다.
[try_files가 React SPA에서 중요한 이유]
React 라우터가 관리하는 경로(예 : /user/component/test)는 서버에 물리적인 파일로 존재하지 않습니다.
try_files 덕분에 nginx는 이 경로를 404에러로 처리하는 대신 메인 index.html파일을 반환합니다.
이후 브라우저에서 React라우터가 실행되어 URL(/user/component/test)을 분석하고, 해당 경로에 맞는 컴포넌트를 렌더링하게 됩니다.
Dockerfile 생성
nginx설정을 마무리한 뒤, react 프로젝트를 docker 이미지화하기 위한 Dockerfile을 생성합니다.
nginx.conf과 마찬가지로 Dockerfile도 루트 디렉터리에 생성합니다.
//Dockerfile
FROM 10.10.5.66:444/library/node:22 as builder
WORKDIR /app
COPY package.json yarn.lock .yarnrc ./
COPY npm_packages ./npm_packages
RUN yarn install --offline --frozen-lockfile
COPY . .
RUN yarn build
FROM 10.10.5.66:444/library/nginx:1.29
COPY --from=builder /app/dist /usr/share/nginx/html
RUN chmod -R 777 /var/cache/nginx && \
chmod -R 777 /var/log/nginx && \
chmod -R 777 /var/run
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 21000
CMD ["nginx", "-g", "daemon off;"]
명령어 설명
Dockerfile의 목표는 React코드의 빌드 파일인 dist파일을 nginx가 바라보게하여 도커 이미지로 변환하게 하는것입니다.
Builder 단계
해당 단계의 목표는 React 코드를 빌드하여 최종 정적 파일(dist파일)을 생성하는 것입니다.
빌드에 필요한 node.js와 yarn 등은 최종 이미지에 포함되지 않습니다.
- FROM 10.10.5.66:444/library/node:22 as builder
- 명령을 수행할 환경을 세팅
- 해당 단계에서는 node.js 런타임과 yarn을 포함하고 있어 react 빌드 환경을 제공해줍니다.
- 폐쇄망으로 인해 개인 이미지 저장소(harbor)를 사용하기 때문에 harbor의 경로인 10.10.5.66:444/library/node:22 를 사용합니다.
- builder라는 alias를 사용합니다.
- WORKDIR /app
- 작업 디렉터리 설정
- 컨테이너 내부에서 이후 명령어가 실행될 루트 디렉터리를 /app으로 지정합니다.
- COPY package.json yarn lock .yarnrc ./
- 의존성 파일 복사(캐시 최적화)
- package.json과 의존성 정보를 담은 파일을 먼저 복사합니다. 만약 pacakge.json이 변경되지 않으면 RUN yarn install레이어는 Docker캐시를 사용하여 설치 과정을 생략해서 빌드 속도가 빨라집니다.
- 해당 방법을 사용하는 이유는 캐시도 있지만, 폐쇄망에서 install시 의존성 다운을 위한 설정이 필요하기 때문입니다. (특히 yarn lock, .yarnrc)
- COPY npm_packages ./npm_packages
- 로컬 패키지 복사
- 해당 방법을 사용하는 폐쇄망에서 install시 의존성을 모두 받지 못하기 때문에 미리 필요한 의존성을 로컬에서 받아서 사용하기 위함도 있습니다.
- RUN yarn install --offline --frozen-lockfile
- 의존성 설치
- yarn install을 통해 node에 필요한 node모듈을 다운로드합니다.
- --offline 옵션으로 오프라인 저장소나 로컬 캐시를 사용하도록 지시합니다.
- --frozen-lockfile 옵션으로 yarn.lock파일에 명시된 버전만 사용하도록 강제합니다.
- COPY . .
- 소스코드 복사
- 프로젝트의 나머지 모든 소스 코드 파일을 /app 디렉터리로 복사합니다.
- RUN yarn build
- 빌드 실행
- package.json에 정의된 build 스크립트(내부적으로 vite build)를 실행하여 React코드를 배포 가능한 정적 파일(dist파일)로 컴파일합니다.
Deploy 단계
해당 단계의 목표는 이전 Builder단계에서 만든 정적파일과 설정파일을 포함하는 최종 nginx 웹서버 이미지를 만드는 것입니다.
- FROM 10.10.5.66:444/library/nginx:1.29
- 명령을 수행할 환경을 세팅
- 정적파일의 웹서버로 사용할 nginx 환경을 구성합니다.
- 폐쇄망으로 인해 개인 이미지 저장소에 저장되어있는 nginx:1.29를 사용합니다.
- COPY --from=builder /app/dist /usr/share/nginx/html
- 핵심 파일 복사
- builder 단계에서 생성한 정적파일인 dist파일을 nginx의 /usr/share/nginx/html(웹 루트 디렉터리) 경로로 복사합니다.
- RUN chmod -R 777 /var/cache/nginx && \
chmod -R 777 /var/log/nginx && \
chmod -R 777 /var/run- 권한 설정
- nginx가 사용하는 로그,캐시,런타임 파일 등을 기록하는데 필요한 경로에 쓰기 권한을 부여합니다.
- RUN rm /etc/nginx/conf.d/default.conf
- 기본 nginx 설정 제거
- 사용자 정의 설정인 nginx.conf를 사용하기 위해 기본으로 가지고 있는 설정 파일인 deafult.conf 파일을 삭제해줍니다.
- COPY nginx/nginx.conf /etc/nginx/conf.d
- 사용자 정의 nginx 설정 등록
- EXPOSE 21000
- 포트 노출
- nginx 컨테이너가 21000번 포트를 노출합니다. 이 포트가 외부로 연결(포트 포워딩)되어야 실제 접근이 가능해집니다.
- CMD ["nginx", "-g", "daemon off;"]
- 컨테이너가 시작될 때 실행될 기본 명령어
- daemon off; 옵션은 nginx를 포그라운드에서 실행하여 docker 컨테이너의 주 프로세스를 유지하도록 합니다.
- daemon off; 옵션이 없는 경우 nginx는 백그라운드에서 실행되고 docker는 프로세스가 종료된것으로 판단하여 컨테이너를 종료하게 됩니다.
Docker image 생성
nginx 설정과 Dockerfile이 준비되었다면 도커 이미지를 생성해보겠습니다.
docker build -t [생성할 이미지 명]:[태그] [경로]
테스트 환경은 vm 리눅스 서버입니다.
먼저 리눅스 서버에 테스트로 올릴 react 소스 코드를 받아옵니다. react 프로젝트의 루트 디렉터리에 이미지 생성에 필요한 Dockerfile이 존재하기 때문에 루트 디렉터리에서 작업을 진행합니다.

docker build -t mobile_framework_react:0.1 명령어를 진행시켜 소스코드를 도커 이미지화 합니다.

도커 빌드가 끝나게 되면 docker images 명령시 이미지가 생성된것을 확인 할 수 있습니다.

Docker Container 실행
생성한 도커 이미지를 실행시킵니다.
docker run -d --name mobile_framework_react -p 21000:21000 mobile_framework_react:0.1
- -d
- 도커 컨테이너를 백그라운드로 실행하는 옵션
- --name mobile_framework_react
- 실행할 컨테이너 이름
- -p 21000:21000
- 포트 포워딩 옵션
- [외부 port] : [컨테이너 수신 port]
- Dockerfile에서 nginx이 사용할 port인 21000과 포트 포워딩
- mobile_framework_react:0.1
- 사용할 도커 이미지

결과


ip가 192.168.43.129인 리눅스 서버에서 nginx가 포트포워딩한 21000 포트로 접근했을때 정상적으로 배포된것을 확인할 수 있습니다.
참고
https://sjparkk-dev1og.tistory.com/53#google_vignette
Nginx - Nginx와 Node.js 환경 서버 구성하기 (feat. Windows)
들어가며 Nginx 이해와 활용 방법에 이어 환경 구성하는 방법을 정리한다. 먼저 운영체제는 Windows 환경에서 진행하였고 우분투와 같이 다른 운영체제에서 사용하시는 분들은 설치 방법등만 차이
sjparkk-dev1og.tistory.com
Reddit의 node 커뮤니티
node 커뮤니티에서 이 게시물을 비롯한 다양한 콘텐츠를 살펴보세요
www.reddit.com
🚀 React + Vite 프로젝트를 Docker로 배포하는 방법
이 글에서는 React + Vite 프로젝트를 Docker 컨테이너로 패키징하고 실행하는 전체 과정을 다루고자 합니다. 또한, Dockerfile을 활용하여 Node.js로 빌드 후, Nginx를 이용한 정적 파일 서빙 방식을 설명하
velog.io
https://despiteallthat.tistory.com/256
[Vite] Vite란? ( 사용하면 리액트 10배 빨라짐 )
오늘은 Vite에 대해 알아보겠습니다. [ Vite란? ] Vite(비트)는 프랑스어로 '빠르다'라는 뜻을 가진 단어로, 차세대 프런트엔드 개발 도구입니다. 이름처럼 빌드와 개발 서버 구동 시간이 매우 빠릅니
despiteallthat.tistory.com
Reddit의 node 커뮤니티
node 커뮤니티에서 이 게시물을 비롯한 다양한 콘텐츠를 살펴보세요
www.reddit.com
React + Nginx 를 도커 이미지로 만들어서 배포하기
react-dockerizing 폴더 밑에 nginx 폴더를 만들고 nginx.conf 파일을 아래와 같이 생성해준다.80 포트에 / 경로로 들어오면 /usr/share/nginx/html 폴더에서 index.html 을 찾는다.react-dockerizing 밑에 D
velog.io
'develop > server' 카테고리의 다른 글
| [npm] 폐쇄망 환경에서 배포시 의존성 문제 해결하기 (0) | 2025.11.10 |
|---|---|
| [ERROR] GitLab pipeline pending (Job is stuck. Check runners.) (0) | 2025.11.09 |
| [GitLab] GitLab Runner 등록 (0) | 2025.11.06 |
| [Docker] 폐쇄망에서 프로젝트 구축하기 (0) | 2025.11.05 |
| [Docker] Docker란 (0) | 2025.10.31 |