cron parse schedule cron-expression

Cron 표현식 마스터하기: 궁극의 온라인 Cron 파서

온라인 Cron 파서로 복잡한 Cron 작업을 쉽게 해독하세요. 사람이 읽을 수 있는 일정과 다음 실행 시간을 즉시 확인할 수 있습니다.

Cron이란 무엇인가? — 역사에서 시작하기

Cron은 Unix 역사에서 가장 오래되고 가장 널리 사용되어 온 유틸리티 중 하나입니다. Ken Thompson이 1979년 벨 연구소에서 Unix V7의 일부로 작성했습니다. "cron"이라는 이름은 그리스어 chronos(χρόνος), 즉 "시간"에서 유래했습니다.

초기 cron 데몬은 매 분마다 깨어나 태스크 목록을 스캔하고, 시각이 일치하는 명령을 실행하는 단순한 구조였습니다. 이 "시간 표현식 + 명령" 쌍의 설계는 무려 40년 이상 본질적으로 바뀌지 않았습니다. 현대 Linux 배포판은 Vixie Cron(Paul Vixie, 1988), cronie 등의 개선된 버전을 사용하며, macOS는 launchd를 채택했습니다. cron의 영향은 애플리케이션 레이어까지 확산되어, Java의 Quartz Scheduler, Python의 APScheduler, Node.js의 node-cron, AWS EventBridge, Google Cloud Scheduler 등이 모두 cron 식 문법을 따르고 있습니다.


표준 5필드 Cron 문법

표준 cron 표현식은 공백으로 구분된 5개의 필드로 구성됩니다.

┌───────── 분   (0–59)
│ ┌─────── 시   (0–23)
│ │ ┌───── 일   (1–31)
│ │ │ ┌─── 월   (1–12 또는 JAN–DEC)
│ │ │ │ ┌─ 요일 (0–7, 0과 7 모두 일요일, 또는 SUN–SAT)
│ │ │ │ │
* * * * *  명령어

각 필드 상세 설명

필드 허용 값 설명
0–59 매 시간 몇 분에 실행할지
0–23 24시간제로 몇 시에 실행할지
1–31 그 달의 몇 번째 날인지
1–12 또는 JAN–DEC 몇 월인지
요일 0–7 또는 SUN–SAT 0과 7 모두 일요일

중요: 「일」과 「요일」 필드를 동시에 * 이외의 값으로 설정하면, cron은 OR 로직으로 동작합니다. 둘 중 하나라도 조건에 맞으면 작업이 실행됩니다. 이 점은 초보자가 자주 혼동하는 부분입니다.


확장 6필드 문법 (초 포함)

Quartz Scheduler(Java), Spring Framework@Scheduled 어노테이션, 일부 클라우드 플랫폼은 맨 앞에 필드를 추가합니다.

┌─────────── 초   (0–59)
│ ┌───────── 분   (0–59)
│ │ ┌─────── 시   (0–23)
│ │ │ ┌───── 일   (1–31)
│ │ │ │ ┌─── 월   (1–12)
│ │ │ │ │ ┌─ 요일 (1–7, Quartz에서 1=일요일)
│ │ │ │ │ │
0 * * * * ?

Quartz의 요일 필드는 Unix cron과 번호 체계가 다릅니다(1=일요일, 7=토요일). 혼용 시 주의가 필요합니다.


특수 문자 상세 설명

* — 모든 값

해당 필드의 모든 가능한 값에 매칭됩니다. * * * * *는 매 분 실행을 의미합니다.

, — 값 목록

여러 개의 개별 값을 지정합니다. 0 9,12,18 * * *는 매일 9:00, 12:00, 18:00에 실행됩니다.

- — 범위

연속된 범위를 지정합니다. 0 9-17 * * 1-5는 월요일부터 금요일까지 오전 9시~오후 5시 매 정시에 실행됩니다.

/ — 스텝 값

*/n은 "매 n 단위마다"를 의미합니다. */15 * * * *는 15분마다 실행입니다. 범위와 조합도 가능합니다. 10-50/10은 10, 20, 30, 40, 50을 의미합니다.

? — 미지정 (Quartz/Spring 전용)

「일」 또는 「요일」 필드에서 "어떤 값이든 상관없음"을 나타냅니다. 두 필드를 동시에 지정하면 모호해지므로, 하나는 ?로 설정해야 합니다.

L — 마지막 (Quartz/Spring 전용)

「일」 필드에서는 그 달의 마지막 날, 「요일」 필드에서는 그 달의 마지막 해당 요일을 나타냅니다. 0 0 L * ?는 매월 마지막 날 자정에 실행됩니다.

W — 가장 가까운 평일 (Quartz/Spring 전용)

15W는 15일에서 가장 가까운 평일을 의미합니다. 15일이 토요일이면 14일(금요일), 일요일이면 16일(월요일)에 실행됩니다.

# — N번째 요일 (Quartz/Spring 전용)

2#3은 "그 달의 세 번째 화요일"을 의미합니다. 형식은 <요일>#<몇 번째>입니다. 0 10 ? * 2#1은 매월 첫 번째 월요일 10:00에 실행됩니다.


특수 시간 별칭

대부분의 cron 구현은 다음과 같은 편리한 별칭을 지원합니다.

별칭 동일한 표현식 설명
@yearly 0 0 1 1 * 매년 1월 1일 자정
@annually 0 0 1 1 * @yearly와 동일
@monthly 0 0 1 * * 매월 1일 자정
@weekly 0 0 * * 0 매주 일요일 자정
@daily 0 0 * * * 매일 자정
@midnight 0 0 * * * @daily와 동일
@hourly 0 * * * * 매 시 정각
@reboot 시스템 부팅 시 1회 실행

자주 쓰는 Cron 표현식 모음

표현식 의미
* * * * * 매 분
0 * * * * 매 시 정각
*/15 * * * * 15분마다
0 0 * * * 매일 자정
30 2 * * * 매일 오전 2:30
0 9-17 * * 1-5 평일 오전 9시~오후 5시 매 정시
0 0 * * 0 매주 일요일 자정
0 0 1 * * 매월 1일 자정
0 0 1 1 * 매년 1월 1일 자정
0 6 * * 1-5 평일 매일 오전 6시
0 */6 * * * 6시간마다

Linux에서의 Crontab 사용법

# 현재 사용자의 crontab 편집
crontab -e

# 현재 crontab 목록 확인
crontab -l

# crontab 삭제
crontab -r

# 다른 사용자의 crontab 편집 (root 전용)
crontab -u username -e

crontab 작성 예시

# 환경 변수 설정
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
[email protected]

# 매일 오전 2:30에 백업 실행
30 2 * * * /usr/local/bin/backup.sh

# 매주 일요일 자정에 정리 작업 (로그 저장)
0 0 * * 0 /usr/local/bin/cleanup.sh >> /var/log/cleanup.log 2>&1

# 15분마다 헬스체크
*/15 * * * * /usr/local/bin/health-check.sh

# 타임존 지정 실행 (GNU cron / cronie 지원)
CRON_TZ=Asia/Seoul
0 9 * * 1-5 /usr/local/bin/morning-report.sh

시스템 전체 Cron 디렉터리

  • /etc/crontab — 시스템 전체 crontab (각 행에 사용자 이름 필드 추가)
  • /etc/cron.d/ — 패키지 및 서비스용 개별 cron 설정 파일
  • /etc/cron.daily/, /etc/cron.hourly/, /etc/cron.weekly/, /etc/cron.monthly/run-parts로 자동 실행되는 스크립트 디렉터리

macOS와 Windows에서의 스케줄링

macOS: launchd

macOS는 launchd를 권장 스케줄링 메커니즘으로 채택하여 .plist 파일로 작업을 정의합니다. 사용자 작업은 ~/Library/LaunchAgents/에, 시스템 작업은 /Library/LaunchDaemons/에 배치합니다. 하지만 cron도 여전히 사용 가능하며, 많은 개발자가 단순함 때문에 cron을 선호합니다.

Windows: 작업 스케줄러

Windows는 schtasks 명령어나 GUI로 작동하는 작업 스케줄러를 사용합니다. WSL(Windows Subsystem for Linux)을 사용하면 Linux 전체 cron 환경을 그대로 이용할 수 있습니다.


애플리케이션 레벨 Cron 스케줄러

Node.js — node-cron

const cron = require('node-cron');

// 매일 오전 2:30에 실행 (타임존 지정)
cron.schedule('30 2 * * *', async () => {
  await runDailyBackup();
}, {
  timezone: "Asia/Seoul"
});

Python — APScheduler

from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger

scheduler = BlockingScheduler()

@scheduler.scheduled_job(CronTrigger.from_crontab('0 9 * * 1-5'))
def morning_job():
    print("평일 오전 9시입니다. 작업을 시작합니다.")

scheduler.start()

Java — Quartz Scheduler

Quartz는 초를 포함한 6필드 표현식을 사용하며, L, W, #, ? 등의 고급 문자를 지원합니다.

// 평일 오전 9:00에 실행
CronScheduleBuilder schedule = CronScheduleBuilder.cronSchedule("0 0 9 ? * MON-FRI");

클라우드 및 컨테이너 스케줄러

AWS EventBridge Scheduler

6필드 cron 표현식(UTC)을 사용하며, 「일」과 「요일」 중 하나는 반드시 ?여야 합니다.

cron(0 2 * * ? *)   # 매일 UTC 오전 2시

Google Cloud Scheduler

표준 Unix 5필드 cron 문법을 사용하며, 타임존 지정이 가능합니다.

Kubernetes CronJob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-image:latest
          restartPolicy: OnFailure

concurrencyPolicy: Forbid를 설정하면 이전 작업이 완료되지 않은 경우 새 작업이 시작되지 않습니다.


타임존 처리

Cron은 기본적으로 시스템 타임존(서버에서는 대개 UTC)을 사용합니다. UTC 서버에서 0 9 * * *로 설정하면 UTC 오전 9시, 즉 한국 시간(UTC+9)으로는 오후 6시에 실행됩니다. 이 차이를 인식하지 못하면 예기치 않은 실행 시각이 발생합니다.

타임존 관련 모범 사례:

  1. crontab 상단에 CRON_TZ=Asia/Seoul처럼 명시적으로 지정하기
  2. 클라우드 플랫폼의 타임존 설정 필드 활용하기
  3. 일광절약시간(DST) 전환 시 작업이 중복 실행되거나 누락될 수 있으므로 UTC 고정 시각을 고려하기
  4. 모든 cron 식에 타임존을 주석으로 명시하기

보안 고려사항

Cron 작업은 높은 권한으로 실행되는 경우가 많아 보안 취약점이 될 수 있습니다.

최소 권한 원칙: 작업 수행에 필요한 최소 권한의 사용자로 실행하고, root 사용은 피하세요.

자격증명 하드코딩 금지: 패스워드, API 키 등을 crontab이나 스크립트에 직접 작성하지 마세요. 권한이 제한된 환경 변수 파일(chmod 600)이나 AWS Secrets Manager 같은 시크릿 관리 서비스를 사용하세요.

스크립트 권한 관리: cron 스크립트가 다른 사용자에게 쓰기 가능하지 않은지 확인하세요.

chmod 750 /usr/local/bin/backup.sh
chown root:staff /usr/local/bin/backup.sh

모니터링과 알림: MAILTO=로 오류를 이메일로 받고, Healthchecks.io나 Cronitor 같은 데드맨 스위치 서비스로 작업이 "실행되지 않은" 경우 알림을 설정하세요.


모범 사례

작업을 멱등성 있게 설계: 여러 번 실행해도 동일한 결과가 나오도록 설계하면 장애 복구가 쉬워집니다.

파일 잠금으로 중복 실행 방지: 작업 실행 시간이 인터벌을 초과할 수 있다면 flock을 활용하세요.

*/5 * * * * flock -n /var/lock/myjob.lock /usr/local/bin/myjob.sh

출력 명시적 리디렉션:

0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

배포 전 표현식 검증: Cron Parser 도구로 정확히 언제 실행되는지 확인한 후 프로덕션에 적용하세요.

crontab 버전 관리: crontab 파일을 Git으로 관리하고 Ansible이나 Puppet으로 일관되게 배포해 "설정 드리프트"를 방지하세요.


자주 묻는 질문 (FAQ)

Q: Cron 작업이 실행되지 않는 이유는 무엇인가요?
가장 흔한 원인: ①스크립트에 실행 권한 없음, ②스크립트가 셸 환경 변수에 의존하지만 cron 환경은 최소한, ③경로 문제(cron은 .bashrc를 읽지 않으므로 모든 명령에 절대 경로 사용), ④cron 데몬이 중지됨(systemctl status cron으로 확인).

Q: */50/5의 차이점은 무엇인가요?
표준 Unix cron에서 */5는 0부터 시작하는 5분 간격(0, 5, 10…55)을 의미합니다. 0/5는 Quartz/AWS EventBridge 표기법으로 동일한 의미입니다.

Q: 1초마다 실행할 수 있나요?
표준 cron의 최소 단위는 1분입니다. 서브미닛 스케줄링에는 Quartz, APScheduler의 인터벌 트리거, 또는 systemd 타이머(OnCalendar=*:*:00/10)를 사용하세요.

Q: 매월 마지막 날에 실행하려면 어떻게 하나요?
표준 cron에는 "마지막 날" 연산자가 없습니다. "내일이 1일인지 확인"하는 방식이 일반적인 대안입니다. Quartz cron에서는 일 필드에 L을 직접 사용할 수 있습니다.

Q: 0 0 * * 0@weekly의 차이점은 무엇인가요?
완전히 동일합니다. 둘 다 매주 일요일 자정에 실행됩니다. @weekly는 대부분의 현대 cron 구현이 제공하는 기억하기 쉬운 별칭입니다.

Q: 터미널에서는 동작하는데 cron에서 실패하는 스크립트는 어떻게 디버깅하나요?
Cron 실행 환경은 최소한(HOME, LOGNAME, PATH=/usr/bin:/bin, SHELL=/bin/sh)이며 .bashrc.profile을 읽지 않습니다. 스크립트 첫 줄에 #!/bin/bashset -e를 추가하고, 절대 경로를 사용하며, stdout/stderr를 로그 파일로 리디렉션하세요.


요약

Cron은 1979년 탄생 이래 Unix 자동화의 핵심으로 기능해 왔으며, 클라우드 시대에도 계속 진화하고 있습니다. 단일 Linux 서버 관리, Kubernetes 워크로드 조율, 클라우드 이벤트 트리거 구성 등 어떤 상황에서든 cron 표현식을 깊이 이해하면 디버깅 시간을 크게 줄이고 운영 장애를 예방할 수 있습니다.

핵심 요점:

  • 5필드 표준 문법으로 대부분의 사용 사례 처리 가능
  • /는 스텝, ,는 목록, -는 범위를 의미
  • 서버에서는 UTC를 사용하거나 CRON_TZ로 명시적 지정
  • 최소 권한, 자격증명 비하드코딩, 모니터링 등 보안 원칙 준수
  • 프로덕션 적용 전 파서 도구로 표현식 검증

개요

Cron 작업은 현대 자동화의 심장부이지만, 그 구문은 숙련된 시스템 관리자에게도 위협적일 수 있습니다. 당사의 온라인 Cron 해석기는 스케줄링에서 추측을 배제하도록 설계되었습니다. 난해한 Cron 표현식을 명확하고 사람이 읽을 수 있는 언어로 번역함으로써, 이 도구는 예약된 작업이 의도한 대로 정확하게 실행되도록 보장합니다. 백업, 정리 스크립트 또는 자동화된 이메일을 관리하든 정확성이 가장 중요합니다.

주요 기능

  • 실시간 번역: 귀하의 Cron 표현식이 일반 텍스트(또는 선호하는 언어)로 무엇을 의미하는지 즉시 확인하십시오.
  • 다음 실행 시간: 로직을 확인하기 위해 다음 5회 이상의 예약된 실행 시간 목록을 봅니다.
  • 모든 필드 지원: 초(6필드) 및 연도(7필드) 변형을 포함한 표준 Cron 형식을 처리합니다.
  • 구문 강조: 시각적 신호를 통해 분, 시간, 일, 월 및 요일을 식별할 수 있습니다.

사용 방법

  1. 입력: 메인 필드에 Cron 표현식을 붙여넣거나 입력하십시오.
  2. 관찰: 입력함에 따라 사람이 읽을 수 있는 번역이 자동으로 업데이트됩니다.
  3. 확인: "다음 실행 시간" 목록을 확인하여 요구 사항과 일치하는지 확인하십시오.
  4. 복사: 처음부터 시작하는 경우 제공된 예제를 사용하십시오.

주요 활용 사례

  • 서버 유지 관리: 야간 데이터베이스 백업 또는 로그 로테이션 예약.
  • 웹 개발: Laravel 또는 Django와 같은 프레임워크에서 반복적인 백그라운드 작업 설정.
  • DevOps: CI/CD 파이프라인 및 자동화된 상태 체크 구성.
  • 개인 생산성: 로컬 머신에서 반복적인 알림 또는 스크립트 실행 관리.

기술적 배경

Cron 표현식은 공백으로 구분된 5~7개의 필드로 구성됩니다. 각 필드는 시간 단위(분, 시간, 일, 월 및 요일)를 나타냅니다. 당사의 해석기는 *(모두), ,(목록), -(범위), /(증가) 및 L(마지막)과 같은 특수 문자를 처리하는 강력한 로직 엔진을 사용합니다. 윤년과 월 길이를 고려하여 다음 발생 시간을 정확하게 계산합니다.

자주 묻는 질문

  • 초를 지원합니까? 예, 초를 포함하는 6필드 Cron 표현식을 지원합니다.
  • @daily와 같은 비표준 별칭을 처리할 수 있습니까? 예, 일반적인 별칭이 지원됩니다.
  • 타임존을 인식합니까? 기본적으로 계산은 UTC를 기준으로 하지만 상황에 따라 관점을 조정할 수 있습니다.

제한 사항

  • 다양한 구현: 시스템(예: Quartz, AWS, Jenkins)마다 Cron 구문에 약간의 차이가 있습니다. 항상 특정 플랫폼에서 확인하십시오.
  • 엣지 케이스: "월말일"(L) 및 "가장 가까운 평일"(W)은 운영 체제에 따라 다르게 작동할 수 있습니다.