# 데이터 안내 — 직원·휴가·급여를 관리하려면 무엇이 필요한가 > 🎓 이 문서의 모든 이름·숫자는 **교육용으로 창작된 가상 자료**입니다. > 가상 회사 「한빛상사(주)」 · 실존 인물·급여와 무관합니다. - 작성일: 2026-09-14 - 읽는 사람: 인사·총무 담당자 (개발 지식 없어도 읽을 수 있게 씀) - 예시 인물: **강도현 (사번 E006, 영업팀 사원)** — 이 사람 한 명을 끝까지 따라갑니다 --- ## 0. 결론부터 인사 데이터는 **표 3개**로 나눕니다. 그리고 **사번**이라는 열쇠 하나로 3개를 묶습니다. ``` ┌────────────────────┐ │ ① 직원 (기본정보) │ ← 사람 1명당 1줄 │ 사번 E006 강도현 │ └─────────┬──────────┘ │ 사번으로 연결 ┌──────┴───────┐ ▼ ▼ ┌───────────┐ ┌───────────┐ │ ② 휴가신청 │ │ ③ 급여명세 │ ← 사람 1명당 여러 줄 │ E006 3건 │ │ E006 9건 │ └───────────┘ └───────────┘ ``` **왜 나누나?** 한 표에 다 넣으면 강도현의 부서가 바뀔 때 **그 사람 줄을 전부 다 고쳐야** 합니다. 9월 급여, 8월 급여, 휴가 3건… 하나라도 빠뜨리면 데이터가 서로 안 맞게 됩니다. 부서를 ①에 한 번만 적어두면 **한 곳만 고치면 끝**입니다. --- ## 1. 표 ① 직원 (기본정보) **한 줄 = 직원 한 명.** 회사에 100명이면 100줄. 사람이 늘 때만 줄이 늘어납니다. | 항목 | 무슨 뜻인가 | 예시 (강도현) | 왜 필요한가 | |---|---|---|---| | **사번** 🔑 | 사람마다 붙는 **고유 번호** | `E006` | **모든 연결의 열쇠.** 절대 바뀌면 안 됨 | | 이름 | 직원 성명 | 강도현 | 화면에 보여주기 위해 | | 부서 | 소속 | 영업팀 | 부서별 집계에 필요 | | 직급 | 직위 | 사원 | 결재선·수당 기준 | | 입사일 | 회사에 들어온 날 | 2023-03-06 | **연차 일수 계산의 기준** | | 퇴사일 | 나간 날 (재직 중이면 빈칸) | (빈칸) | 퇴사자 제외 집계에 필요 | | 재직상태 | 재직 / 휴직 / 퇴사 | 재직 | 급여 지급 대상 판단 | | 연차 부여일수 | 올해 받은 연차 | 15일 | 잔여 계산의 출발점 | > ⚠️ **퇴사일을 "없음"이나 "0"으로 채우지 마세요.** 빈칸은 빈칸으로 두어야 합니다. > 억지로 채우면 "2023년에 퇴사한 사람"처럼 잘못 읽힙니다. --- ## 2. 표 ② 휴가신청 **한 줄 = 신청 1건.** 강도현이 올해 3번 신청했으면 3줄입니다. | 항목 | 무슨 뜻인가 | 예시 | 왜 필요한가 | |---|---|---|---| | **신청번호** 🔑 | 신청마다 붙는 고유 번호 | `L015` | 이 줄을 가리키는 이름표 | | **사번** 🔗 | **누가 신청했나** | `E006` | ← **①과 연결되는 고리** | | 휴가 종류 | 연차 / 반차 / 병가 | 연차 | **종류마다 차감 규칙이 다름** | | 시작일 · 종료일 | 언제부터 언제까지 | 09-21 ~ 09-22 | 일수 계산, 일정 파악 | | 일수 | 며칠인가 | 2.0 | 반차는 0.5 | | 사유 | 왜 쓰나 | 개인 사유 | 승인 판단 근거 | | 상태 | 대기 / 승인 / 반려 | 대기 | **승인된 것만 연차에서 차감** | | 처리자 · 처리일 | 누가 언제 결재했나 | (빈칸) | 기록 추적용 | > ⚠️ **대기 중인 건의 처리자·처리일은 빈칸입니다.** 아직 처리를 안 했으니까요. > 이걸 임의로 채우면 "이미 결재된 건"으로 잘못 집계됩니다. **💡 여기가 핵심**: 표 ①에 "사용한 연차 일수"를 저장하지 **않습니다.** 대신 ②에서 **상태가 '승인'이고 종류가 연차·반차인 줄의 일수를 더해서** 그때그때 계산합니다. ``` 강도현 잔여연차 = ① 부여 15일 − ② 승인된 연차·반차 합계 3일 = 12일 ``` 이렇게 해야 승인 버튼 한 번에 모든 숫자가 저절로 맞습니다. (→ 실제 동작은 앱에서 "이름 클릭 → 연차 계산 내역"으로 확인하세요) --- ## 3. 표 ③ 급여명세 **한 줄 = 한 사람의 한 달치 급여.** 강도현의 1월~9월이면 9줄입니다. | 항목 | 무슨 뜻인가 | 예시 (가상) | 왜 필요한가 | |---|---|---|---| | **급여번호** 🔑 | 명세서 고유 번호 | `PY2609-E006` | 이 줄의 이름표 | | **사번** 🔗 | **누구 급여인가** | `E006` | ← **①과 연결되는 고리** | | 귀속연월 | **어느 달 일한 값인가** | 2026-09 | 지급일과 **다를 수 있음** | | 지급일 | 실제로 돈이 나간 날 | 2026-10-10 | 회계 처리 기준 | | 기본급 | 고정 급여 | 2,800,000 | | | 연장수당 | 초과근무 수당 | 180,000 | **근태 데이터에서 계산** | | 식대 등 | 비과세 항목 | 200,000 | 세금 계산이 달라짐 | | **지급 합계** | 받을 돈 총액 | 3,180,000 | | | 국민연금·건강보험·고용보험 | 4대보험 공제 | 각각 | 법정 공제 | | 소득세·지방소득세 | 세금 공제 | 각각 | 법정 공제 | | **공제 합계** | 떼는 돈 총액 | 412,000 | | | **실지급액** | 통장에 들어가는 돈 | 2,768,000 | `지급합계 − 공제합계` | | 상태 | 작성중 / 확정 / 지급완료 | 확정 | **확정 후에는 고치지 않음** | > ⚠️ **급여 표는 다른 표와 성격이 다릅니다.** > 1. **민감정보**입니다. 아무나 보면 안 되고, 권한 관리가 필요합니다. > 2. **확정된 급여는 고치지 않습니다.** 잘못됐으면 지우는 게 아니라 > **다음 달에 정정 항목으로 반영**합니다. 회계·세무 기록이기 때문입니다. > 3. 그래서 급여는 **"귀속연월"과 "지급일"을 반드시 따로** 둡니다. > 9월에 일한 값을 10월에 주는 회사가 많기 때문입니다. --- ## 4. 어떻게 연결하나 — **사번이 열쇠** ### 규칙은 딱 하나 > **모든 표에 「사번」을 넣고, 사번이 같으면 같은 사람이다.** 강도현 한 사람의 자료는 실제로는 이렇게 흩어져 있습니다. | 표 | 강도현의 자료 | |---|---| | ① 직원 | `E006 · 강도현 · 영업팀 · 사원 · 2023-03-06 입사 · 연차 15일` | | ② 휴가 | `L008(승인 3일)` `L015(대기 2일)` `L021(반려 5일)` — **3줄** | | ③ 급여 | `PY2601-E006` … `PY2609-E006` — **9줄** | 화면에 "강도현의 연차 잔여 12일"을 보여주려면 컴퓨터는 이렇게 합니다. 1. ①에서 **사번 E006** 줄을 찾아 → 부여 15일 확인 2. ②에서 **사번이 E006이고 상태가 승인**인 줄만 골라 → 일수 합계 3일 3. 15 − 3 = **12일** ### 왜 이름으로 연결하면 안 되나 ❌ | 문제 | 무슨 일이 생기나 | |---|---| | **동명이인** | 김민수가 2명이면 누구 급여인지 알 수 없음 | | **개명·혼인** | 이름이 바뀌면 과거 자료와 연결이 끊김 | | **띄어쓰기·오타** | `강도현` 과 `강 도현` 은 컴퓨터에겐 **다른 사람** | > 💡 사번은 **한 번 정하면 절대 바꾸지 않습니다.** > 퇴사해도 그 사번은 다른 사람에게 물려주지 않습니다. 과거 급여·휴가 기록이 딸려오기 때문입니다. ### 1명 : 여러 줄 (1대다 관계) ``` ① 직원 E006 강도현 ─┬─→ ② 휴가 L008, L015, L021 (3줄) └─→ ③ 급여 PY2601 … PY2609 (9줄) ``` - ①은 **사람당 1줄**, ②③은 **사람당 여러 줄**입니다. 이걸 **1대다(1:N)** 관계라고 부릅니다. - 반대는 없습니다. 휴가 1건이 2명 것일 수는 없으니까요. ### 지켜야 할 5가지 | # | 규칙 | 안 지키면 | |---|---|---| | 1 | 표마다 **고유번호(🔑)를 하나씩** 둔다 | 같은 줄인지 다른 줄인지 구분 불가 | | 2 | 연결은 **반드시 사번(🔗)으로** 한다 | 동명이인·개명에서 자료가 엉킴 | | 3 | ①에 없는 사번을 ②③에 쓰지 않는다 | **주인 없는 휴가·급여**가 생김 | | 4 | **계산으로 나오는 값은 저장하지 않는다** | 잔여연차를 저장해두면 승인할 때마다 어긋남 | | 5 | **빈칸은 빈칸으로 둔다** | 임의로 채우면 집계가 틀림 | --- ## 5. 한 걸음 더 — 표를 더 나눠야 할 때 우리 교육용 앱은 단순하게 **연차 부여일수를 ① 직원 표에** 넣어 뒀습니다. 하지만 실제 제품(Frappe HR 등)은 **「연차 부여」를 별도 표로 분리**합니다. | 왜 나누나 | 설명 | |---|---| | **연도별로 쌓인다** | 2025년 15일, 2026년 16일… 해마다 줄이 늘어남 | | **종류가 여러 개다** | 연차·보건휴가·대체휴가를 각각 따로 부여 | | **이월·소멸이 있다** | 작년 미사용분 이월, 기한 지나면 소멸 — **기록이 남아야 함** | | ④ 연차부여 (참고) | 예시 | |---|---| | 부여번호 🔑 | `AL2026-E006` | | 사번 🔗 | `E006` | | 적용연도 | 2026 | | 휴가 종류 | 연차 | | 부여일수 | 15 | | 사용기한 | 2026-12-31 | 지금 당장은 필요 없습니다. **"나중에 이렇게 커진다"는 것만 알아두시면 됩니다.** --- ## 5-1. 실제 예제 파일 — `data/가상_인사총무.json` 위 설명을 **그대로 담은 예제 파일**을 만들어 두었습니다. 열어서 직접 보시면 됩니다. 📂 **`data/가상_인사총무.json`** 이 파일은 **앱에서 그대로 뽑아낸 사본**입니다. 항목명만 한글로 바꿨을 뿐, 내용은 앱과 완전히 같습니다. ### 이 파일을 앱이 실제로 읽게 하려면 앱은 여는 방법에 따라 데이터 출처가 달라집니다. **숫자는 어느 쪽이든 똑같습니다.** | 여는 방법 | 데이터 출처 | 화면 왼쪽 아래 표시 | |---|---|---| | HTML 파일 **더블클릭** | 파일 안의 내장 데이터 | 📦 내장 데이터 | | **로컬 서버**로 열기 | **이 JSON 파일** | 📂 데이터 파일 | ``` node 로컬서버.mjs ← 터미널에서 실행 http://127.0.0.1:8123/ ← 브라우저에서 이 주소로 접속 Ctrl + C ← 중지 ``` > **왜 더블클릭으로는 못 읽나?** 브라우저 보안 정책 때문입니다. > 웹페이지가 내 컴퓨터의 파일을 마음대로 읽으면 위험하므로, 브라우저가 막습니다. > 로컬 서버를 켜면 "웹사이트처럼" 취급되어 읽을 수 있게 됩니다. | 묶음 | 건수 | 한 줄의 뜻 | |---|---|---| | `직원` | **12건** | 직원 1명 | | `휴가신청` | **24건** | 신청 1건 (승인 14 · 대기 6 · 반려 4) | | `비품품목` | **10건** | 품목 1종 | | `비품신청` | **18건** | 신청 1건 (승인 10 · 대기 5 · 반려 3) | | `급여명세` | **12건** | 직원 1명의 **2026년 9월분** 급여 | ### 이 파일의 급여 숫자 (전 직원 동일) | 항목 | 금액 | |---|---| | 기본급 | 3,000,000원 | | 수당 | + 200,000원 | | 공제 | − 100,000원 | | **지급액** | **3,100,000원** | | 12명 지급 총액 | 37,200,000원 | > ⚠️ **실제 세금·4대보험은 계산하지 않았습니다.** > `공제`는 설명용 고정 금액 **한 항목**뿐입니다. 실제 급여대장에는 국민연금·건강보험· > 고용보험·소득세·지방소득세가 각각 따로 들어갑니다(§3 표 참고). > 전 직원 금액을 똑같이 둔 이유는, **"직급별 급여 차이"가 아니라 "표를 어떻게 연결하는가"** > 에 집중하도록 하기 위해서입니다. ### 파일이 규칙을 지키는지 검사한 결과 ✅ 만들고 나서 §4의 규칙을 실제로 지켰는지 확인했습니다. | 검사 항목 | 결과 | |---|---| | ①에 없는 사번이 다른 표에 있는가 (**주인 없는 줄**) | **0건** ✅ | | 없는 품목코드를 비품신청이 가리키는가 | **0건** ✅ | | 고유번호(사번·신청번호·품목코드·급여번호)가 겹치는가 | **없음** ✅ | | 지급액 = 기본급 + 수당 − 공제 가 맞는가 | **12건 모두 일치** ✅ | | 대기 건의 처리자·처리일이 빈칸(null)인가 | **모두 빈칸** ✅ | | **앱 화면 숫자와 일치하는가** | 강도현 잔여 **12.0** · 전사 소진율 **19.1%** · 재고부족 **4종** ✅ | ### 연결이 실제로 어떻게 되는지 — 강도현(E006)으로 확인 ``` ① 직원 "사번":"E006", "이름":"강도현", "연차부여일수":15 │ ├─ ② 휴가 L008 승인 3.0일 · L015 대기 2.0일 · L021 반려 5.0일 │ ├─ 비품 P001 승인 · P011 대기 · P016 반려 │ └─ ③ 급여 "급여번호":"PY202609-E006", "지급액":3100000 ``` **강도현 잔여연차 = 15 − 3.0 = 12.0일** → ①에서 부여 15일을 가져오고, ②에서 **사번이 E006 · 상태가 승인 · 종류가 연차/반차**인 줄의 일수만 더해 뺀 결과입니다. **어디에도 "12"라고 적어두지 않았습니다.** 대기 2일과 반려 5일은 **합쳐서 7일이나 되는데도** 잔여를 전혀 건드리지 않습니다. ### 이 파일에서 확인할 수 있는 것들 | 사번 | 이름 | 부여 | 사용 | 잔여 | 왜 그런가 | |---|---|---|---|---|---| | E006 | 강도현 | 15 | 3.0 | **12.0** | 연차 3일 **승인**분만 차감 (대기 2일·반려 5일은 무시) | | E009 | 한지우 | 15 | 0.5 | **14.5** | **반차**는 0.5일 | | E008 | 임재원 | 16 | 5.0 | **11.0** | 연차 5일 승인 · **병가 2일은 차감 안 함** | | E005 | 최유진 | 17 | 3.0 | **14.0** | 연차 3일 승인 · **병가 2일 승인돼도 차감 안 함** | | E001 | 김서연 | 20 | 3.5 | **16.5** | 연차 3일 + **반차 0.5일** | > 💡 **여기가 이 파일의 핵심입니다.** 임재원·최유진은 병가가 **승인까지 됐는데도** > 연차가 줄지 않았고, 강도현은 신청이 3건이나 있는데 **승인된 1건만** 반영됐습니다. > 숫자를 저장하지 않고 **계산하기 때문에** 이 규칙이 저절로 지켜집니다. ### ⚠️ 한 가지 예외 — 급여는 계산 결과를 저장합니다 §4 규칙 4번은 *"계산으로 나오는 값은 저장하지 않는다"* 였습니다. 그런데 이 파일의 급여명세에는 **`지급액`이 저장되어 있습니다.** 왜일까요? | 잔여연차 | 지급액 | |---|---| | 지금 상태를 보여주는 **현재값** | 그때 지급한 **과거 기록** | | 승인 한 번에 바뀌어야 정상 | **바뀌면 안 됨** (회계·세무 기록) | | → **계산한다** | → **찍어서 보관한다** | 급여는 이미 통장에 나간 돈입니다. 나중에 기본급 규정이 바뀌었다고 해서 2026년 9월 지급액이 따라 바뀌면 **안 됩니다.** 그래서 확정 시점의 금액을 **그대로 박아두고**, 상태를 `확정`으로 잠급니다. > 정리하면: **"지금 얼마인가"는 계산하고, "그때 얼마였나"는 저장한다.** --- ## 6. 우리 앱의 현재 상태 | 표 | 우리 앱에 있나 | 비고 | |---|---|---| | ① 직원 | ✅ 있음 (`DATA_EMP`, 12명) | 퇴사일·재직상태는 앱에서 생략 | | ② 휴가신청 | ✅ 있음 (`DATA_LEAVE`, 24건) | 상태 4가지 — 대기/승인/반려/**취소** | | ③ 급여명세 | ✅ **있음** (`DATA_PAY`, 12건) | 💰 메뉴에서 **조회 전용**으로 볼 수 있음 | | ④ 연차부여 | ❌ 없음 | ①에 합쳐 둠 (단순화) | | (총무) 비품·비품신청 | ✅ 있음 (10종 / 18건) | 구조는 ②와 **똑같음** — 신청 → 승인 → 숫자 차감 | > **급여에서 계산을 뺀 이유**: 4대보험료율·세액표가 해마다 바뀌고 복잡해서, > 계산까지 넣으면 "ERP의 구조"가 아니라 "급여 계산법"을 가르치는 수업이 되어 버립니다. > 그래서 앱의 급여 화면은 **보기만 하고 고칠 수 없게** 만들었습니다. ### 취소해도 줄을 지우지 않습니다 §7의 *"지우지 말고 상태로 표시하라"* 는 원칙을 **앱도 그대로 따릅니다.** 직원이 대기 중인 신청을 취소하면, 줄이 사라지는 게 아니라 상태만 `대기 → 취소`로 바뀝니다. | | 취소 전 | 취소 후 | |---|---|---| | 목록에 | 있음 (`⏳ 대기`) | **있음** (`⊘ 취소`) | | 잔여연차·재고 | — | **변동 없음** | | 담당자의 「처리할 신청」 | 있음 | **빠짐** | | 담당자의 「처리 완료」 | 없음 | **나타남** | --- ## 7. 자주 하는 실수 5가지 | 실수 | 왜 문제인가 | 어떻게 해야 하나 | |---|---|---| | 엑셀 한 장에 다 넣기 | 부서 바뀌면 수십 줄을 다 고쳐야 함 | 표 3개로 나누고 사번으로 연결 | | 이름을 열쇠로 쓰기 | 동명이인·개명에서 깨짐 | 사번을 쓴다 | | 잔여연차를 적어두기 | 승인할 때마다 손으로 고쳐야 하고, 반드시 어긋남 | **계산해서 보여준다** | | 빈칸에 0이나 "없음" 채우기 | 0일 처리된 것처럼 집계됨 | 빈칸으로 둔다 | | 퇴사자 줄을 지우기 | 과거 급여·휴가 기록이 통째로 사라짐 | 지우지 말고 **퇴사일·재직상태로 표시** | --- ## 8. 다음에 읽으면 좋은 것 - **`data/가상_인사총무.json`** — 이 문서 내용을 그대로 담은 **예제 파일** (직원 12 · 휴가 6 · 급여 12) - `PRD.md` §4 — 우리 앱의 실제 데이터 명세 (위 ①②를 그대로 구현한 것) - `PRD.md` §5 — 잔여연차·재고 계산 규칙 - `레퍼런스.md` §2 — Frappe HR이 휴가 배정(allocation)을 어떻게 분리해 두는지 --- ## 부록. 이 문서의 예제 데이터 요약 | 파일 | `data/가상_인사총무.json` (앱에서 뽑아낸 사본) | |---|---| | 기준월 | 2026-09 | | 직원 | 12명 (E001~E012, 4개 부서 × 3명) | | 휴가신청 | **24건** — 승인 14 · 대기 6 · 반려 4 | | 비품품목 | **10종** (재고 부족 4종) | | 비품신청 | **18건** — 승인 10 · 대기 5 · 반려 3 | | 급여명세 | 12건 — 12명 × 2026년 9월분 | | 급여 (전원 동일) | 기본급 300만 + 수당 20만 − 공제 10만 = **지급액 310만원** (12명 총 3,720만원) | | 세금·4대보험 | **계산하지 않음** (교육용 단순화) | | 주요 계산값 | 강도현 잔여 **12.0일** · 전사 소진율 **19.1%** | | 무결성 검사 | 주인 없는 줄 0 · 고유번호 중복 없음 · 지급액 12건 일치 · **앱 화면과 일치** |