API 명세서: QR 코드 기반 시간제 근로자 출퇴근 관리 시스템
버전: 1.0
작성일자: 2025년 4월 5일
기반 문서: 요구사항 분석서 v1.0
1. 일반 사양
1.1 기본 정책
| 항목 | 내용 |
|---|---|
| 프로토콜 | HTTPS (TLS 1.3 강제) |
| 콘텐츠 타입 | application/json (응답/요청) |
| 타임존 | 한국 표준시(KST, UTC+9) → 모든 timestamp는 YYYY-MM-DDTHH:mm:ss+09:00 (ISO 8601) |
| 인코딩 | UTF-8 |
| API 버전링 | /api/v1/ prefix 사용 |
1.2 인증 방식
| 역할 | 인증 수단 |
|---|---|
| 시간제 근로자 | 휴대폰 OTP (SMS 발송) + 1회용 Token (X-OTP-TOKEN 헤더) |
| 근로자 담당자 | JWT Token (발급 후 30분 만료) + IP 기반 로그인 제한 |
| 최종 관리자 | 고정 IP 인증 + 2FA (OTP/Google Authenticator) → 별도 /auth/admin/login 경로 |
http
Copy block
Header: X-Auth-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Header: X-Source-IP: 203.145.x.x
1.3 오류 응답 표준
json
Copy block
{
"code": "ERR_001",
"message": "Invalid phone number format",
"details": {
"field": "phone_number",
"value": "010-1234"
}
}
| 코드 규칙 | 설명 |
|---|---|
2xx |
성공 (200: OK, 201: Created) |
4xx |
클라이언트 오류 (400: Bad Request, 401: Unauthorized, 403: Forbidden, 404: Not Found) |
5xx |
서버 오류 (500: Internal Server Error, 503: Service Unavailable) |
2. API 엔드포인트 상세 명세
🔐 인증 (Auth)
| 메서드 | 경로 | 설명 |
|---|---|---|
| POST | /api/v1/auth/login/employee |
근로자 로그인 (휴대폰 번호 입력 → OTP 발송 요청) |
| POST | /api/v1/auth/verify/employee |
근로자 OTP 인증 후 토큰 발급 |
| POST | /api/v1/auth/login/admin |
관리자 로그인 (IP + 2FA) |
예: 근로자 출근 신청 인증 흐름
http
Copy block
POST /api/v1/auth/login/employee HTTP/1.1
Content-Type: application/json
{
"phone_number": "+82-10-1234-5678"
}
// ✅ 200 OK
{
"otp_reference_id": "otp_ref_abc123",
"message": "인증번호가 발송되었습니다."
}
POST /api/v1/auth/verify/employee HTTP/1.1
{
"phone_number": "+82-10-1234-5678",
"otp_reference_id": "otp_ref_abc123",
"code": "123456"
}
// ✅ 200 OK
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx",
"expires_in": 1800, // 초 단위 (30분)
"role": "employee"
}
👥 근로자 관리 (Employees)
| 메서드 | 경로 | 설명 | 권한 |
|---|---|---|---|
| GET | /api/v1/employees |
근로자 목록 조회 (페이지네이션) | admin, manager |
| POST | /api/v1/employees |
근로자 등록 (등록 시 SMS 알림 자동 발송) | admin |
| GET | /api/v1/employees/{id} |
상세 정보 조회 (출퇴근 기록 포함) | admin, manager |
| PUT | /api/v1/employees/{id} |
근로자 정보 수정 | admin |
| DELETE | /api/v1/employees/{id} |
근로자 삭제 (soft delete) | admin |
예: 근로자 등록 요청
http
Copy block
POST /api/v1/employees HTTP/1.1
{
"name": "홍길동",
"phone_number": "+82-10-9876-5432",
"hourly_wage": 10000,
"start_date": "2025-04-15",
"department": "기계작업",
"note": "부서 이관 신규 등록"
}
// ✅ 201 Created
{
"id": 1045,
"created_at": "2025-04-15T10:30:00+09:00"
// 추가: 근로자 등록 SMS 발송 트리거 완료 로그 기재
}
⏰ 출퇴근 처리 (Attendances)
| 메서드 | 경로 | 설명 |
|---|---|---|
| POST | /api/v1/attendances/check-in |
출근 처리 |
| POST | /api/v1/attendances/check-out |
퇴근 처리 |
| GET | /api/v1/attendances?employee_id=1045&date=2025-04-15 |
당일 출퇴근 내역 조회 |
| GET | /api/v1/attendances/my |
자신의 최근 7일 출퇴근 내역 조회 (근로자용) |
로직 규칙
- 당일 출근 기록이 없으면 퇴근 불가 (409 Conflict)
- 출근 후 15분 미만 시도 →
423 Locked(재검토 요청) - 퇴근 시각 < 출근 시각 →
409 Conflict+ 자동 보정 제안
예: 출근 신청
http
Copy block
POST /api/v1/attendances/check-in HTTP/1.1
X-Auth-Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
{
"employee_id": 1045,
"planned_check_in_time": "2025-04-15T09:00:00+09:00", // 자동 설정 기본값
"real_check_in_time": "2025-04-15T08:55:30+09:00"
}
// ✅ 201 Created
{
"id": 8932,
"status": "pending", // 담당자 승인 대기
"check_in_time": "2025-04-15T08:55:30+09:00",
"approval_url": "https://company.com/approve?id=enc_8932"
}
✅ 승인/반려 처리 (Approvals)
| 메서드 | 경로 | 설명 |
|---|---|---|
| PUT | /api/v1/approvals/{attendance_id} |
승인 또는 반려 처리 |
| GET | /api/v1/approvals?status=pending&manager_id=12 |
대기 중인 출퇴근 내역 조회 (담당자용) |
예: 승인 요청
http
Copy block
PUT /api/v1/approvals/8932 HTTP/1.1
X-Auth-Token: admin_token_abc...
{
"action": "approved", // "rejected" 가능
"rejection_reason": "출근 시간 기록 오류 (08:55 → 09:05로 수정 필요)",
"corrected_check_in_time": "2025-04-15T09:05:00+09:00"
}
// ✅ 200 OK
{
"id": 8932,
"status": "approved",
"approved_at": "2025-04-15T09:10:03+09:00",
"approver_phone": "+82-10-5555-6666"
}
📌 승인/반려 즉시 → 근로자 및 담당자에게 SMS 발송 (내부 이벤트 기반 처리)
💰 급여 관리 (Salaries)
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /api/v1/salaries?employee_id=1045&month=2025-04 |
해당 월 급여 내역 조회 |
| POST | /api/v1/salaries/calculate |
급여 산정 (기존 기록 재계산) |
| PUT | /api/v1/salaries/{id}/pay |
입금 처리 (입금 날짜, 계좌 기록) |
예: 급여 산정 요청
http
Copy block
POST /api/v1/salaries/calculate HTTP/1.1
{
"employee_id": 1045,
"period_start": "2025-04-01",
"period_end": "2025-04-30",
"include_unpaid_approved": false // 기본: 미입금만
}
// ✅ 201 Created
{
"salary_id": 5678,
"period_start": "2025-04-01",
"period_end": "2025-04-30",
"total_worked_hours": 86.75,
"hourly_wage": 10000,
"total_payable_amount": 867500,
"reduction_reasons": [
{
"type": "late_arrival",
"count": 1,
"deduction_amount": -20000
}
],
"final_amount": 847500
}
입금 처리
http
Copy block
PUT /api/v1/salaries/5678/pay HTTP/1.1
{
"payment_date": "2025-05-10T14:30:00+09:00",
"bank_account": "123-45678-90123",
"note": "신한은행 → KB연동 via Excel 업로드"
}
// ✅ 200 OK (SMS 발송 트리거 포함)
{
"payment_confirmed_at": "2025-05-10T14:30:05+09:00",
"sms_sent_to_employees": true,
"sms_sent_to_managers": true
}
📊 리포트 및 Export
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /api/v1/reports/export |
출퇴근/급여 목록 Excel/CSV/PDF Export |
예: 출퇴근 기록 Export 요청
http
Copy block
GET /api/v1/reports/export?format=excel&type=attendance&month=2025-04 HTTP/1.1 X-Auth-Token: admin_token_abc... // ✅ 200 OK (파일 다운로드) Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet Filename: attendance_2025-04.xlsx // 생성된 파일 구조 (시트별) - 시트 1: 출퇴근 전용 목록 - 시트 2: 급여 연계 요약 (시간/금액) - 시트 3: 승인 이력 추적
3. 기술 구현 고려 사항
3.1 QR 코드 URL 규칙
- 형식:
https://company.com/a/{encoded_hash}encoded_hash= AES-256(employee_id:{id},type:check-in,timestamp:YYYYMMDD, secret_key)- 만료 시간: 생성 후 5분
- 한 번 사용 시 무효화 (DB
qr_codes테이블에 사용 이력 저장)
3.2 SMS 알림 콜백
- 모든 SMS 전송은
POST /api/v1/sms/callback통해 상태 수신 - 템플릿 ID로 관리 (예:
SMS_01: 근무 시작 알림,SMS_02: 급여 지급 완료 등)
3.3 이중 방지 로직
| 문제 | 해결책 |
|---|---|
| 중복 출근 신청 | attendances 테이블: (employee_id, check_in_date, type) 유니크 인덱스 |
| 중복 QR 사용 | qr_codes 테이블: usage_count 필드 (1 초과 불가) + TTL 자동 소거 |
| 병렬 급여 지급 | 최종 관리자 전용 lock 테이블 사용 (salary_lock: id=2025-04 등) |
3.4 스키마 기본 구조
sql
Copy block
-- 근로자 (employees)
CREATE TABLE employees (
id BIGINT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
phone_number TEXT ENCRYPTED, -- AES
hourly_wage INT CHECK(hourly_wage >= minimum_hourly_wage),
start_date DATE NOT NULL,
department TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 출퇴근 (attendances)
CREATE TABLE attendances (
id BIGINT PRIMARY KEY,
employee_id BIGINT NOT NULL REFERENCES employees(id),
type VARCHAR(10) CHECK(type IN ('check_in','check_out')),
planned_time TIMESTAMP WITH TIME ZONE,
real_time TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
status VARCHAR(10) DEFAULT 'pending' CHECK(status IN ('pending','approved','rejected')),
approval_url TEXT NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 승인/반려 (approvals)
CREATE TABLE approvals (
id BIGINT PRIMARY KEY,
attendance_id BIGINT NOT NULL REFERENCES attendances(id),
action VARCHAR(10) CHECK(action IN ('approved','rejected')),
rejection_reason TEXT,
corrected_time TIMESTAMP WITH TIME ZONE,
approver_phone TEXT NOT NULL,
approved_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- 급여 (salaries)
CREATE TABLE salaries (
id BIGINT PRIMARY KEY,
employee_id BIGINT NOT NULL,
period_start DATE NOT NULL,
period_end DATE NOT NULL,
worked_hours DECIMAL(5,2),
hourly_wage INT,
total_payable INT,
final_amount INT NOT NULL,
payment_date DATE,
bank_account TEXT,
paid_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
4. 보안 요구사항 상세
| 항목 | 구현 사항 |
|---|---|
| 인증 토큰 보안 | JWT HS256, 30분 만료, 리프레시 토큰 미사용 (단일 토큰 모델) |
| IP 인증 | /admin/* 경로 요청 시 X-Forwarded-For 검증 (백엔드 로드밸런서 설정 필요) |
| 데이터 무결성 | 모든 입력 필드: length/min/max 제약 + SQL injection 방지 (ORM 사용 권장) |
| 감사 로그 | audit_logs 테이블 → 모든 PUT/DELETE 요청 기록 (사용자 IP, 시간, 내용 전부) |
5. 개발 참고 사항
Front-End 연동 시 고려사항
- QR 코드 스캔 후 자동 리다이렉트된 URL은 5초 간 유효 → 재시도 시 경고 표시
- 출근 폼: 자동 시간 설정이 사용자 수정 가능하되, 5분 이내 only로 제한 (시간대역 기반 로직)
- 급여 계산 예측 시뮬레이션을 통한 최종 금액 확인 UI 제공
백엔드 실행 흐름
plaintext
Copy block
출퇴근 신청 → 출퇴근 레코드 생성 (status: pending)
↓
이벤트 콜백 → 담당자에게 SMS 발송 (approval URL 포함)
↓
담ak자 승인/반려 → approval 기록 + 근로자 SMS 발송
↓
급여 산정 → calculate API 실행 + final_amount 저장
↓
입금 처리 → paid_at 기록 + 급여 확정 SMS 발송
6. 부록: 외부 시스템 연동용 이벤트 API
SMS 전송 이벤트
- 외부 SMS Gateway 연동을 위한 POST 기반 웹훅
POST /webhook/sms-delivery
json
Copy block
{
"event": "sms_delivered",
"to": "+82-10-xxx-xxxx",
"template_id": "SMS_03",
"content": "[출퇴근 승인] 홍길동 님의 2025-04-15 출근이 승인되었습니다. 근무시간: 8시간 25분.",
"status": "delivered",
"timestamp": "2025-04-15T09:15:32+09:00"
}
✅ 이 API 명세는 요구사항 분석서 v1.0 기반으로 작성되었으며, 실제 구현 시 HTTP 클라이언트 테스팅을 위해 Postman Collection 또는 OpenAPI 3.0 YAML/JSON 지원 가능합니다.
문서 마감일: 2025년 4월 12일 (구현 개발 일정 기준)