요약 — 마감과 정산처럼 달의 경계에 맞춰 반복되는 업무는 규칙이 단순하지만 실행은 자주 흔들립니다. EOMONTH
와 EDATE
를 표준 도구로 삼아 월말 기준일과 특정 일자를 자동 계산해 두면, 달력이 바뀌어도 스케줄이 스스로 업데이트되고 리마인더까지 함께 굴러갑니다. 이 글은 월말 오프셋과 월중 특정일 두 축을 중심으로 스케줄을 설계하고, 주말 보정과 알림일 산정까지 포함한 끝단까지의 공식을 제공합니다.
다운로드
- 샘플 작업 목록 CSV: D3_eomonth_sample_tasks.csv
- 확장 스케줄 결과 CSV: D3_eomonth_result_schedule.csv
샘플 데이터 설명
샘플은 반복 업무를 최소 단위로 정의한 작업 테이블입니다. 각 행은 주기와 마감 규칙을 담습니다. 결과 파일은 6개월 범위로 작업이 전개된 스케줄 테이블입니다.
작업 테이블 D3_eomonth_sample_tasks.csv
컬럼 | 의미 | 예시 | 설명 |
---|---|---|---|
task_id |
작업 식별자 | T01 | 행 고유 키 |
task_name |
작업명 | VAT 보고서 마감 | 사내 용어 그대로 |
anchor_date |
기준 시작월 | 2025-07-01 | 이 달부터 주기 전개 |
cycle_months |
반복 주기 | 1 | 1은 매월, 3은 분기 |
rule_type |
마감 규칙 종류 | M_END_OFFSET | 월말 기준 또는 월중 특정일 |
offset_days |
월말 기준 오프셋 | -2 | 월말 전후 일수. 월말 이틀 전은 -2 |
day_in_month |
월중 일자 | 15 | rule_type이 DAY_OF_MONTH일 때 사용 |
shift_weekend |
주말 보정 | YES | 마감일이 토일이면 전 영업일로 당김 |
lead_days_before_due |
알림 리드일 | 3 | 마감 며칠 전 알림일 산정 |
notes |
비고 | 월말 이틀 전 마감 | 설명 기록 |
스케줄 테이블 D3_eomonth_result_schedule.csv
컬럼 | 의미 | 예시 | 계산 개념 |
---|---|---|---|
period_month |
대상 월의 첫날 | 2025-09-01 | anchor에서 주기만큼 EDATE |
due_date |
해당 월의 마감일 | 2025-09-28 | 월말 오프셋 또는 지정 일자, 주말 보정 포함 |
reminder_date |
알림일 | 2025-09-23 | due_date에서 리드일 차감 |
rule_type |
적용 규칙 | M_END_OFFSET | 월말 기준 |
offset_days |
오프셋 | -2 | EOMONTH 결과에 더함 |
day_in_month |
월중 일자 | 15 | 해당 일자 또는 말일로 보정 |
shift_weekend |
주말 보정 | YES | 토일이면 이전 영업일 |
설계의 핵심 사고방식
- 월 시퀀스를 먼저 만든다 — 기준월의 첫날 하나만 있으면
EDATE
로 원하는 개수만큼 월을 펼칠 수 있습니다. - 마감일을 두 가지 규칙으로 통합한다 — 월말 오프셋과 월중 특정일을 하나의 수식 블록에서 분기합니다.
- 주말 보정은 마지막에 한 번 — 보정 전 날짜가 확정된 다음에만
WORKDAY.INTL
로 전 영업일 보정을 적용합니다. - 알림일은 마감일의 파생값 — 마감일에서 리드일만큼 뺀 값을 별도 열로 둡니다.
Excel 365 공식
기준월의 첫날이 B2
라면 6개월 시퀀스는 다음처럼 만듭니다.
=EDATE(EOMONTH($B$2,-1)+1, SEQUENCE(6,1,0,1))
스케줄 표에서 행별로 마감일을 계산하는 일반형입니다. 표 구조 참조를 사용합니다.
=LET(
p, [@period_month],
rule, [@rule_type],
off, [@offset_days],
dim, [@day_in_month],
base, IF(rule="M_END_OFFSET",
EOMONTH(p,0)+off,
MIN(DATE(YEAR(p),MONTH(p),dim), EOMONTH(p,0))
),
adj, IF(AND([@shift_weekend]="YES", WEEKDAY(base,2)>5),
WORKDAY.INTL(base,-1),
base
),
adj
)
알림일은 아주 간단합니다.
=[@due_date] - [@lead_days_before_due]
Google Sheets 공식
기준월의 첫날이 B2
라면 다음으로 6개월 시퀀스를 만듭니다.
=EDATE(EOMONTH($B$2,-1)+1, SEQUENCE(6))
행별 마감일 일반형입니다. 참조 열 주소만 시트에 맞게 조정하십시오.
=LET(
p, C2,
rule, D2,
off, E2,
dim, F2,
base, IF(rule="M_END_OFFSET",
EOMONTH(p,0)+off,
MIN(DATE(YEAR(p),MONTH(p),dim), EOMONTH(p,0))
),
adj, IF(AND(G2="YES", WEEKDAY(base,2)>5), WORKDAY.INTL(base,-1), base),
adj
)
알림일은 다음과 같습니다.
=H2 - I2
규칙 검증 체크리스트
-- 분기 작업이 매 3번째 달에만 나타나는지
=COUNTIF(FILTER(스케줄[task_id], 스케줄[task_id]="T05"), "T05") = 2 -- 6개월 전개라면 2번
-- 월말 오프셋 결과가 해당 월 범위를 벗어나지 않는지
=AND(
스케줄[due_date] >= 스케줄[period_month],
스케줄[due_date] <= EOMONTH(스케줄[period_month],0) + MAX(0, 스케줄[offset_days])
)
-- 주말 보정이 제대로 동작하는지
=COUNTIF(스케줄[due_date], "=토" ) + COUNTIF(스케줄[due_date], "=일") = 0 -- 요일 표시 형식에서 확인
실무 팁과 주의점
- DAY_OF_MONTH는 말일을 넘지 않게 — 31일 같은 값이 짧은 달에서 문제를 일으키지 않도록
MIN(DATE(...), EOMONTH(...))
로 안전장치를 넣으세요. - 주말 보정 방향을 정책으로 고정 — 본문은 이전 영업일로 당기는 방식을 썼습니다. 조직에 따라 다음 영업일로 미는 방식이라면
WORKDAY.INTL(base,1)
로 바꾸면 됩니다. - 휴일 달력과 결합 — 법정 공휴일까지 고려하려면
WORKDAY.INTL
의 네 번째 인자로 휴일 범위를 넘기면 됩니다. - 리드일은 숫자 열로 유지 — 알림일 수식이 텍스트에 걸리지 않도록 반드시 숫자 열로 관리합니다.
재현 가이드
- 작업 테이블 CSV를 불러오고 표 이름을 Tasks로 지정합니다.
- 첫 행의
anchor_date
를 기준으로 기준월 첫날을 구해 옆 열에 배치합니다.=EOMONTH([@anchor_date],-1)+1
- 시퀀스 열을 만들어 6개월을 펼치고,
cycle_months
에 맞지 않는 달은 숨기거나 필터링합니다. rule_type
분기에 따라 마감일을 계산하고, 필요하면 주말 보정과 알림일을 추가합니다.
마무리
마감 규칙은 두 가지뿐입니다. 월말 기준 오프셋과 월중 지정일. EOMONTH
는 말일을 정확하게 잡아 주고, EDATE
는 달을 흔들림 없이 이동시킵니다. 이 두 축을 중심으로 수식을 모듈화하면 스케줄은 사람이 아닌 규칙이 운영하게 됩니다. 위 CSV를 내려받아 본문 공식을 그대로 적용해 보십시오. 기준월만 바뀌어도 리포트 달력 전체가 자동으로 따라오는 경험을 바로 얻을 수 있습니다.