# πŸ› οΈ Spring Boot Blog API Server ## πŸš€ Project Overview κΈ°μ‘΄ **Jekyll(GitHub Pages)** 둜 μš΄μ˜ν•˜λ˜ 정적 λΈ”λ‘œκ·Έμ˜ ν•œκ³„λ₯Ό κ·Ήλ³΅ν•˜κ³ , ν™•μž₯ κ°€λŠ₯ν•œ λΈ”λ‘œκ·Έ μ‹œμŠ€ν…œμ„ κ΅¬μΆ•ν•˜κΈ° μœ„ν•΄ κ°œλ°œν•œ **Spring Boot 기반의 REST API μ„œλ²„**μž…λ‹ˆλ‹€. 정적 μ‚¬μ΄νŠΈμ—μ„œλŠ” κ΅¬ν˜„ν•˜κΈ° μ–΄λ €μ› λ˜ **동적 ν¬μŠ€νŒ… 관리, κ΄€λ¦¬μž λŒ€μ‹œλ³΄λ“œ(Admin), λŒ“κΈ€ μ‹œμŠ€ν…œ** λ“±μ˜ κΈ°λŠ₯을 직접 κ΅¬ν˜„ν•˜μ—¬ λΈ”λ‘œκ·Έ 운영의 νš¨μœ¨μ„±μ„ λ†’μ˜€μŠ΅λ‹ˆλ‹€. **RESTful 원칙**에 μž…κ°ν•œ API 섀계와 **Spring Security**λ₯Ό ν™œμš©ν•œ λ³΄μ•ˆ/인증 λ‘œμ§μ„ μ μš©ν•˜μ—¬ λ°±μ—”λ“œ μ•„ν‚€ν…μ²˜ μ—­λŸ‰μ„ κ°•ν™”ν•˜λŠ” 데 쀑점을 λ‘μ—ˆμŠ΅λ‹ˆλ‹€. ### 🎯 Key Objectives * **Migration**: 정적 파일(Jekyll) μ˜μ‘΄μ„±μ„ μ œκ±°ν•˜κ³  DB 기반의 동적 μ‹œμŠ€ν…œμœΌλ‘œ μ „ν™˜ * **Feature Expansion**: μ›Ή 에디터, κ²Œμ‹œκΈ€ 관리, 방문자 톡계 λ“± κ΄€λ¦¬μž(Admin) κΈ°λŠ₯ μΆ”κ°€ * **Architecture**: ν”„λ‘ νŠΈμ—”λ“œμ™€ λ°±μ—”λ“œλ₯Ό λΆ„λ¦¬ν•œ REST API μ„œλ²„ ꡬ좕 ### πŸ› οΈ Tech Stack * **Java 21, Spring Boot 3.5.9** * **Spring Security, JWT** (Auth) * **JPA (Hibernate), QueryDSL** (ORM) * **PostgreSQL, Redis** (Cache/Session) * **Markdown Parser** (Content) --- ## 🐳 Infrastructure & Deployment μ•ˆμ •μ μ΄κ³  독립적인 μ‹€ν–‰ ν™˜κ²½μ„ 보μž₯ν•˜κΈ° μœ„ν•΄ **Docker** 기반의 μ»¨ν…Œμ΄λ„ˆ μ•„ν‚€ν…μ²˜λ₯Ό κ΅¬μΆ•ν–ˆμŠ΅λ‹ˆλ‹€. ### πŸ—οΈ Dockerfile Highlights 제곡된 Dockerfile은 λ³΄μ•ˆκ³Ό 이미지 κ²½λŸ‰ν™”μ— μ΄ˆμ μ„ 맞좰 μ„€κ³„λ˜μ—ˆμŠ΅λ‹ˆλ‹€. - **Multi-stage Build**: λΉŒλ“œ ν™˜κ²½(JDK)κ³Ό μ‹€ν–‰ ν™˜κ²½(JRE)을 λΆ„λ¦¬ν•˜μ—¬ μ΅œμ’… 이미지 크기λ₯Ό μ΅œμ†Œν™”ν–ˆμŠ΅λ‹ˆλ‹€. - **Alpine Linux**: κ²½λŸ‰ν™”λœ alpine 베이슀 이미지λ₯Ό μ‚¬μš©ν•˜μ—¬ 배포 νš¨μœ¨μ„±μ„ λ†’μ˜€μŠ΅λ‹ˆλ‹€. - **Security (Non-root)**: μ»¨ν…Œμ΄λ„ˆ νƒˆμ·¨ μ‹œ 호슀트 μ‹œμŠ€ν…œ 보호λ₯Ό μœ„ν•΄ 루트 κΆŒν•œμ΄ μ•„λ‹Œ spring μ „μš© μœ μ €λ‘œ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•©λ‹ˆλ‹€.
πŸ‘‰ Dockerfile 미리보기 ```Dockerfile # 1. Build Stage FROM eclipse-temurin:21-jdk-alpine AS build WORKDIR /app COPY . . RUN ./gradlew clean bootJar -x test # 2. Run Stage FROM eclipse-temurin:21-jre-alpine WORKDIR /app # λ³΄μ•ˆμ„ μœ„ν•œ μ „μš© μœ μ € 생성 및 κΆŒν•œ λΆ€μ—¬ RUN addgroup -S spring && adduser -S spring -G spring COPY --from=build --chown=spring:spring /app/build/libs/*.jar app.jar USER spring:spring ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"] ```
### πŸš€ How to Run (with Docker Compose) DB(PostgreSQL), Cache(Redis), Object Storage(MinIO)λ₯Ό ν¬ν•¨ν•œ 전체 인프라λ₯Ό ν•œ λ²ˆμ— μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. ```Bash # 1. ν”„λ‘œμ νŠΈ λΉŒλ“œ 및 μ»¨ν…Œμ΄λ„ˆ μ‹€ν–‰ $ docker-compose up -d --build # 2. 둜그 확인 $ docker-compose logs -f blog-api ```` --- ## πŸ”Œ API Reference **Base URL**: `http://localhost:8080` **Auth**: `Authorization: Bearer {Access_Token}` ### 1. 곡톡 응닡 규격 (Common Response) λͺ¨λ“  API 응닡은 μ•„λž˜ ν‘œμ€€ 포맷을 λ”°λ¦…λ‹ˆλ‹€. ```json { "code": "SUCCESS", // κ²°κ³Ό μ½”λ“œ (SUCCESS λ˜λŠ” ERROR_CODE) "message": "μš”μ²­ 성곡", // 응닡 λ©”μ‹œμ§€ "data": { ... } // μ‹€μ œ 데이터 (없을 경우 null) } ``` ## κ΄€λ ¨ λ¬Έμ„œ - [**ENDPOINT**](https://affine.wypark.me/workspace/f85df0c4-a315-4166-94a8-6558cdafff1d/p13joh_beKNJ6R-I9KrFW) - [**API λͺ…μ„Έμ„œ**](https://affine.wypark.me/workspace/f85df0c4-a315-4166-94a8-6558cdafff1d/7fRNXK9utxG4mcekWivGK)