Search

Spring Boot ๋ฐฐํฌํ•˜๊ธฐ

Spring Boot ์•ฑ Nginx๋กœ ๋ฐฐํฌํ•˜๊ธฐ

๊ฐœ์š”

Spring Boot ์•ฑ์€ ๋‚ด์žฅ ํ†ฐ์บฃ์—์„œ ์‹คํ–‰๋˜๋ฉฐ, Nginx๋Š” ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋กœ์„œ ์•ž๋‹จ์—์„œ ์š”์ฒญ์„ ๋ฐ›์•„ Spring Boot์— ์ „๋‹ฌํ•œ๋‹ค.
React๋Š” ์ •์  ํŒŒ์ผ์„ ์ง์ ‘ ์„œ๋น™ํ•˜๋ฉด ๋์ง€๋งŒ, Spring Boot๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค! Spring Boot๋Š” ์ž๊ธฐ ์ž์‹ ์ด ์›น ์„œ๋ฒ„(๋‚ด์žฅ ํ†ฐ์บฃ)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ ์Šค์Šค๋กœ HTTP ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.
๊ทธ๋Ÿฐ๋ฐ ์™œ Nginx๋ฅผ ์•ž์— ๋‘๋ƒ๊ณ ์š”? Nginx๊ฐ€ ์•ž์—์„œ SSL ์ฒ˜๋ฆฌ, ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ, ์ •์  ํŒŒ์ผ ์บ์‹ฑ, ๋ณด์•ˆ์„ ๋‹ด๋‹นํ•ด์ฃผ๋ฉด, Spring Boot๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”. ๋งˆ์น˜ ์‹๋‹น์—์„œ ํ™€ ์ง์›(Nginx)์ด ์†๋‹˜ ์‘๋Œ€๋ฅผ ํ•˜๊ณ , ์ฃผ๋ฐฉ์žฅ(Spring Boot)์€ ์š”๋ฆฌ์—๋งŒ ์ง‘์ค‘ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์•„์š”!

๋ฐฐํฌ ์•„ํ‚คํ…์ฒ˜

graph LR
    A[๐Ÿ‘ค ์‚ฌ์šฉ์ž<br/>๋ธŒ๋ผ์šฐ์ €] -->|"<https://api.example.com><br/>ํฌํŠธ 443"| B[๐Ÿ–ฅ๏ธ Nginx<br/>๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ]
    B -->|"<http://localhost:8080><br/>๋‚ด๋ถ€ ํ†ต์‹ "| C[๐Ÿƒ Spring Boot<br/>๋‚ด์žฅ ํ†ฐ์บฃ]
    C --> D[๐Ÿ—„๏ธ Database<br/>MySQL/PostgreSQL]

    style B fill:#90EE90
    style C fill:#87CEEB
Mermaid
๋ณต์‚ฌ
flowchart TD
    A["๐Ÿ’ป ๋กœ์ปฌ ๊ฐœ๋ฐœ"] -->|"./gradlew build<br/>๋˜๋Š” mvn package"| B["๐Ÿ“ฆ JAR ํŒŒ์ผ ์ƒ์„ฑ<br/>app.jar"]
    B -->|"scp ๋˜๋Š” CI/CD"| C["๐Ÿ–ฅ๏ธ ์„œ๋ฒ„์— ์—…๋กœ๋“œ"]
    C --> D["๐Ÿƒ java -jar app.jar<br/>Spring Boot ์‹คํ–‰"]
    D --> E["โš™๏ธ Nginx ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ<br/>์„ค์ • + SSL"]
    E --> F["๐ŸŒ ์„œ๋น„์Šค ์˜คํ”ˆ!"]

    style B fill:#FFD700
    style E fill:#90EE90
Mermaid
๋ณต์‚ฌ

Step 1: Spring Boot ์•ฑ ๋นŒ๋“œ

# Gradle ํ”„๋กœ์ ํŠธ ./gradlew clean build -x test # ๊ฒฐ๊ณผ: build/libs/myapp-0.0.1-SNAPSHOT.jar # Maven ํ”„๋กœ์ ํŠธ mvn clean package -DskipTests # ๊ฒฐ๊ณผ: target/myapp-0.0.1-SNAPSHOT.jar
Bash
๋ณต์‚ฌ

Step 2: ์„œ๋ฒ„์— ์—…๋กœ๋“œ ๋ฐ ์‹คํ–‰

# JAR ํŒŒ์ผ ์—…๋กœ๋“œ scp build/libs/myapp-0.0.1-SNAPSHOT.jar ubuntu@์„œ๋ฒ„IP:/home/ubuntu/app/ # ์„œ๋ฒ„์—์„œ ์‹คํ–‰ cd /home/ubuntu/app java -jar myapp-0.0.1-SNAPSHOT.jar
Bash
๋ณต์‚ฌ

Systemd ์„œ๋น„์Šค๋กœ ๋“ฑ๋ก (๊ถŒ์žฅ!)

ํ„ฐ๋ฏธ๋„์—์„œ ์ง์ ‘ java -jar๋กœ ์‹คํ–‰ํ•˜๋ฉด, SSH ์—ฐ๊ฒฐ์ด ๋Š์–ด์ง€๋ฉด ์•ฑ๋„ ๊ฐ™์ด ์ฃฝ์–ด์š”. ๊ทธ๋ž˜์„œ systemd ์„œ๋น„์Šค๋กœ ๋“ฑ๋กํ•ด์•ผ ํ•ด์š”!
sudo nano /etc/systemd/system/myapp.service
Bash
๋ณต์‚ฌ
[Unit] Description=My Spring Boot Application After=network.target [Service] User=ubuntu ExecStart=/usr/bin/java -jar /home/ubuntu/app/myapp-0.0.1-SNAPSHOT.jar SuccessExitStatus=143 Restart=always RestartSec=5 StandardOutput=journal StandardError=journal Environment=SPRING_PROFILES_ACTIVE=prod Environment=SERVER_PORT=8080 [Install] WantedBy=multi-user.target
Plain Text
๋ณต์‚ฌ
# ์„œ๋น„์Šค ๋“ฑ๋ก ๋ฐ ์‹œ์ž‘ sudo systemctl daemon-reload sudo systemctl start myapp sudo systemctl enable myapp # ์ƒํƒœ ํ™•์ธ sudo systemctl status myapp # ๋กœ๊ทธ ํ™•์ธ sudo journalctl -u myapp -f
Bash
๋ณต์‚ฌ
ํ•ญ๋ชฉ
์„ค๋ช…
After=network.target
๋„คํŠธ์›Œํฌ๊ฐ€ ์ค€๋น„๋œ ํ›„ ์‹œ์ž‘
Restart=always
์•ฑ์ด ์ฃฝ์œผ๋ฉด ์ž๋™ ์žฌ์‹œ์ž‘
RestartSec=5
์žฌ์‹œ์ž‘ ์ „ 5์ดˆ ๋Œ€๊ธฐ
Environment
ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ • (ํ”„๋กœํŒŒ์ผ, ํฌํŠธ ๋“ฑ)

Step 3: Nginx ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์„ค์ •

sudo nano /etc/nginx/sites-available/spring-app
Bash
๋ณต์‚ฌ
server { listen 80; server_name api.example.com; # โญ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ โ€” Spring Boot๋กœ ์ „๋‹ฌ location / { proxy_pass <http://localhost: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; # ํƒ€์ž„์•„์›ƒ ์„ค์ • proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # WebSocket ์ง€์› (ํ•„์š”์‹œ) proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # ํฐ ํŒŒ์ผ ์—…๋กœ๋“œ ํ—ˆ์šฉ client_max_body_size 10M; }
Plain Text
๋ณต์‚ฌ

ํ”„๋ก์‹œ ํ—ค๋”๊ฐ€ ์™œ ํ•„์š”ํ•ด?

sequenceDiagram
    participant ์‚ฌ์šฉ์ž as ๐Ÿ‘ค ์‚ฌ์šฉ์ž<br/>IP: 203.0.113.50
    participant Nginx as ๐Ÿ–ฅ๏ธ Nginx<br/>IP: 10.0.0.1
    participant Spring as ๐Ÿƒ Spring Boot<br/>IP: 127.0.0.1

    ์‚ฌ์šฉ์ž->>Nginx: ์š”์ฒญ (IP: 203.0.113.50)

    Note over Nginx: ํ—ค๋” ์—†์ด ์ „๋‹ฌํ•˜๋ฉด<br/>Spring์€ Nginx IP๋งŒ ๋ณด์ž„

    Nginx->>Spring: ์š”์ฒญ ์ „๋‹ฌ
    Note over Nginx,Spring: X-Real-IP: 203.0.113.50<br/>X-Forwarded-For: 203.0.113.50<br/>X-Forwarded-Proto: https

    Note over Spring: ์ด์ œ ์ง„์งœ ์‚ฌ์šฉ์ž IP๋ฅผ<br/>์•Œ ์ˆ˜ ์žˆ์–ด์š”!
Mermaid
๋ณต์‚ฌ
ํ—ค๋”
์—ญํ• 
Host
์›๋ž˜ ์š”์ฒญ๋œ ๋„๋ฉ”์ธ ์ด๋ฆ„
X-Real-IP
์‹ค์ œ ํด๋ผ์ด์–ธํŠธ IP
X-Forwarded-For
ํ”„๋ก์‹œ ์ฒด์ธ์„ ๊ฑฐ์นœ IP ๋ชฉ๋ก
X-Forwarded-Proto
์›๋ž˜ ํ”„๋กœํ† ์ฝœ (http/https)
์ด ํ—ค๋”๊ฐ€ ์—†์œผ๋ฉด Spring Boot๋Š” ๋ชจ๋“  ์š”์ฒญ์ด 127.0.0.1(Nginx)์—์„œ ์˜จ ๊ฒƒ์œผ๋กœ ์ธ์‹ํ•ด์š”. ์‚ฌ์šฉ์ž์˜ ์ง„์งœ IP๋ฅผ ์•Œ ์ˆ˜ ์—†๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ !

Step 4: ํ™œ์„ฑํ™” ๋ฐ SSL ์ ์šฉ

# ์‚ฌ์ดํŠธ ํ™œ์„ฑํ™” sudo ln -s /etc/nginx/sites-available/spring-app /etc/nginx/sites-enabled/ # ํ…Œ์ŠคํŠธ ๋ฐ ์ ์šฉ sudo nginx -t && sudo systemctl reload nginx # SSL ์ ์šฉ sudo certbot --nginx -d api.example.com
Bash
๋ณต์‚ฌ

์ตœ์ข… ์„ค์ • (HTTPS ํฌํ•จ)

# ์—…์ŠคํŠธ๋ฆผ ์ •์˜ (๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ๋Œ€๋น„) upstream spring_backend { server localhost:8080; } server { listen 443 ssl http2; server_name api.example.com; ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem; # ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ location / { proxy_pass http://spring_backend; 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; } # Health Check ์—”๋“œํฌ์ธํŠธ (๋กœ๊น… ์ œ์™ธ) location = /actuator/health { proxy_pass http://spring_backend; access_log off; } client_max_body_size 10M; } server { listen 80; server_name api.example.com; return 301 https://$host$request_uri; }
Plain Text
๋ณต์‚ฌ

Spring Boot application.yml ์„ค์ •

server: port: 8080 forward-headers-strategy: framework # โญ ํ”„๋ก์‹œ ํ—ค๋” ์ธ์‹ (ํ•„์ˆ˜!) # Actuator (Health Check) management: endpoints: web: exposure: include: health
YAML
๋ณต์‚ฌ
forward-headers-strategy: framework ์„ค์ •์„ ๊ผญ ํ•ด์ฃผ์„ธ์š”! ์ด๊ฑธ ์•ˆ ํ•˜๋ฉด Spring Boot๊ฐ€ Nginx๊ฐ€ ๋ณด๋‚ด์ฃผ๋Š” X-Forwarded-* ํ—ค๋”๋ฅผ ๋ฌด์‹œํ•ด์š”.

์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ

๋ฌธ์ œ
์›์ธ
ํ•ด๊ฒฐ
502 Bad Gateway
Spring Boot๊ฐ€ ์•ˆ ๋Œ์•„๊ฐ€๊ณ  ์žˆ์Œ
systemctl status myapp์œผ๋กœ ํ™•์ธ
504 Gateway Timeout
์‘๋‹ต ์‹œ๊ฐ„ ์ดˆ๊ณผ
proxy_read_timeout ๋Š˜๋ฆฌ๊ธฐ
CORS ์—๋Ÿฌ
ํ”„๋ก ํŠธ-๋ฐฑ ๋„๋ฉ”์ธ ๋‹ค๋ฆ„
Spring Boot์— CORS ์„ค์ • or Nginx์—์„œ ์ฒ˜๋ฆฌ
๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ๋ฌดํ•œ ๋ฃจํ”„
X-Forwarded-Proto ๋ฏธ์„ค์ •
ํ”„๋ก์‹œ ํ—ค๋” ์„ค์ • ํ™•์ธ
ํŒŒ์ผ ์—…๋กœ๋“œ ์‹คํŒจ
ํฌ๊ธฐ ์ œํ•œ
client_max_body_size ๋Š˜๋ฆฌ๊ธฐ

์‹ค์Šต

์‹ค์Šต ํ™˜๊ฒฝ

ํ•ญ๋ชฉ
๊ฐ’
๋กœ์ปฌ ํ”„๋กœ์ ํŠธ
Spring Boot + Gradle
๋นŒ๋“œ ๊ฒฐ๊ณผ๋ฌผ
build/libs/APP.war
์„œ๋ฒ„
alohaserver4.cafe24.com
WAR ๋ฐฐํฌ ๊ฒฝ๋กœ
/var/www/krules/backend/
์ œ์–ด ์Šคํฌ๋ฆฝํŠธ
start.sh / stop.sh / restart.sh
SSH ์ ‘์†
Host alias alohaserver4 ์‚ฌ์šฉ
Spring Boot๋Š” ํŒŒ์ผ ๋ณต์‚ฌ๋งŒ์œผ๋กœ ๋๋‚˜์ง€ ์•Š์•„์š”. APP.war ์—…๋กœ๋“œ โ†’ restart.sh ์›๊ฒฉ ์‹คํ–‰ ์ˆœ์„œ๋กœ ๋ฐฐํฌํ•ด์•ผ ํ•ด์š”!

๋ฐฐํฌ ํŒŒ์ผ ๊ตฌ์กฐ

๐Ÿ“ย ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ/ โ”œโ”€โ”€ ๐Ÿ“„ย deploy.bat โ† ๋นŒ๋“œ + ์—…๋กœ๋“œ + ์žฌ์‹œ์ž‘ ์ž๋™ํ™” โ”œโ”€โ”€ ๐Ÿ“„ย start.bat โ† ์„œ๋ฒ„ ์•ฑ ์›๊ฒฉ ์‹œ์ž‘ โ”œโ”€โ”€ ๐Ÿ“„ย stop.bat โ† ์„œ๋ฒ„ ์•ฑ ์›๊ฒฉ ์ข…๋ฃŒ โ””โ”€โ”€ ๐Ÿ“„ย restart.bat โ† ์„œ๋ฒ„ ์•ฑ ์›๊ฒฉ ์žฌ์‹œ์ž‘ ๐Ÿ“ย ์„œ๋ฒ„ /var/www/krules/backend/ โ”œโ”€โ”€ ๐Ÿ’ปย APP.war โ† ๋ฐฐํฌ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ โ”œโ”€โ”€ ๐Ÿ“œย start.sh โ† APP.war ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์‹คํ–‰ (๋กœ๊ทธ ์ €์žฅ) โ”œโ”€โ”€ ๐Ÿ“œย stop.sh โ† APP.war ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ โ”œโ”€โ”€ ๐Ÿ“œย restart.sh โ† stop.sh โ†’ start.sh ์ˆœ์„œ๋กœ ์žฌ์‹œ์ž‘ ๐Ÿ“ย ์„œ๋ฒ„ /var/www/krules/log/ โ””โ”€โ”€ ๐Ÿ“ฐย appwar_20260422_120000.log โ† ์‹คํ–‰ ๋กœ๊ทธ (start.sh ์ž๋™ ์ƒ์„ฑ)
Plain Text
๋ณต์‚ฌ

์‚ฌ์ „ ์ค€๋น„: ์„œ๋ฒ„ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ (์ตœ์ดˆ 1ํšŒ)

# ์„œ๋ฒ„ ์ ‘์† ssh alohaserver4 # ๋ฐฐํฌ ๊ฒฝ๋กœ ์ƒ์„ฑ mkdir -p /var/www/krules/backend mkdir -p /var/www/krules/log
Bash
๋ณต์‚ฌ

start.sh

#!/bin/bash # ํ˜„์žฌ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์œ„์น˜ํ•œ ๊ฒฝ๋กœ๋กœ ์ด๋™ cd "$(dirname "$0")" # ๋กœ๊ทธ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ LOG_DIR="../log" mkdir -p "$LOG_DIR" LOG_FILE="$LOG_DIR/appwar_$(date +%Y%m%d_%H%M%S).log" # JAVA_HOME์ด ์„ค์ •๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด java ๋ช…๋ น์–ด ์‚ฌ์šฉ JAVA_CMD=${JAVA_HOME:-}/bin/java if [ ! -x "$JAVA_CMD" ]; then JAVA_CMD=java fi # JVM ๋ฉ”๋ชจ๋ฆฌ ์ œํ•œ (์ตœ์†Œ 128MB, ์ตœ๋Œ€ 256MB) JAVA_OPTS="-Xms128m -Xmx256m" # Spring ํ”„๋กœํŒŒ์ผ ๋ช…์‹œ (server = ์‹ค์„œ๋ฒ„ ์„ค์ •, local = ๋กœ์ปฌ ๊ฐœ๋ฐœ) SPRING_OPTS="--spring.profiles.active=server" # APP.war ํŒŒ์ผ์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•˜๊ณ  ๋กœ๊ทธ ์ €์žฅ $JAVA_CMD $JAVA_OPTS -jar APP.war $SPRING_OPTS > "$LOG_FILE" 2>&1 &
JavaScript
๋ณต์‚ฌ

stop.sh

#!/bin/bash # APP.war ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ ์Šคํฌ๋ฆฝํŠธ # ํ˜„์žฌ ๊ฒฝ๋กœ์˜ APP.war ํ”„๋กœ์„ธ์Šค๋งŒ ์ข…๋ฃŒ cd "$(dirname "$0")" APP_PATH="$(pwd)/APP.war" PIDS=$(ps -ef | grep '[j]ava.*-jar' | grep "$APP_PATH" | awk '{print $2}') if [ -z "$PIDS" ]; then echo "์‹คํ–‰ ์ค‘์ธ APP.war ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค." exit 0 fi for PID in $PIDS; do echo "APP.war ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ: $PID" kill $PID sleep 1 if ps -p $PID > /dev/null; then echo "๊ฐ•์ œ ์ข…๋ฃŒ: $PID" kill -9 $PID fi echo "์ข…๋ฃŒ ์™„๋ฃŒ: $PID" sleep 1 done echo "๋ชจ๋“  APP.war ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
JavaScript
๋ณต์‚ฌ

restart.sh (ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— ์ €์žฅ)

start.sh์™€ stop.sh๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ํ˜ธ์ถœํ•˜๋Š” ์žฌ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ์˜ˆ์š”.
#!/bin/bash # APP.war ์žฌ์‹œ์ž‘ ์Šคํฌ๋ฆฝํŠธ (stop.sh โ†’ start.sh ์ˆœ์„œ๋กœ ์‹คํ–‰) cd "$(dirname "$0")" echo "=== APP.war ์žฌ์‹œ์ž‘ ์‹œ์ž‘ ===" # ๊ธฐ์กด ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ bash stop.sh # ํ”„๋กœ์„ธ์Šค ์™„์ „ ์ข…๋ฃŒ ๋Œ€๊ธฐ sleep 2 # ์ƒˆ ํ”„๋กœ์„ธ์Šค ์‹œ์ž‘ bash start.sh echo "=== APP.war ์žฌ์‹œ์ž‘ ์™„๋ฃŒ ==="
Bash
๋ณต์‚ฌ

1๋‹จ๊ณ„: ์ˆ˜๋™ ๋ฐฐํฌ

flowchart TB
    A["๐Ÿ’ป ๋กœ์ปฌ<br>gradlew clean bootWar"] -->|"APP.war ์ƒ์„ฑ"| B["๐Ÿ“ฆ APP.war"]
    B -->|"scp ์—…๋กœ๋“œ<br>WAR + sh ํŒŒ์ผ"| C["๐Ÿ–ฅ๏ธ ์„œ๋ฒ„<br>/var/www/krules/backend/"]
    C -->|"plink restart.sh"| D["๐Ÿƒ Spring Boot ์žฌ์‹œ์ž‘"]
    D --> E["๐ŸŒ ๋ธŒ๋ผ์šฐ์ € ํ™•์ธ"]
Mermaid
๋ณต์‚ฌ
# 1. ๋กœ์ปฌ์—์„œ WAR ๋นŒ๋“œ ./gradlew clean bootWar # ๋นŒ๋“œ ๊ฒฐ๊ณผ ํ™•์ธ ls build/libs/ # APP.war ํŒŒ์ผ ์ƒ์„ฑ๋จ # 2. ์„œ๋ฒ„์— APP.war + sh ํŒŒ์ผ ์—…๋กœ๋“œ scp build/libs/APP.war alohaserver4:/var/www/krules/backend/APP.war scp start.sh stop.sh restart.sh alohaserver4:/var/www/krules/backend/ # 3. sh ํŒŒ์ผ ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ (์ตœ์ดˆ 1ํšŒ) ssh alohaserver4 "chmod +x /var/www/krules/backend/*.sh" # 4. restart.sh ์›๊ฒฉ ์‹คํ–‰ ssh alohaserver4 "cd /var/www/krules/backend && bash restart.sh" # 5. ๋กœ๊ทธ ํ™•์ธ ssh alohaserver4 "tail -f /var/www/krules/log/appwar_*.log"
Bash
๋ณต์‚ฌ

2๋‹จ๊ณ„: ํ”„๋ก ํŠธ์—”๋“œ .env ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •

๋ฐฑ์—”๋“œ API ์ฃผ์†Œ๋ฅผ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋ถ„๋ฆฌํ•ด์„œ ๊ด€๋ฆฌํ•ด์š”. Vite ํ”„๋กœ์ ํŠธ๋Š” VITE_ ์ ‘๋‘์‚ฌ, CRA๋Š” REACT_APP_ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์—ฌ์•ผ ์ธ์‹ํ•ด์š”.
# .env.local (๋กœ์ปฌ ๊ฐœ๋ฐœ์šฉ โ€” .gitignore์— ์ถ”๊ฐ€ ๊ถŒ์žฅ) VITE_API_URL=http://localhost:8080/api # VITE_API_URL=http://192.168.30.19:8080/api # ๊ฐ™์€ ๋„คํŠธ์›Œํฌ ๋‹ค๋ฅธ PC ํ…Œ์ŠคํŠธ # .env.production (๋ฐฐํฌ์šฉ) # ๋ฐฉ์‹ A (์„œ๋ธŒ๋„๋ฉ”์ธ): api.๊ตญ๋ฃฐ.com โ†’ Spring Boot # VITE_API_URL=http://xn--3e0b91t.com/api # HTTP ์ ์šฉ ์ „ # VITE_API_URL=https://api.xn--3e0b91t.com/api # HTTPS ์ ์šฉ ํ›„ # ๋ฐฉ์‹ B (๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ): ๊ตญ๋ฃฐ.com/api โ†’ Spring Boot # VITE_API_URL=http://xn--3e0b91t.com/api # HTTP ์ ์šฉ ์ „ # VITE_API_URL=https://xn--3e0b91t.com/api # HTTPS ์ ์šฉ ํ›„
Bash
๋ณต์‚ฌ
React ์ฝ”๋“œ์—์„œ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•ด์š”:
// ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ API ์ฃผ์†Œ๋ฅผ ์ฝ์–ด์˜ด const res = await fetch(`${import.meta.env.VITE_API_URL}/products`);
JavaScript
๋ณต์‚ฌ

3๋‹จ๊ณ„: Nginx ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์„ค์ • โ€” ๋ฐฉ์‹ ์„ ํƒ

๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์ด ์žˆ์–ด์š”. ์ƒํ™ฉ์— ๋งž๊ฒŒ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์„ธ์š”!
graph TD
    A["๐ŸŒ ์‚ฌ์šฉ์ž ์š”์ฒญ"] --> B{๋ฐฉ์‹ ์„ ํƒ}
    B -->|"๋ฐฉ์‹ A<br>์„œ๋ธŒ๋„๋ฉ”์ธ"| C["api.๊ตญ๋ฃฐ.com<br>โ†’ Spring Boot :8080"]
    B -->|"๋ฐฉ์‹ B<br>๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ"| D["๊ตญ๋ฃฐ.com/api/**<br>โ†’ Spring Boot :8080"]
    C --> E["๐Ÿƒ Spring Boot"]
    D --> E
Mermaid
๋ณต์‚ฌ
๋น„๊ต
๋ฐฉ์‹ A โ€” ์„œ๋ธŒ๋„๋ฉ”์ธ
๋ฐฉ์‹ B โ€” ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ
API URL
api.๊ตญ๋ฃฐ.com/api/...
๊ตญ๋ฃฐ.com/api/...
DNS ์„ค์ •
api ์„œ๋ธŒ๋„๋ฉ”์ธ A๋ ˆ์ฝ”๋“œ ์ถ”๊ฐ€ ํ•„์š”
์ถ”๊ฐ€ DNS ๋ถˆํ•„์š”
SSL ์ธ์ฆ์„œ
api ์„œ๋ธŒ๋„๋ฉ”์ธ ์ธ์ฆ์„œ ๋ณ„๋„ ๋ฐœ๊ธ‰
๊ธฐ์กด ๋„๋ฉ”์ธ ์ธ์ฆ์„œ ๊ณต์œ 
Nginx ํŒŒ์ผ ์ˆ˜
2๊ฐœ (ํ”„๋ก ํŠธ + ๋ฐฑ์—”๋“œ ๊ฐ๊ฐ)
1๊ฐœ (ํ•˜๋‚˜์˜ server ๋ธ”๋ก์— ํ†ตํ•ฉ)
์ถ”์ฒœ ์ƒํ™ฉ
API ์„œ๋ฒ„๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ๋•Œ
๋„๋ฉ”์ธ ํ•˜๋‚˜๋กœ ํ’€์Šคํƒ์„ ๋‹จ์ˆœํ•˜๊ฒŒ ๊ตฌ์„ฑํ•  ๋•Œ

๋ฐฉ์‹ A โ€” ์„œ๋ธŒ๋„๋ฉ”์ธ (api.๊ตญ๋ฃฐ.com)

ssh alohaserver4 nano /etc/nginx/conf.d/krules-backend.conf
Bash
๋ณต์‚ฌ
# ๋ฐฑ์—”๋“œ ์ „์šฉ ์„œ๋ฒ„ ๋ธ”๋ก (api ์„œ๋ธŒ๋„๋ฉ”์ธ) server { listen 80; server_name api.xn--3e0b91t.com; location / { proxy_pass <http://localhost: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; proxy_connect_timeout 60s; proxy_read_timeout 60s; } client_max_body_size 10M; }
Plain Text
๋ณต์‚ฌ
ํ”„๋ก ํŠธ์—”๋“œ .env.production:
VITE_API_URL=https://api.xn--3e0b91t.com/api
Bash
๋ณต์‚ฌ

๋ฐฉ์‹ B โ€” ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ (๊ตญ๋ฃฐ.com/api)

ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๋ฅผ ํ•˜๋‚˜์˜ Nginx ์„œ๋ฒ„ ๋ธ”๋ก์—์„œ ์ฒ˜๋ฆฌํ•ด์š”. ๋„๋ฉ”์ธ ํ•˜๋‚˜๋กœ ํ’€์Šคํƒ ๊ตฌ์„ฑํ•  ๋•Œ ํŽธํ•ด์š”!
ssh alohaserver4 nano /etc/nginx/conf.d/krules.conf
Bash
๋ณต์‚ฌ
server { listen 80; server_name xn--3e0b91t.com www.xn--3e0b91t.com; # โ”€โ”€ ํ”„๋ก ํŠธ์—”๋“œ (React Vite ์ •์  ํŒŒ์ผ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ root /var/www/krules/frontend; index index.html; location / { try_files $uri $uri/ /index.html; } location /assets/ { expires 1y; add_header Cache-Control "public, immutable"; } # โ”€โ”€ ๋ฐฑ์—”๋“œ (Spring Boot ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ # /api/ ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์š”์ฒญ์€ Spring Boot๋กœ ์ „๋‹ฌ location /api/ { proxy_pass <http://localhost:8080>; # โ† /api/ ๊ฒฝ๋กœ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ 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; proxy_connect_timeout 60s; proxy_read_timeout 60s; client_max_body_size 10M; } gzip on; gzip_types text/plain text/css application/json application/javascript text/xml; }
Plain Text
๋ณต์‚ฌ
proxy_pass <http://localhost:8080>; โ€” ๋์— / ๋ฅผ ๋ถ™์ด์ง€ ์•Š์œผ๋ฉด /api/ ๊ฒฝ๋กœ๊ฐ€ ๊ทธ๋Œ€๋กœ Spring Boot์— ์ „๋‹ฌ๋ผ์š”. Spring Boot์˜ RequestMapping๋„ /api/... ๋กœ ๋งž์ถฐ์•ผ ํ•ด์š”!
ํ”„๋ก ํŠธ์—”๋“œ .env.production:
VITE_API_URL=https://xn--3e0b91t.com/api
Bash
๋ณต์‚ฌ
nginx -t && systemctl reload nginx
Bash
๋ณต์‚ฌ

3๋‹จ๊ณ„: ๊ฐœ๋ณ„ ์ œ์–ด bat ํŒŒ์ผ (์„œ๋ฒ„ ๊ด€๋ฆฌ์šฉ)

PuTTY์˜ plink.exe(์›๊ฒฉ ๋ช…๋ น), pscp.exe(ํŒŒ์ผ ๋ณต์‚ฌ)๋ฅผ ์‚ฌ์šฉํ•ด์š”. ์„ค์น˜: https://www.putty.org/ โ†’ ๋‹ค์šด๋กœ๋“œ ํ›„ PATH์— ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ bat ํŒŒ์ผ๊ณผ ๊ฐ™์€ ํด๋”์— ๋‘์„ธ์š”.

start.bat

@echo off chcp 65001 > nul set REMOTE_USER=root set REMOTE_HOST=alohaserver4.cafe24.com set REMOTE_PATH=/var/www/krules/backend :: ๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ (์•ˆ ๋ณด์ด๊ฒŒ) for /f "delims=" %%p in ('powershell -Command "$p = Read-Host ''SSH Password'' -AsSecureString; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($p); [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"') do set REMOTE_PASS=%%p echo [START] Spring Boot ์•ฑ ์‹œ์ž‘ ์ค‘... plink -pw %REMOTE_PASS% %REMOTE_USER%@%REMOTE_HOST% "cd %REMOTE_PATH% && bash start.sh" echo ์™„๋ฃŒ! pause
Shell
๋ณต์‚ฌ

stop.bat

@echo off chcp 65001 > nul set REMOTE_USER=root set REMOTE_HOST=alohaserver4.cafe24.com set REMOTE_PATH=/var/www/krules/backend :: ๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ (์•ˆ ๋ณด์ด๊ฒŒ) for /f "delims=" %%p in ('powershell -Command "$p = Read-Host ''SSH Password'' -AsSecureString; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($p); [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"') do set REMOTE_PASS=%%p echo [STOP] Spring Boot ์•ฑ ์ข…๋ฃŒ ์ค‘... plink -pw %REMOTE_PASS% %REMOTE_USER%@%REMOTE_HOST% "cd %REMOTE_PATH% && bash stop.sh" echo ์™„๋ฃŒ! pause
Shell
๋ณต์‚ฌ

restart.bat

@echo off chcp 65001 > nul set REMOTE_USER=root set REMOTE_HOST=alohaserver4.cafe24.com set REMOTE_PATH=/var/www/krules/backend :: ๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ (์•ˆ ๋ณด์ด๊ฒŒ) for /f "delims=" %%p in ('powershell -Command "$p = Read-Host ''SSH Password'' -AsSecureString; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($p); [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"') do set REMOTE_PASS=%%p echo [RESTART] Spring Boot ์•ฑ ์žฌ์‹œ์ž‘ ์ค‘... plink -pw %REMOTE_PASS% %REMOTE_USER%@%REMOTE_HOST% "cd %REMOTE_PATH% && bash restart.sh" echo ์™„๋ฃŒ! pause
Shell
๋ณต์‚ฌ

4๋‹จ๊ณ„: ํ†ตํ•ฉ ๋ฐฐํฌ ์ž๋™ํ™” (deploy.bat)

clean bootWar โ†’ APP.war + sh ํŒŒ์ผ ์—…๋กœ๋“œ โ†’ restart.sh ์›๊ฒฉ ์‹คํ–‰๊นŒ์ง€ ํ•œ ๋ฒˆ์—!

deploy.bat

@echo off chcp 65001 > nul echo. echo ============================================= echo Spring Boot bootWar Build ^& Deploy echo ============================================= echo. :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ :: ์„ค์ •๊ฐ’ :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ set PROJECT_DIR=%~dp0 set REMOTE_USER=root set REMOTE_HOST=alohaserver4.cafe24.com set REMOTE_PATH=/var/www/krules/backend :: ๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ (์•ˆ ๋ณด์ด๊ฒŒ) for /f "delims=" %%p in ('powershell -Command "$p = Read-Host ''SSH Password'' -AsSecureString; $BSTR=[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($p); [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)"') do set REMOTE_PASS=%%p echo. :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ :: [1] bootWar ๋นŒ๋“œ :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ echo [1/3] bootWar ๋นŒ๋“œ ์ค‘... cd /d %PROJECT_DIR% call gradlew.bat clean bootWar if errorlevel 1 ( echo. echo [์˜ค๋ฅ˜] ๋นŒ๋“œ ์‹คํŒจ! ์—๋Ÿฌ๋ฅผ ํ™•์ธํ•˜์„ธ์š”. pause exit /b 1 ) echo ๋นŒ๋“œ ์™„๋ฃŒ - APP.war ์ƒ์„ฑ๋จ echo. :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ :: [2] ํŒŒ์ผ ์—…๋กœ๋“œ :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ echo [2/3] ํŒŒ์ผ ์—…๋กœ๋“œ ์ค‘... pscp -pw %REMOTE_PASS% build\libs\APP.war %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_PATH%/APP.war if errorlevel 1 ( echo. echo [์˜ค๋ฅ˜] WAR ์—…๋กœ๋“œ ์‹คํŒจ! pause exit /b 1 ) pscp -pw %REMOTE_PASS% start.sh stop.sh restart.sh %REMOTE_USER%@%REMOTE_HOST%:%REMOTE_PATH%/ echo ์—…๋กœ๋“œ ์™„๋ฃŒ echo. :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ :: [3] ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ echo [3/3] ์„œ๋ฒ„ ์žฌ์‹œ์ž‘ ์ค‘... plink -pw %REMOTE_PASS% %REMOTE_USER%@%REMOTE_HOST% "chmod +x %REMOTE_PATH%/*.sh && cd %REMOTE_PATH% && bash restart.sh" if errorlevel 1 ( echo. echo [์˜ค๋ฅ˜] ์žฌ์‹œ์ž‘ ์‹คํŒจ! pause exit /b 1 ) :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ :: [4] ์™„๋ฃŒ :: โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ echo. echo ============================================= echo ๋ฐฐํฌ ์™„๋ฃŒ! echo ๋กœ๊ทธ ํ™•์ธ: echo ssh %REMOTE_USER%@%REMOTE_HOST% echo tail -f /var/www/krules/log/appwar_*.log echo ============================================= echo. pause
Shell
๋ณต์‚ฌ
์‹คํ–‰ ๋ฐฉ๋ฒ•: deploy.bat ๋”๋ธ”ํด๋ฆญ โ†’ bootWar ๋นŒ๋“œ โ†’ WAR + sh ์—…๋กœ๋“œ โ†’ restart.sh ์‹คํ–‰๊นŒ์ง€ ์ž๋™!

(์„ ํƒ) SSH ํ‚ค ์ธ์ฆ์œผ๋กœ ๋น„๋ฐ€๋ฒˆํ˜ธ ์—†์ด ๋ฐฐํฌ

# 1. SSH ํ‚ค ์ƒ์„ฑ (์ด๋ฏธ ์žˆ์œผ๋ฉด ์ƒ๋žต) ssh-keygen -t ed25519 -C "deploy-key" # 2. ๊ณต๊ฐœํ‚ค๋ฅผ ์„œ๋ฒ„์— ๋“ฑ๋ก ssh-copy-id alohaserver4
Bash
๋ณต์‚ฌ
ํ‚ค ๋“ฑ๋ก ํ›„ ๊ฐ bat ํŒŒ์ผ์—์„œ pscp -pw / plink -pw ๋Œ€์‹  ํ‘œ์ค€ ๋ช…๋ น์œผ๋กœ ๊ต์ฒด:
:: WAR ์—…๋กœ๋“œ (pscp โ†’ scp) scp build\\libs\\APP.war alohaserver4:%REMOTE_PATH%/APP.war scp start.sh stop.sh restart.sh alohaserver4:%REMOTE_PATH%/ :: ์›๊ฒฉ ์‹คํ–‰ (plink โ†’ ssh) ssh alohaserver4 "chmod +x %REMOTE_PATH%/*.sh && cd %REMOTE_PATH% && bash restart.sh"
Shell
๋ณต์‚ฌ

์ฒดํฌ๋ฆฌ์ŠคํŠธ

~/.ssh/config ์— alohaserver4 Host ์„ค์ • ์™„๋ฃŒ?
์„œ๋ฒ„์— /var/www/krules/backend/ ๋ฐ /var/www/krules/log/ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ?
ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— start.sh / stop.sh / restart.sh ํŒŒ์ผ ์กด์žฌ?
./gradlew clean bootWar โ†’ build/libs/APP.war ์ƒ์„ฑ ํ™•์ธ?
scp APP.war + *.sh ์—…๋กœ๋“œ ์„ฑ๊ณต?
์„œ๋ฒ„์—์„œ chmod +x /var/www/krules/backend/*.sh ์™„๋ฃŒ?
ssh alohaserver4 "cd /var/www/krules/backend && bash restart.sh" ์‹คํ–‰ ํ™•์ธ?
tail -f /var/www/krules/log/appwar_*.log ๋กœ ์ •์ƒ ๊ธฐ๋™ ๋กœ๊ทธ ํ™•์ธ?
Nginx conf.d/krules-backend.conf ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์„ค์ •?
nginx -t ํ†ต๊ณผ ๋ฐ systemctl reload nginx ์™„๋ฃŒ?
start.bat / stop.bat / restart.bat ๊ฐœ๋ณ„ ๋™์ž‘ ํ™•์ธ?
deploy.bat ํ†ตํ•ฉ ๋ฐฐํฌ ํ…Œ์ŠคํŠธ ์™„๋ฃŒ?

ํ•ต์‹ฌ ์ •๋ฆฌ

Spring Boot = ๋‚ด์žฅ ํ†ฐ์บฃ์œผ๋กœ ์ž์ฒด ์‹คํ–‰ โ†’ Nginx๋Š” ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ์—ญํ• 
systemd ์„œ๋น„์Šค ๋“ฑ๋ก์œผ๋กœ ์•ฑ ์ž๋™ ์‹œ์ž‘/์žฌ์‹œ์ž‘ ๋ณด์žฅ
ํ”„๋ก์‹œ ํ—ค๋”(X-Real-IP, X-Forwarded-For ๋“ฑ) ์„ค์ • ํ•„์ˆ˜
Spring Boot forward-headers-strategy: framework ์„ค์ • ํ•„์ˆ˜
Certbot์œผ๋กœ HTTPS ์ ์šฉ + HTTPโ†’HTTPS ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ