Spring Boot jar 배포하기 (systemd + Nginx)
Spring Boot로 만든 애플리케이션을 리눅스 서버에 올리는 방법은 여러 가지가 있지만, 가장 단순하고 안정적인 방법은 실행 가능한 jar 하나를 systemd 서비스로 돌리고 앞단에 Nginx를 두는 구성이다. 이 글은 빌드부터 서버 업로드, 서비스 등록, Nginx 연결, 재배포까지 Spring Boot 배포 과정을 한 번에 정리한다. Java 설치는 자바 JDK 설치 방법에 먼저 정리해 두었다.

전체 구성
사용자 -> Nginx(443, HTTPS) -> Spring Boot(127.0.0.1:8080)
Spring Boot 프로세스는 systemd 가 실행하고 재시작을 관리
애플리케이션은 외부에 직접 열지 않고 127.0.0.1에만 묶어 두고, HTTPS와 도메인 처리는 Nginx가 맡는다.
Spring Boot 배포 1단계 jar 빌드
# Gradle
./gradlew clean bootJar
ls build/libs/ # myapp-0.0.1-SNAPSHOT.jar
# Maven
./mvnw clean package -DskipTests
ls target/
Spring Boot 배포 2단계 서버에 올리기
# 서버 준비 (전용 계정과 디렉터리)
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo mkdir -p /opt/myapp
sudo chown myapp:myapp /opt/myapp
# 내 컴퓨터에서 업로드
scp build/libs/myapp-0.0.1-SNAPSHOT.jar web1:/tmp/app.jar
# 서버에서 위치 이동
sudo mv /tmp/app.jar /opt/myapp/app.jar
sudo chown myapp:myapp /opt/myapp/app.jar
파일 전송은 scp sftp 사용법에 정리했다.
Spring Boot 배포 3단계 systemd 서비스 등록
# /etc/myapp/app.env
SERVER_PORT=8080
SERVER_ADDRESS=127.0.0.1
SPRING_PROFILES_ACTIVE=prod
SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/mydb
SPRING_DATASOURCE_USERNAME=myapp
SPRING_DATASOURCE_PASSWORD=change_me
# /etc/systemd/system/myapp.service
[Unit]
Description=My Spring Boot App
After=network-online.target mysql.service
Wants=network-online.target
[Service]
User=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/app.env
ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar /opt/myapp/app.jar
SuccessExitStatus=143
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo chmod 600 /etc/myapp/app.env
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
journalctl -u myapp -f
Spring Boot는 SERVER_PORT 같은 환경 변수를 server.port 설정으로 자동 인식한다. DB 비밀번호가 든 env 파일은 권한을 600으로 좁힌다. unit 파일 항목 설명은 systemd 서비스 만들기에 있다. DB 연결 설정은 Java에서 MySQL 연결하기를 참고하자.
Spring Boot 배포 4단계 Nginx 연결
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1: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;
}
}
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d app.example.com
server 블록 구성은 Nginx server 블록, HTTPS 설정은 Nginx 리버스 프록시와 SSL에 있다. 프록시 뒤에서 원래 접속 주소를 올바르게 인식하려면 application.properties에 server.forward-headers-strategy=native를 넣는다.
재배포 순서
# 새 jar 업로드 후
sudo cp /opt/myapp/app.jar /opt/myapp/app.jar.bak # 롤백용
sudo mv /tmp/app.jar /opt/myapp/app.jar
sudo chown myapp:myapp /opt/myapp/app.jar
sudo systemctl restart myapp
journalctl -u myapp -n 50
restart 하는 동안 몇 초간 502 오류가 날 수 있다. application.properties에 server.shutdown=graceful을 넣으면 처리 중이던 요청을 마무리한 뒤 종료한다. 버전별 jar를 releases 폴더에 두고 심볼릭 링크로 바꾸는 방식도 있다(심볼릭 링크 활용). 공식 안내는 Spring Boot 설치 배포 문서에 있다.
Spring Boot 배포 정리
jar 빌드, 전용 계정으로 업로드, systemd로 실행과 재시작 관리, Nginx로 HTTPS와 도메인 처리. 이 네 단계면 컨테이너 없이도 안정적으로 Spring Boot를 운영할 수 있다. 컨테이너로 운영하고 싶다면 Dockerfile 작성법의 멀티 스테이지 예제를 참고하자. 전날 글은 리눅스 alias 설정이다.
첫 댓글을 남겨보세요