κΈμ¬ κ΄λ¦¬ νλ«νΌ λ°±μλ API μλ²
| λΆλ₯ | κΈ°μ |
|---|---|
| Framework | Spring Boot 3.5.7 |
| Language | Java 21 |
| Database | MySQL 8.0 |
| ORM | Spring Data JPA / Hibernate |
| Security | Spring Security + JWT (jjwt 0.12.6) |
| API Docs | springdoc-openapi 2.7.0 |
| Build | Gradle 8.x |
| Test | JUnit 5 + JaCoCo |
| Cache | Spring Cache |
DDD(Domain-Driven Design) μ€νμΌμ ν¨ν€μ§ ꡬ쑰λ₯Ό μ±ννμ¬ λΉμ¦λμ€ λλ©μΈ μ€μ¬μΌλ‘ μ½λλ₯Ό μ‘°μ§νμ΅λλ€.
com.example.paycheck/
βββ api/ # Presentation Layer
β βββ auth/ # μΈμ¦ (λ‘κ·ΈμΈ, ν ν° κ°±μ )
β βββ employer/ # κ³ μ©μ£Ό μ μ© API
β β βββ contract/ # κ³μ½ κ΄λ¦¬
β β βββ correctionrequest/ # μ μ μμ² μ²λ¦¬
β β βββ salary/ # κΈμ¬ κ΄λ¦¬
β β βββ worker/ # κ·Όλ‘μ κ΄λ¦¬
β β βββ workrecord/ # 근무 κΈ°λ‘
β β βββ workplace/ # μ¬μ
μ₯ κ΄λ¦¬
β βββ worker/ # κ·Όλ‘μ μ μ© API
β
βββ domain/ # Domain Layer
β βββ user/ # μ¬μ©μ λλ©μΈ
β βββ employer/ # κ³ μ©μ£Ό λλ©μΈ
β βββ worker/ # κ·Όλ‘μ λλ©μΈ
β βββ workplace/ # μ¬μ
μ₯ λλ©μΈ
β βββ contract/ # κ³μ½ λλ©μΈ
β βββ workrecord/ # 근무 κΈ°λ‘ λλ©μΈ
β β βββ entity/
β β βββ dto/
β β βββ repository/
β β βββ service/ # CQRS ν¨ν΄ μ μ©
β β β βββ WorkRecordCommandService
β β β βββ WorkRecordQueryService
β β β βββ WorkRecordCoordinatorService
β β β βββ WorkRecordGenerationService
β β βββ enums/
β βββ allowance/ # μ£Όκ° μλΉ λλ©μΈ
β βββ salary/ # κΈμ¬ λλ©μΈ
β βββ correction/ # μ μ μμ² λλ©μΈ
β βββ payment/ # κ²°μ λλ©μΈ
β βββ notification/ # μλ¦Ό λλ©μΈ
β βββ holiday/ # 곡ν΄μΌ λλ©μΈ
β
βββ common/ # κ³΅ν΅ μ νΈλ¦¬ν°
β βββ dto/ # ApiResponse λνΌ
β βββ exception/ # μ μ μμΈ μ²λ¦¬
β
βββ global/ # ν‘λ¨ κ΄μ¬μ¬
βββ config/ # Spring μ€μ
βββ security/ # μΈμ¦/μΈκ°
β βββ jwt/ # JWT ν ν° μ²λ¦¬
β βββ permission/ # 리μμ€ κΆν κ²μ¦
βββ oauth/kakao/ # μΉ΄μΉ΄μ€ OAuth
WorkRecord λλ©μΈμμ λͺ λ Ήκ³Ό μ‘°νμ μ± μμ λΆλ¦¬νμ΅λλ€.
WorkRecordCommandService β μμ±, μμ , μμ (μν λ³κ²½)
WorkRecordQueryService β μ‘°ν (μ½κΈ° μ μ©)
WorkRecordCoordinatorService β λλ©μΈ κ° νλ ₯ μ‘°μ¨
WorkRecordGenerationService β μΌμ κΈ°λ° μΌκ΄ μμ±
μ μ© μ΄μ :
- 근무 κΈ°λ‘μ μ‘°νκ° λΉλ²νκ³ λͺ λ Ήμ μλμ μΌλ‘ μ μ
- κΈμ¬ κ³μ°, μ£Όκ° μλΉ μ§κ³ λ± λͺ λ Ή μ 볡μ‘ν λΆμ ν¨κ³Ό λ°μ
- μλΉμ€ μ± μ λΆλ¦¬λ‘ ν μ€νΈ μ©μ΄μ± ν₯μ
κ° λ¦¬μμ€λ³ Permission ν΄λμ€κ° μμ κΆ κ²μ¦ λ‘μ§μ λ΄λΉν©λλ€.
@PreAuthorize("@workplacePermission.canAccess(#workplaceId)")
public WorkplaceResponse getWorkplace(Long workplaceId) { ... }κ²μ¦ νλͺ©:
- κ³ μ©μ£Όκ° ν΄λΉ μ¬μ μ₯μ μμ μμΈμ§
- κ·Όλ‘μκ° ν΄λΉ κ³μ½μ λΉμ¬μμΈμ§
- μμ²μκ° ν΄λΉ 리μμ€μ μ κ·Ό κΆνμ΄ μλμ§
λ°μ΄ν° 무결μ±κ³Ό μ΄λ ₯ κ΄λ¦¬λ₯Ό μν΄ λ Όλ¦¬μ μμ λ₯Ό μ μ©νμ΅λλ€.
// WorkRecord
enum WorkRecordStatus { SCHEDULED, COMPLETED, DELETED }
// Workplace
boolean isActive;User (EMPLOYER/WORKER)
β
βββ Employer βββββββββββ¬ββ Workplace
β β β
βββ Worker βββββββββββββ΄ββ WorkerContract
β
βββββββββββββββΌββββββββββββββ
β β β
WorkRecord WeeklyAllowance Salary
β β
CorrectionRequest Payment
| λλ©μΈ | μ€λͺ | ν΅μ¬ λ‘μ§ |
|---|---|---|
| WorkRecord | 근무 μΌμ /κΈ°λ‘ | μν κ΄λ¦¬, λΉμΌ κΈμ¬ κ³μ° |
| WeeklyAllowance | μ£Όκ° μλΉ | μ£Όν΄μλΉ, μ£Ό 40μκ° μ΄κ³Ό μ°μ₯μλΉ |
| Salary | μλ³ κΈμ¬ | μλΉ μ§κ³, 곡μ κ³μ°, μ€μλ Ήμ‘ |
| CorrectionRequest | μ μ μμ² | CREATE/UPDATE/DELETE μν¬νλ‘μ° |
| Payment | κ²°μ | ν μ€ λ₯λ§ν¬, μλ μ€ν¨ μ²λ¦¬ |
PayCheckμ ν΅μ¬ κΈ°λ₯μΈ κΈμ¬ μλ κ³μ°μ νκ΅ λ Έλλ²μ μ² μ ν μ€μν©λλ€.
| κ΅¬λΆ | 5μΈ λ―Έλ§ | 5μΈ μ΄μ |
|---|---|---|
| κΈ°λ³ΈκΈ | O | O |
| μ£Όν΄μλΉ | O | O |
| μΌκ°μλΉ (22:00~06:00) | X | O (50%) |
| ν΄μΌμλΉ (μ£Όλ§/곡ν΄μΌ) | X | O (50%) |
| μ°μ₯μλΉ (8μκ°/40μκ° μ΄κ³Ό) | X | O (50%) |
ν΄μΌ μΌκ° μ°μ₯ 근무 μ κ°μ°μ¨ μ€μ²© μ μ©:
νμΌ μΌκ° 8μκ° μ΄κ³Ό = κΈ°λ³ΈκΈ Γ 2.0 (μΌκ° 50% + μ°μ₯ 50%)
ν΄μΌ μΌκ° 8μκ° μ΄κ³Ό = κΈ°λ³ΈκΈ Γ 2.5 (ν΄μΌ 50% + μΌκ° 50% + μ°μ₯ 50%)
μ£Όν΄μλΉκ³Ό μ°μ₯μλΉμ μ£Ό λ¨μλ‘ κ³μ°λλ―λ‘, μκΈλ μ΄ ν¬ν¨λ μ£Όμ μλΉμ λ€μ λ¬λ‘ μ΄μλ©λλ€.
μκΈλ : 1μ 15μΌ (μμμΌ)
[1/8~1/14 μ£Ό] β 1μ κΈμ¬μ ν¬ν¨
[1/15~1/21 μ£Ό] β μκΈλ ν¬ν¨ β 2μ κΈμ¬λ‘ μ΄μ
μμΈ κ³μ° λ‘μ§: SALARY_CALCULATION_POLICY.md
κ²°μ : Access Token + Refresh Token μ΄μ€ ν ν° κ΅¬μ‘°
Access Token : 15λΆ (μ§§μ μ ν¨κΈ°κ°, μλͺ
λ§ κ²μ¦)
Refresh Token : 7μΌ (κΈ΄ μ ν¨κΈ°κ°, DB μ μ₯)
μ΄μ :
- Access Token νμ·¨ μ νΌν΄ μ΅μν
- Refresh TokenμΌλ‘ UX μ ν μμ΄ ν ν° κ°±μ
- Refresh Token νμ μΌλ‘ 보μ κ°ν
κ²°μ : λ¨μΌ μν°ν° + μν Enum
enum WorkRecordStatus {
SCHEDULED, // μμ (κΈμ¬ κ³μ° X)
COMPLETED, // μλ£ (κΈμ¬ κ³μ° O)
DELETED // μμ (μννΈ μμ )
}λμ κ²ν :
- WorkSchedule + WorkRecord λΆλ¦¬ β μ‘°μΈ λ³΅μ‘λ μ¦κ°
- 물리μ μμ β μ΄λ ₯ μΆμ λΆκ°
μ ν μ΄μ :
- λ¨μΌ ν μ΄λΈλ‘ 쿼리 λ¨μν
- μν κΈ°λ° κΈμ¬ κ³μ° ν¬ν¨/μ μΈ λͺ ν
- μμ μ΄λ ₯ μ μ§λ‘ κ°μ¬ μΆμ κ°λ₯
κ²°μ : λ¨μΌ CorrectionRequest μν°ν°μ type νλ μΆκ°
enum CorrectionRequestType {
CREATE, // 근무 κΈ°λ‘ μμ± μμ²
UPDATE, // 근무 μκ° μμ μμ²
DELETE // 근무 κΈ°λ‘ μμ μμ²
}μ΄μ :
- μΈ κ°μ§ μμ² λͺ¨λ μΉμΈ/λ°λ € μν¬νλ‘μ°κ° λμΌ
- μν°ν° λΆλ¦¬ μ μ€λ³΅ μ½λ λ°μ
- ν΅ν© κ΄λ¦¬λ‘ μλ¦Ό/μ΄λ ₯ μ²λ¦¬ μΌμν
μ±κ³΅ μλ΅:
{
"success": true,
"data": { ... }
}μλ¬ μλ΅:
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "ν΄λΉ 리μμ€λ₯Ό μ°Ύμ μ μμ΅λλ€."
}
}| κΈ°λ₯ | Method | Endpoint |
|---|---|---|
| μΉ΄μΉ΄μ€ λ‘κ·ΈμΈ | POST | /api/auth/kakao/login |
| μ¬μ μ₯ λ±λ‘ | POST | /api/employer/workplaces |
| κ·Όλ‘μ μΆκ° | POST | /api/employer/workplaces/{id}/workers |
| 근무 μΌμ λ±λ‘ | POST | /api/employer/work-records |
| 근무 μλ£ μ²λ¦¬ | PUT | /api/employer/work-records/{id}/complete |
| κΈμ¬ κ³μ° | POST | /api/employer/salaries/calculate |
| μ μ μμ² μΉμΈ | PUT | /api/employer/correction-requests/{id}/approve |
| SSE μλ¦Ό ꡬλ | GET | /api/notifications/stream |
μ 체 API λͺ μΈ: API_SPECIFICATION.md
- Java 21+
- Gradle 8.x
- MySQL 8.0+
# μ μ₯μ ν΄λ‘
git clone https://github.com/your-repo/PayCheck-backend.git
cd PayCheck-backend
# νκ²½ μ€μ (application.yml λλ application-local.yml)
# MySQL μ°κ²° μ 보 μ€μ νμ
# λΉλ
./gradlew clean build
# μ€ν
./gradlew bootRun# μ 체 ν
μ€νΈ
./gradlew test
# νΉμ ν
μ€νΈ ν΄λμ€
./gradlew test --tests WorkRecordCommandServiceTest
# 컀λ²λ¦¬μ§ 리ν¬νΈ
./gradlew jacocoTestReport
# κ²°κ³Ό: build/reports/jacoco/test/html/index.htmlμλ² μ€ν ν Swagger UI μ μ:
http://localhost:8080/swagger-ui.html
| λ¬Έμ | μ€λͺ |
|---|---|
| API λͺ μΈμ | REST API μμΈ λͺ μΈ λ° JSON μμ |
| ERD | μν°ν° κ΄κ³λ λ° ν μ΄λΈ μ€κ³ |
| κΈμ¬ κ³μ° μ μ± | κΈμ¬ κ³μ° λ‘μ§ μμΈ λ¬Έμ |
| μ μ νλ‘μ° | μ¬μ©μ μλλ¦¬μ€ |
<type>(<scope>): <subject>
# Types
feat : μλ‘μ΄ κΈ°λ₯
fix : λ²κ·Έ μμ
refactor : 리ν©ν λ§
test : ν
μ€νΈ μΆκ°/μμ
docs : λ¬Έμ λ³κ²½
chore : λΉλ, μ€μ λ³κ²½
# Scopes
auth, salary, workrecord, contract, user, api, db, config
# Example
feat(workrecord): add batch creation for work schedules
fix(salary): correct weekly allowance calculation for edge cases
MIT License