React-Springboot Project Deploy Guide

danhyeon·2026년 1월 23일

Deploy

목록 보기
5/6

<<환경 및 전제 조건>>

backend : Spring Boot(3.5.x) + Spring Data JPA + JDK21

database: MySQL(8.x)

databaseName: cardb

frontend: React(VITE) + nginx(reverse proxy)

[소스코드 준비하기]

  1. backend
...생략

springBoot {
    mainClass = 'com.carbackend.CarbackendApplication'
}

bootJar {
    archiveFileName = 'app.jar'
}

...생략
  • gradle 빌드 시 애플리케이션 진입점(메인 클래스)을 못찾는 경우 예방
  • 빌드 산출물(JAR) 파일명 직접 지정
spring:
  application:
    name: carbackend
  datasource:
    url: jdbc:mysql://localhost:3306/cardb
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL8Dialect
  • MySQL 버전에 따라 DB 커넥션 시점에 하이버네이트 Dialect가 없는 경우 에러 발생
FROM openjdk:21-jdk-slim
COPY build/libs/app.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
EXPOSE 8080
  1. frontend
VITE_API_URL=/api
  • 서버 환경 IP가 유동적일 수 있으므로 FrontEnd 호스트에 따라 자연스럽게 백엔드 요청 호스트가 정해지도록 세팅
# Build stage
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Production stage
FROM nginx:stable-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
  • 프론트엔드의 경우 빌드 환경에 따라 결과에 영향을 크게 받으므로 빌드-배포 두 단계로 구성
  • Node이미지로 올린 컨테이너에서 빌드 → nginx이미지로 올린 컨테이너에 빌드된 파일 복사
worker_processes 1;

events {
  worker_connections 1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;

  sendfile        on;
  keepalive_timeout 65;

  server {
    listen 80;

    location / {
      root /usr/share/nginx/html;
      try_files $uri /index.html;
    }

    location /api/ {
      proxy_pass http://backend:8080/;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      rewrite ^/api/(.*)$ /$1 break;
    }
  }
}
  • listen 80; → Nginx가 포트 80(HTTP 기본 포트)에서 요청을 대기하도록 지정
  • location / { ... } → URL 경로가 / (루트)나 그 하위 경로일 때 웹서버가 정적 파일을 제공하도록 적용
  • root /usr/share/nginx/html; → /usr/share/nginx/html 디렉토리를 문서 루트(웹 루트)로 지정
  • 예를 들어, /index.html 요청이 들어오면 /usr/share/nginx/html/index.html 파일이 반환
  • try_files $uri /index.html; → 클라이언트가 요청한 URI에 해당하는 파일이 있으면 그 파일을 반환하고 없으면 /index.html을 대신 반환
  • location /api/ { … } → /api/로 시작하는 URI에만 매칭 (/api 일 경우 /apiSomething 같은 경로도 포함됨)
  • proxy_pass http://backend:8080/; → /api/ 경로에 해당하는 요청을 도커 네트워크 내 backend라는 호스트의 8080 포트로 전달(리버스 프록시)
  • proxy_set_header Host $host; → 원본 요청의 호스트 헤더 전달
  • proxy_set_header X-Real-IP $remote_addr; → 원본 요청의 클라이언트 실제 IP 전달
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; → 프록시된 요청이 여러 단계를 거칠 경우, IP 체인을 전달
  • proxy_set_header X-Forwarded-Proto $scheme; → 원본 요청이 HTTP인지 HTTPS인지 백엔드에 알려줌
  • rewrite ^/api/(.*)$ /$1 break; → /api/ 경로 뒤의 URI 부분을 잘라내어 백엔드로 전달하는 규칙

[리눅스 서버 구축]

  1. Docker 설치 - Locky Linux(+dnf) 기준
sudo dnf install -y dnf-utils device-mapper-persistent-data lvm2
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER
  • dnf-utils : dnf 패키지 관리에 필요한 다양한 유틸리티 패키지 모음
  • -y : 사용자 확인 없이 자동으로 설치 진행
  • device-mapper-persistent-data와 lvm2 : Docker 저장소 사용과 관련된 디스크 및 볼륨 관리 패키지로, Docker 설치와 운용에 필요
  • dnf config-manager를 사용해 Docker 공식 저장소를 repo에 추가(이 저장소를 통해 Docker CE(Community Edition) 패키지를 설치)
  • docker-ce : Docker 엔진(서버) 패키지 설치
  • docker-ce-cli : Docker 명령어 클라이언트 도구 설치
  • containerd.io : Docker 컨테이너 런타임(컨테이너 실행 환경) 패키지
  • systemctl enable : 시스템 부팅 시 자동으로 시작할 서비스 등록
  • 현재 사용자($USER)를 docker 그룹에 추가 (-a는 추가, -G는 그룹) → sudo 없이 도커 명령어를 실행
  1. Docker Compose 설치
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
  • curl 명령어로 Docker Compose의 최신 리눅스 x86_64 바이너리를 GitHub에서 다운로드
  • -L 옵션은 URL이 리다이렉션 될 경우 따라가도록 하는 옵션
  • 다운로드한 파일을 /usr/local/bin/docker-compose 위치에 저장합니다.
  • 다운로드한 Docker Compose 실행 파일에 실행 권한을 부여
  1. git 및 jdk 설치
sudo dnf install -y git
sudo dnf install -y java-21-openjdk-devel
readlink -f $(which java)
  1. docker-compose 디렉터리 및 파일 구성
~/
ㄴcompose
	ㄴdocker-compose.yml
version: "3.8"

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "80:80"
    depends_on:
      - backend

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
	    SPRING_PROFILES_ACTIVE=prod
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/cardb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: 1234
      SPRING_PROFILES_ACTIVE: prod
    depends_on:
      - db

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 1234
      MYSQL_DATABASE: cardb
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:
  1. backend 리포지토리 clone 및 빌드
~/compose# git clone <repo url> backend
cd backend
chmod +x ./gradlew
./gradlew clean build
  1. frontend 리포지토리 clone
~/compose# git clone <repo url> frontend
  1. 도커 컴포즈 올리기
docker-compose down
docker-compose up -d --build
docker ps [-a]
docker logs <containerID>
docker exec -it <containerId> <CMD>

[접속 및 테스트]

ip addr

해당 서버의 ip주소 확인 후 http://[hostIP]로 접속

profile
문제를 반복하지 않기

0개의 댓글