Dev Notes
Web Vitals
Web Vitals
Dev Notes
DocsCron 해석 라이브러리, cRonstrue
Web Vitals
Web Vitals
GitHub
Library21분

Cron 해석 라이브러리, cRonstrue

Cron 표현식을 자연어로 해석하는 JavaScript 라이브러리 cRonstrue 소개

2025년 10월 2일
croncronstruei18nschedulingutility

적용 환경: Node.js 18+, 모든 모던 브라우저, TypeScript 지원

들어가며

사내 프로젝트에서 MLOps 환경의 모델 스케줄 잡을 설정하는 부분이 있었는데, UI 상에서 입력된 cron 표현식이 어떤 의미인지 해석하여 보여달라는 요청이 들어왔습니다. 0 15 10 ? * MON-FRI 같은 문자열을 보고 즉시 의미를 파악하기란 쉽지 않으므로, 자연어로 변환하여 함께 표시해주면 사용자 경험이 훨씬 나아질 것이라는 판단이었습니다.

이 변환 로직을 직접 구현하려 하면 의외로 까다롭습니다. cron 문법 자체가 다양한 특수 문자(*, ?, /, #, L)를 조합하여 복잡한 스케줄을 표현하기 때문에, 모든 케이스를 파싱하고 자연어로 조립하는 과정이 상당한 분량의 코드를 요구합니다. 해당 프로젝트에서는 i18n으로 다국어까지 지원해야 했기 때문에 직접 구현하기에는 부담이 컸고, 검색을 통해 다국어 지원까지 갖춘 해석 라이브러리를 발견하여 소개합니다.

cRonstrue는 cron 표현식을 사람이 읽을 수 있는 문장으로 변환하는 JavaScript 라이브러리입니다. 외부 종속성이 전혀 없고, 30개 이상의 로케일을 지원하며, toString 메서드 하나로 해석이 완료됩니다.

Cron 표현식 기초

표준 cron 표현식은 5개의 필드로 구성되며, 왼쪽부터 각각 분, 시, 일, 월, 요일을 나타냅니다.

필드값 범위특수 문자예시
분(Minute)0–59* , - /*/5 — 5분마다
시(Hour)0–23* , - /9-17 — 오전 9시~오후 5시
일(Day of Month)1–31* , - / ? L W15 — 매월 15일
월(Month)1–12 또는 JAN–DEC* , - /1,4,7,10 — 분기 첫 달
요일(Day of Week)0–6 또는 SUN–SAT* , - / ? L #MON-FRI — 평일

정보

일부 시스템(Quartz, Spring 등)에서는 초(seconds) 필드가 맨 앞에 추가되어 6필드 형태를 사용하기도 합니다. cRonstrue는 5필드와 6필드 형식을 모두 지원합니다.

*는 "모든 값", /는 "간격", #은 "n번째 요일"을 의미합니다. 예를 들어 SUN#2는 "두 번째 일요일"이고, */5는 "5 간격마다"를 뜻합니다. 이처럼 cron은 짧은 문자열에 상당히 복잡한 스케줄 정보를 압축하기 때문에, 자연어 해석의 필요성이 높습니다.

설치와 기본 사용법

npm을 사용하여 패키지를 설치합니다. 별도의 peer dependency가 없으므로 이 한 줄이면 충분합니다.

Bash
npm install cronstrue

사용하려는 스크립트에서 import한 뒤, toString 메서드에 cron 표현식을 전달하면 해석된 문자열이 반환됩니다.

TypeScript
import cronstrue from 'cronstrue';
 
cronstrue.toString("* * * * *");
// "Every minute"
 
cronstrue.toString("0 23 ? * MON-FRI");
// "At 11:00 PM, Monday through Friday"
 
cronstrue.toString("23 12 * * SUN#2");
// "At 12:23 PM, on the second Sunday of the month"
 
cronstrue.toString("0/5 14,18 * * ?");
// "Every 5 minutes, at 02:00 PM and 06:00 PM"

표현식이 복잡해질수록 cRonstrue의 가치가 드러납니다. 위 마지막 예시처럼 0/5 14,18 * * ?를 보고 바로 "오후 2시와 6시에 5분마다"라는 해석을 떠올리기는 쉽지 않지만, cRonstrue는 이를 한 줄의 호출로 해결합니다.

옵션 상세

toString 메서드의 두 번째 매개변수로 객체를 전달하면 출력 형식을 세밀하게 제어할 수 있습니다. 사용 가능한 옵션은 총 7가지입니다.

옵션타입기본값설명
throwExceptionOnParseErrorbooleantrue파싱 실패 시 예외를 throw할지, 오류 메시지를 문자열로 반환할지 결정
verbosebooleanfalse더 상세한 설명 생성 여부
dayOfWeekStartIndexZerobooleantrue요일 인덱스 0을 일요일로 해석할지 여부
monthStartIndexZerobooleanfalse월 인덱스 0을 1월로 해석할지 여부
use24HourTimeFormatbooleanfalse24시간제 시간 형식 사용 여부
localestring"en"출력 언어 로케일
logicalAndDayFieldsbooleanfalseday-of-month와 day-of-week 필드를 AND 논리로 해석할지 여부

use24HourTimeFormat과 로케일

use24HourTimeFormat의 기본값은 false이지만, 일본어(ja), 독일어(de) 등 일부 로케일에서는 자동으로 24시간제가 적용됩니다. 한국어(ko)는 12시간제가 기본이므로, 24시간제가 필요하다면 use24HourTimeFormat: true를 명시적으로 설정해야 합니다.

아래 예시를 통해 옵션에 따른 출력 차이를 비교할 수 있습니다.

TypeScript
cronstrue.toString("0 23 * * *");
// "At 11:00 PM"

verbose 옵션은 생략 가능한 정보("every day", "every month" 등)까지 명시적으로 포함시켜 줍니다. 관리 대시보드처럼 정확한 의미 전달이 중요한 맥락에서는 verbose: true를 권장합니다.

다국어 지원 (i18n)

cRonstrue의 강점 중 하나는 30개 이상의 로케일을 지원한다는 점입니다. 다국어 해석을 사용하려면 로케일 관련 모듈을 별도로 import해야 합니다.

TypeScript
// 모든 로케일이 포함된 번들 (파일 크기 큼)
import cronstrue from 'cronstrue/i18n';
 
cronstrue.toString("0 15 10 ? * MON-FRI", { locale: "ko" });
// "월요일에서 금요일까지, 오전 10:15에"
 
cronstrue.toString("0 15 10 ? * MON-FRI", { locale: "ja" });
// "月曜日 から 金曜日 まで、10:15に"

번들 크기 최적화

cronstrue/i18n은 30개 이상의 로케일을 모두 포함하기 때문에 번들 크기가 상당히 큽니다. 프로덕션 환경에서 1~2개 언어만 필요하다면 개별 로케일 임포트 방식이 훨씬 효율적입니다.

cRonstrue가 지원하는 전체 로케일 목록은 GitHub 저장소에서 확인할 수 있으며, 자주 사용되는 로케일 코드는 다음과 같습니다.

로케일 코드언어
ko한국어
en영어
ja일본어
zh_CN중국어 간체
zh_TW중국어 번체
de독일어
fr프랑스어
es스페인어

유효성 검사

cRonstrue는 cron 표현식을 해석하는 라이브러리이지, 유효성을 검사하는 라이브러리가 아닙니다. 잘못된 표현식이 들어와도 가능한 한 해석을 시도하므로, 유효성 검사가 필요하다면 별도의 라이브러리를 함께 사용해야 합니다.

라이브러리역할특징
cron-parser파싱 및 유효성 검사다음 실행 시간 계산, strict 모드 지원
cron-validate유효성 검사 전용경량, 검사만 필요할 때 적합

cron-parser는 v5.x부터 API가 크게 변경되었으므로, 기존 default export 방식 대신 CronExpressionParser 클래스를 named export로 가져와 사용해야 합니다.

TypeScript
import { CronExpressionParser } from 'cron-parser';
 
function isValidCron(expression: string): boolean {
  try {
    CronExpressionParser.parse(expression);
    return true;
  } catch {
    return false;
  }
}
 
// 다음 실행 시간 계산도 가능합니다
const interval = CronExpressionParser.parse('0 15 10 ? * MON-FRI');
console.log('다음 실행:', interval.next().toString());

cRonstrue와 cron-parser를 조합하면, 입력된 표현식의 유효성을 검사한 뒤 유효한 경우에만 자연어 해석을 보여주는 견고한 UI를 구현할 수 있습니다.

정리

핵심 정리

  • cRonstrue는 cron 표현식을 자연어로 변환하는 제로 디펜던시 라이브러리입니다
  • 30개 이상의 로케일을 지원하며, 개별 로케일만 선택적으로 import하여 번들 크기를 최적화할 수 있습니다
  • 유효성 검사가 필요하다면 cron-parser 또는 cron-validate와 함께 사용하는 것을 권장합니다

참고 자료

  • cRonstrue GitHub 저장소
  • cron-parser GitHub 저장소
  • Crontab Guru — Cron 표현식 에디터
  • Wikipedia: Cron
Written by

Mirunamu (Park Geonwoo)

Software Developer

관련 글 더보기

Library

Next.js Redis 캐시 핸들러 직접 만들기

Next.js의 이중 캐시 인터페이스를 Redis로 구현하여 npm 패키지로 배포한 과정

읽기
다음 글Next.js Redis 캐시 핸들러 직접 만들기
목차
  • 들어가며
  • Cron 표현식 기초
  • 설치와 기본 사용법
  • 옵션 상세
  • 다국어 지원 (i18n)
  • 정리
  • 참고 자료