Develop

Jenkins 빌드 스케줄러 완벽 가이드 — Jenkinsfile에 cron 트리거 추가하는 방법

Jenkins UI에서 직접 관리하던 파이프라인을 Jenkinsfile로 전환하고, cron 트리거로 매일 자동 빌드를 구성하는 방법을 정리했습니다. H 표현식을 이용한 부하 분산과 UTC 시간대 대처 팁까지 상세히 다룹니다.

JenkinsCI/CD파이프라인cron자동배포
Jenkins Configure 화면의 Triggers 섹션 — Build periodically 체크 후 'H 17 * * *' cron 표현식을 입력한 상태. 다음 실행 예정 시각이 UTC 기준으로 표시되어 있다.
  • ·Jenkins 최초 출시: 2011년 (Hudson 포크)
  • ·cron 표현식: 분 시 일 월 요일 순서로 5개 필드
  • ·Jenkinsfile 위치: 프로젝트 루트 디렉토리
  • ·triggers 등록: 파이프라인을 최소 1회 수동 실행해야 스케줄 활성화
초기에 Next.js 블로그 정적 사이트를 빌드할 때, 빌드 예약을 위해 Jenkins UI 스케줄 기능을 썼었는데 매번 설정 페이지 들어가서 고치기가 너무 귀찮더군요. 그래서 Jenkinsfile 내에 `triggers { cron('H 17 * * *') }`를 추가했습니다. 코드 형상 관리도 되고 완벽하다고 자부했는데, 커밋 후 아무리 기다려도 자동 빌드가 돌지 않아 당황했습니다. 알고 보니 Jenkins Job의 Pipeline script from SCM 방식은 코드가 올라간 후 최소 1회는 수동 빌드를 해줘야 Jenkins가 Jenkinsfile 내의 트리거를 파싱하여 스케줄을 스위치한다는 사실을 그제야 배웠습니다. 또한, 서버 시간대가 한국(KST)이 아닌 표준시(UTC)로 세팅되어 있어서 새벽 2시에 맞추려면 UTC 17시로 설정해야 한다는 시간차 삽질도 빼놓을 수 없는 실무 경험입니다.

1. 주기적인 자동 빌드를 위한 인프라 구축

왜 CI/CD 환경에서 Jenkins 빌드 스케줄러가 필요할까

바쁜 실무 속에서 개발자가 매번 배포할 때마다 손수 빌드 버튼을 누르는 것은 여간 피곤한 일이 아닙니다. 특히 사용자 트래픽이 가장 적은 새벽 시간대에 주기적으로 배포를 수행하거나, 매일 밤 대규모 통합 테스트를 일괄 실행해야 하는 작업이라면 수동으로 처리하는 것은 불가능에 가깝죠. Jenkins 빌드 스케줄러는 이러한 반복적인 빌드 명령을 백그라운드 크론잡(Cron Job) 형태로 자동화해 주는 고마운 엔진입니다. 설정만 제대로 해둔다면 사람이 잠든 시간에도 서버가 스스로 최신 마스터 브랜치 코드를 당겨와 빌드 검증을 단행하고 릴리즈까지 깔끔하게 밀어주므로, 개발 팀의 인프라 피로도를 대폭 낮추고 지속적 통합의 안정성을 높여줍니다.

선언적 파이프라인으로 Jenkinsfile 설정 방식 선택하기

과거에는 Jenkins 관리자 화면의 UI에서 Job 설정창을 켜고 Groovy 코드를 텍스트 박스에 주구장창 직접 기재하는 방식을 많이 썼습니다. 하지만 이 방식은 Jenkins 서버 자체에 백업본이 묶여 있어서, 인프라 장비가 깨지거나 마이그레이션을 할 때 설정 정보 복구가 지옥으로 변하는 치명적인 취약점이 있습니다. 그래서 모던 DevOps에서는 프로젝트 루트에 Jenkinsfile이라는 설정 명세서를 생성하고 배포 코드를 소스 커밋 관리 대상에 포함하는 SCM(Source Control Management) 연동 전략을 채택합니다. 이 구조를 정착시키면 배포 흐름의 히스토리가 깃 버전 단위로 투명하게 관리되며, 팀원 중 누가 배포 스케줄을 변경했는지 Git Commit 로그로 명확하게 추적할 수 있어 협업 관점에서 비교할 수 없을 정도로 쾌적해집니다.

2. 시간 기반 자동 빌드 예약

자동 실행 주기를 예약하는 Jenkins cron 트리거의 역할

선언적 파이프라인에서 특정 주기로 빌드를 개시하도록 지시하는 규칙을 트리거(Trigger)라고 부릅니다. 그중에서도 정해진 스케줄러 시간표를 기반으로 동작하는 것이 바로 Jenkins cron 트리거입니다. 리눅스의 crontab 스펙과 호환되어 매일 특정 시간, 특정 요일에만 맞춤형으로 깃허브 코드를 풀해 배포하도록 예약을 잡아둡니다. 다만 처음 Jenkinsfile을 도입한 초보 개발자들이 가장 흔히 겪는 현상 중 하나는, cron 블록을 기재하고 깃에 푸시했는데도 예정 시각에 전혀 작동하지 않는 에러입니다. Jenkins 엔진은 브랜치에 올라간 새 코드를 컴파일하기 전까지는 파일 내용 안에 어떤 스케줄러가 박혔는지 인지하지 못합니다. 따라서 최초에 반드시 1회는 수동 빌드를 직접 눌러 실행시켜 줘야 비로소 파이프라인 내부의 triggers 구문을 읽고 서버 내에 백그라운드 cron 스케줄을 정식으로 가입시켜 줍니다.

다양한 요구사항에 대응하는 Jenkins 빌드 트리거 비교

Jenkins 환경에서 코드를 자동으로 빌드하기 위해 동원하는 트리거 전략은 여러 가지가 있습니다. 첫째, 우리가 지금 다루는 cron 방식은 일정 주기마다 강제로 빌드를 켜서 새벽 배포나 일일 정적 분석에 유용합니다. 둘째, 저장소의 변경 여부를 주기적으로 체크해 새 코드가 있을 때만 수행하는 pollSCM 방식이 있는데, 이는 변경이 없을 때도 불필요하게 깃허브 서버로 네트워크 풀링을 지속한다는 아쉬움이 있습니다. 셋째, 코드가 푸시되는 순간 즉각 빌드를 쏘는 GitHub Webhook 방식이 현대 웹앱 개발에서는 가장 널리 쓰이며 속도도 빠르지만, 내부망으로 차단된 폐쇄형 사내 서버에는 웹훅 포트를 뚫기 어려워 도입이 곤란하죠. 넷째, 선행 빌드가 통과하면 이어서 배포를 켜는 upstream 트리거가 있어 성격과 인프라 조건에 맞춰 조화롭게 교차 매핑을 단행해야 최적의 CI 망이 확보됩니다.

3. 크론 스펙 분석 및 설정 요령

실무에서 유용한 Jenkins cron 표현식 구성 요소

크론 표현식은 공백으로 나뉜 총 5개의 시간/날짜 필드로 이루어집니다. 왼쪽부터 순서대로 분(0~59), 시(0~23), 일(1~31), 월(1~12), 요일(0~7, 0과 7은 일요일)을 나타내죠. 0 2 * * *이라고 적으면 매일 새벽 2시 0분에 정확하게 빌드가 도는 식입니다. 쉼표(,)를 이용해 여러 시각을 묶거나 하이픈(-)으로 월~금 평일 범위를 잡을 수도 있으며 슬래시(/)로 간격을 끊는 것도 지원합니다. 시간을 나타내는 두 번째 필드가 앞으로 가기 십상인데, 제일 앞은 무조건 '분'이라는 크론 문법 특성을 잊지 말아야 합니다. 헷갈릴 때는 crontab.guru 같은 크론 분석기 웹 서비스를 띄워두고 규칙을 정교하게 다듬는 것이 잘못된 시각에 운영 배포가 나가는 끔찍한 실무 참사를 예방하는 든든한 방패가 됩니다.

서버 과부하를 예방하는 Jenkins cron H 표현식과 시간대 팁

Jenkins는 표준 크론 문법 외에 H (Hash)라는 아주 특별한 분산 예약용 키워드를 제공합니다. 만약 사내에 수십 개의 빌드 Job이 존재하고 모두가 정각에 실행되도록 0 4 * * *라고 하드코딩해 두면, 새벽 4시 정각에 CPU와 메모리가 동시에 피크를 치며 빌드 서버 전체가 크래시나 뻗어버립니다. 이때 분 자리에 H 4 * * *를 써주면, Jenkins는 빌드 프로젝트의 이름을 해싱하여 04:00부터 04:59 사이의 겹치지 않는 임의의 분(예: 4시 23분)을 알아서 선정해 매번 안정적으로 실행해 줍니다. 부하 분산을 위해 H 적용은 실무에서 거의 반필수 사항이죠. 더불어, 젠킨스 시스템 운영체제 시간대가 세계 표준시(UTC)로 통돌아가고 있다면 한국 시각(KST)보다 9시간 느리다는 점을 계산에 꼭 반영해야 합니다. 즉 한국 기준 새벽 2시에 빌드하고 싶다면 H 17 * * *로 기재해야 엉뚱한 업무 시간 중간에 빌드 사이클이 돌아서 라이브 서버 데이터가 꼬이는 불상사를 피할 수 있습니다.

4. 파이프라인 실제 구현

프로젝트 소스 코드에 Jenkinsfile cron 설정 작성하기

실제 적용을 위해 프로젝트 루트 경로에 확장자 없이 Jenkinsfile을 생성하고, 선언적 파이프라인의 pipeline 최상위 블록 바로 아래에 triggers 지시어를 삽입합니다. 반드시 stages 블록이 실행되기 전 영역에 위치시켜야 정상 파싱됩니다. 스케줄을 기재할 때 cron 구문을 괄호로 감싸 넣어주고 문자열로 묶어 선언하죠. 이렇게 기술된 Jenkinsfile을 깃 저장소에 푸시해 주면, 빌드에 필요한 Node JS 툴 체인 셋업과 배포 명령이 단일 코드로 통제되므로 개발 환경이 달라져도 일관성 있는 배포 파이프라인 가동 능력이 완전히 확보됩니다.

pipeline {
  agent any
  tools { nodejs 'NodeJS' }
  triggers {
    cron('H 17 * * *') // UTC 17:00 (한국 시간 새벽 2시 경 자동 실행)
  }
  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
    }
    stage('Install') {
      steps {
        sh 'npm ci'
      }
    }
    stage('Build') {
      steps {
        sh 'npm run build'
      }
    }
    stage('Deploy') {
      steps {
        sh './deploy.sh'
      }
    }
  }
}

처음 등록 시 수동 빌드가 필요한 Jenkins SCM 설정법

코드를 올렸다면 Jenkins 웹 콘솔 창으로 접속하여 Job 설정을 SCM 기반으로 전환해 주어야 합니다. 신규 Pipeline Job을 개설한 뒤 설정 탭 하단의 Pipeline 섹션에서 Definition 값을 'Pipeline script from SCM'으로 토글합니다. SCM 목록에서 Git을 고르고 리포지토리 SSH 주소와 자격증명 키를 바인딩해 준 뒤 Script Path 항목에 우리가 적어둔 'Jenkinsfile' 이름을 매핑하면 끝나죠. 저장을 완료한 이후에는, 앞서 다뤘던 것처럼 최초 1회 'Build Now'를 마우스로 눌러서 테스트 빌드를 끝내야 합니다. 이 초기 수동 컴파일 단계를 생략하면, 백날 크론 시각이 지나도 Jenkins 스케줄 대기열에 배포 태스크가 올라가지 않아 며칠간 자동 배포가 멈춘 채 방치될 위험이 다분합니다.

스케줄러 작동 여부를 파악하는 Jenkins triggers 등록 확인법

수동 빌드가 한 차례 통과하고 나면, 트리거 예약 스케줄이 정상 활성화되었는지 바로 검증이 가능합니다. Jenkins 프로젝트 메인 홈 화면 좌측의 설정 메뉴로 들어가면, 기존에는 꺼져 있었던 'Build periodically' 체크 박스가 자동으로 활성화되어 있으며 텍스트 필드 안에 우리가 Jenkinsfile에 적었던 크론 코드가 주입되어 있는 걸 목격할 수 있습니다. 특히 입력창 하단에 초록색 글씨로 'Would next run at...' 문구와 함께 현지 시간 기준으로 매핑된 다음 실행 시각 미리보기가 노출됩니다. 이 시간을 읽어보고 우리가 의도했던 한국 시간의 대역과 정확히 맞아떨어지는지 최종 점검하면, 런타임에 시간 오차 없이 완벽하게 스위칭되는 배포 스케줄러 세팅이 완료됩니다.

자주 묻는 질문

Jenkinsfile에 cron triggers를 분명 올렸는데 왜 자동 빌드 스케줄이 등록이 안 되나요?+

Jenkins 선언적 파이프라인의 동작 원리상, triggers 블록은 서버가 Jenkinsfile을 읽어서 로드하기 전까지는 활성화되지 않습니다. 깃에 푸시한 후, 최초 1회는 수동으로 'Build Now' 버튼을 클릭해 전체 배포 프로세스를 한 번 끝마쳐 주어야 스케줄러가 정식 등록됩니다.

스케줄 시각 기준을 한국 시간(KST)으로 맞추고 싶은데 서버 시간이 UTC일 때 팁이 있나요?+

Jenkins 시스템 정보의 user.timezone이 UTC로 잡혀있다면 크론 표현식 작성 시 한국 시간에서 9시간을 뺀 시간(UTC)으로 계산해 주어야 합니다. 예를 들어 한국 시간 새벽 2시는 9시간을 차감한 UTC 17시이므로 cron('H 17 * * *') 형식으로 역산 기재하셔야 오차 없이 가동됩니다.

관련 글