POOOLING FOREST
크론탭(Crontab), 아직도 바보같이 시간만 맞춰서 쓰시나요? - 크론탭(Crontab)을 단순한 알람 시계처럼 쓰고 계신가요? 셸 명령어와 조건문을 활용해 복잡한 스케줄링
Engineering & Tech

크론탭(Crontab), 아직도 바보같이 시간만 맞춰서 쓰시나요?

크론탭(Crontab)을 단순한 알람 시계처럼 쓰고 계신가요? 셸 명령어와 조건문을 활용해 복잡한 스케줄링 조건을 한 줄로 해결하는 8년 차 개발자의 노하우를 공개합니다.

김테크

8년차 개발자

안녕하세요. 풀링포레스트에서 백엔드와 인프라를 담당하고 있는 8년차 개발자 김테크입니다.

개발자라면 누구나 한 번쯤 crontab -e를 입력하고 검은 화면 깜빡이는 커서 앞에서 멍하니 있어본 경험이 있을 겁니다. 저도 신입 시절에는 크론탭(Cronjob)이 그저 정해진 시간에 스크립트를 실행해 주는 단순하고 무식한 알람 시계라고만 생각했습니다. 복잡한 스케줄링이 필요하면 "아, 이건 크론으로는 안 되니까 배치 서버 로직에서 예외 처리를 해야겠네"라며 애플리케이션 코드에 덕지덕지 if 문을 추가하곤 했죠.

최근에 사내 정산 시스템의 레거시 코드를 걷어내던 중, 조금 특이한 요구사항을 마주했습니다. "매주 화요일 오전 7시에 정산 스크립트를 돌리되, 그 화요일이 '월의 마지막 화요일'이라면 실행하지 말 것"이라는 조건이었죠.

처음에는 별생각 없이 Python 스크립트 내부에서 날짜를 계산하려고 했습니다. 그러다 문득 8년 차 개발자로서 자존심이 상하더군요. '고작 이 정도 조건을 체크하려고 무거운 애플리케이션 코드를 수정해서 배포까지 다시 해야 하나?'라는 회의감이 들었습니다. 그때 머리를 한 대 맞은 것 같은 깨달음을 얻었습니다. 크론탭 설정 한 줄만으로 이 조건을 해결할 수 있다는 사실을 뒤늦게 알았기 때문입니다.

우리는 흔히 크론탭의 앞부분인 시간 설정(* * * * *)에만 집착합니다. 하지만 크론탭이 실행하는 것은 결국 셸(Shell) 명령어입니다. 즉, 셸이 할 수 있는 조건문은 크론탭에서도 그대로 쓸 수 있다는 뜻입니다.

예를 들어 앞서 말한 "월의 마지막 화요일 제외" 같은 조건은 다음과 같이 && 연산자와 date 명령어 조합으로 아주 우아하게 해결됩니다.

0 7 * * Tue [ "$(date -d +7days +%m)" = "$(date +%m)" ] && /path/to/script.sh

이 한 줄의 마법을 해석해 볼까요?

  1. 매주 화요일 7시에 깨어납니다.

  2. date -d +7days +%m: 오늘 날짜에 7일을 더한 달(Month)을 구합니다.

  3. date +%m: 오늘 날짜의 달을 구합니다.

  4. 두 값이 같다면(=), 즉 다음 주도 여전히 이번 달이라면, 오늘은 '마지막 화요일'이 아닙니다.

  5. 이 조건이 참(True)일 때만 && 뒤에 있는 스크립트를 실행합니다.

만약 오늘이 마지막 화요일이라면 7일 뒤는 다음 달이 될 테니 조건문이 거짓(False)이 되고, 스크립트는 실행되지 않습니다. 리눅스 서버 기준으로는 -d 옵션을 쓰지만, 로컬 맥북(macOS)에서 테스트하신다면 -v 옵션을 써야 한다는 점만 주의하면 됩니다.

이 원리를 깨닫고 나니 응용할 곳이 무궁무진했습니다.

운영팀에서 종종 "공휴일에는 배치 돌리지 말아 주세요"라는 요청을 할 때가 있습니다. 예전 같으면 별도 DB 테이블에 공휴일을 관리했겠지만, 이제는 간단한 텍스트 파일(HOLIDAYS.txt) 하나와 grep 명령어만 있으면 됩니다.

0 7 * * * ! grep -qx "$(date +%F)" /path/to/HOLIDAYS.txt && /path/to/job.sh

grep으로 오늘 날짜가 휴일 목록에 있는지 확인하고, 없을 때(!)만 실행하게 하는 것이죠. 심지어 curl을 이용해 외부 API에서 날씨 정보를 가져와 "맑은 날에만 실행"하거나, 뉴스 RSS를 긁어와 특정 키워드가 있을 때만 알림을 보내는 것도 크론탭 한 줄로 가능합니다. 물론 프로덕션 환경에서 뉴스나 날씨에 의존적인 배치를 돌릴 일은 거의 없겠지만, 핵심은 크론탭이 생각보다 훨씬 '동적(Dynamic)'일 수 있다는 점입니다.

우리는 종종 Airflow나 Jenkins 같은 거창한 도구를 도입해야만 스케줄링 문제를 해결할 수 있다고 착각합니다. 하지만 도구의 복잡함에 매몰되기 전에, 기본 도구인 리눅스 셸과 크론탭이 가진 잠재력을 먼저 살펴보는 건 어떨까요? 때로는 가장 오래된 도구가 가장 강력하고 효율적인 해결책이 되기도 하니까요.

오늘 여러분의 크론탭 리스트를 한번 열어보세요. 혹시 애플리케이션 코드 안에서 처리하고 있던 불필요한 날짜 계산 로직이 있다면, 과감하게 셸 스크립트의 영역으로 넘겨보는 것을 추천합니다. 그게 바로 '인프라를 다루는 맛' 아니겠습니까.

지금 읽으신 내용, 귀사에 적용해보고 싶으신가요?

상황과 목표를 알려주시면 가능한 옵션과 현실적인 도입 경로를 제안해드립니다.