파일
wbx-spring/docs/00-setup-guide.md
accura 476f8a0565 Initial commit: WBX Spring Framework Core
Spring Boot 3.5.0 + Java 21 기반 엔터프라이즈 프레임워크
- Auth: JWT, MFA/TOTP, OAuth2 SSO, PasswordPolicy, LoginHistory
- RBAC: Role-Permission, DeptScope, Redis 캐시
- Approval: Handler 패턴 결재 엔진
- Notification: SSE 실시간 알림
- File: Local/Azure Blob/AWS S3/GCP Storage
- DataSource: Multi-DB 라우팅 (MySQL/PG/Oracle/MSSQL)
- Admin: Thymeleaf 11화면 콘솔
- Compat: WBX FastAPI 호환 (에러/페이징)
- Flyway: 4종 DBMS 마이그레이션
- Scripts: install.bat/sh, deploy-prod.sh
- Docs: 설치가이드(OnPremise/Cloud), 개발자가이드 PDF

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:27:18 +09:00

18 KiB

WBX Spring Framework — 설치/배포 가이드

소스: D:\WBX02\wbx-spring-core 기술: Spring Boot 3.5.0 + Java 21 + MySQL/PG/Oracle/MSSQL + Redis


1. 사전 요구사항

1-1. 서버 사양

항목 최소 사양 권장 사양
OS RHEL 8+ / Ubuntu 22.04+ / Windows Server 2019+ RHEL 9 / Rocky Linux 9
CPU 4 vCPU 8 vCPU
RAM 8 GB 16 GB
Disk 50 GB SSD 100 GB SSD
Network 1 Gbps 10 Gbps

1-2. 필수 소프트웨어

SW 버전 용도 필수
JDK 21 LTS (Eclipse Temurin 권장) Spring Boot 런타임
Git 2.x 소스코드 관리
MySQL 8.0+ DB (택 1)
PostgreSQL 14+ DB (택 1) 선택
Oracle 19c+ DB (택 1) 선택
MSSQL 2019+ DB (택 1) 선택
Redis 7.x 캐시/세션 권장
Docker 24+ 컨테이너 배포 선택
Nginx/Caddy latest 리버스 프록시 (프로덕션) 선택

Gradle은 Wrapper(gradlew)가 자동 다운로드하므로 별도 설치 불필요

1-3. 포트

포트 서비스 접근 범위
443 HTTPS (Nginx/Caddy) 외부
80 HTTP → 443 리다이렉트 외부
8080 Spring Boot 내부 (localhost)
3306 MySQL 내부
5432 PostgreSQL 내부
1521 Oracle 내부
1433 MSSQL 내부
6379 Redis 내부 (bind 127.0.0.1)

2. JDK 21 설치

Windows

# 방법 A: Winget (권장)
winget install EclipseAdoptium.Temurin.21.JDK

# 방법 B: ZIP 수동 설치
# https://adoptium.net/temurin/releases/?version=21 에서 다운로드
# 환경변수 설정
[System.Environment]::SetEnvironmentVariable('JAVA_HOME', 'D:\tools\jdk-21.0.6+7', 'User')
[System.Environment]::SetEnvironmentVariable('Path', $env:Path + ';D:\tools\jdk-21.0.6+7\bin', 'User')
java -version

Linux (RHEL/Rocky/CentOS)

sudo dnf install -y java-21-openjdk-devel
# 또는 Temurin
sudo dnf install -y https://packages.adoptium.net/artifactory/rpm/centos/9/$(uname -m)/Packages/temurin-21-jdk-*.rpm
echo 'export JAVA_HOME=/usr/lib/jvm/temurin-21-jdk' >> ~/.bashrc
source ~/.bashrc && java -version

Ubuntu/Debian

sudo apt install -y wget apt-transport-https gpg
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | sudo gpg --dearmor -o /usr/share/keyrings/adoptium.gpg
echo "deb [signed-by=/usr/share/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/adoptium.list
sudo apt update && sudo apt install -y temurin-21-jdk
java -version

macOS

brew install temurin@21
java -version

3. 소스코드 & 로컬 개발

3-1. 소스코드 가져오기

git clone https://github.com/accura0117/wbx-spring-core.git
cd wbx-spring-core

3-2. 빠른 설치 (설치 스크립트)

스크립트가 JDK/Git/Docker 사전 검사, 빌드, .env 템플릿 생성, 디렉토리 생성을 자동 처리합니다.

# Windows
scripts\install.bat

# Linux/macOS
chmod +x scripts/install.sh && ./scripts/install.sh

3-3. 로컬 DB 생성 (Docker Compose 또는 직접)

# 방법 A: Docker Compose (권장)
docker compose -f docker-compose-dev.yml up -d
# → MySQL(:3306) + Redis(:6379) 자동 시작

# PostgreSQL 사용 시:
docker compose -f docker-compose-dev.yml --profile pg up -d
# → PostgreSQL(:5432) + Redis(:6379) 자동 시작

# 방법 B: 직접 설치 후 DB 생성
# MySQL
CREATE DATABASE wbx_spring CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wbxapp'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON wbx_spring.* TO 'wbxapp'@'localhost';

# PostgreSQL
CREATE USER wbxapp WITH PASSWORD 'password';
CREATE DATABASE wbx_spring OWNER wbxapp ENCODING 'UTF8';

3-4. 빌드 & 실행

설치 스크립트를 사용하지 않는 경우 수동으로 빌드합니다.

# Windows
gradlew.bat build -x test
gradlew.bat bootRun

# Linux/macOS
chmod +x gradlew
./gradlew build -x test
./gradlew bootRun

3-5. 확인

기본 context-path는 /spring입니다. 독립 도메인 시 SERVER_CONTEXT_PATH=/로 변경.

http://localhost:8080/spring/health             → {"status":"ok","app":"wbx-spring"}
http://localhost:8080/spring/admin/login        → Admin Console
http://localhost:8080/spring/swagger-ui         → Swagger UI

3-6. 초기 관리자 등록

curl -X POST http://localhost:8080/spring/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@company.com","username":"admin","password":"Admin1234!","fullName":"관리자","isAdmin":true}'

4. 프로필 시스템

4-1. 9개 프로필

프로필 파일 용도
(기본) application.yml 로컬 개발 (MySQL, ddl-auto:update)
prod application-prod.yml 프로덕션 (Flyway 활성, Swagger 비활성, 로깅)
mysql application-mysql.yml MySQL 드라이버/Dialect/Flyway
postgresql application-postgresql.yml PostgreSQL 드라이버/Dialect/Flyway
oracle application-oracle.yml Oracle 드라이버/Dialect/Flyway
mssql application-mssql.yml MSSQL 드라이버/Dialect/Flyway
azure application-azure.yml Azure Entra SSO + Blob Storage
aws application-aws.yml AWS Cognito SSO + S3
test application-test.yml 테스트 (H2 인메모리, Flyway 비활성)

4-2. 프로필 조합 예시

# On-Premise MySQL
java -jar app.jar --spring.profiles.active=prod,mysql

# On-Premise Oracle
java -jar app.jar --spring.profiles.active=prod,oracle

# Azure + MSSQL
java -jar app.jar --spring.profiles.active=prod,mssql,azure

# AWS + PostgreSQL
java -jar app.jar --spring.profiles.active=prod,postgresql,aws

# 테스트
./gradlew test  # application-test.yml 자동 사용

4-3. 환경변수

변수 기본값 설명 필수
JWT_SECRET (dev key) JWT 시크릿 (프로덕션 필수 변경!)
SERVER_CONTEXT_PATH /spring 독립 도메인이면 /
DB_HOST localhost DB 호스트
DB_PORT 3306 DB 포트
DB_NAME wbx_spring DB 이름
DB_USER wbxapp DB 사용자
DB_PASS password DB 비밀번호
DB_POOL_SIZE 20 HikariCP 커넥션 풀
SPRING_DATA_REDIS_HOST localhost Redis 호스트
CORS_ORIGIN https://app.company.com CORS 허용 도메인
SPRING_PROFILES_ACTIVE (없음) 프로필 조합

Azure 전용

변수 설명
AZURE_CLIENT_ID Entra App Registration Client ID
AZURE_CLIENT_SECRET Entra App Secret
AZURE_TENANT_ID Azure AD Tenant ID
AZURE_STORAGE_ACCOUNT Blob Storage Account Name
AZURE_STORAGE_KEY Blob Storage Access Key
AZURE_CONTAINER Blob Container Name (기본: uploads)

AWS 전용

변수 설명
AWS_COGNITO_CLIENT_ID Cognito User Pool Client ID
AWS_COGNITO_CLIENT_SECRET Cognito Client Secret
AWS_USER_POOL_ID Cognito User Pool ID
AWS_REGION AWS Region (기본: ap-northeast-2)
AWS_S3_BUCKET S3 Bucket Name
AWS_ACCESS_KEY IAM Access Key
AWS_SECRET_KEY IAM Secret Key

5. 주요 기능 활성화

5-1. MFA/TOTP (Google Authenticator 호환)

wbx:
  spring:
    mfa:
      enabled: true              # true로 활성화
      force-for-external: true   # 외부 사용자 강제
      force-for-internal: false  # 내부 사용자 (Entra CA로 대체)
      totp-issuer: "WBX Platform"

활성화 시 로그인 흐름: POST /api/auth/loginmfa_required: truePOST /api/auth/mfa/verify

5-2. Azure Entra SSO

--spring.profiles.active=prod,mssql,azure + 환경변수 설정으로 자동 활성화. OAuth2 OIDC 로그인 → WBX 호환 JWT 자동 발급 → 사용자 자동 등록.

5-3. 파일 스토리지 전환

wbx:
  spring:
    file:
      storage-type: local        # 기본: 로컬 파일시스템
      # storage-type: azure-blob # Azure Blob Storage
      # storage-type: aws-s3     # AWS S3
      # storage-type: gcp-storage # Google Cloud Storage

5-4. Multi-DataSource 라우팅

wbx:
  spring:
    datasource:
      routing-enabled: true      # 활성화
      wbxgw:
        url: jdbc:mysql://localhost:3306/wbx_gw
        username: wbxapp
        password: password

서비스에서 @DataSource("wbxgw") 어노테이션으로 DB 전환.


6. 프로덕션 배포

6-1. 서비스 계정 (Linux)

sudo useradd -r -m -s /bin/bash wbxapp
sudo mkdir -p /opt/wbx-app
sudo chown wbxapp:wbxapp /opt/wbx-app

6-2. 타임존 · 인코딩

sudo timedatectl set-timezone Asia/Seoul
sudo localectl set-locale LANG=ko_KR.UTF-8

6-3. 시스템 리밋

# /etc/security/limits.d/wbxapp.conf
wbxapp soft nofile 65535
wbxapp hard nofile 65535

6-4. Redis 보안

sudo sed -i 's/^bind .*/bind 127.0.0.1/' /etc/redis/redis.conf
echo 'requirepass RedisP@ss123' | sudo tee -a /etc/redis/redis.conf
sudo systemctl restart redis

6-5. 배포 디렉토리

/opt/wbx-app/
  ├── app.jar                  # Spring Boot Fat JAR
  ├── .env                     # 환경변수 (시크릿)
  ├── logs/                    # 로그
  ├── uploads/                 # 파일 업로드 (local storage)
  └── backup/                  # 백업

6-6. JAR 빌드 & 배포

# 빌드 서버
./gradlew bootJar

# 운영 서버로 전송
scp build/libs/wbx-spring-core-*.jar wbxapp@server:/opt/wbx-app/app.jar

# .env 파일
cat > /opt/wbx-app/.env << 'EOF'
JWT_SECRET=your-production-secret-key-minimum-256-bits
DB_HOST=localhost
DB_PORT=3306
DB_NAME=wbx_spring
DB_USER=wbxapp
DB_PASS=StrongP@ss
SPRING_PROFILES_ACTIVE=prod,mysql
SERVER_CONTEXT_PATH=/
EOF
chmod 600 /opt/wbx-app/.env

6-7. systemd 서비스 (Linux)

# /etc/systemd/system/wbx-app.service
[Unit]
Description=WBX Spring Application
After=network.target

[Service]
Type=simple
User=wbxapp
WorkingDirectory=/opt/wbx-app
EnvironmentFile=/opt/wbx-app/.env
ExecStart=/usr/bin/java \
  -XX:+UseG1GC \
  -XX:MaxRAMPercentage=75.0 \
  -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE} \
  -jar /opt/wbx-app/app.jar
Restart=always
RestartSec=5
StandardOutput=append:/opt/wbx-app/logs/app.log
StandardError=append:/opt/wbx-app/logs/app.log

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now wbx-app
journalctl -u wbx-app -f

6-8. Windows 서비스

# NSSM으로 서비스 등록 (https://nssm.cc)
nssm install WbxSpring "D:\tools\jdk-21\bin\java.exe" "-Xmx512m -jar D:\wbx-app\app.jar --spring.profiles.active=prod,mysql"
nssm set WbxSpring AppDirectory D:\wbx-app
nssm set WbxSpring AppEnvironmentExtra JWT_SECRET=your-secret SERVER_CONTEXT_PATH=/
nssm start WbxSpring

6-9. Docker 배포

./gradlew bootJar
docker build -t wbx-spring:latest .
docker compose up -d

7. 리버스 프록시

7-1. Nginx

upstream spring_app {
    server 127.0.0.1:8080;
    keepalive 32;
}

server {
    listen 443 ssl http2;
    server_name app.company.com;

    ssl_certificate     /etc/ssl/certs/app.pem;
    ssl_certificate_key /etc/ssl/private/app.key;

    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-Content-Type-Options nosniff always;
    add_header Strict-Transport-Security "max-age=63072000" always;

    location / {
        proxy_pass http://spring_app;
        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;
        client_max_body_size 50m;
    }

    # SSE 알림 (버퍼링 비활성화)
    location /api/notifications/stream {
        proxy_pass http://spring_app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}

7-2. Caddy

app.company.com {
    reverse_proxy localhost:8080
}

# 공유 도메인 (WBX + Spring Boot)
wbx.kr {
    handle /spring/* {
        reverse_proxy localhost:8080
    }
    handle {
        reverse_proxy localhost:5000
    }
}

7-3. WBX FastAPI 동시 운영

# Nginx — URL prefix로 분기
location /api/gw/ {
    proxy_pass http://127.0.0.1:8001;  # WBX FastAPI
}
location / {
    proxy_pass http://127.0.0.1:8080;  # Spring Boot
}

JWT SECRET_KEY를 두 시스템이 동일하게 설정해야 SSO가 작동합니다.


8. 방화벽 · 보안

Linux (firewalld)

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# DB 포트는 외부 차단 (기본)

SELinux

sudo setsebool -P httpd_can_network_connect 1

보안 체크리스트

  • SSH 키 기반 인증 (비밀번호 로그인 비활성화)
  • 서비스 계정(wbxapp)에 sudo 권한 없음
  • DB 포트 외부 차단 (localhost만 접근)
  • Redis bind 127.0.0.1 + requirepass
  • .env 파일 600 권한
  • Swagger UI 프로덕션 비활성화 (prod 프로필 자동)
  • Nginx 보안 헤더 (HSTS, X-Frame, X-Content-Type)

9. Admin Console

11개 화면, 25개 엔드포인트:

화면 URL 기능
로그인 /admin/login 이메일+비밀번호 폼 인증
대시보드 /admin 활성 사용자, 로그인 횟수, 역할 수
사용자 목록 /admin/users 추가, 상세 링크
사용자 상세 /admin/users/{id} 수정, 삭제, 잠금해제, 비밀번호초기화, 역할할당/해제
역할 목록 /admin/roles 추가, 삭제, 상세 링크
역할 상세 /admin/roles/{id} 수정, 권한 추가/삭제
권한 매트릭스 /admin/permissions 전체 역할-모듈-액션 현황, 삭제
로그인 이력 /admin/login-history 최근 50건
감사 로그 /admin/audit-logs 최근 100건
시스템 설정 /admin/config K-V 설정 추가/수정
시스템 상태 /admin/system-health JVM Heap, OS, Java, Spring Boot 버전

10. 백업 · 복구

DB 백업 (cron)

#!/bin/bash
# /opt/wbx-app/backup/db-backup.sh
DATE=$(date +%Y%m%d_%H%M%S)
mysqldump -u wbxapp -p wbx_spring | gzip > /opt/wbx-app/backup/wbx_spring_${DATE}.sql.gz
find /opt/wbx-app/backup -name '*.gz' -mtime +30 -delete

# crontab -e
0 2 * * * /opt/wbx-app/backup/db-backup.sh

앱 롤백

cp /opt/wbx-app/app.jar /opt/wbx-app/backup/app-prev.jar
# 새 JAR 배포 후 문제 발생 시:
cp /opt/wbx-app/backup/app-prev.jar /opt/wbx-app/app.jar
sudo systemctl restart wbx-app

11. 모니터링

Actuator + Prometheus

# application-prod.yml에 이미 설정됨
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
# Health Check
curl http://localhost:8080/health
curl http://localhost:8080/actuator/health
curl http://localhost:8080/actuator/prometheus  # Prometheus 메트릭

# Grafana 대시보드: ID 12900 (JVM Micrometer) Import

12. Flyway 마이그레이션

src/main/resources/db/migration/
├── common/              # 공통 Seed (INSERT)
│   ├── V001__seed_roles.sql
│   └── V002__seed_system_config.sql
├── mysql/               # MySQL DDL (11 테이블)
│   └── V001__create_tables.sql
├── postgresql/          # PostgreSQL DDL
│   └── V001__create_tables.sql
├── oracle/              # Oracle DDL
│   └── V001__create_tables.sql
└── mssql/               # MSSQL DDL
    └── V001__create_tables.sql
  • 개발: hibernate.ddl-auto=update (Flyway 비활성)
  • 프로덕션: flyway.enabled=true + ddl-auto=validate (자동)

13. 체크리스트

로컬 개발

[ ] JDK 21 설치 + java -version 확인
[ ] Git clone
[ ] 설치 스크립트 실행 (scripts/install.bat 또는 scripts/install.sh)
[ ] docker-compose-dev.yml up (또는 직접 DB/Redis 설치)
[ ] ./gradlew bootRun → http://localhost:8080/spring/health OK
[ ] 관리자 등록 (POST /spring/api/auth/register)
[ ] Admin Console 로그인 (/spring/admin/login)
[ ] Swagger UI 확인 (/spring/swagger-ui)

프로덕션

[ ] 배포 스크립트 실행 (sudo scripts/deploy-prod.sh) 또는 수동 설정:
[ ] 서비스 계정 (wbxapp) 생성
[ ] 타임존 Asia/Seoul, 로케일 UTF-8
[ ] .env 파일 생성 (JWT_SECRET 필수 변경!)
[ ] DB 생성 + 사용자 권한
[ ] Redis 설치 + bind 127.0.0.1 + requirepass
[ ] JAR 빌드 (./gradlew bootJar)
[ ] 서버 전송 + /opt/wbx-app 배치
[ ] systemd 서비스 등록 + 시작
[ ] Health Check 확인
[ ] 리버스 프록시 설정 (Nginx/Caddy)
[ ] SSL 인증서 설치
[ ] 방화벽 443 오픈, DB 포트 내부만
[ ] SELinux httpd_can_network_connect (RHEL)
[ ] 관리자 등록 + Admin Console 접속 확인
[ ] DB 백업 cron 등록
[ ] 모니터링 Prometheus 연동 (선택)

14. 트러블슈팅

증상 원인 해결
BUILD FAILED JDK 버전 java -version → 21 확인
DB 연결 실패 URL/인증 .env + application-{db}.yml 확인
포트 충돌 8080 사용 중 server.port=8081 또는 기존 프로세스 종료
Admin 리다이렉트 오류 context-path SERVER_CONTEXT_PATH 환경변수 확인
JWT 에러 시크릿 키 불일치 WBX FastAPI와 동일 JWT_SECRET 사용
Redis 연결 실패 미실행 Redis 없이도 동작 (캐시 비활성화)
한글 깨짐 DB 인코딩 CHARACTER SET utf8mb4 확인
Flyway 실패 DDL 호환 DB 프로필 확인 (oracle/mssql/mysql/postgresql)
SSO 오류 OAuth2 설정 AZURE_CLIENT_ID, AZURE_TENANT_ID 확인
MFA 안됨 미활성화 wbx.spring.mfa.enabled=true 설정
502 Bad Gateway 앱 미기동 systemctl status wbx-app, logs 확인
OOM (메모리) 힙 부족 -XX:MaxRAMPercentage=75 또는 RAM 증설