Skip to content

thdud7/WageManager-backend

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

270 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PayCheck Backend

κΈ‰μ—¬ 관리 ν”Œλž«νΌ λ°±μ—”λ“œ API μ„œλ²„

Java Spring Boot Test Coverage


기술 μŠ€νƒ

λΆ„λ₯˜ 기술
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

핡심 섀계 원칙

1. CQRS νŒ¨ν„΄ (Command Query Responsibility Segregation)

WorkRecord λ„λ©”μΈμ—μ„œ λͺ…λ Ήκ³Ό 쑰회의 μ±…μž„μ„ λΆ„λ¦¬ν–ˆμŠ΅λ‹ˆλ‹€.

WorkRecordCommandService     β†’ 생성, μˆ˜μ •, μ‚­μ œ (μƒνƒœ λ³€κ²½)
WorkRecordQueryService       β†’ 쑰회 (읽기 μ „μš©)
WorkRecordCoordinatorService β†’ 도메인 κ°„ ν˜‘λ ₯ 쑰율
WorkRecordGenerationService  β†’ 일정 기반 일괄 생성

적용 이유:

  • 근무 기둝은 μ‘°νšŒκ°€ λΉˆλ²ˆν•˜κ³  λͺ…령은 μƒλŒ€μ μœΌλ‘œ 적음
  • κΈ‰μ—¬ 계산, μ£Όκ°„ μˆ˜λ‹Ή 집계 λ“± λͺ…λ Ή μ‹œ λ³΅μž‘ν•œ λΆ€μˆ˜ 효과 λ°œμƒ
  • μ„œλΉ„μŠ€ μ±…μž„ λΆ„λ¦¬λ‘œ ν…ŒμŠ€νŠΈ μš©μ΄μ„± ν–₯상

2. Permission 기반 μ ‘κ·Ό μ œμ–΄

각 λ¦¬μ†ŒμŠ€λ³„ Permission ν΄λž˜μŠ€κ°€ μ†Œμœ κΆŒ 검증 λ‘œμ§μ„ λ‹΄λ‹Ήν•©λ‹ˆλ‹€.

@PreAuthorize("@workplacePermission.canAccess(#workplaceId)")
public WorkplaceResponse getWorkplace(Long workplaceId) { ... }

검증 ν•­λͺ©:

  • κ³ μš©μ£Όκ°€ ν•΄λ‹Ή 사업μž₯의 μ†Œμœ μžμΈμ§€
  • κ·Όλ‘œμžκ°€ ν•΄λ‹Ή κ³„μ•½μ˜ λ‹Ήμ‚¬μžμΈμ§€
  • μš”μ²­μžκ°€ ν•΄λ‹Ή λ¦¬μ†ŒμŠ€μ— μ ‘κ·Ό κΆŒν•œμ΄ μžˆλŠ”μ§€

3. Soft Delete νŒ¨ν„΄

데이터 무결성과 이λ ₯ 관리λ₯Ό μœ„ν•΄ 논리적 μ‚­μ œλ₯Ό μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.

// 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인 미만 사업μž₯ vs 5인 이상 사업μž₯

ꡬ뢄 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


기술적 μ˜μ‚¬κ²°μ •

1. JWT 토큰 μ „λž΅

κ²°μ •: Access Token + Refresh Token 이쀑 토큰 ꡬ쑰

Access Token  : 15λΆ„ (짧은 μœ νš¨κΈ°κ°„, μ„œλͺ…λ§Œ 검증)
Refresh Token : 7일 (κΈ΄ μœ νš¨κΈ°κ°„, DB μ €μž₯)

이유:

  • Access Token νƒˆμ·¨ μ‹œ ν”Όν•΄ μ΅œμ†Œν™”
  • Refresh Token으둜 UX μ €ν•˜ 없이 토큰 κ°±μ‹ 
  • Refresh Token νšŒμ „μœΌλ‘œ λ³΄μ•ˆ κ°•ν™”

2. 근무 기둝 μƒνƒœ 섀계

κ²°μ •: 단일 μ—”ν‹°ν‹° + μƒνƒœ Enum

enum WorkRecordStatus {
    SCHEDULED,  // μ˜ˆμ • (κΈ‰μ—¬ 계산 X)
    COMPLETED,  // μ™„λ£Œ (κΈ‰μ—¬ 계산 O)
    DELETED     // μ‚­μ œ (μ†Œν”„νŠΈ μ‚­μ œ)
}

λŒ€μ•ˆ κ²€ν† :

  • WorkSchedule + WorkRecord 뢄리 β†’ 쑰인 λ³΅μž‘λ„ 증가
  • 물리적 μ‚­μ œ β†’ 이λ ₯ 좔적 λΆˆκ°€

선택 이유:

  • 단일 ν…Œμ΄λΈ”λ‘œ 쿼리 λ‹¨μˆœν™”
  • μƒνƒœ 기반 κΈ‰μ—¬ 계산 포함/μ œμ™Έ λͺ…ν™•
  • μ‚­μ œ 이λ ₯ μœ μ§€λ‘œ 감사 좔적 κ°€λŠ₯

3. μ •μ • μš”μ²­ νƒ€μž… 톡합

κ²°μ •: 단일 CorrectionRequest 엔티티에 type ν•„λ“œ μΆ”κ°€

enum CorrectionRequestType {
    CREATE,  // 근무 기둝 생성 μš”μ²­
    UPDATE,  // 근무 μ‹œκ°„ μˆ˜μ • μš”μ²­
    DELETE   // 근무 기둝 μ‚­μ œ μš”μ²­
}

이유:

  • μ„Έ κ°€μ§€ μš”μ²­ λͺ¨λ‘ 승인/반렀 μ›Œν¬ν”Œλ‘œμš°κ°€ 동일
  • μ—”ν‹°ν‹° 뢄리 μ‹œ 쀑볡 μ½”λ“œ λ°œμƒ
  • 톡합 κ΄€λ¦¬λ‘œ μ•Œλ¦Ό/이λ ₯ 처리 일원화

API ꡬ쑰

응닡 ν˜•μ‹

성곡 응닡:

{
  "success": true,
  "data": { ... }
}

μ—λŸ¬ 응닡:

{
  "success": false,
  "error": {
    "code": "NOT_FOUND",
    "message": "ν•΄λ‹Ή λ¦¬μ†ŒμŠ€λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."
  }
}

μ£Όμš” API μ—”λ“œν¬μΈνŠΈ

κΈ°λŠ₯ 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

API λ¬Έμ„œ

μ„œλ²„ μ‹€ν–‰ ν›„ 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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages