# 데이터 매핑 사양

**버전** 0.1 (2026-08-12) · **상태** 개발 착수용 초안
**대상** 5240 조회 응답 한 건이 구글 캘린더 이벤트 하나가 되기까지.

이 문서는 **F-08(캘린더 동기화)** 를 만드는 사람이 본다. 규칙의 근거는 기능정의서 R-01~R-07에 있다.

---

## 0. 전제 — 신청건 하나 = 이벤트 하나

5240에는 **삭제도 변경도 없고 취소만 있으며, 부분 취소가 없다.** 고치려면 취소하고 새로
신청하므로 그것은 다른 신청번호의 새 건이다. 따라서 **신청건과 캘린더 이벤트는 1:1**이고,
이미 만든 이벤트의 날짜·종류가 뒤에서 바뀌는 일이 없다.

바뀌는 것은 **결재중(20) → 결재완료(30) 전이 하나뿐**이고, 그때 제목의 `[진행중]`만 뗀다.

이 전제가 매핑을 단순하게 만든다. 병합·분할·기간 조정이 필요 없다.

---

## 1. 이벤트 식별 표식 — 가장 먼저 정할 것

대조 삭제(S-01)가 안전하려면 **"이 이벤트를 우리가 만들었는가"** 를 이벤트만 보고 판별할 수
있어야 한다. 사람이 손으로 넣은 일정을 지우면 되돌릴 방법이 없다.

구글 캘린더 이벤트의 `extendedProperties.private`에 다음을 넣는다.

| 키 | 값 | 쓰임 |
|---|---|---|
| `x5240` | `"1"` | **우리가 만든 것인가** — 이 키가 없으면 어떤 경우에도 건드리지 않는다 |
| `servareaId` | 예: `300` | 연동함 식별. 한 캘린더를 여러 연동함이 쓰는 사고를 잡는다 |
| `kind` | `LEAV` / `BSTRIP` / `EDU` | 갈래 |
| `reqNo` | 예: `101254` | 신청번호 — 대조의 열쇠 |
| `staffId` | 예: `100:2007:00204:kkHT` | 누구 것인가 |
| `srcStatus` | `20` / `30` | 만들 때의 결재상태. 20→30 전이 감지에 쓴다 |

- **대조 키는 `(servareaId, kind, reqNo)`** 다. 이 조합이 같으면 같은 일정이다.
- `private`에 넣는 까닭 — 이벤트를 구독하는 직원에게 보이지 않는다. `shared`에 넣으면
  직원 캘린더에 내부 식별자가 노출된다.
- 표식 없는 이벤트는 **읽지도 지우지도 않는다.** 사람이 넣은 것으로 본다.

---

## 2. 공통 필드 매핑

| 캘린더 필드 | 값 | 비고 |
|---|---|---|
| `summary` | 아래 **3. 제목 규칙** | |
| `start` / `end` | 아래 **4. 날짜와 시간** | 종일이 기본 |
| `description` | 비운다 | 사유(`REASON`)는 **넣지 않는다** — 개인정보이고 옵션 1426의 통제 밖이다 |
| `location` | 비운다 | 출장지도 넣지 않는다(가림 규칙이 없으므로 제목에만 최소로) |
| `transparency` | `transparent` | 회사 휴가가 직원 개인 일정의 "바쁨"을 덮지 않게 한다 |
| `visibility` | `default` | 캘린더 자체의 공개 설정을 따른다 |
| `reminders` | 끔(`useDefault: false`, 목록 비움) | 남의 휴가에 알림이 울리면 안 된다 |
| `extendedProperties.private` | **1. 표식** | |

> **`description`을 비우는 것은 의도된 결정이다.** 담을 것이 없어서가 아니라, 한 번 담기
> 시작하면 무엇을 담을지의 기준이 옵션 1426 바깥에 하나 더 생기기 때문이다.

---

## 3. 제목 규칙

```
[진행중] 홍길동 · 연차
└─ 20일 때만  └─ 직원명  └─ 표시명
```

| 요소 | 규칙 |
|---|---|
| `[진행중] ` | `REQ_STATUS_CD = '20'` 일 때만 앞에 붙인다. 30이면 없다 |
| 직원명 | `STAFF_NM` |
| 구분자 | ` · ` (가운뎃점, 앞뒤 공백) |
| 표시명 | 마스킹 대상이면 `MASK_NM`, 아니면 `TYPE_NM` |

**마스킹 치환**

| `MASK_YN` | 제목에 쓰는 이름 |
|---|---|
| `N` | `TYPE_NM` (예: `연차`) |
| `Y` | `MASK_NM` (예: `기타휴가`) |
| `Y` 인데 `MASK_NM`이 비었다 | **O-01 미결** — 정해야 한다. 잠정 `휴가`를 권한다 |

- 미표시 대상(`CNFG_VAL01`)은 **응답에 아예 오지 않는다.** 연동이 거를 일이 없다.
- 갈래별 표시명 출처는 아래 5장.

---

## 4. 날짜와 시간

**기본은 종일 이벤트**다. 근태 일정은 시각보다 "그날 자리에 없다"가 중요하다.

| 조건 | 이벤트 형태 |
|---|---|
| 반차 아님(`STA_HALF_YN='N'`, `END_HALF_YN='N'`) | **종일** — `start.date = STA_YMD`, `end.date = END_YMD + 1일` |
| 반차이고 `STA_HM`/`END_HM`이 있다 | **시간** — `start.dateTime`, `end.dateTime` (타임존 `Asia/Seoul`) |
| 반차인데 시각이 없다 | **종일**로 두고 제목 끝에 ` (반차)` 를 붙인다 |

> ⚠ **구글 종일 이벤트의 `end.date`는 배타적이다.** 8/10 하루 휴가는
> `start.date=2026-08-10`, `end.date=2026-08-11`이다. 여기서 하루를 빼먹으면 **모든 휴가가
> 하루씩 짧게** 보인다 — 가장 흔한 실수다.

---

## 5. 갈래별 매핑

### 5.1 휴가 (`kind = LEAV`)

| 응답 필드 | 이벤트 |
|---|---|
| `STAFF_NM` | 제목의 직원명 |
| `TYPE_NM` / `MASK_NM` | 제목의 표시명 |
| `STA_YMD` / `END_YMD` | 기간 |
| `STA_HM` / `END_HM` | 반차일 때 시각 |
| `REQ_NO` | 표식 `reqNo` |

휴가 테이블에는 **휴가신청(1022)·조퇴/외출(1122)·경조휴가(1123)** 가 함께 쌓이며 **셋 다
내보낸다.** 신청서 종류를 구분하지 않으므로 매핑도 하나다.

### 5.2 출장 (`kind = BSTRIP`)

휴가와 같다. 표시명은 `TAA_BSTRIP_TYPE_CD` 공통코드에서 온다.
**가림 규칙이 없다** — 출장 구분이 그대로 나간다.

### 5.3 교육 (`kind = EDU`)

| 출처 | 표시명 | 기간 |
|---|---|---|
| `EDUT_REQ` | `EDUT_COURS.EDU_NM`(과정명) | `EDUT_COURSN.END_YMD` |
| `EDUT_HST2` | `EDU_NM`(직접입력) | 자체 `STA_YMD`/`END_YMD` |

API 응답에서는 둘 다 `TYPE_NM`(= `TYPE_NM_RAW`)으로 평탄화되어 온다. 연동은 구분할 필요가 없다.

> **교육에는 `CHG_DATE`가 없다(NULL).** 증분 비교가 듣지 않으므로 **대조로만** 맞춘다.

---

## 6. 대조 동작

| 상태 | 판정 | 동작 |
|---|---|---|
| 응답에 있고 캘린더에 없다 | 새 신청 | **생성** |
| 양쪽에 있고 `srcStatus`가 20인데 응답은 30 | 결재 완료됨 | **수정** — 제목의 `[진행중]` 제거, 표식 `srcStatus`를 30으로 |
| 양쪽에 있고 나머지가 같다 | 변화 없음 | **건드리지 않는다** |
| 캘린더에 있고 응답에 없다 | 취소승인 / 1426 미표시 전환 / 범위 밖 | **삭제**(단 S-02~S-04 확인 후) |
| 표식이 없다 | 사람이 만든 일정 | **건드리지 않는다** |

**수정은 `patch`로 한다.** 지웠다 다시 만들면 직원이 걸어 둔 알림·색상 설정이 사라진다.

---

## 7. 열린 항목

| # | 항목 | 비고 |
|---|---|---|
| O-01 | `MASK_NM`이 비었을 때 쓸 이름 | 잠정 `휴가` 제안 |
| M-01 | 반차인데 시각이 없을 때 ` (반차)` 표기를 쓸지 | 화면 문구와 맞춰야 함 |
| M-02 | 한 캘린더를 여러 연동함이 가리키는 것을 막을지 | 표식 `servareaId`로 감지는 되나 차단 정책 미정 |
