docs: Embedded Redis 반영 가이드 업데이트 + auth guard 경고 수정

- 설치가이드_OnPremise.pdf: Redis를 선택 사항으로 변경, Embedded Redis 안내
- 개발자가이드.pdf: Docker/Redis 필수 → 선택, Embedded Redis 자동 구동 안내
- 개발환경_사전설치_가이드.txt: Docker/Redis 섹션 Embedded Redis 기반으로 수정
- regenerate_pdfs.py: PDF 재생성 스크립트 추가
- auth.guard.ts: Vue Router deprecated next() 콜백 → return 방식으로 수정

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
이 Commit은 다음에 포함되어 있습니다:
2026-03-27 15:08:48 +09:00
부모 6b248c6a69
커밋 dd263a6e46
5개의 변경된 파일396개의 추가작업 그리고 25개의 파일을 삭제

파일 보기

@@ -0,0 +1,372 @@
"""
WBX Spring Framework PDF 가이드 재생성 스크립트.
Docker/Redis → Embedded Redis 변경 사항 반영.
사용법: python regenerate_pdfs.py
"""
import os
import copy
from PyPDF2 import PdfReader, PdfWriter
from fpdf import FPDF
DOCS_DIR = os.path.dirname(os.path.abspath(__file__))
FONT_PATH = r"C:\Windows\Fonts\malgun.ttf"
FONT_BOLD_PATH = r"C:\Windows\Fonts\malgunbd.ttf"
class KoreanPDF(FPDF):
"""Korean-capable PDF with consistent styling."""
def __init__(self):
super().__init__()
self.add_font("malgun", "", FONT_PATH)
self.add_font("malgun", "B", FONT_BOLD_PATH)
self.set_auto_page_break(auto=True, margin=20)
def header_line(self, title):
self.set_font("malgun", "B", 9)
self.set_text_color(100, 100, 100)
self.cell(0, 6, title, ln=True)
self.set_draw_color(30, 60, 120)
self.set_line_width(0.5)
self.line(10, self.get_y(), 200, self.get_y())
self.ln(4)
def section_title(self, text):
self.set_font("malgun", "B", 14)
self.set_text_color(30, 60, 120)
self.cell(0, 10, text, ln=True)
self.ln(2)
def sub_title(self, text):
self.set_font("malgun", "B", 11)
self.set_text_color(40, 40, 40)
self.cell(0, 8, text, ln=True)
self.ln(1)
def body(self, text):
self.set_font("malgun", "", 10)
self.set_text_color(60, 60, 60)
self.multi_cell(0, 6, text)
self.ln(2)
def code_block(self, text):
self.set_fill_color(245, 245, 245)
self.set_font("malgun", "", 9)
self.set_text_color(40, 40, 40)
x = self.get_x()
self.set_x(x + 5)
self.multi_cell(180, 5.5, text, fill=True)
self.ln(3)
def bullet(self, text):
self.set_font("malgun", "", 10)
self.set_text_color(60, 60, 60)
x = self.get_x()
self.set_x(x + 5)
self.cell(5, 6, "\u2022")
self.multi_cell(170, 6, text)
def note_box(self, text):
self.set_fill_color(255, 248, 220)
self.set_draw_color(200, 180, 100)
self.set_font("malgun", "B", 9)
self.set_text_color(120, 90, 0)
y = self.get_y()
self.rect(12, y, 186, 20, style="DF")
self.set_xy(15, y + 3)
self.multi_cell(180, 5, text)
self.set_y(y + 23)
def page_number(self):
self.set_y(-15)
self.set_font("malgun", "", 8)
self.set_text_color(150, 150, 150)
self.cell(0, 10, f"- {self.page_no()} -", align="C")
def replace_pages(src_path, replacements, out_path):
"""Replace specific pages in a PDF with new fpdf2-generated pages.
replacements: dict of {page_index: fpdf_generation_function}
"""
reader = PdfReader(src_path)
writer = PdfWriter()
# Generate replacement pages
replacement_pages = {}
for page_idx, gen_func in replacements.items():
pdf = gen_func()
tmp = os.path.join(DOCS_DIR, f"_tmp_page_{page_idx}.pdf")
pdf.output(tmp)
tmp_reader = PdfReader(tmp)
replacement_pages[page_idx] = tmp_reader.pages[0]
# Build output
for i, page in enumerate(reader.pages):
if i in replacement_pages:
writer.add_page(replacement_pages[i])
else:
writer.add_page(page)
with open(out_path, "wb") as f:
writer.write(f)
# Cleanup temp files
for page_idx in replacements:
tmp = os.path.join(DOCS_DIR, f"_tmp_page_{page_idx}.pdf")
if os.path.exists(tmp):
os.remove(tmp)
print(f" [OK] {os.path.basename(out_path)}")
# ============================================================
# 1. 설치가이드_OnPremise.pdf — Page 3 (requirements), Page 9 (Redis)
# ============================================================
def onprem_page3():
"""Page 3: 사전 요구사항 - Redis를 선택으로 변경."""
pdf = KoreanPDF()
pdf.add_page()
pdf.header_line("WBX Spring Framework | On-Premise 설치 가이드")
pdf.section_title("1. 사전 요구사항 \u00b7 서버 사양")
pdf.sub_title("1-1. 최소 서버 사양")
pdf.body("항목 최소 사양 권장 사양\n"
"OS RHEL 8+ / Ubuntu 22.04+ RHEL 9 / Rocky Linux 9\n"
"CPU 4 vCPU 8 vCPU\n"
"RAM 8 GB 16 GB\n"
"Disk 50 GB SSD 100 GB SSD (RAID)\n"
"Network 1 Gbps 10 Gbps")
pdf.sub_title("1-2. 필수 소프트웨어")
pdf.body("소프트웨어 버전 용도\n"
"JDK 21 (Temurin LTS) Spring Boot 런타임\n"
"DB Oracle 19c+ 등 애플리케이션 데이터\n"
"Nginx 1.24+ 리버스 프록시, SSL")
pdf.sub_title("1-2b. 선택 소프트웨어")
pdf.body("소프트웨어 버전 용도\n"
"Redis 7.x 캐시 (미설치 시 Embedded Redis 자동 구동)")
pdf.note_box("NOTE: Redis를 별도 설치하지 않아도 WBX Spring에 내장된 Embedded Redis가\n"
"자동으로 시작됩니다. 운영 환경에서는 성능을 위해 외부 Redis 설치를 권장합니다.")
pdf.sub_title("1-3. 네트워크 포트")
pdf.body("포트 서비스 접근 범위 비고\n"
"443 HTTPS 외부 Nginx SSL\n"
"80 HTTP 외부->443 리다이렉트\n"
"8080 Spring Boot 내부 Nginx에서만 접근\n"
"8081 wtm-api 내부 WTM 프로젝트\n"
"3306 MySQL 내부 DB 선택에 따라\n"
"5432 PostgreSQL 내부 \n"
"1521 Oracle 내부 \n"
"1433 MSSQL 내부 \n"
"6379 Redis 내부 선택 (Embedded Redis 자동 대체)")
pdf.page_number()
return pdf
def onprem_page9():
"""Page 9: Redis 설치 섹션 재작성."""
pdf = KoreanPDF()
pdf.add_page()
pdf.header_line("WBX Spring Framework | On-Premise 설치 가이드")
pdf.section_title("5. Redis 설치 (선택)")
pdf.note_box("WBX Spring Framework에는 Embedded Redis가 내장되어 있어 별도 설치 없이도\n"
"앱이 정상 구동됩니다. 운영 환경에서 높은 성능이 필요한 경우에만 설치하세요.")
pdf.sub_title("5-1. Embedded Redis (기본 — 설치 불필요)")
pdf.body("앱 시작 시 다음 순서로 자동 동작합니다:")
pdf.bullet("외부 Redis 감지 시 -> 외부 Redis 사용 (운영 환경)")
pdf.bullet("외부 Redis 없음 -> Embedded Redis 자동 시작 (개발/소규모 운영)")
pdf.bullet("Embedded Redis 실패 -> 인메모리 캐시 전환 (최후 안전장치)")
pdf.ln(3)
pdf.sub_title("5-2. 외부 Redis 설치 (선택 — 대규모 운영 환경 권장)")
pdf.code_block(
"sudo dnf install -y redis\n"
"sudo systemctl enable --now redis\n\n"
"# 보안: bind + password\n"
"sudo sed -i 's/^bind .*/bind 127.0.0.1/' /etc/redis/redis.conf\n"
"echo 'requirepass RedisP@ss123' | sudo tee -a /etc/redis/redis.conf\n"
"sudo systemctl restart redis\n\n"
"# 확인\n"
"redis-cli -a RedisP@ss123 ping # PONG"
)
pdf.sub_title("5-3. .env 설정 (외부 Redis 사용 시)")
pdf.code_block(
"SPRING_DATA_REDIS_HOST=127.0.0.1\n"
"# 또는 원격 Redis 서버 주소\n"
"# SPRING_DATA_REDIS_HOST=redis.company.com"
)
pdf.page_number()
return pdf
# ============================================================
# 2. 개발자가이드.pdf — Page 3 (사전 준비), Page 4 (Docker Compose)
# ============================================================
def dev_page3():
"""Page 3: 개발환경 설정 - Docker/Redis 부분 수정."""
pdf = KoreanPDF()
pdf.add_page()
pdf.header_line("WBX Spring Framework | 개발자 가이드")
pdf.section_title("Chapter 0. 개발환경 설정 - IDE \u00b7 프로젝트 생성")
pdf.sub_title("0-1. 사전 준비")
pdf.bullet("JDK 21 설치 (Eclipse Temurin 권장)")
pdf.bullet("Git 설치 (git config user.name / user.email)")
pdf.bullet("Docker Desktop 설치 (선택 - 로컬 DB 컨테이너 사용 시에만)")
pdf.bullet("IDE 설치 (아래 택 1)")
pdf.ln(2)
pdf.note_box("NOTE: Redis는 Embedded Redis가 앱과 함께 자동 시작되므로 별도 설치가 필요\n"
"없습니다. Docker Desktop도 DB를 직접 설치하면 불필요합니다.")
pdf.sub_title("온보딩 플로우")
pdf.body("1) JDK 설치 -> 2) IDE 설정 -> 3) DB 준비 -> 4) 프로젝트 생성 -> 5) bootRun -> 6) Swagger 확인")
pdf.sub_title("0-2. IDE 선택 가이드")
pdf.body("IDE 권장 대상 핵심 장점\n"
"IntelliJ IDEA 메인 개발 Spring Boot 최적, 리팩터링, DB 브라우저\n"
"VS Code 경량/FE 병행 Extension Pack, DevContainer\n"
"Eclipse/STS 무료/레거시 Spring Tool Suite 플러그인")
pdf.sub_title("0-3. IntelliJ IDEA 필수 설정")
pdf.bullet("플러그인: Spring Boot, Lombok, JPA Buddy, GitToolBox, .env, SonarLint")
pdf.bullet("Annotation Processor 활성화 (Settings > Build > Compiler)")
pdf.bullet("Hot Reload: Build project automatically + Allow auto-make")
pdf.ln(1)
pdf.code_block(
"Run Configuration:\n"
" Main class: kr.co.accura.wbx.spring.WbxSpringCoreApplication\n"
" Env: JWT_SECRET=dev-secret-key"
)
pdf.sub_title("0-4. VS Code 필수 설정")
pdf.bullet("Extension: Java Pack, Spring Boot Pack, Lombok, Gradle, REST Client, GitLens")
pdf.bullet(".vscode/settings.json - Lombok, Gradle Wrapper, 포맷터 설정")
pdf.bullet(".vscode/launch.json - Spring Boot 디버깅 프로필 (local, test)")
pdf.page_number()
return pdf
def dev_page4():
"""Page 4: Docker Compose 및 프로젝트 생성 - Redis 부분 수정."""
pdf = KoreanPDF()
pdf.add_page()
pdf.header_line("WBX Spring Framework | 개발자 가이드")
pdf.code_block(
'// .vscode/launch.json\n'
'{\n'
' "type": "java",\n'
' "name": "App (Local)",\n'
' "mainClass": "kr.co.accura.wbx.spring.WbxSpringCoreApplication",\n'
' "env": {"JWT_SECRET": "dev-secret-key"}\n'
'}'
)
pdf.sub_title("0-5. Eclipse / STS 설정")
pdf.bullet("Spring Tools 4 플러그인 설치 (Eclipse Marketplace)")
pdf.bullet("Lombok 설치: java -jar lombok.jar -> Eclipse 경로 선택")
pdf.bullet("Gradle Import: File > Import > Existing Gradle Project")
pdf.bullet("Annotation Processor: Project Properties > Java Compiler 에서 활성화")
pdf.ln(2)
pdf.sub_title("0-6. 프로젝트 생성 (3가지 방법)")
pdf.body("방법 A: Spring Initializr (start.spring.io)")
pdf.code_block("Project: Gradle-Kotlin | Java: 21 | Boot: 3.5.0\n"
"Group: kr.co.accura | Artifact: {앱}-api\n"
"-> Generate -> 압축 해제 -> wbx-spring-starter 의존성 추가")
pdf.body("방법 B: Git Template Repository")
pdf.code_block("git clone https://git.wbx.kr/accura/wbx-spring-template.git my-app\n"
"cd my-app && ./init.sh --name my-app --group kr.co.accura")
pdf.sub_title("0-7. 설치 스크립트 (권장)")
pdf.body("프로젝트에 포함된 설치 스크립트가 JDK 자동 설치, Git 사전 검사, 빌드, .env 템플릿 생성을 자동 처리합니다.")
pdf.code_block("# Windows\nscripts\\install.bat\n\n# Linux/macOS\nchmod +x scripts/install.sh && ./scripts/install.sh")
pdf.body("TIP: JDK 미설치 시 스크립트가 자동으로 설치합니다.")
pdf.sub_title("0-8. 로컬 개발 인프라")
pdf.body("Redis는 Embedded Redis가 앱 시작 시 자동 구동되므로 별도 설치가 필요 없습니다.\n"
"DB만 Docker Compose 또는 직접 설치하면 됩니다.")
pdf.code_block("# Docker로 DB만 시작 (Redis 불필요)\n"
"docker compose -f docker-compose-dev.yml up -d mysql\n\n"
"# 또는 DB를 직접 설치한 경우 바로 앱 실행\n"
"gradlew.bat bootRun")
pdf.note_box("Embedded Redis 동작: 앱 시작 시 외부 Redis 감지 -> 없으면 자동 시작 -> 실패 시 인메모리 캐시")
pdf.page_number()
return pdf
def dev_page5():
"""Page 5: DevContainer + 코드 품질 도구 - Redis 부분 수정."""
pdf = KoreanPDF()
pdf.add_page()
pdf.header_line("WBX Spring Framework | 개발자 가이드")
pdf.sub_title("0-9. DevContainer (VS Code)")
pdf.body("devcontainer.json 으로 JDK 21 + DB가 포함된 완전한 개발 환경을 컨테이너로 제공합니다.\n"
"Redis는 Embedded Redis가 자동 구동되므로 DevContainer에 별도 포함하지 않아도 됩니다.\n"
"팀원 전체 동일 환경 보장.")
pdf.sub_title("0-10. 코드 품질 도구")
pdf.bullet("Spotless - 코드 포맷 자동화 (./gradlew spotlessApply)")
pdf.bullet("CheckStyle - 코드 규칙 검사")
pdf.bullet("JaCoCo - 테스트 커버리지 (최소 70%)")
pdf.bullet("SonarLint - IDE 실시간 코드 분석")
pdf.bullet(".editorconfig - IDE 공통 코드 스타일 (UTF-8, LF, 4 spaces)")
pdf.page_number()
return pdf
# ============================================================
# Main
# ============================================================
def main():
print("WBX Spring Framework PDF 가이드 재생성")
print("=" * 50)
# 1. 설치가이드_OnPremise.pdf
print("\n[1] 설치가이드_OnPremise.pdf")
src = os.path.join(DOCS_DIR, "WBX_Spring_Framework_설치가이드_OnPremise.pdf")
out = os.path.join(DOCS_DIR, "WBX_Spring_Framework_설치가이드_OnPremise.pdf")
replace_pages(src, {
2: onprem_page3, # Page 3: 사전 요구사항 (Redis 선택으로)
8: onprem_page9, # Page 9: Redis 설치 (Embedded Redis 안내)
}, out)
# 2. 설치가이드_Cloud.pdf — 변경 없음 (클라우드 관리형 Redis 사용)
print("\n[2] 설치가이드_Cloud.pdf")
print(" [SKIP] 클라우드 환경은 관리형 Redis(Azure Cache/ElastiCache) 사용 - 변경 불필요")
# 3. 개발자가이드.pdf
print("\n[3] 개발자가이드.pdf")
src = os.path.join(DOCS_DIR, "WBX_Spring_Framework_개발자가이드.pdf")
out = os.path.join(DOCS_DIR, "WBX_Spring_Framework_개발자가이드.pdf")
replace_pages(src, {
2: dev_page3, # Page 3: 사전 준비 (Docker/Redis 선택)
3: dev_page4, # Page 4: Docker Compose (Redis 불필요)
4: dev_page5, # Page 5: DevContainer (Redis 제외)
}, out)
print("\n" + "=" * 50)
print("완료! 변경된 PDF:")
print(" - WBX_Spring_Framework_설치가이드_OnPremise.pdf (Page 3, 9)")
print(" - WBX_Spring_Framework_개발자가이드.pdf (Page 3, 4, 5)")
print(" - WBX_Spring_Framework_설치가이드_Cloud.pdf (변경 없음)")
if __name__ == "__main__":
main()