업로드와 검수 창구
Next.js 화면이 파일 업로드, 초안 검수, 조직도, 감사 기록을 보여준다. 손님이 서류를 내는 접수창구다.
실전 사례 03 · 인사 데이터 검수실
사람, 부서, 근무 비율이 한 줄에 섞인 엑셀은 편하지만 위험하다. HRIS는 조직을 방, 자리를 의자, 직원을 사람으로 나눠 장부에 담는다. 그리고 AI에게는 펜이 아니라 포스트잇만 준다 — AI는 원장을 직접 고치지 못하고 “이렇게 정리하면 좋겠다”는 초안만 붙인다. 최종 반영은 언제나 사람이 승인한다.
부품은 수업에서 본 그대로다. 화면(매장), 주방(백엔드), 장부(DB)가 각자 역할을 맡는다. 6교시 DB 데모에서 만든 사람/자리/근무기록 장부의 실전 버전이 바로 이 앱이다.
Next.js 화면이 파일 업로드, 초안 검수, 조직도, 감사 기록을 보여준다. 손님이 서류를 내는 접수창구다.
서버가 업로드 → 검증 → AI 초안 → 승인 요청 → 롤백을 정해진 순서로 처리한다. 함부로 원장에 손대지 않는 주방장이다.
조직(방), 자리(의자), 사람, 좌석 배치, 월별 근무 기록, 감사 기록이 PostgreSQL 장부에 나뉘어 남는다.
HRIS는 비개발자도 장부 구조를 이해하도록 안내 화면을 먼저 두고, 인사 엑셀은 별도의 Data Intake(자료 접수) 창구로만 받는다.
파이프라인은 컨베이어벨트다. 색 약속 그대로 주황=AI, 초록=저장, 회색=사람과 기계적 절차다. AI(주황)가 다섯 칸 중 한 칸뿐이라는 점이 이 앱의 핵심이다.
현장 HR이 쓰던 직원, 조직, 월별 근무 비율 엑셀을 접수창구에 올린다.
AI를 부르기 전에 시트, 열 이름, 샘플 행, 누락값을 기계적으로 먼저 읽는다. 서류 겉면 확인이다.
AI가 장부 구조와 파일 요약을 읽고 “이 열은 이 장부의 이 칸”이라는 정리 초안을 포스트잇으로 붙인다.
담당자가 초안을 보고 고치고, 관리자가 승인해야만 다음으로 간다. 원장 반영 전 마지막 관문이다.
승인된 내용만 장부에 들어가고, 누가 올리고 누가 승인했는지 감사 기록이 함께 남는다.
카드를 누르면 해당 교시로 돌아가 복습할 수 있다.
수업의 사람/자리/근무기록 장부 데모가 그대로 커진 앱이다. 엑셀 한 장을 여섯 장부로 나눈다.
2교시 · LLM 책상에 안전한 자료만2교시의 책상 그대로다. 단, 직원 개인정보 전체가 아니라 장부 구조와 샘플 몇 줄만 올려준다.
4교시 · 참고자료 RAG 대신 안전한 컨텍스트 설계문서를 검색해 오는 대신, 보여줄 자료를 사람이 미리 골라 고정한다. “무엇을 안 보여줄까”가 설계의 핵심이다.
5교시 · API 업로드와 승인의 통로화면은 파일과 선택값을 주문서(API 요청)로 보내고, 주방은 검수 세션과 초안을 응답서로 돌려준다.
1교시 · 토큰 비용 영수증철AI 초안 한 번마다 모델명, input/output 토큰, 예상 비용이 llm_usage_log 영수증철에 남는다.
6교시 · 감사 로그 장부 옆의 CCTV업로드, AI 분석, 승인, 롤백이 전부 audit_log에 남는다. 인사 데이터는 “되돌릴 수 있는 기록”이 생명이다.
이 지시서의 핵심은 “고쳐라”가 아니라 “정리 계획을 만들어라”다. 펜은 뺏고 포스트잇만 쥐여주는 문장들이다.
역할: HR 데이터 정리 분석가
절대 규칙:
- 원장(master data)을 직접 수정하거나 넣지 않는다.
- 사용자의 법인 범위(legal_entity_scope) 밖 데이터는
제안하지 않는다.
- 민감 필드는 표시만 하고, 사람이 확인할
질문을 만든다.
- 결과는 정해진 JSON 형식으로만 반환한다.
입력:
- 현재 DB 장부 구조 (live schema)
- 업로드 파일 요약 (시트, 열, 샘플 행)
- 사용자 권한과 법인 범위
{
"sourceClassification": "employee_master + org + fte",
"mappingSuggestions": [
{
"sourceColumn": "부서명",
"targetTable": "managing_org",
"targetColumn": "name"
}
],
"missingFields": ["legal_entity_code"],
"sensitiveFields": ["work_email"],
"questionsForLocalHr": [
"부서 코드가 전사 기준과 같은가요?"
],
"hrisUploadDraft": "review_required"
}
5교시에서 본 API 주문 창구 그대로다. 실제 파일 내용은 공개하지 않고, 오가는 서류의 모양만 보여준다.
{
"route": "/api/admin/data-intake",
"files": [
"employees.xlsx",
"org_units.xlsx",
"monthly_fte.xlsx"
],
"mode": "prepare_with_ai",
"legal_entity_scope": ["KR01"]
}
{
"session_id": "intake_2026_06_25_01",
"status": "review_required",
"file_count": 3,
"drafts": {
"org_units_to_create": 8,
"positions_to_create": 42,
"employee_rows": 3544
},
"logs": {
"llm_usage_log_id": "usage_881",
"audit_log_id": "audit_441"
}
}
2교시의 책상 그대로다. 다만 이 책상의 특징은 “올리는 것”보다 “안 올리는 것”이다. 직원 개인정보 원본은 책상에 올라오지 않는다.
원장 직접 수정 금지, 민감 필드 표시, JSON 출력 형식을 고정하는 금지선 종이.
로그인한 담당자의 역할과 접근 가능한 법인. AI가 이 범위를 넘지 못하게 한다.
현재 DB의 테이블, 칸, 연결 규칙. 오래된 문서가 아니라 실제 장부 구조가 기준이다.
업로드 파일의 시트명, 열 이름, 샘플 몇 줄, 누락 패턴. 원본 전체가 아니라 요약본이다.
열↔장부 연결 초안, 사람에게 물어볼 질문, 민감 필드 표시 — 그리고 비용 영수증 한 장.
6교시에서 배운 “역할별 장부 나누기”가 실전에서는 이렇게 된다. 엑셀 한 장이 여섯 장부로 나뉜다.
| 장부 | 역할 | 비유 |
|---|---|---|
| managing_org | 부서와 팀 구조 저장 | 방 |
| position | 조직 안의 역할 자리 저장 | 의자 |
| person | 실제 사람의 신원 카드 저장 | 사람 |
| assignment | 누가 어느 의자에 앉았는지 기록 | 좌석 배치표 |
| assignment_fte_period | 월별 실제 근무 비율 기록 | 월별 근무 기록 |
| audit_log | 변경과 승인 이력 기록 | CCTV 기록 |
사람, 자리, 월별 근무 비율이 한 줄에 섞이면 중복과 오류가 쌓인다. 장부를 나누고 연결하는 것이 DB의 일이다.
AI가 원장을 직접 고치면 사고를 되돌릴 수 없다. 초안을 만들게 하고, 반영은 사람 승인 뒤에만 한다.
인사 데이터는 민감하다. 누가 요청했고 누가 승인했는지 audit_log에 남아야 나중에 되돌릴 수 있다.