- 설치가이드_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>
373 줄
15 KiB
Python
373 줄
15 KiB
Python
"""
|
|
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()
|