Skip to content

Latest commit

ย 

History

History
1253 lines (1097 loc) ยท 31.9 KB

File metadata and controls

1253 lines (1097 loc) ยท 31.9 KB

Build-Up Platform API ํ…Œ์ŠคํŠธ ์˜ˆ์‹œ

์ฃผ์˜: Base URL์€ http://localhost:8080/api ์ž…๋‹ˆ๋‹ค.

Swagger UI: http://localhost:8080/api/swagger-ui/index.html


๐Ÿ“Œ ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •

1. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์‹œ์ž‘

# Docker ๋ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘
./start-dev.sh

์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ๋‹ค์Œ์„ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:

  • MySQL 8.0 ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ (ํฌํŠธ: 3306)
  • phpMyAdmin ์‹œ์ž‘ (ํฌํŠธ: 8081)
  • ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์‚ฝ์ž… (roles, admin ๊ณ„์ •)
  • Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹œ์ž‘ (ํฌํŠธ: 8080)

2. ๊ธฐ๋ณธ ๊ณ„์ • ์ •๋ณด

์ดˆ๊ธฐํ™” ์Šคํฌ๋ฆฝํŠธ(docker/mysql/init/02-insert-sample-data.sql)๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ณ„์ •:

์—ญํ•  ์•„์ด๋”” ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค๋ช…
๊ด€๋ฆฌ์ž admin Admin123!@ ์‹œ์Šคํ…œ ์ „์ฒด ๊ด€๋ฆฌ ๊ถŒํ•œ

๋กœ๊ทธ์ธ ํ…Œ์ŠคํŠธ:

curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"Admin123!@","rememberMe":false}'

3. ์„œ๋น„์Šค ์ ‘์†


๋ชฉ์ฐจ

  1. ์ธ์ฆ/์ธ๊ฐ€ API (Auth)
  2. ๊ณ„์•ฝ ๊ด€๋ฆฌ API (Contract)
  3. ํŒŒ์ผ ์—…๋กœ๋“œ API (Upload)
  4. GlobalExceptionHandler ํ…Œ์ŠคํŠธ

1. ์ธ์ฆ/์ธ๊ฐ€ API (Auth)

1.1 ์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ

์š”์ฒญ

curl -X GET 'http://localhost:8080/api/v1/auth/exists?userId=testuser001'

์„ฑ๊ณต ์‘๋‹ต (200)

{
  "success": true,
  "message": "์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "exists": false
  }
}

์‹คํŒจ ์‘๋‹ต - ํŒŒ๋ผ๋ฏธํ„ฐ ๋ˆ„๋ฝ (400)

{
  "success": false,
  "message": "ํ•„์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค: userId (String)",
  "code": "COMMON_403",
  "data": null
}

1.2 ๊ทผ๋กœ์ž ํšŒ์›๊ฐ€์ž… 1๋‹จ๊ณ„

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/auth/register/employee/step1 \
  -H "Content-Type: application/json" \
  -d '{
    "empName": "ํ™๊ธธ๋™",
    "userId": "testuser001",
    "password": "Test123@@",
    "confirmPassword": "Test123@@",
    "secretKey": "SECRET-KEY-12345",
    "agreeTerms": true,
    "agreePrivacy": true
  }'

ํ•„๋“œ ์„ค๋ช…

  • empName (ํ•„์ˆ˜): ํ•œ๊ธ€, ์˜๋ฌธ, ๊ณต๋ฐฑ๋งŒ ๊ฐ€๋Šฅ, 1~50์ž
  • userId (ํ•„์ˆ˜): ์˜๋ฌธ ์†Œ๋ฌธ์ž, ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅ, 6~20์ž
  • password (ํ•„์ˆ˜): ์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž(@$!%*#?&) ํฌํ•จ, 8~20์ž
  • confirmPassword (ํ•„์ˆ˜): password์™€ ์ผ์น˜ํ•ด์•ผ ํ•จ
  • secretKey (์„ ํƒ): ํ˜„์žฅ ์—ฐ๋™์šฉ, ์ตœ๋Œ€ 100์ž
  • agreeTerms (ํ•„์ˆ˜): ์„œ๋น„์Šค ์ด์šฉ์•ฝ๊ด€ ๋™์˜, true์—ฌ์•ผ ํ•จ
  • agreePrivacy (ํ•„์ˆ˜): ๊ฐœ์ธ์ •๋ณด ์ฒ˜๋ฆฌ๋ฐฉ์นจ ๋™์˜, true์—ฌ์•ผ ํ•จ

์„ฑ๊ณต ์‘๋‹ต (201)

{
  "success": true,
  "message": "ํšŒ์›๊ฐ€์ž…์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "userId": "testuser001",
    "empName": "ํ™๊ธธ๋™",
    "registrationToken": "550e8400-e29b-41d4-a716-446655440000",
    "expiresAt": "2025-11-11T15:30:00"
  }
}

์‹คํŒจ ์‘๋‹ต - Validation ์˜ค๋ฅ˜ (400)

{
  "success": false,
  "message": "ํ•„๋“œ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.",
  "code": "COMMON_401",
  "data": {
    "password": "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž(@$!%*#?&)๋ฅผ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค",
    "userId": "๋กœ๊ทธ์ธ ID๋Š” ์˜๋ฌธ ์†Œ๋ฌธ์ž์™€ ์ˆซ์ž๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค"
  }
}

์‹คํŒจ ์‘๋‹ต - ์•„์ด๋”” ์ค‘๋ณต (409)

{
  "success": false,
  "message": "์ด๋ฏธ ์‚ฌ์šฉ ์ค‘์ธ ์•„์ด๋””์ž…๋‹ˆ๋‹ค",
  "code": "AUTH_1006",
  "data": null
}

1.3 ๊ทผ๋กœ์ž ํšŒ์›๊ฐ€์ž… 2๋‹จ๊ณ„

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/auth/register/employee/step2 \
  -H "Content-Type: application/json" \
  -d '{
    "registrationToken": "550e8400-e29b-41d4-a716-446655440000",
    "residentNum": "990101-1234567",
    "phone": "01012345678",
    "email": "test@example.com",
    "empAddress": "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123",
    "emergencyPhone": "01087654321"
  }'

ํ•„๋“œ ์„ค๋ช…

  • registrationToken (ํ•„์ˆ˜): 1๋‹จ๊ณ„ ์™„๋ฃŒ ์‹œ ๋ฐœ๊ธ‰๋ฐ›์€ ํ† ํฐ
  • residentNum (ํ•„์ˆ˜): ์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ ํ˜•์‹ (XXXXXX-XXXXXXX), AES-256-GCM ์•”ํ˜ธํ™” ์ €์žฅ
  • phone (ํ•„์ˆ˜): ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ (010XXXXXXXX, ์ˆซ์ž๋งŒ)
  • email (์„ ํƒ): ์ด๋ฉ”์ผ ํ˜•์‹
  • empAddress (์„ ํƒ): ์ฃผ์†Œ, ์ตœ๋Œ€ 255์ž
  • emergencyPhone (์„ ํƒ): ๋น„์ƒ์—ฐ๋ฝ๋ง (11์ž๋ฆฌ ์ˆซ์ž)

์„ฑ๊ณต ์‘๋‹ต (200)

{
  "success": true,
  "message": "๊ทผ๋กœ์ž ์ •๋ณด๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "userId": "testuser001",
    "empName": "ํ™๊ธธ๋™",
    "role": "EMPLOYEE",
    "profileData": {
      "phone": "01012345678",
      "email": "test@example.com",
      "empAddress": "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123"
    }
  }
}

์‹คํŒจ ์‘๋‹ต - ํ† ํฐ ๋งŒ๋ฃŒ/๋ฌดํšจ (401)

{
  "success": false,
  "message": "๋“ฑ๋ก ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ๊ฑฐ๋‚˜ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค",
  "code": "AUTH_1012",
  "data": null
}

1.4 ํ˜„์žฅ ๊ด€๋ฆฌ์ž ํšŒ์›๊ฐ€์ž…

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/auth/register/manager \
  -H "Content-Type: application/json" \
  -d '{
    "managerName": "๊น€์ฒ ์ˆ˜",
    "userId": "manager001",
    "password": "Manager123!@",
    "confirmPassword": "Manager123!@",
    "secretKey": "MANAGER-SECRET-KEY-12345",
    "phone": "010-1234-5678"
  }'

ํ•„๋“œ ์„ค๋ช…

  • managerName (ํ•„์ˆ˜): ํ•œ๊ธ€, ์˜๋ฌธ, ๊ณต๋ฐฑ๋งŒ ๊ฐ€๋Šฅ, 1~50์ž
  • userId (ํ•„์ˆ˜): ์˜๋ฌธ ์†Œ๋ฌธ์ž, ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅ, 6~20์ž
  • password (ํ•„์ˆ˜): ์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž(@$!%*#?&) ํฌํ•จ, 8~20์ž
  • confirmPassword (ํ•„์ˆ˜): password์™€ ์ผ์น˜ํ•ด์•ผ ํ•จ
  • secretKey (ํ•„์ˆ˜): ํ˜„์žฅ ๊ด€๋ฆฌ์ž์šฉ ์‹œํฌ๋ฆฟํ‚ค, ์ตœ๋Œ€ 100์ž
  • phone (ํ•„์ˆ˜): ์ „ํ™”๋ฒˆํ˜ธ (010-XXXX-XXXX ๋˜๋Š” 01XXXXXXXXX)

์„ฑ๊ณต ์‘๋‹ต (201)

{
  "success": true,
  "message": "ํ˜„์žฅ ๊ด€๋ฆฌ์ž ํšŒ์›๊ฐ€์ž…์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "userId": "manager001",
    "role": "MANAGER",
    "profileData": {
      "managerName": "๊น€์ฒ ์ˆ˜",
      "phone": "010-1234-5678"
    }
  }
}

1.5 ๋กœ๊ทธ์ธ

์š”์ฒญ ์˜ˆ์‹œ 1: ํ…Œ์ŠคํŠธ ๊ทผ๋กœ์ž ๊ณ„์ •

curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "username": "testuser001",
    "password": "Test123@@",
    "rememberMe": false
  }'

์š”์ฒญ ์˜ˆ์‹œ 2: ํ…Œ์ŠคํŠธ ๊ด€๋ฆฌ์ž ๊ณ„์ •

curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "username": "manager001",
    "password": "Manager123!@",
    "rememberMe": true
  }'

ํ•„๋“œ ์„ค๋ช…

  • username (ํ•„์ˆ˜): ๋กœ๊ทธ์ธ ID
  • password (ํ•„์ˆ˜): ๋น„๋ฐ€๋ฒˆํ˜ธ
  • rememberMe (์„ ํƒ): true(30์ผ), false(7์ผ), ๊ธฐ๋ณธ๊ฐ’ false

์„ฑ๊ณต ์‘๋‹ต (200)

{
  "success": true,
  "message": "๋กœ๊ทธ์ธ ์„ฑ๊ณต",
  "code": null,
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "tokenType": "Bearer",
    "expiresIn": 3600,
    "userId": "testuser001",
    "role": "EMPLOYEE"
  }
}

์‘๋‹ต ํ—ค๋”

Set-Cookie: refreshToken=<JWT_TOKEN>; Path=/; Max-Age=604800; HttpOnly; Secure; SameSite=Strict

์‹คํŒจ ์‘๋‹ต - ์ธ์ฆ ์‹คํŒจ (401)

{
  "success": false,
  "message": "์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค",
  "code": "AUTH_1005",
  "data": null
}

์‹คํŒจ ์‘๋‹ต - Role ์—†์Œ (403)

{
  "success": false,
  "message": "์‚ฌ์šฉ์ž์˜ ์—ญํ• ์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋ฌธ์˜ํ•˜์„ธ์š”.",
  "code": "AUTH_1013",
  "data": null
}

1.6 ๋‚ด ์ •๋ณด ์กฐํšŒ (์ธ์ฆ ํ•„์š”)

์š”์ฒญ ์˜ˆ์‹œ

curl -X GET http://localhost:8080/api/v1/auth/me \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

์„ฑ๊ณต ์‘๋‹ต - ๊ทผ๋กœ์ž (200)

{
  "success": true,
  "message": "์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ ์„ฑ๊ณต",
  "code": null,
  "data": {
    "userId": "testuser001",
    "role": "EMPLOYEE",
    "profileData": {
      "empName": "ํ™๊ธธ๋™",
      "phone": "01012345678",
      "email": "test@example.com",
      "empAddress": "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123"
    }
  }
}

์„ฑ๊ณต ์‘๋‹ต - ๊ด€๋ฆฌ์ž (200)

{
  "success": true,
  "message": "์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ ์„ฑ๊ณต",
  "code": null,
  "data": {
    "userId": "manager001",
    "role": "MANAGER",
    "profileData": {
      "managerName": "๊น€์ฒ ์ˆ˜",
      "phone": "010-1234-5678",
      "siteId": 1
    }
  }
}

์‹คํŒจ ์‘๋‹ต - ํ† ํฐ ์—†์Œ/๋งŒ๋ฃŒ (401)

{
  "success": false,
  "message": "์ธ์ฆ ํ† ํฐ์ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค",
  "code": "AUTH_1003",
  "data": null
}

1.7 ํ† ํฐ ์žฌ๋ฐœ๊ธ‰

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/auth/token/refresh \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -c cookies.txt

์„ฑ๊ณต ์‘๋‹ต (200)

{
  "success": true,
  "message": "ํ† ํฐ ์žฌ๋ฐœ๊ธ‰ ์„ฑ๊ณต",
  "code": null,
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "tokenType": "Bearer",
    "expiresIn": 3600,
    "userId": "testuser001",
    "role": "EMPLOYEE"
  }
}

์‹คํŒจ ์‘๋‹ต - Refresh Token ์—†์Œ (401)

{
  "success": false,
  "message": "Refresh Token์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค",
  "code": "AUTH_1008",
  "data": null
}

2. ๊ณ„์•ฝ ๊ด€๋ฆฌ API (Contract)

์ฃผ์˜: ๋ชจ๋“  ๊ณ„์•ฝ API๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•˜๋ฉฐ, ์—ญํ• ๋ณ„ ์ ‘๊ทผ ์ œ์–ด๊ฐ€ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

2.1 ๊ณ„์•ฝ ๋ชฉ๋ก ์กฐํšŒ (MANAGER, CORPORATION, ADMIN๋งŒ)

์š”์ฒญ ์˜ˆ์‹œ 1: ๊ธฐ๋ณธ ์กฐํšŒ

curl -X GET 'http://localhost:8080/api/v1/1/contracts' \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

์š”์ฒญ ์˜ˆ์‹œ 2: ํ•„ํ„ฐ๋ง + ํŽ˜์ด์ง•

curl -X GET 'http://localhost:8080/api/v1/1/contracts?employeeId=1&status=FULLY_SIGNED&page=1&size=20' \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ

  • siteId (Path ํ•„์ˆ˜): ํ˜„์žฅ ID
  • employeeId (์„ ํƒ): ๊ทผ๋กœ์ž ID ํ•„ํ„ฐ
  • empType (์„ ํƒ): DAILY(์ผ์šฉ์ง) ๋˜๋Š” PERMANENT(์ƒ์šฉ์ง)
  • status (์„ ํƒ): DRAFT(์ดˆ์•ˆ), PENDING(๋Œ€๊ธฐ์ค‘), FULLY_SIGNED(์™„๋ฃŒ)
  • from (์„ ํƒ): ๊ณ„์•ฝ ์‹œ์ž‘์ผ ๋ฒ”์œ„ ์‹œ์ž‘ (YYYY-MM-DD)
  • to (์„ ํƒ): ๊ณ„์•ฝ ์‹œ์ž‘์ผ ๋ฒ”์œ„ ์ข…๋ฃŒ (YYYY-MM-DD)
  • page (์„ ํƒ): ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ, ๊ธฐ๋ณธ๊ฐ’ 1
  • size (์„ ํƒ): ํŽ˜์ด์ง€ ํฌ๊ธฐ, ๊ธฐ๋ณธ๊ฐ’ 20, ์ตœ๋Œ€ 100

์„ฑ๊ณต ์‘๋‹ต (200)

{
  "success": true,
  "message": "๊ณ„์•ฝ ๋ชฉ๋ก ์กฐํšŒ๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "contracts": [
      {
        "contractId": 1,
        "empType": "PERMANENT",
        "status": "FULLY_SIGNED",
        "employeeStartDate": "2024-01-01",
        "employeeEndDate": null,
        "employeeName": "ํ™๊ธธ๋™",
        "residentNum": "990101-1******",
        "corporationName": "์ฃผ์‹ํšŒ์‚ฌ ๋นŒ๋“œ์—…",
        "createdAt": "2024-01-01T09:00:00"
      }
    ],
    "pageInfo": {
      "currentPage": 1,
      "pageSize": 20,
      "totalElements": 1,
      "totalPages": 1
    }
  }
}

์‹คํŒจ ์‘๋‹ต - ๊ถŒํ•œ ์—†์Œ (403)

{
  "success": false,
  "message": "์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค",
  "code": "AUTH_1011",
  "data": null
}

2.2 ์ƒ์šฉ์ง ๊ณ„์•ฝ ์ƒ์„ฑ (MANAGER, ADMIN๋งŒ)

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/1/contracts/regular \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "employeeId": 1,
    "corporationId": 1,
    "managerId": 1,
    "role": "ํ˜„์žฅ ๊ด€๋ฆฌ์ž",
    "empType": "PERMANENT",
    "employeeStartDate": "2024-01-01",
    "employeeEndDate": null,
    "details": {
      "workPlace": "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123",
      "workType": "์ผ๋ฐ˜๊ฑด์„คํ˜„์žฅ๊ทผ๋กœ์ž",
      "workStartTime": "09:00:00",
      "workEndTime": "18:00:00",
      "breakStartTime": "12:00:00",
      "breakEndTime": "13:00:00",
      "workOnDays": "์›”~๊ธˆ",
      "workOffDays": "ํ† , ์ผ",
      "workPay": 3000000.00,
      "additionalHourPay": 150000.00,
      "additionalNightPay": 100000.00,
      "additionalHolidayPay": 200000.00,
      "payDay": 25,
      "payPeriod": "MONTHLY",
      "payType": "TRANSFER",
      "isEoiApplicable": true,
      "isWciApplicable": true,
      "isNpsApplicable": true,
      "isNhiApplicable": true
    }
  }'

ํ•„๋“œ ์„ค๋ช… (๊ธฐ๋ณธ ์ •๋ณด)

  • employeeId (ํ•„์ˆ˜): ๊ทผ๋กœ์ž ID
  • corporationId (ํ•„์ˆ˜): ๊ธฐ์—… ID
  • managerId (์„ ํƒ): ๊ด€๋ฆฌ์ž ID
  • role (์„ ํƒ): ๊ณ„์•ฝ ์‹œ ์—ญํ• 
  • empType (ํ•„์ˆ˜): PERMANENT๋งŒ ํ—ˆ์šฉ (์ƒ์šฉ์ง)
  • employeeStartDate (ํ•„์ˆ˜): ๊ทผ๋กœ ์‹œ์ž‘์ผ (YYYY-MM-DD)
  • employeeEndDate (์„ ํƒ): ๊ทผ๋กœ ์ข…๋ฃŒ์ผ, null์ด๋ฉด ๊ณ„์† ๊ทผ๋กœ
  • details (ํ•„์ˆ˜): ๊ณ„์•ฝ ์ƒ์„ธ ์ •๋ณด (์•„๋ž˜ ์ฐธ์กฐ)

ํ•„๋“œ ์„ค๋ช… (details - ๊ทผ๋ฌด ์ •๋ณด)

  • workPlace (์„ ํƒ): ๊ทผ๋ฌด ์žฅ์†Œ
  • workType (์„ ํƒ): ์ง์ข…
  • workStartTime (์„ ํƒ): ๊ทผ๋ฌด ์‹œ์ž‘ ์‹œ๊ฐ„ (HH:MM:SS)
  • workEndTime (์„ ํƒ): ๊ทผ๋ฌด ์ข…๋ฃŒ ์‹œ๊ฐ„
  • breakStartTime (์„ ํƒ): ํœด๊ฒŒ ์‹œ์ž‘ ์‹œ๊ฐ„
  • breakEndTime (์„ ํƒ): ํœด๊ฒŒ ์ข…๋ฃŒ ์‹œ๊ฐ„
  • workOnDays (์„ ํƒ): ๊ทผ๋ฌด์ผ
  • workOffDays (์„ ํƒ): ํœด์ผ

ํ•„๋“œ ์„ค๋ช… (details - ๊ธ‰์—ฌ ์ •๋ณด)

  • workPay (ํ•„์ˆ˜): ๊ธฐ๋ณธ ์ž„๊ธˆ
  • additionalHourPay (์„ ํƒ): ์‹œ๊ฐ„์™ธ ๊ทผ๋กœ ์ˆ˜๋‹น
  • additionalNightPay (์„ ํƒ): ์•ผ๊ฐ„ ๊ทผ๋กœ ์ˆ˜๋‹น
  • additionalHolidayPay (์„ ํƒ): ํœด์ผ ๊ทผ๋กœ ์ˆ˜๋‹น

ํ•„๋“œ ์„ค๋ช… (details - ์ง€๊ธ‰ ์ •๋ณด)

  • payDay (ํ•„์ˆ˜): ์ž„๊ธˆ ์ง€๊ธ‰์ผ (1~31)
  • payPeriod (ํ•„์ˆ˜): DAILY(์ผ๊ธ‰), WEEKLY(์ฃผ๊ธ‰), MONTHLY(์›”๊ธ‰)
  • payType (ํ•„์ˆ˜): CASH(ํ˜„๊ธˆ), TRANSFER(๊ณ„์ขŒ์ด์ฒด)

ํ•„๋“œ ์„ค๋ช… (details - 4๋Œ€๋ณดํ—˜)

  • isEoiApplicable (์„ ํƒ): ๊ณ ์šฉ๋ณดํ—˜ ์ ์šฉ ์—ฌ๋ถ€
  • isWciApplicable (์„ ํƒ): ์‚ฐ์žฌ๋ณดํ—˜ ์ ์šฉ ์—ฌ๋ถ€
  • isNpsApplicable (์„ ํƒ): ๊ตญ๋ฏผ์—ฐ๊ธˆ ์ ์šฉ ์—ฌ๋ถ€
  • isNhiApplicable (์„ ํƒ): ๊ฑด๊ฐ•๋ณดํ—˜ ์ ์šฉ ์—ฌ๋ถ€

์„ฑ๊ณต ์‘๋‹ต (201)

{
  "success": true,
  "message": "์ƒ์šฉ์ง ๊ณ„์•ฝ์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "contractId": 1,
    "status": "DRAFT",
    "empType": "PERMANENT",
    "createdAt": "2024-01-01T09:00:00"
  }
}

์‹คํŒจ ์‘๋‹ต - ๊ทผ๋กœ์ž ํƒ€์ž… ๋ถˆ์ผ์น˜ (422)

{
  "success": false,
  "message": "๊ทผ๋กœ์ž์—๊ฒŒ ์ด๋ฏธ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๊ณ„์•ฝ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค",
  "code": "CONTRACT_2003",
  "data": null
}

2.3 ์ผ์šฉ์ง ๊ณ„์•ฝ ์ƒ์„ฑ (MANAGER, ADMIN๋งŒ)

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/1/contracts/daily \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "employeeId": 2,
    "corporationId": 1,
    "managerId": 1,
    "role": "ํ˜„์žฅ ๊ด€๋ฆฌ์ž",
    "empType": "DAILY",
    "employeeStartDate": "2024-01-01",
    "employeeEndDate": "2024-01-31",
    "details": {
      "workPlace": "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123",
      "workType": "์ผ๋ฐ˜๊ฑด์„คํ˜„์žฅ๊ทผ๋กœ์ž",
      "workStartTime": "09:00:00",
      "workEndTime": "18:00:00",
      "breakStartTime": "12:00:00",
      "breakEndTime": "13:00:00",
      "workOnDays": "์›”~ํ† ",
      "workOffDays": "์ผ",
      "workPay": 150000.00,
      "additionalHourPay": 0.00,
      "additionalNightPay": 0.00,
      "additionalHolidayPay": 0.00,
      "payDay": 1,
      "payPeriod": "DAILY",
      "payType": "CASH",
      "isEoiApplicable": false,
      "isWciApplicable": true,
      "isNpsApplicable": false,
      "isNhiApplicable": false
    }
  }'

ํ•„๋“œ ์„ค๋ช…

  • ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒ์šฉ์ง๊ณผ ๋™์ผ
  • empType์€ DAILY๋งŒ ํ—ˆ์šฉ (์ผ์šฉ์ง)
  • ์ผ์šฉ์ง์€ ์ผ๋ฐ˜์ ์œผ๋กœ:
    • employeeEndDate ์ง€์ • (๊ณ„์•ฝ ์ข…๋ฃŒ์ผ ๋ช…์‹œ)
    • payPeriod: DAILY (์ผ๊ธ‰)
    • payType: CASH ๋˜๋Š” TRANSFER
    • 4๋Œ€๋ณดํ—˜: ์‚ฐ์žฌ๋ณดํ—˜๋งŒ ์ ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ

์„ฑ๊ณต ์‘๋‹ต (201)

{
  "success": true,
  "message": "์ผ์šฉ์ง ๊ณ„์•ฝ์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
  "code": null,
  "data": {
    "contractId": 2,
    "status": "DRAFT",
    "empType": "DAILY",
    "createdAt": "2024-01-01T09:00:00"
  }
}

3. ํŒŒ์ผ ์—…๋กœ๋“œ API (Upload)

3.1 ์„œ๋ช… ์ด๋ฏธ์ง€ Presigned URL ๋ฐœ๊ธ‰ (์ธ์ฆ ํ•„์š”)

์š”์ฒญ ์˜ˆ์‹œ

curl -X POST http://localhost:8080/api/v1/uploads/signatures \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "resourceType": "CONTRACT",
    "resourceId": "123",
    "signerRole": "EMPLOYEE",
    "fileExtension": "png"
  }'

ํ•„๋“œ ์„ค๋ช…

  • resourceType (ํ•„์ˆ˜): ๋ฆฌ์†Œ์Šค ํƒ€์ž… (์˜ˆ: CONTRACT)
  • resourceId (ํ•„์ˆ˜): ๋ฆฌ์†Œ์Šค ID (๊ณ„์•ฝ ID ๋“ฑ)
  • signerRole (ํ•„์ˆ˜): ์„œ๋ช…์ž ์—ญํ•  (EMPLOYEE, MANAGER, CORPORATION)
  • fileExtension (ํ•„์ˆ˜): ํŒŒ์ผ ํ™•์žฅ์ž (png, jpg, jpeg, pdf)

์„ฑ๊ณต ์‘๋‹ต (200)

{
  "success": true,
  "message": "Presigned URL์ด ๋ฐœ๊ธ‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
  "code": null,
  "data": {
    "uploadUrl": "https://build-up-contracts.s3.ap-northeast-2.amazonaws.com/uploads/contracts/123/EMPLOYEE.png?signature=xxx",
    "expiresAt": "2025-11-11T15:15:00",
    "s3Key": "uploads/contracts/123/EMPLOYEE.png",
    "bucket": "build-up-contracts"
  }
}

์‚ฌ์šฉ ๋ฐฉ๋ฒ•

  1. ์œ„ API๋กœ Presigned URL ๋ฐœ๊ธ‰
  2. ๋ฐœ๊ธ‰๋ฐ›์€ uploadUrl๋กœ PUT ์š”์ฒญํ•˜์—ฌ ํŒŒ์ผ ์ง์ ‘ ์—…๋กœ๋“œ:
    curl -X PUT "<uploadUrl>" \
      -H "Content-Type: image/png" \
      --data-binary @signature.png
  3. ์—…๋กœ๋“œ ์™„๋ฃŒ ํ›„ ๋ณ„๋„์˜ complete API ํ˜ธ์ถœ (๊ฒ€์ฆ์šฉ)

์‹คํŒจ ์‘๋‹ต - Validation ์‹คํŒจ (400)

{
  "success": false,
  "message": "ํ•„๋“œ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.",
  "code": "COMMON_401",
  "data": {
    "fileExtension": "์ง€์›ํ•˜์ง€ ์•Š๋Š” ํŒŒ์ผ ํ˜•์‹์ž…๋‹ˆ๋‹ค. (png, jpg, jpeg, pdf๋งŒ ๊ฐ€๋Šฅ)"
  }
}

4. GlobalExceptionHandler ํ…Œ์ŠคํŠธ

4.1 ํ•„์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ˆ„๋ฝ (400 + COMMON_403)

์š”์ฒญ

curl -X GET http://localhost:8080/api/v1/auth/exists

์‘๋‹ต (400)

{
  "success": false,
  "message": "ํ•„์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋ˆ„๋ฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค: userId (String)",
  "code": "COMMON_403",
  "data": null
}

4.2 JSON ํŒŒ์‹ฑ ์˜ค๋ฅ˜ (400 + COMMON_400)

์š”์ฒญ

curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "test", invalid json'

์‘๋‹ต (400)

{
  "success": false,
  "message": "์š”์ฒญ ๋ณธ๋ฌธ์„ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. JSON ํ˜•์‹์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”.",
  "code": "COMMON_400",
  "data": null
}

4.3 HTTP ๋ฉ”์„œ๋“œ ์˜ค๋ฅ˜ (405 + COMMON_405)

์š”์ฒญ

curl -X DELETE http://localhost:8080/api/v1/auth/login

์‘๋‹ต (405)

{
  "success": false,
  "message": "์ง€์›ํ•˜์ง€ ์•Š๋Š” HTTP ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค: DELETE (์ง€์›ํ•˜๋Š” ๋ฉ”์„œ๋“œ: [POST])",
  "code": "COMMON_405",
  "data": null
}

4.4 ์กด์žฌํ•˜์ง€ ์•Š๋Š” URL (404 + COMMON_404)

์š”์ฒญ

curl -X GET http://localhost:8080/api/v1/nonexistent

์‘๋‹ต (404)

{
  "success": false,
  "message": "์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค",
  "code": "COMMON_404",
  "data": null
}

4.5 Validation ์˜ค๋ฅ˜ (400 + COMMON_401)

์š”์ฒญ

curl -X POST http://localhost:8080/api/v1/auth/register/employee/step1 \
  -H "Content-Type: application/json" \
  -d '{
    "empName": "ํ™๊ธธ๋™123",
    "userId": "test",
    "password": "weak",
    "confirmPassword": "weak",
    "agreeTerms": false,
    "agreePrivacy": true
  }'

์‘๋‹ต (400)

{
  "success": false,
  "message": "ํ•„๋“œ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.",
  "code": "COMMON_401",
  "data": {
    "empName": "์ด๋ฆ„์€ ํ•œ๊ธ€, ์˜๋ฌธ, ๊ณต๋ฐฑ๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค",
    "userId": "๋กœ๊ทธ์ธ ID๋Š” 6์ž ์ด์ƒ 20์ž ์ดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค",
    "password": "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 8์ž ์ด์ƒ 20์ž ์ดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค",
    "agreeTerms": "์„œ๋น„์Šค ์ด์šฉ์•ฝ๊ด€์— ๋™์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค"
  }
}

4.6 ์ธ์ฆ ์˜ค๋ฅ˜ (401)

์š”์ฒญ - ํ† ํฐ ์—†์ด ์ธ์ฆ ํ•„์š” ์—”๋“œํฌ์ธํŠธ ํ˜ธ์ถœ

curl -X GET http://localhost:8080/api/v1/auth/me

์‘๋‹ต (401)

{
  "success": false,
  "message": "์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค",
  "code": "AUTH_1001",
  "data": null
}

4.7 ๊ถŒํ•œ ์˜ค๋ฅ˜ (403)

์š”์ฒญ - EMPLOYEE ๊ถŒํ•œ์œผ๋กœ MANAGER ์ „์šฉ ์—”๋“œํฌ์ธํŠธ ํ˜ธ์ถœ

curl -X POST http://localhost:8080/api/v1/1/contracts/regular \
  -H "Authorization: Bearer <EMPLOYEE_ACCESS_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{...}'

์‘๋‹ต (403)

{
  "success": false,
  "message": "์ ‘๊ทผ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค",
  "code": "AUTH_1011",
  "data": null
}

5. ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค

์‹œ๋‚˜๋ฆฌ์˜ค 1: ๊ทผ๋กœ์ž ํšŒ์›๊ฐ€์ž… โ†’ ๋กœ๊ทธ์ธ โ†’ ๋‚ด ์ •๋ณด ์กฐํšŒ

# 1. ์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ
curl -X GET 'http://localhost:8080/api/v1/auth/exists?userId=testuser002'

# 2. ํšŒ์›๊ฐ€์ž… 1๋‹จ๊ณ„
curl -X POST http://localhost:8080/api/v1/auth/register/employee/step1 \
  -H "Content-Type: application/json" \
  -d '{
    "empName": "๊น€ํ…Œ์ŠคํŠธ",
    "userId": "testuser002",
    "password": "Test123@@",
    "confirmPassword": "Test123@@",
    "secretKey": "SECRET-KEY-67890",
    "agreeTerms": true,
    "agreePrivacy": true
  }'

# 3. ํšŒ์›๊ฐ€์ž… 2๋‹จ๊ณ„ (registrationToken์„ 2๋‹จ๊ณ„ ์‘๋‹ต์—์„œ ๋ณต์‚ฌ)
curl -X POST http://localhost:8080/api/v1/auth/register/employee/step2 \
  -H "Content-Type: application/json" \
  -d '{
    "registrationToken": "<๋ณต์‚ฌํ•œ ํ† ํฐ>",
    "residentNum": "950505-2123456",
    "phone": "01098765432",
    "email": "test2@example.com",
    "empAddress": "๊ฒฝ๊ธฐ๋„ ์„ฑ๋‚จ์‹œ ๋ถ„๋‹น๊ตฌ",
    "emergencyPhone": "01011112222"
  }'

# 4. ๋กœ๊ทธ์ธ
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "username": "testuser002",
    "password": "Test123@@",
    "rememberMe": false
  }'

# 5. ๋‚ด ์ •๋ณด ์กฐํšŒ (accessToken์„ ๋กœ๊ทธ์ธ ์‘๋‹ต์—์„œ ๋ณต์‚ฌ)
curl -X GET http://localhost:8080/api/v1/auth/me \
  -H "Authorization: Bearer <๋ณต์‚ฌํ•œ accessToken>"

# 6. ํ† ํฐ ์žฌ๋ฐœ๊ธ‰
curl -X POST http://localhost:8080/api/v1/auth/token/refresh \
  -b cookies.txt \
  -c cookies.txt

์‹œ๋‚˜๋ฆฌ์˜ค 2: ํ˜„์žฅ ๊ด€๋ฆฌ์ž ํšŒ์›๊ฐ€์ž… โ†’ ๊ณ„์•ฝ ์ƒ์„ฑ

# 1. ํ˜„์žฅ ๊ด€๋ฆฌ์ž ํšŒ์›๊ฐ€์ž…
curl -X POST http://localhost:8080/api/v1/auth/register/manager \
  -H "Content-Type: application/json" \
  -d '{
    "managerName": "์ด๊ด€๋ฆฌ",
    "userId": "manager002",
    "password": "Manager123!@",
    "confirmPassword": "Manager123!@",
    "secretKey": "MANAGER-SECRET-999",
    "phone": "010-9999-8888"
  }'

# 2. ๋กœ๊ทธ์ธ
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "username": "manager002",
    "password": "Manager123!@",
    "rememberMe": false
  }'

# 3. ์ƒ์šฉ์ง ๊ณ„์•ฝ ์ƒ์„ฑ (accessToken ๋ณต์‚ฌ, employeeId๋Š” ๊ธฐ์กด ๊ทผ๋กœ์ž ID ์‚ฌ์šฉ)
curl -X POST http://localhost:8080/api/v1/1/contracts/regular \
  -H "Authorization: Bearer <๋ณต์‚ฌํ•œ accessToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "employeeId": 1,
    "corporationId": 1,
    "managerId": 1,
    "role": "ํ˜„์žฅ ๊ด€๋ฆฌ์ž",
    "empType": "PERMANENT",
    "employeeStartDate": "2024-02-01",
    "employeeEndDate": null,
    "details": {
      "workPlace": "์ธ์ฒœ์‹œ ์—ฐ์ˆ˜๊ตฌ ์†ก๋„๊ตญ์ œ๋„์‹œ",
      "workType": "๊ฑด์ถ•๊ณต์‚ฌ ํ˜„์žฅ๊ทผ๋กœ์ž",
      "workStartTime": "08:00:00",
      "workEndTime": "17:00:00",
      "breakStartTime": "12:00:00",
      "breakEndTime": "13:00:00",
      "workOnDays": "์›”~๊ธˆ",
      "workOffDays": "ํ† , ์ผ, ๊ณตํœด์ผ",
      "workPay": 3500000.00,
      "additionalHourPay": 200000.00,
      "additionalNightPay": 150000.00,
      "additionalHolidayPay": 250000.00,
      "payDay": 25,
      "payPeriod": "MONTHLY",
      "payType": "TRANSFER",
      "isEoiApplicable": true,
      "isWciApplicable": true,
      "isNpsApplicable": true,
      "isNhiApplicable": true
    }
  }'

# 4. ๊ณ„์•ฝ ๋ชฉ๋ก ์กฐํšŒ
curl -X GET 'http://localhost:8080/api/v1/1/contracts?page=1&size=20' \
  -H "Authorization: Bearer <๋ณต์‚ฌํ•œ accessToken>"

6. Postman Collection ์ž„ํฌํŠธ ํ˜•์‹

์•„๋ž˜ JSON์„ ๋ณต์‚ฌํ•˜์—ฌ Postman์—์„œ Import โ†’ Raw text๋กœ ์ž„ํฌํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

{
  "info": {
    "name": "Build-Up Platform API",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "http://localhost:8080/api",
      "type": "string"
    },
    {
      "key": "access_token",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Auth",
      "item": [
        {
          "name": "์•„์ด๋”” ์ค‘๋ณต ํ™•์ธ",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/auth/exists?userId=testuser001",
              "host": ["{{base_url}}"],
              "path": ["v1", "auth", "exists"],
              "query": [
                {
                  "key": "userId",
                  "value": "testuser001"
                }
              ]
            }
          }
        },
        {
          "name": "๊ทผ๋กœ์ž ํšŒ์›๊ฐ€์ž… 1๋‹จ๊ณ„",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"empName\": \"ํ™๊ธธ๋™\",\n  \"userId\": \"testuser001\",\n  \"password\": \"Test123@@\",\n  \"confirmPassword\": \"Test123@@\",\n  \"secretKey\": \"SECRET-KEY-12345\",\n  \"agreeTerms\": true,\n  \"agreePrivacy\": true\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/auth/register/employee/step1",
              "host": ["{{base_url}}"],
              "path": ["v1", "auth", "register", "employee", "step1"]
            }
          }
        },
        {
          "name": "๋กœ๊ทธ์ธ",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "const response = pm.response.json();",
                  "if (response.success && response.data.accessToken) {",
                  "  pm.collectionVariables.set('access_token', response.data.accessToken);",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"username\": \"testuser001\",\n  \"password\": \"Test123@@\",\n  \"rememberMe\": false\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/auth/login",
              "host": ["{{base_url}}"],
              "path": ["v1", "auth", "login"]
            }
          }
        },
        {
          "name": "๋‚ด ์ •๋ณด ์กฐํšŒ",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/auth/me",
              "host": ["{{base_url}}"],
              "path": ["v1", "auth", "me"]
            }
          }
        }
      ]
    },
    {
      "name": "Contract",
      "item": [
        {
          "name": "๊ณ„์•ฝ ๋ชฉ๋ก ์กฐํšŒ",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/1/contracts?page=1&size=20",
              "host": ["{{base_url}}"],
              "path": ["v1", "1", "contracts"],
              "query": [
                {
                  "key": "page",
                  "value": "1"
                },
                {
                  "key": "size",
                  "value": "20"
                }
              ]
            }
          }
        },
        {
          "name": "์ƒ์šฉ์ง ๊ณ„์•ฝ ์ƒ์„ฑ",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{access_token}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"employeeId\": 1,\n  \"corporationId\": 1,\n  \"managerId\": 1,\n  \"role\": \"ํ˜„์žฅ ๊ด€๋ฆฌ์ž\",\n  \"empType\": \"PERMANENT\",\n  \"employeeStartDate\": \"2024-01-01\",\n  \"employeeEndDate\": null,\n  \"details\": {\n    \"workPlace\": \"์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ํ…Œํ—ค๋ž€๋กœ 123\",\n    \"workType\": \"์ผ๋ฐ˜๊ฑด์„คํ˜„์žฅ๊ทผ๋กœ์ž\",\n    \"workStartTime\": \"09:00:00\",\n    \"workEndTime\": \"18:00:00\",\n    \"breakStartTime\": \"12:00:00\",\n    \"breakEndTime\": \"13:00:00\",\n    \"workOnDays\": \"์›”~๊ธˆ\",\n    \"workOffDays\": \"ํ† , ์ผ\",\n    \"workPay\": 3000000.00,\n    \"additionalHourPay\": 150000.00,\n    \"additionalNightPay\": 100000.00,\n    \"additionalHolidayPay\": 200000.00,\n    \"payDay\": 25,\n    \"payPeriod\": \"MONTHLY\",\n    \"payType\": \"TRANSFER\",\n    \"isEoiApplicable\": true,\n    \"isWciApplicable\": true,\n    \"isNpsApplicable\": true,\n    \"isNhiApplicable\": true\n  }\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/1/contracts/regular",
              "host": ["{{base_url}}"],
              "path": ["v1", "1", "contracts", "regular"]
            }
          }
        }
      ]
    }
  ]
}

7. ์ฃผ์š” ์—๋Ÿฌ ์ฝ”๋“œ ์ •๋ฆฌ

๊ณตํ†ต ์—๋Ÿฌ (COMMON_XXX)

์—๋Ÿฌ ์ฝ”๋“œ HTTP ์„ค๋ช…
COMMON_400 400 ์ž˜๋ชป๋œ ์š”์ฒญ (JSON ํŒŒ์‹ฑ ์˜ค๋ฅ˜)
COMMON_401 400 Validation ์˜ค๋ฅ˜
COMMON_402 400 ํƒ€์ž… ๋ณ€ํ™˜ ์˜ค๋ฅ˜
COMMON_403 400 ํ•„์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ˆ„๋ฝ
COMMON_404 404 ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ
COMMON_405 405 ์ง€์›ํ•˜์ง€ ์•Š๋Š” HTTP ๋ฉ”์„œ๋“œ
COMMON_500 500 ์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜

์ธ์ฆ ์—๋Ÿฌ (AUTH_1XXX)

์—๋Ÿฌ ์ฝ”๋“œ HTTP ์„ค๋ช…
AUTH_1001 401 ์ธ์ฆ ์‹คํŒจ
AUTH_1003 401 ์œ ํšจํ•˜์ง€ ์•Š์€ ํ† ํฐ
AUTH_1005 401 ์ž˜๋ชป๋œ ์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ
AUTH_1006 409 ์•„์ด๋”” ์ค‘๋ณต
AUTH_1008 401 Refresh Token ์—†์Œ
AUTH_1011 403 ๊ถŒํ•œ ์—†์Œ
AUTH_1012 401 ๋“ฑ๋ก ํ† ํฐ ๋งŒ๋ฃŒ
AUTH_1013 403 Role ์—†์Œ

๊ณ„์•ฝ ์—๋Ÿฌ (CONTRACT_2XXX)

์—๋Ÿฌ ์ฝ”๋“œ HTTP ์„ค๋ช…
CONTRACT_2001 404 ๊ณ„์•ฝ์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ
CONTRACT_2003 422 ๊ทผ๋กœ์ž ํƒ€์ž… ๋ถˆ์ผ์น˜

8. ์ฐธ๊ณ  ์‚ฌํ•ญ

๋น„๋ฐ€๋ฒˆํ˜ธ ๊ทœ์น™

  • ๊ธธ์ด: 8~20์ž
  • ํฌํ•จ: ์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž(@$!%*#?&)
  • ์˜ˆ์‹œ: Test123@@, Manager123!@, Admin@2024

์ฃผ๋ฏผ๋“ฑ๋ก๋ฒˆํ˜ธ ๊ทœ์น™

  • ํ˜•์‹: XXXXXX-XXXXXXX (13์ž๋ฆฌ, ํ•˜์ดํ”ˆ ํฌํ•จ)
  • ์˜ˆ์‹œ: 990101-1234567
  • ์•”ํ˜ธํ™”: AES-256-GCM์œผ๋กœ ์•”ํ˜ธํ™”๋˜์–ด DB ์ €์žฅ
  • ๋งˆ์Šคํ‚น: API ์‘๋‹ต ์‹œ ๋’ท์ž๋ฆฌ ๋งˆ์Šคํ‚น (์˜ˆ: 990101-1******)

ํœด๋Œ€ํฐ ๋ฒˆํ˜ธ ๊ทœ์น™

  • ๊ทผ๋กœ์ž: 010XXXXXXXX (ํ•˜์ดํ”ˆ ์—†์ด 11์ž๋ฆฌ ์ˆซ์ž)
  • ๊ด€๋ฆฌ์ž: 010-XXXX-XXXX ๋˜๋Š” 010XXXXXXXX (๋‘˜ ๋‹ค ๊ฐ€๋Šฅ)

JWT ํ† ํฐ

  • Access Token: ์‘๋‹ต Body์— ํฌํ•จ, ๋งŒ๋ฃŒ ์‹œ๊ฐ„ 3600์ดˆ (1์‹œ๊ฐ„)
  • Refresh Token: HttpOnly ์ฟ ํ‚ค๋กœ ์ „๋‹ฌ, ๋งŒ๋ฃŒ ์‹œ๊ฐ„:
    • rememberMe=false: 604800์ดˆ (7์ผ)
    • rememberMe=true: 2592000์ดˆ (30์ผ)
  • ํ† ํฐ ์‚ฌ์šฉ: Authorization: Bearer <ACCESS_TOKEN> ํ—ค๋”๋กœ ์ „๋‹ฌ

์—ญํ• ๋ณ„ ์ ‘๊ทผ ๊ถŒํ•œ

  • EMPLOYEE: ๋‚ด ์ •๋ณด ์กฐํšŒ๋งŒ ๊ฐ€๋Šฅ
  • MANAGER: ๊ณ„์•ฝ ์ƒ์„ฑ/์กฐํšŒ ๊ฐ€๋Šฅ
  • CORPORATION: ๊ณ„์•ฝ ์กฐํšŒ ๊ฐ€๋Šฅ
  • ADMIN: ๋ชจ๋“  ๊ถŒํ•œ

๋ฌธ์„œ ๋ฒ„์ „: 1.0 ์ตœ์ข… ์ˆ˜์ •์ผ: 2025-11-11 ์ž‘์„ฑ์ž: Build-Up Team