πŸ’» PROJECT/[Spring Boot, React] λ…μ„œ μŠ΅κ΄€ 관리 μ„œλΉ„μŠ€

[Spring Boot, React] λ…μ„œ μŠ΅κ΄€ 관리 μ„œλΉ„μŠ€(1μ°¨ 개발)

devCloud 2026. 1. 4. 01:33
728x90

1. ν”„λ‘œμ νŠΈ μ†Œκ°œ

이 ν”„λ‘œμ νŠΈλŠ” Spring Boot와 React둜 κ΅¬ν˜„ν•œ ν’€μŠ€νƒ λ…μ„œ μŠ΅κ΄€ 관리 μ„œλΉ„μŠ€μž…λ‹ˆλ‹€. λ…μ„œ 기둝과 λͺ©ν‘œ μ„€μ •, 차트 기반 μ§„ν–‰λ₯  μ‹œκ°ν™”λ₯Ό 톡해 μ‚¬μš©μžκ°€ λ…μ„œ μ„±κ³Όλ₯Ό κ°κ΄€μ μœΌλ‘œ μΆ”μ ν•˜λ„λ‘ μ„€κ³„ν–ˆμŠ΅λ‹ˆλ‹€. λ…μ„œ λ‚΄μš©μ„ μ²΄κ³„μ μœΌλ‘œ 기둝해 기얡을 κ°•ν™”ν•˜κ³  μŠ΅κ΄€ν™”λ₯Ό λ•λŠ” μ„œλΉ„μŠ€κ°€ ν•„μš”ν•˜λ‹€κ³  νŒλ‹¨ν•΄ 주제둜 μ„ μ •ν–ˆμŠ΅λ‹ˆλ‹€.

 

2. 기술 μŠ€νƒ

Backend(Spring Boot)

ꡬ뢄 기술 버전 μš©λ„
ν”„λ ˆμž„μ›Œν¬ Spring Boot 3.3.0 메인 λ°±μ—”λ“œ ν”„λ ˆμž„μ›Œν¬
μ–Έμ–΄ Java 17 μ„œλ²„ μ‚¬μ΄λ“œ 둜직
ORM Spring Data JPA (Hibernate) - λ°μ΄ν„°λ² μ΄μŠ€ 연동
λ³΄μ•ˆ Spring Security - 인증/인가, μ„Έμ…˜ 관리
ν…œν”Œλ¦Ώ Thymeleaf - μ„œλ²„ μ‚¬μ΄λ“œ λ Œλ”λ§ (SPA 폴백)
μ•”ν˜Έν™” BCryptPasswordEncoder - λΉ„λ°€λ²ˆν˜Έ ν•΄μ‹±
λΉŒλ“œ 도ꡬ Gradle 8.12.1 λΉŒλ“œ 및 μ˜μ‘΄μ„± 관리
λͺ¨λ‹ˆν„°λ§ Spring Actuator - ν—¬μŠ€μ²΄ν¬ (/actuator/health)

 

Frontend(React)

ꡬ뢄 기술 버전 μš©λ„
ν”„λ ˆμž„μ›Œν¬ React 18.2.0 UI 라이브러리
μ–Έμ–΄ TypeScript 4.9.5 νƒ€μž… μ•ˆμ •μ„±
λΌμš°νŒ… React Router DOM 7.2.0 SPA λΌμš°νŒ…
HTTP ν΄λΌμ΄μ–ΈνŠΈ Axios 1.3.4 API 톡신
차트 Chart.js + react-chartjs-2 4.4.8 / 5.3.0 데이터 μ‹œκ°ν™”
차트 ν”ŒλŸ¬κ·ΈμΈ chartjs-plugin-zoom 2.2.0 차트 쀌/팬 κΈ°λŠ₯
CSS ν”„λ ˆμž„μ›Œν¬ Tailwind CSS 3.4.4 μœ ν‹Έλ¦¬ν‹° 기반 μŠ€νƒ€μΌλ§
λΉŒλ“œ 도ꡬ Create React App 5.0.1 React ν”„λ‘œμ νŠΈ μ„€μ •
폰트 Pretendard - ν•œκΈ€ μ›Ήν°νŠΈ

 

Database

ν™˜κ²½ 기술 μš©λ„
개발 H2 Database 파일 기반 (./data/booktine)
운영 MySQL8 Render 배포 μ‹œ μ‚¬μš©

 

DevOps & 배포

ꡬ뢄 기술 μš©λ„
μ»¨ν…Œμ΄λ„ˆν™” Docker λ©€ν‹°μŠ€ν…Œμ΄μ§€ λΉŒλ“œ
베이슀 이미지 gradle:8.7-jdk17 (λΉŒλ“œ) / eclipse-temurin:17-jre (λŸ°νƒ€μž„)
배포 ν”Œλž«νΌ Render (Free Tier) λ°±μ—”λ“œ + 정적 파일 ν˜ΈμŠ€νŒ…
버전 관리 Git + GitHub μ†ŒμŠ€ μ½”λ“œ 관리

 

3. μ•„ν‚€ν…μ²˜ ꡬ쑰

3.1 전체 μ•„ν‚€ν…μ²˜

μ•„ν‚€ν…μ²˜λ₯Ό ν•œ μ€„λ‘œ μš”μ•½ν•˜λ©΄, λΈŒλΌμš°μ €μ—μ„œ λŒμ•„κ°€λŠ” React SPAκ°€ HTTP(REST API)둜 Spring Boot λ°±μ—”λ“œμ— μš”μ²­ν•˜κ³ , λ°±μ—”λ“œλŠ” λ³΄μ•ˆ(μ„Έμ…˜) → 컨트둀러 → μ„œλΉ„μŠ€ → 리포지토리(JPA) 순으둜 μ²˜λ¦¬ν•œ λ’€ DB(H2/MySQL)와 연동해 κ²°κ³Όλ₯Ό λ‹€μ‹œ λ‚΄λ €μ£ΌλŠ” κ΅¬μ‘°μž…λ‹ˆλ‹€.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Client (Browser)                     β”‚
β”‚                    React SPA (TypeScript)                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό HTTP (REST API)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Spring Boot Server                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ Controller  β”‚→ β”‚   Service   β”‚→ β”‚     Repository      β”‚  β”‚
β”‚  β”‚   Layer     β”‚  β”‚    Layer    β”‚  β”‚  (Spring Data JPA)  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                              β”‚              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚              Spring Security (Session)              β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Database (H2 / MySQL)                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Client(Browser) – React SPA(TypeScript)
    • μ‚¬μš©μžκ°€ ν™”λ©΄μ—μ„œ ν–‰λ™ν•˜λ©΄(쑰회/등둝/μˆ˜μ • λ“±) SPAκ°€ API μš”μ²­μ„ 보내고, 응닡 데이터λ₯Ό λ°›μ•„ 화면을 λ‹€μ‹œ κ·Έλ¦½λ‹ˆλ‹€. SPAλŠ” 기본적으둜 λΈŒλΌμš°μ €μ—μ„œ JS둜 화면을 κ°±μ‹ ν•˜λŠ” 방식(CSR)κ³Ό 잘 λ§žμŠ΅λ‹ˆλ‹€.
  2. HTTP(REST API)
    • ν”„λ‘ νŠΈμ™€ λ°±μ—”λ“œλŠ” HTTP둜 ν†΅μ‹ ν•˜κ³ , REST μŠ€νƒ€μΌλ‘œ "λ¦¬μ†ŒμŠ€μ— λŒ€ν•œ μš”μ²­/응닡" ν˜•νƒœλ‘œ APIλ₯Ό μ„€κ³„ν•©λ‹ˆλ‹€ (μ‹€λ¬΄μ—μ„œλ„ HTTP APIλ₯Ό ν”νžˆ REST API라고 λΆ€λ¦…λ‹ˆλ‹€).
  3. Spring Boot Server λ‚΄λΆ€: Security → Controller → Service → Repository
    • Spring Security (Session)
      • μš”μ²­μ΄ 컨트둀러둜 λ“€μ–΄μ˜€κΈ° 전에, Spring Securityκ°€ λ¨Όμ € κ°œμž…ν•΄μ„œ 인증/인가λ₯Ό μ²˜λ¦¬ν•©λ‹ˆλ‹€. μ„Έμ…˜ 방식이면, 둜그인 ν›„ μƒμ„±λœ μ„Έμ…˜κ³Ό ν΄λΌμ΄μ–ΈνŠΈ μΏ ν‚€(μ„Έμ…˜ μ‹λ³„μž)λ₯Ό κΈ°μ€€μœΌλ‘œ “λˆ„κ΅¬μ˜ μš”μ²­μΈμ§€”λ₯Ό ν™•μΈν•˜κ³  μ ‘κ·Ό κΆŒν•œμ„ μ μš©ν•©λ‹ˆλ‹€.
    • Controller Layer
      • μ»¨νŠΈλ‘€λŸ¬λŠ” “μ–΄λ–€ URL/HTTP λ©”μ„œλ“œ μš”μ²­μ„ μ–΄λ–€ λ©”μ„œλ“œκ°€ μ²˜λ¦¬ν• μ§€”λ₯Ό λ§€ν•‘ν•˜κ³ , μš”μ²­/μ‘λ‹΅μ˜ μž…κ΅¬ 역할을 ν•©λ‹ˆλ‹€. (예: @RequestMapping, @GetMapping λ“±)
    • Service Layer
      • μ„œλΉ„μŠ€λŠ” λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ λͺ¨μ•„μ„œ μ²˜λ¦¬ν•˜λŠ” κ³„μΈ΅μž…λ‹ˆλ‹€. 보톡 “κ·œμΉ™ 적용, 검증, νŠΈλžœμž­μ…˜ λ‹¨μœ„μ˜ μž‘μ—… μ‘°ν•©”이 μ—¬κΈ°μ„œ 이루어지고, μ»¨νŠΈλ‘€λŸ¬λŠ” μ„œλΉ„μŠ€ ν˜ΈμΆœμ— μ§‘μ€‘ν•΄μ„œ μ–‡κ²Œ μœ μ§€ν•©λ‹ˆλ‹€.
    • Repository (Spring Data JPA)
      • λ¦¬ν¬μ§€ν† λ¦¬λŠ” DB 접근을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€. Spring Data JPA의 Repository μΆ”μƒν™”λŠ” 반볡적인 데이터 μ ‘κ·Ό λ³΄μΌλŸ¬ν”Œλ ˆμ΄νŠΈλ₯Ό 쀄여 CRUD 쀑심 μž‘μ—…μ„ κ°„λ‹¨ν•˜κ²Œ λ§Œλ“€κ³ , μ‹€μ œ SQL 싀행은 JPA κ΅¬ν˜„μ²΄(예: Hibernate)κ°€ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
  4. Database (H2 / MySQL)
    • 개발 ν™˜κ²½μ—μ„œλŠ” H2, μš΄μ˜μ—μ„œλŠ” MySQL처럼 ν™˜κ²½μ— 따라 DBλ₯Ό 달리 두고, JPAλ₯Ό 톡해 같은 도메인 λͺ¨λΈ/리포지토리 ꡬ쑰둜 μ ‘κ·Όν•˜λŠ” ν˜•νƒœκ°€ ν”ν•©λ‹ˆλ‹€. (그만큼 계측 뢄리가 DB ꡐ체에도 μœ λ¦¬ν•©λ‹ˆλ‹€.)

 

이 ꡬ쑰의 μ˜λ„

  • 관심사 뢄리: λ³΄μ•ˆ, μš”μ²­ 처리, λΉ„μ¦ˆλ‹ˆμŠ€ 둜직, DB 접근을 λΆ„λ¦¬ν•΄μ„œ λ³€κ²½ 영ν–₯ λ²”μœ„λ₯Ό μ€„μž…λ‹ˆλ‹€.
  • μœ μ§€λ³΄μˆ˜/ν…ŒμŠ€νŠΈ 용이: μ»¨νŠΈλ‘€λŸ¬λŠ” μž…μΆœλ ₯, μ„œλΉ„μŠ€λŠ” κ·œμΉ™, λ¦¬ν¬μ§€ν† λ¦¬λŠ” 데이터 μ ‘κ·ΌμœΌλ‘œ 역할이 λͺ…ν™•ν•΄μ§‘λ‹ˆλ‹€.
  • λ³΄μ•ˆμ€ 곡톡 κ΄€λ¬Έ: λͺ¨λ“  μš”μ²­μ΄ 컨트둀러 전에 λ³΄μ•ˆ 검증을 κ±°μΉ˜λ„λ‘ κ°•μ œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

 

2.2 ν”„λ‘œμ νŠΈ 디렉토리 ꡬ쑰

Booktine/
β”œβ”€β”€ frontend/                          # React ν”„λ‘ νŠΈμ—”λ“œ
β”‚   └── src/
β”‚       β”œβ”€β”€ components/                # μž¬μ‚¬μš© κ°€λŠ₯ν•œ UI μ»΄ν¬λ„ŒνŠΈ
β”‚       β”‚   β”œβ”€β”€ AuthModal.tsx          # 둜그인/νšŒμ›κ°€μž… λͺ¨λ‹¬
β”‚       β”‚   β”œβ”€β”€ Header.tsx             # 상단 λ„€λΉ„κ²Œμ΄μ…˜
β”‚       β”‚   β”œβ”€β”€ Footer.tsx             # ν•˜λ‹¨ ν‘Έν„°
β”‚       β”‚   β”œβ”€β”€ MonthlyBarChart.tsx    # 월별 λ…μ„œλŸ‰ λ§‰λŒ€ 차트
β”‚       β”‚   β”œβ”€β”€ AnnualLineChart.tsx    # μ—°κ°„ λ…μ„œλŸ‰ 라인 차트
β”‚       β”‚   β”œβ”€β”€ GenreDoughnutChart.tsx # μž₯λ₯΄λ³„ 도넛 차트
β”‚       β”‚   └── HomeGenreDoughnutChart.tsx
β”‚       β”œβ”€β”€ pages/                     # νŽ˜μ΄μ§€ μ»΄ν¬λ„ŒνŠΈ
β”‚       β”‚   β”œβ”€β”€ MainPage.tsx           # λžœλ”© νŽ˜μ΄μ§€
β”‚       β”‚   β”œβ”€β”€ HomePage.tsx           # λŒ€μ‹œλ³΄λ“œ ν™ˆ
β”‚       β”‚   β”œβ”€β”€ BookNote.tsx           # λ…μ„œ λ…ΈνŠΈ λͺ©λ‘
β”‚       β”‚   β”œβ”€β”€ CreatePostPage.tsx     # λ…ΈνŠΈ μž‘μ„±/μˆ˜μ •
β”‚       β”‚   β”œβ”€β”€ PostDetailPage.tsx     # λ…ΈνŠΈ 상세 보기
β”‚       β”‚   β”œβ”€β”€ ProgressPage.tsx       # 톡계/μ§„ν–‰ 상황
β”‚       β”‚   └── SettingsPage.tsx       # μ„€μ •/ν”„λ‘œν•„
β”‚       β”œβ”€β”€ services/
β”‚       β”‚   └── AuthService.ts         # 인증 API 호좜
β”‚       β”œβ”€β”€ lib/
β”‚       β”‚   └── api.ts                 # Axios μΈμŠ€ν„΄μŠ€
β”‚       └── styles/
β”‚           └── main.css               # μ „μ—­ μŠ€νƒ€μΌ
β”‚
└── src/main/java/booktine/Booktine/   # Spring Boot λ°±μ—”λ“œ
    β”œβ”€β”€ config/
    β”‚   └── SecurityConfig.java        # Spring Security μ„€μ •
    β”œβ”€β”€ controller/
    β”‚   β”œβ”€β”€ AuthController.java        # 인증 API
    β”‚   β”œβ”€β”€ PostController.java        # κ²Œμ‹œκΈ€ CRUD API
    β”‚   β”œβ”€β”€ ProgressController.java    # 톡계 API
    β”‚   β”œβ”€β”€ RecommendationController.java # λ„μ„œ μΆ”μ²œ API
    β”‚   β”œβ”€β”€ SettingsController.java    # μ„€μ • API
    β”‚   └── UploadController.java      # 파일 μ—…λ‘œλ“œ API
    β”œβ”€β”€ controller/dto/
    β”‚   β”œβ”€β”€ ProgressResponse.java
    β”‚   β”œβ”€β”€ MonthlyData.java
    β”‚   β”œβ”€β”€ GenreData.java
    β”‚   └── RecommendedBook.java
    β”œβ”€β”€ model/                         # JPA μ—”ν‹°ν‹°
    β”‚   β”œβ”€β”€ User.java                  # μ‚¬μš©μž
    β”‚   β”œβ”€β”€ Post.java                  # λ…μ„œ λ…ΈνŠΈ
    β”‚   β”œβ”€β”€ Memo.java                  # λ©”λͺ¨ (Embeddable)
    β”‚   └── Author.java                # μž‘μ„±μž 정보 (Embeddable)
    β”œβ”€β”€ repository/
    β”‚   β”œβ”€β”€ UserRepository.java
    β”‚   └── PostRepository.java
    └── service/
        β”œβ”€β”€ UserService.java           # μ‚¬μš©μž λΉ„μ¦ˆλ‹ˆμŠ€ 둜직
        β”œβ”€β”€ PostService.java           # κ²Œμ‹œκΈ€ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직
        β”œβ”€β”€ ProgressService.java       # 톡계 계산 둜직
        └── RecommendationService.java # μ•ŒλΌλ”˜ API 연동
728x90