5240구글 캘린더 연동
관리
← 개발기획문서초안↓ 내려받기

5240 ↔ 구글 캘린더 연동 — 기능정의서

버전 0.1 (2026-08-12) · 상태 개발 착수용 초안 전제 이 문서의 규칙은 대부분 google.insapien.co.kr 콘솔에서 이미 화면으로 구현해 확인한 것이다. 글로만 있는 규칙과 화면으로 확인한 규칙을 섞지 않기 위해, 각 항목에 근거를 함께 적는다.


0. 이 연동이 하는 일

5240 근태에 쌓인 휴가·출장·교육 일정을 구글 캘린더로 내보낸다. 단방향이다 — 구글 캘린더의 일정을 5240으로 들여오지 않고, 직원 개인 일정을 읽지도 않는다.

받는 쪽은 회사가 만든 공유 캘린더 하나이고, 직원은 그것을 각자 구독한다.

범위 밖 (명시적으로 제외)

제외 대상이유
근무일정(근무유형)기본근무·유일·휴무까지 매일 값이 있어 직원 수 × 365일이 쌓인다. 휴가가 그 속에 묻혀 캘린더가 못 쓰게 된다 — 연동량 과다이지 구현 난도가 아니다
교육계획신청(EDUT_PLAN_REQ/PLAN_REQ2)수강예정 년월만 있고 날짜가 없다. 확정 일정이 아니라 수요조사다
구글 → 5240 역방향하지 않는다
직원 개인 캘린더 직접 쓰기(도메인 전체 위임)기능은 설계에 있으나 이번 범위에서 잠근다. Workspace 최고관리자 승인과 보안 검토가 선행

근무일정을 되살릴 일이 생기면 UNION 하나를 더하는 일이 아니다. 근무일정조회 화면은 신청 테이블의 합집합이 아니라 일자별 우선순위를 적용한 결과 1건을 보여준다(조직 근무계획과 개인 신청이 겹치면 개인 신청 우선, 변경은 변경일자 이후만 반영). 근거: 근태 매뉴얼 「근무일정조회/근무일정표/근무시간표」.


1. 용어

용어뜻
연동함(tenant)고객사 하나. 서비스영역 ID(SERVAREA_ID) 하나에 연동 설정 한 벌이 붙는다
연동 계정5240에서 자료를 읽어 갈 때 쓰는 직원 계정. 이 계정의 조직조회권한이 곧 동기화 범위
갈래(branch)내보낼 일정의 종류 — 휴가 / 출장 / 교육
기간 창(window)내보낼 기간. 오늘 기준 과거 N개월 ~ 미래 M개월로 매 실행 시 다시 계산
대조(reconcile)기간 창 전체를 다시 읽어 캘린더와 맞추는 것. 없어진 것은 지우고 달라진 것은 고친다

2. 기능 목록

#기능주체비고
F-01연동함 등록·전환5240 운영서비스영역 ID 단위
F-02구글 계정 종류 판별 및 연동 방식 선택고객사 인사담당콘솔 1단계
F-03구글 OAuth 연결(클라이언트 등록·동의)고객사 인사담당콘솔 2단계 ①
F-04내보낼 범위·갈래·기간·상태 설정고객사 인사담당콘솔 2단계 ②
F-05내보내기 미리보기고객사 인사담당콘솔 3단계
F-06직원 안내문·공지문 생성고객사 인사담당콘솔 4단계
F-075240 일정 조회 API5240 제품신규 개발 — api-proposal/ 참조 구현 있음
F-08캘린더 동기화(생성·수정·삭제)연동 서버신규 개발 — 미구현
F-09동기화 결과 통지연동 서버실패·중단 시 담당자 메일
F-10준비 상태 점검(무엇이 막고 있나)콘솔구현됨

F-01~F-06, F-10은 콘솔에 이미 구현되어 동작한다. 신규 개발은 F-07·F-08·F-09다.


3. 대상 데이터

3.1 휴가 — TAAT_LEAV_REQ

이 테이블에는 휴가신청만 있는 것이 아니다. EAPT_RULE 기준 이 테이블을 쓰는 신청서는 셋이다.

APPL_CD신청서캘린더
1022휴가신청내보낸다
1122조퇴/외출 신청내보낸다
1123경조휴가신청내보낸다

조퇴/외출도 시스템 구조상 휴가다. 무엇을 감출지는 오로지 옵션 1426이 정한다 — 신청서 종류로 거르지 않는다. 따라서 EAPT_REQ 조인이 필요 없고, 테이블을 통째로 읽는다.

3.2 출장 — TAAT_BSTRIP_REQ

단일 테이블. 시작·종료 일시가 모두 있다.

3.3 교육 — EDUT_REQ + EDUT_HST2 (둘)

테이블무엇기간을 어디서 얻나
EDUT_REQ개설된 차수에 신청이 테이블에 없다 → EDUT_COURSN(과정·시작일·차수)에서 종료일, EDUT_COURS에서 과정명
EDUT_HST2과정명 직접입력(외부 교육)자체 보유(STA_YMD/END_YMD)

교육 과정명은 공통코드가 아니라 자유 문자열이라 CMMF_CODE_ML로 뽑을 수 없다. 갈래마다 TYPE_NM_RAW에 이름을 담아 올리고 NVL(TYPE_NM_RAW, CMMF_CODE_ML(...))로 받는다.

교육에는 최종수정일시 컬럼이 없다. CHG_DATE가 NULL이므로 증분 비교가 교육에는 듣지 않는다. 대조로만 맞춘다.


4. 업무 규칙

R-01 · 조회 범위는 연동 계정의 조직조회권한이 정한다

AUTT_SRCH_BASE(AUTH_TYPE_CD='111') + ORGF_LINE. 제품 홈 화면과 같은 패턴이다. 화면에서 전사를 골라도 권한 밖 직원은 나가지 않는다. 요청의 orgCd는 그 안에서 더 좁히기만 한다.

이유 — 인터페이스 키가 새더라도 전사 인사정보가 통째로 나가지 않게 하려는 것이다. 키는 "누구로서 조회하는가"까지만 정하고, 무엇이 보이는가는 제품의 권한 설정이 정한다.

R-02 · 조직은 하위조직을 포함하지 않는다

부서를 고르면 그 부서에 직접 속한 직원만 나간다. 하위 부서는 들어가지 않는다. inclOrgYn 같은 파라미터를 두지 않는다 — 받아 두면 언젠가 'Y'가 들어와 범위가 조용히 넓어진다.

⚠ 하위 불포함이라고 ORGF_LINE을 빼면 안 된다. 그 함수는 "요청 조직의 하위"가 아니라 "연동 계정에게 권한이 있는 조직의 하위" 를 계산하는 권한 경계다. 없애면 권한 밖 인사정보가 샌다. 이름이 닮아 혼동하기 쉬운 자리라 못박는다.

R-03 · 캘린더에 실리는 상태는 결재완료(30)가 기본

상태캘린더
10 임시저장나가지 않음
20 결재중설정에서 「결재중도 포함」을 켠 경우에만. 제목 앞에 [진행중]
30 결재완료나감
40 반려나가지 않음

API의 reqStatusCds 기본값은 30 이다. 기본을 20,30으로 두면 연동이 값을 빠뜨렸을 때 결재도 안 끝난 휴가가 조용히 나간다 — 빠뜨린 쪽이 안전한 값이어야 한다.

R-04 · 취소는 「응답에서 사라짐」으로 나타난다

5240에는 삭제도 변경도 없다. 취소만 있고, 취소 후에는 새로 결재를 받는다. 부분 취소는 없다 — 한 신청건은 통째로 살아 있거나 통째로 없다. 그래서 신청건 하나 = 캘린더 일정 하나가 성립한다.

→ 취소신청이 결재를 도는 동안 휴가 테이블에는 아무것도 늘지 않는다.

별도 표시를 붙이지 않는다.

근거(데모 데이터 대조, 2026-08-12)

취소신청서상태원건원건 상태
157830 승인157240
10125530 승인10125440
10124620 결재중10102230 유지

이미 나간 일정의 날짜·종류는 뒤에서 바뀌지 않는다. 유일한 변화는 20 → 30 전이이고, 그때 제목의 [진행중]만 뗀다.

R-05 · 무엇을 감출지는 옵션 1426(HIDE_LEAV_CDS)이 정한다

값뜻처리
CNFG_VAL01미표시 코드응답에 아예 넣지 않는다 — 연동 쪽에서 거를 기회를 주지 않는 편이 안전하다
CNFG_VAL02마스킹 코드MASK_YN='Y'로 표시해 내보낸다
CNFG_VAL03마스킹 표시명MASK_NM으로 함께 내보낸다

규칙을 연동 쪽에 복사해 두지 않는다 — 복사하면 제품과 기준이 갈린다.

MASK_YN만 받고 무엇으로 바꿔 쓸지 모르면 마스킹이 반쪽이 된다.

R-06 · 기간은 겹치면 뽑는다

STA_YMD <= endYmd AND END_YMD >= staYmd. 시작일만 보면 달을 걸친 휴가가 빠진다.

기간 창은 오늘 기준으로 매 실행 시 다시 계산된다(고정 날짜가 아니다). 상한 400일.

R-07 · 조회 실패와 빈 결과를 구분한다

retCode가 0이 아니면 연동은 캘린더를 건드리지 않는다. 빈 배열을 "휴가가 없다"로 읽으면 이미 등록한 일정을 몽땅 지운다.


5. 동기화 규칙 (F-08)

취소·미표시 전환이 모두 "응답에서 사라짐"으로 나타나므로, 동기화는 기간 창 스냅샷 대조다. 훅도 변경분 조회도 필요 없다.

대조 절차

  1. 기간 창 전체를 API로 읽는다
  2. 캘린더에서 이 연동이 만든 일정만 골라 온다
  3. 응답에 있고 캘린더에 없다 → 생성
  4. 양쪽에 있고 내용이 다르다 → 수정 (사실상 20→30 전이뿐)
  5. 캘린더에 있고 응답에 없다 → 삭제

안전장치 (필수)

#규칙이유
S-01이 연동이 만든 일정만 지운다. 이벤트마다 표식(신청번호·갈래·직원ID)을 남긴다사람이 손으로 넣은 일정을 지우면 안 된다
S-02조회 실패 시 아무것도 지우지 않는다R-07
S-03정상 응답 0건·급감도 의심한다. 삭제 예정 건수가 임계를 넘으면 중단하고 담당자에게 알린다권한 축소·조직 개편이면 오류 없이 0건이 온다 → 전 직원 일정 일괄 삭제 사고
S-04기간 창 안만 대조한다창이 하루씩 움직이므로, 창 밖까지 대조하면 멀쩡한 과거 일정을 "응답에 없다"고 지운다
S-05삭제 후 재생성이 아니라 수정한다직원이 걸어 둔 알림 설정이 사라지지 않는다. 단 교육은 CHG_DATE가 없어 증분 비교 불가

6. 고객사 설정 항목 (F-02~F-04)

항목값비고
계정 종류워크스페이스 / 개인 지메일방식보다 먼저 정한다. 관리 콘솔 유무로 판별
연동 방식공유 캘린더 / 담당자 확인용 / 도메인 위임(잠금)기본은 공유 캘린더
공유 방법주소를 받아 초대 / 링크 공개개인 지메일 조직에서만. 유출 위험을 고객사가 고른다
범위본인 / 부서 / 전사하위조직 불포함(R-02)
갈래휴가 / 출장 / 교육근무일정 없음
기간 창과거 N개월 / 미래 M개월오늘 기준 재계산
결재중 포함예 / 아니오R-03
캘린더 ID…@group.calendar.google.com

계정 종류가 가르는 것

워크스페이스개인 지메일
OAuth 동의화면내부 앱 — 게시·검증·테스터 한도·7일 만료 전부 없음외부 앱 강제 — 프로덕션 게시 필요
캘린더 공유 대상도메인·그룹에 한 번에주소를 받아 초대하거나 링크 공개
직원↔구글 계정 매핑회사 메일이 곧 구글 계정회사가 모르는 개인 주소 — 직원에게 받아야 함
도메인 전체 위임가능(잠금 상태)불가

OAuth 클라이언트는 고객사가 소유한다(2026-08-12 결정). 따라서 워크스페이스 고객사는 동의화면을 「내부」로 두어 게시·검증이 아예 필요 없다.


7. 인터페이스 요약

POST /getTaaCalendarApiList.do — 서버 간 호출. 기존 JSON API 24개와 같은 형식.

상세와 참조 구현(SQL·컨트롤러·서비스·요청/응답 샘플)은 docs/api-proposal/ 에 있다. 이 폴더는 제품 소스에 반영하지 않았고 실행해 본 적도 없다 — 컴파일·쿼리 실행 모두 미검증이다.


8. 열려 있는 결정

#항목누가
O-01마스킹 표시명이 비어 있을 때 캘린더에 무엇으로 내보낼지5240
O-02삭제 임계(S-03)를 몇 %로 둘지5240
O-03동기화 실행 주기와 실패 통지 방법5240
O-04초대 방식에서 직원 지메일 주소를 어디에 보관할지고객사·5240
O-05SERVAREA_ID 파라미터화(현재 콘솔 조회는 데모 300 고정)5240

부록 · 근거 자료

자료위치
준비사항 9항목(결정과 이유)콘솔 /prep · app/lib/prep.ts
API 참조 구현docs/api-proposal/
콘솔 설계 문서docs/superpowers/specs/2026-08-11-google-console-redesign-design.md
초기 검토(일부 무효 — 상단 정정 주석 참조)docs/2026-08-10-google-calendar-sync-plan.md
제품 리버스 문서kiwibox_eGov4.2/spec-docs, spec-db/Table/*
근태 매뉴얼tna-docs/