-
Notifications
You must be signed in to change notification settings - Fork 0
Worker Flow
l2juhan edited this page Apr 18, 2026
·
3 revisions
근로자가 사용하는 주요 기능의 플로우를 설명합니다.
| 항목 | 내용 |
|---|---|
| 대상 사용자 | userType: "WORKER" |
| 진입점 | WorkerWeeklyCalendarScreen (홈 화면) |
| 주요 기능 | 주간 근무 조회, 월간 캘린더, 근무 추가/정정 요청, 급여명세서 조회 |
| API 모듈 |
src/api/worker/ (도메인별 분리) |
┌─────────────────────────────────────────────────────────────────┐
│ 주간 캘린더 화면 구조 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────┐ │
│ │ Header │ │
│ ├───────────────────────────────────────────┤ │
│ │ WeeklyDateBar │ │
│ │ "2월 3주차 근무" │ │
│ │ [Mon] [Tue] [Wed] [Thu] [Fri] [Sat] [Sun]│ │
│ ├───────────────────────────────────────────┤ │
│ │ NoticeBoard (공지사항 카드 목록) │ │
│ ├───────────────────────────────────────────┤ │
│ │ WorkListSection │ │
│ │ "이번 주 근무 리스트" [+ 근무 추가] │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ WorkCard (접기/펼치기) │ │ │
│ │ │ [로고] 근무지명 09:00~15:00 뱃지 │ │ │
│ │ │ (펼침 시: 근무지, 휴게시간, │ │ │
│ │ │ 시급, 총급여, 정정요청 버튼) │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ │ ┌─────────────────────────────────────┐ │ │
│ │ │ WorkCard ... │ │ │
│ │ └─────────────────────────────────────┘ │ │
│ ├───────────────────────────────────────────┤ │
│ │ WeeklySummary │ │
│ │ "이번주(3주차) 총 근무시간" 12시간 │ │
│ │ "이번 주 예상 근무비" 120,000원 │ │
│ └───────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 주간 근무 조회 플로우 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [화면 진입] │
│ │ │
│ ▼ │
│ baseDate(현재 날짜) 기준으로 주간 범위 계산 │
│ getWeekRange(baseDate) → { startDate, endDate } │
│ (예: 2026-02-16 ~ 2026-02-22) │
│ │ │
│ ▼ │
│ useWorkRecords(startDate, endDate) │
│ │ │
│ ▼ │
│ GET /api/worker/work-records?startDate=...&endDate=... │
│ │ │
│ ├─→ 성공 → WorkItem[] 저장 │
│ │ │ │
│ │ ├─→ WorkListSection에 카드 렌더링 │
│ │ │ │
│ │ └─→ WeeklySummary 계산 │
│ │ totalHours = Σ totalWorkMinutes / 60 │
│ │ estimatedPay = Σ totalSalary │
│ │ │
│ └─→ 실패 → 빈 배열 표시 │
│ │
└─────────────────────────────────────────────────────────────────┘
엔드포인트: GET /api/worker/work-records
Query Parameters:
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
| startDate | string | ✅ | 조회 시작일 (yyyy-MM-dd) |
| endDate | string | ✅ | 조회 종료일 (yyyy-MM-dd) |
Response Body (성공 시):
{
"success": true,
"data": [
{
"id": 10,
"contractId": 1,
"workerName": "이주한",
"workerCode": "NZU623",
"workplaceName": "밥은화",
"workDate": "2026-02-16",
"startTime": "09:00:00",
"endTime": "15:00:00",
"breakMinutes": 0,
"totalWorkMinutes": 360,
"status": "SCHEDULED",
"isModified": false,
"memo": null
}
],
"error": null
}interface WorkItem {
id: number;
contractId: number;
workerName: string;
workerCode: string;
workplaceName: string;
workDate: string; // "2026-02-16"
startTime: string; // "09:00:00"
endTime: string; // "15:00:00"
breakMinutes: number | null;
totalWorkMinutes: number;
status: "SCHEDULED" | "COMPLETED" | "DELETED";
isModified: boolean;
memo: string | null;
baseSalary: number | null;
nightSalary: number | null;
holidaySalary: number | null;
totalSalary: number | null;
}주간 캘린더의 "이번 주 근무 리스트"는 다음 우선순위로 정렬된다.
| 우선순위 | 상태 | 2차 정렬 |
|---|---|---|
| 1 |
근무중 (현재 시각이 startTime~endTime 사이) |
startTime 오름차순 |
| 2 |
근무예정 (SCHEDULED, 시작 전) |
startTime 오름차순 |
| 3 |
근무완료 (COMPLETED 또는 종료 시각 경과) |
startTime 오름차순 |
이전에는
startTime역순으로만 정렬되어 현재 진행 중인 근무를 찾기 어려웠다.
구현: src/components/worker/weeklyCalendar/WorkListSection.tsx
근로자가 새로운 근무를 추가 요청하는 과정입니다. 사장님의 승인이 필요합니다.
┌─────────────────────────────────────────────────────────────────┐
│ 근무 추가 요청 플로우 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [+ 근무 추가] 버튼 클릭 │
│ │ │
│ ▼ │
│ AddWorkRequestModal 표시 (BottomSheetModal) │
│ │ │
│ ▼ │
│ useWorkplaces → 활성 근무지 목록 로드 │
│ (계약 목록 → 상세 조회 → 근무지명/시급 가공) │
│ │ │
│ ▼ │
│ 사용자가 WheelPicker로 항목 선택: │
│ │ │
│ │ • 근무지 선택 (활성 계약 기반) │
│ │ • 근무일 선택 (해당 월의 일자) │
│ │ • 시작 시간 (시:분) │
│ │ • 종료 시간 (시:분) │
│ │ • 휴게 시간 (0~60분, 10분 단위) │
│ │ │
│ ▼ │
│ [요청하기] 버튼 클릭 │
│ │ │
│ ▼ │
│ POST /api/worker/correction-requests │
│ { type: "CREATE", contractId, requestedWorkDate, ... } │
│ │ │
│ ├─→ 성공 → 모달 닫기 + "요청 완료" Alert │
│ │ │
│ └─→ 실패 → "요청 실패" Alert (에러 메시지 표시) │
│ │
└─────────────────────────────────────────────────────────────────┘
근로자가 기존 근무 기록의 수정을 요청하는 과정입니다. 사장님의 승인이 필요합니다.
┌─────────────────────────────────────────────────────────────────┐
│ 근무 기록 정정 요청 플로우 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ WorkCard 펼침 → [근무기록 정정요청] 버튼 클릭 │
│ │ │
│ ▼ │
│ WorkerCorrectionRequestModal 표시 (BottomSheetModal) │
│ │ │
│ ▼ │
│ 기존 근무 데이터로 폼 초기화 (useCorrectionForm) │
│ │ │
│ │ 기존 값 → 정정 값 │
│ │ ────────── ────────── │
│ │ 시작일 시작일 (WheelPicker) │
│ │ 시작시간 시작시간 (시:분) │
│ │ 종료일 종료일 (WheelPicker) │
│ │ 종료시간 종료시간 (시:분) │
│ │ 휴게시간 휴게시간 (0~60분) │
│ │ │
│ ▼ │
│ 변경 사항 감지 (hasChanges) │
│ │ │
│ ├─→ 변경 없음 → [정정 요청하기] 버튼 비활성화 │
│ │ │
│ └─→ 변경 있음 → [정정 요청하기] 버튼 활성화 │
│ │ │
│ ▼ │
│ [정정 요청하기] 버튼 클릭 │
│ │ │
│ ▼ │
│ POST /api/worker/correction-requests │
│ { type: "UPDATE", workRecordId, requestedWorkDate, ... }│
│ │ │
│ ├─→ 성공 → 모달 닫기 + "요청 완료" Alert │
│ │ │
│ └─→ 실패 → "요청 실패" Alert (에러 메시지 표시) │
│ │
└─────────────────────────────────────────────────────────────────┘
엔드포인트: POST /api/worker/correction-requests
Request Body:
{
"type": "CREATE",
"contractId": 1,
"requestedWorkDate": "2026-02-18",
"requestedStartTime": "09:00",
"requestedEndTime": "15:00",
"requestedBreakMinutes": 30,
"requestedMemo": ""
}Request Body:
{
"type": "UPDATE",
"workRecordId": 10,
"requestedWorkDate": "2026-02-18",
"requestedStartTime": "10:00",
"requestedEndTime": "16:00",
"requestedBreakMinutes": 30,
"requestedMemo": ""
}Request Body:
{
"type": "DELETE",
"workRecordId": 10,
"requestedWorkDate": "2026-02-18",
"requestedStartTime": "09:00",
"requestedEndTime": "15:00"
}Response Body (공통):
{
"success": true,
"data": {
"id": 1,
"type": "UPDATE",
"workRecordId": 10,
"contractId": null,
"originalWorkDate": "2026-02-18",
"originalStartTime": "09:00:00",
"originalEndTime": "15:00:00",
"requestedWorkDate": "2026-02-18",
"requestedStartTime": "10:00",
"requestedEndTime": "16:00",
"requestedBreakMinutes": 30,
"requestedMemo": null,
"status": "PENDING",
"requester": { "id": 1, "name": "이주한" },
"reviewedAt": null,
"createdAt": "2026-02-18T12:00:00"
},
"error": null
}주간 캘린더와 월간 캘린더에서 공통으로 사용하는 훅 구조입니다.
┌─────────────────────────────────────────────────────────────────┐
│ 훅 재사용 구조 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [Screen Level] (주간캘린더 / 월간캘린더) │
│ │ │
│ ├─→ useWorkRecords(startDate, endDate) │
│ │ → 기간별 근무 기록 조회 (API 호출 + 상태 관리) │
│ │ → { works, isLoading, refetch } │
│ │ │
│ └─→ useCorrectionRequest() │
│ → 모달 열기/닫기 상태 + API 호출 │
│ → { correctionModalVisible, addModalVisible, │
│ openCorrectionModal, handleCorrectionSubmit, │
│ openAddModal, handleAddWorkSubmit, ... } │
│ │
│ [Modal Level] │
│ │ │
│ ├─→ useCorrectionForm(work, visible) │
│ │ → 정정 요청 모달 전용 폼 상태 + WheelPicker 연동 │
│ │ → WorkerCorrectionRequestModal에서 사용 │
│ │ │
│ ├─→ useWorkRequestForm(workplacePickerItems) │
│ │ → 근무 추가 모달 전용 폼 상태 + WheelPicker 연동 │
│ │ → AddWorkRequestModal에서 사용 │
│ │ │
│ └─→ useWorkplaces() │
│ → 활성 근무지 목록 조회 + WheelPicker 아이템 변환 │
│ → AddWorkRequestModal에서 사용 │
│ │
└─────────────────────────────────────────────────────────────────┘
| 컴포넌트 | 위치 | 설명 |
|---|---|---|
| BottomSheetModal | components/common/ |
하단 슬라이드업 모달 (overlay + slide-up 애니메이션, Keyboard 리스너 기반 키보드 회피, 스와이프 닫기) |
| WheelPicker | components/common/ |
iOS 스타일 드럼 롤 피커 (Animated.FlatList 기반) |
| WorkCard | components/worker/weeklyCalendar/ |
근무 카드 (접기/펼치기, 상태 뱃지, 상세 정보) |
| WorkListSection | components/worker/weeklyCalendar/ |
근무 리스트 헤더 + 카드 목록 |
| WeeklySummary | components/worker/weeklyCalendar/ |
주간 총 근무시간 및 예상 근무비 |
| 화면 | 설명 | 관련 Issue |
|---|---|---|
| WorkerWeeklyCalendarScreen | 주간 캘린더 (근무 리스트, 요약, 공지) | #6 |
| AddWorkRequestModal | 근무 추가 요청 모달 | #6 |
| WorkerCorrectionRequestModal | 근무 기록 정정 요청 모달 | #6 |
백엔드가 GET /api/worker/contracts 리스트 응답에 상세 정보를 포함하도록 확장되어, N+1 API 호출을 제거했다.
| 필드 | 타입 | 비고 |
|---|---|---|
workplaceId |
number | 신규 추가 |
workplaceName |
string | 신규 필수 필드 |
paymentDay |
number | 매월 급여지급일 (1~31) |
payrollDeductionType |
string | 4대보험/소득세 공제 방식 |
hourlyWage |
number | 시급 |
status |
string | 활성/비활성 |
N+1 제거 효과:
| 시점 | API 호출 횟수 |
|---|---|
| 이전 (계약 N개) |
getContracts() 1회 + getContractDetail() N회 = 1+N회
|
| 이후 |
getContracts() 1회로 완료 |
영향받은 훅:
-
useWorkplaces—getContractDetail()호출 제거, 리스트 응답에서 직접 매핑 -
useSalaryStatement—getContractDetail()호출 제거,calculateSalary만 호출
급여 상세 화면에서 4대보험 개별 항목과 주휴수당을 표시하기 위한 필드가 추가됐다.
지급 항목 (PaymentSection)
- ✅
weeklyPaidLeaveAmount— 주휴수당 (신규) - ❌ 가족수당 행 삭제 (백엔드와 미사용 확정)
공제 항목 (DeductionSection)
- ✅
nationalPension— 국민연금 - ✅
healthInsurance— 건강보험 - ✅
longTermCare— 장기요양 - ✅
employmentInsurance— 고용보험 - ❌ 노동조합비 행 삭제
| 메서드 | 엔드포인트 | 설명 |
|---|---|---|
| GET | /api/worker/contracts |
계약 목록 조회 (상세 필드 포함 — PR #47) |
| GET | /api/worker/contracts/{id} |
계약 상세 조회 |
| GET | /api/worker/work-records?startDate=...&endDate=... |
기간별 근무 기록 조회 |
| GET | /api/worker/work-records/{id} |
근무 기록 상세 조회 |
| POST | /api/worker/correction-requests |
정정요청 생성 (CREATE/UPDATE/DELETE) |
| GET | /api/worker/correction-requests |
보낸 정정요청 목록 |
| DELETE | /api/worker/correction-requests/{id} |
정정요청 취소 |
| GET | /api/worker/salaries/{id} |
급여 상세 (4대보험 개별 항목, 주휴수당 포함) |
| POST | /api/worker/salaries/contracts/{id}/calculate |
급여 계산 (year, month) |
| GET | /api/worker/payments |
송금 내역 목록 |