사용법
**Parser** 탭에 5필드 cron 표현식을 붙여 넣으면 각 필드 — 분(0–59), 시(0–23), 일(1–31), 월(1–12 또는 `JAN-DEC`), 요일(0–6 또는 `SUN-SAT`, 일요일이 0) — 을 검증하고 다음 N회의 실행 시각을 출력합니다. 지원 구문: `*`(모두), 범위 `a-b`, 리스트 `a,b,c`, 스텝 `*/n`과 `a-b/n`, 대소문자 무시 월·요일 이름. 일과 요일을 모두 제한했을 때 본 파서는 Vixie cron의 OR가 아닌 **AND**(POSIX 동작)를 채택합니다. 트레이드오프는 FAQ를 참고하세요.
**Builder** 탭에서는 빈도 선택기로 표현식을 조립할 수 있습니다. *매분·매시·매일·매주·매월·매년*을 고르고 조건을 좁히면 됩니다. 예를 들어 "15분마다, 평일만, 09:00–17:00"은 `*/15 9-17 * * 1-5`를 생성합니다. 다음 실행 미리보기는 호스트 브라우저의 로컬 타임존을 사용하므로 같은 타임존의 서버에서 `/etc/crontab`이 동작하는 결과와 일치합니다. 운영 cron이 UTC로 동작한다면 배포 전에 오프셋을 머릿속으로 조정하세요. 파서는 자체 완결적이며 — 네트워크 요청이나 외부 cron 라이브러리 없음 — 표현식과 기기의 벽시계 시각은 페이지 밖으로 나가지 않습니다.
예제
매시 정각 유지보수 훅
입력
expression: 0 * * * *
starting: Mon 2026-05-18 14:00 local time
preview: next 5 runs
출력
Mon 2026-05-18 15:00
Mon 2026-05-18 16:00
Mon 2026-05-18 17:00
Mon 2026-05-18 18:00
Mon 2026-05-18 19:00
`0 * * * *`는 "매시 정각"의 표준 표현입니다 — 분을 0으로 고정하고 다른 필드는 모두 `*`입니다. 흔한 실수는 "매시" 의도로 `* * * * *`를 쓰는 것으로, 실제로는 매분 실행됩니다(60배 잦음). 진짜 매시 실행을 원한다면 분 필드를 고정하세요. 1시간보다 짧은 주기에는 `*/15`나 `0,15,30,45`를 씁니다. 정각 정렬 일정에서는 둘이 동등하지만 Vixie cron에서는 `0,15,30,45`가 HUP·재시작 타이밍을 가로질러 정확하게 남고, `*/15`는 crontab 파싱 시점에 한 번만 읽힙니다.
평일 영업시간 폴링
입력
expression: */15 9-17 * * 1-5
interpret: every 15 minutes, 09:00–17:45, Monday–Friday
preview: next 4 runs after Fri 2026-05-15 17:45
출력
Mon 2026-05-18 09:00
Mon 2026-05-18 09:15
Mon 2026-05-18 09:30
Mon 2026-05-18 09:45
# Note: 17:00–17:45 inclusive on Friday, then the cron sleeps the entire
# weekend and resumes Monday 09:00. The 4× /hour cadence × 9 active hours
# × 5 weekdays = 180 fires per week.
영업시간 헬스체크의 전형적인 예입니다. 시간 범위 `9-17`은 *양 끝을 포함*하므로 17:45도 실행됩니다. 요일 `1-5`는 월요일부터 금요일을 의미합니다(일요일=0, 토요일=6). `*/15 9-17`의 조합은 시간당 4회 × 9시간 = 평일 1일 36회, 주 180회입니다. 야간 유휴 전에 18:00 정각에 마지막 실행이 필요하다면 OR로 추가합니다. `0,15,30,45 9-17 * * 1-5`로 바꾸고 `0 18 * * 1-5`를 별도 줄로 추가하세요. 하나의 표현식으로 서로 다른 시 패턴을 OR로 묶을 수는 없습니다.
월말 보고서 — 일/요일 함정
입력
expression: 0 9 28-31 * 1
interpret: POSIX (AND) — only when the 28th-31st is also a Monday
Vixie (OR) — every day 28-31 OR every Monday출력
POSIX behavior (this parser):
Mon 2026-12-28 09:00 # 28th is a Monday
Mon 2027-03-29 09:00 # next 28-31 + Monday match
...
Vixie crond behavior (most Linux distros):
Every day 28-31 of any month
PLUS every Monday
≈ 4 + 4 = 8 fires per month on average
가장 많이 언급되는 cron 함정입니다. POSIX 표준은 일과 요일이 모두 제한되면 AND(교집합)로 처리하지만, 대부분의 Linux 배포판에 포함되는 Vixie cron(`cronie` / `cron`)은 OR(합집합)로 처리합니다. 동일한 표현식이 로컬 테스트와 운영 서버에서 5배 잦게 실행될 수 있습니다. 두 필드를 모두 제한한 표현식은 본 파서로 한 번 점검하세요. 진짜 월말 작업이 필요하다면 `0 9 28-31 * *`처럼 요일을 `*`로 두고 작업 본체에 날짜 확인을 넣으세요. `[ "$(date -d tomorrow +%d)" = "01" ] && run.sh`는 *진짜 마지막 날*에만 실행합니다.
자주 묻는 질문
여기는 5필드인데 다른 곳에서 6필드나 7필드 표현식을 보는 이유는?
표준 Unix cron — Linux·BSD·macOS의 `/etc/crontab`이 파싱하는 형식 — 은 5필드(분·시·일·월·요일)를 사용합니다. 6필드 버전은 앞에 **초** 필드를 추가한 것으로 Quartz Scheduler(Java)와 다수의 AWS·Spring 스케줄러가 받습니다. 7필드 버전은 뒤에 **년** 필드를 추가한 Quartz 전용입니다. 앞에 초를 두는 형식은 `WithSeconds` 옵션을 켠 robfig/cron 같은 일부 Go 라이브러리도 사용합니다. 6필드 표현식을 여기에 붙이면 "필드 과다" 오류가 납니다. 초(또는 년)를 빼고 분 이후 가운데 5필드만 파싱하세요. 표준 `crond`는 어떤 방언이든 분당 1회보다 빠르게 실행할 수 없습니다.
cron은 `@daily`, `@reboot` 같은 단축 표기를 지원하나요?
Vixie cron은 7개의 별칭을 지원합니다. `@yearly` / `@annually`(= `0 0 1 1 *`), `@monthly`(= `0 0 1 * *`), `@weekly`(= `0 0 * * 0`), `@daily` / `@midnight`(= `0 0 * * *`), `@hourly`(= `0 * * * *`), `@reboot`(시스템 부팅 시 1회). 별칭은 Vixie 확장이며 POSIX에는 없으므로 일부 Docker 베이스 이미지에 들어 있는 최소 busybox-cron에서는 동작하지 않을 수 있습니다. 본 파서는 별칭을 받지 **않습니다**. 펼친 5필드 형식으로 붙여 넣으세요. `@reboot`은 등가 표현식이 없으며 시간 트리거가 아닌 이벤트 트리거(부팅)입니다. 같은 "부팅 시 1회" 의미는 `OnBootSec`을 사용하는 systemd timer가 현대적 대안입니다.
이 파서는 어떤 타임존을 사용하나요? 운영 cron은 UTC로 동작합니다.
다음 실행 미리보기는 브라우저의 로컬 타임존(`Intl.DateTimeFormat().resolvedOptions().timeZone`에서 가져옴)을 사용합니다. 서버가 UTC로 동작하고 브라우저가 JST나 KST라면 미리보기는 실제 서버 실행보다 9시간 뒤를 표시합니다. 대부분의 현대 cron은 환경 변수 `CRON_TZ=...`이나 `TZ=...`을 인식합니다. `/etc/crontab`에서 줄별 또는 전체로 설정할 수 있습니다. systemd timer에서는 `OnCalendar=` 지시자가 `OnCalendar=Mon..Fri 09:00 Asia/Tokyo`처럼 명시적 타임존을 받습니다. 일광 절약 시간(DST)이 문제를 더 어렵게 합니다. DST를 채택하는 지역에서 로컬 02:30로 예약된 작업은 봄철 시계 전진일에는 건너뛰고 가을철 시계 복귀일에는 2회 실행됩니다(소박한 cron 기준). 운영 작업을 UTC로 돌리는 것이 표준 권장인 이유입니다.
`*/5`는 `0/5`나 `0,5,10,15,...`과 어떻게 다른가요?
분 필드에서는 세 형식 모두 POSIX/Vixie cron에서 동등합니다. 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55분에 실행됩니다. 차이는 시작점이 0이 아니거나 비표준 범위에서 나타납니다. `5/15`(Quartz)는 "5에서 시작해 15마다" → 5, 20, 35, 50을 의미하며 `*/15`는 이걸 *생성하지 않습니다*. `1-30/5`는 "1–30 사이에서 5분마다" → 1, 6, 11, 16, 21, 26입니다. POSIX/Vixie cron은 `a-b/n` 형식을 지원하지만 `a/n`(시작 + 스텝) 형식은 지원하지 않습니다. 그것은 Quartz 확장입니다. 의심스러우면 명시적 리스트 `0,5,10,...`로 펼쳐 최대 이식성을 확보하세요. 분을 건너뛰고 싶을 때도 리스트가 유용합니다 — `0,3,6,9`는 불규칙 간격으로 시간당 4회 실행됩니다.
Linux의 cron이 파서 예측과 다른 날에 실행되는 이유는?
거의 확실히 예시 3에서 다룬 DOM/DOW 불일치입니다. 본 파서는 POSIX 표준(AND)을 따르지만 대부분의 Linux 배포판에 포함된 cron 데몬은 Vixie 관습(OR)을 따릅니다. 서버에서 확인하려면 `man 5 crontab`을 실행하고 "day-of-week"를 검색하세요. 매뉴얼 페이지에 로컬 동작이 명시되어 있습니다. 다른 원인 가능성: 편집 환경과 서버의 타임존 불일치(위 UTC FAQ 참고), `cron`이 실행 중이 아님(`systemctl status cron`), 메일이 설정되지 않아 `MAILTO=`가 조용히 실패, 사용자의 `PATH`에 `/usr/local/bin`이 없어 스크립트의 셔뱅은 해결되지만 첫 명령이 실패 등. 표현식 의미를 디버그하기 전에 먼저 `* * * * * date >> /tmp/cron.log`를 테스트 crontab에 추가해 cron 자체가 동작하는지 확인하세요.
cron 대 systemd timer 대 Kubernetes CronJob은 어떻게 선택하나요?
**cron**은 `/etc/crontab`과 가동시간을 직접 관리하는 단일 Linux 호스트에서 셸 스크립트 스타일의 자동화(로그 회전, 백업, 단순 폴링, 취미 프로젝트)에 적합합니다. **systemd timer**는 이미 서비스를 systemd로 관리 중이고 `journalctl`로 통합 로깅, 의존 순서(`network-online.target` *이후*), 동시 실행을 피하기 위한 랜덤 지연, 재부팅을 가로지른 미실행 작업의 영속화(`Persistent=true`)가 필요할 때 씁니다. **Kubernetes CronJob**은 워크로드가 클러스터에서 동작할 때 — Pod 단위 리소스 격리, 자동 재시작·재시도, 평소의 k8s 도구를 통한 가시성이 장점이지만 작은 작업에도 10~30초의 콜드 스타트 지연이 비용입니다. 클러스터 없이 클라우드 네이티브한 단발 작업에는 **AWS EventBridge Scheduler**, **Cloud Scheduler**, **Azure Logic Apps** 모두 cron 형식 표현식을 받으며 작업이 유휴인 동안에는 컴퓨팅을 돌리지 않아도 됩니다.
관련 개념
cron은 AT&T 벨 연구소에서 7판 Unix(1979년)의 일부로 탄생했으며 Brian Kernighan이 작성한 것으로 전해집니다. 원조는 `/usr/lib/crontab`을 분당 1회 스캔해 일치하는 항목을 exec하는 데몬이었습니다. **Paul Vixie의 재작성**(1987년)이 사용자별 crontab, 월·요일 명명 별칭, `@daily` / `@reboot` 닉네임, 그리고 다음 해 발표된 POSIX 표준에서 어긋난 **DOM + DOW의 OR 의미**를 도입했습니다. Vixie cron은 Linux와 BSD의 사실상 표준이 되었으며 현대 파생으로 `cronie`(Red Hat / Fedora), `bcron`(Debian), `dcron`(Alpine, Slackware)이 있습니다. POSIX 엄격 구현은 주로 상용 Unix와 임베디드 busybox-cron에 있습니다. DOM/DOW 불일치는 가장 많이 인용되는 cron 함정이며 POSIX 자체보다 7년 정도 앞섭니다.
**형식 자체에도 방언**이 필드 수를 넘어 존재합니다. `JAN-DEC`과 `SUN-SAT` 별칭은 Vixie 확장으로 POSIX에는 없고, Quartz Scheduler는 초 필드, 연도 필드, 특수 문자 `L`(마지막), `W`(평일), `#`(월의 N번째 요일), `?`(DOM/DOW에 값 미지정)을 추가합니다. AWS EventBridge는 Quartz 의미를 따르면서 `?` 요구사항을 추가합니다. Spring의 `@Scheduled`는 또 다른 변형입니다. cron 표현식을 시스템 간 복사할 때는 필드 수, DOM/DOW 의미, 명명 별칭 지원 여부를 확인하세요. 한 시스템에서 동작하는 표현식이 다른 시스템에서는 조용히 오작동하거나 파싱을 거부할 수 있습니다.
세 가지 **현대 대안**이 서로 다른 영역에서 cron의 자리를 잠식하고 있습니다. **systemd timer**는 systemd로 관리되는 Linux 서버(2015년 이후 대부분의 배포판)에서 cron을 대체합니다. unit 시스템과 통합되고 journald로 로깅하며 무작위화와 영속화를 지원하고 더 읽기 쉬운 `OnCalendar=Mon..Fri 09:00` 구문을 받습니다. **Kubernetes CronJob**은 컨테이너화된 워크로드에 Pod 격리와 재시도 정책을 갖춘 cron 의미를 가져옵니다. **클라우드 매니지드 스케줄러**(AWS EventBridge Scheduler, Google Cloud Scheduler, Azure Logic Apps Scheduler)는 cron 표현식을 받으면서 매니지드 인프라에서 실행되어 상시 가동 호스트를 없앱니다. 애플리케이션 내부 작업 스케줄링에는 Java의 Quartz, Python의 APScheduler, Go의 robfig/cron, Node의 node-cron 같은 라이브러리가 cron 의미를 직접 내장합니다. 이런 대안이 있어도 소박한 crontab은 모든 Unix 계열 머신에서 계속 살아 있습니다. 작은 표면적과 `/etc/crontab`의 단순함이 대부분의 대체재보다 오래 살아남게 할 것입니다.