본문 바로가기
CI.CD/Jenkins

[Jenkins] Pipeline의 시작: Scripted vs Declarative (문법 완벽 가이드)

반응형

과거의 젠킨스는 '마우스 클릭'으로 모든 것을 설정하는 Freestyle Project가 주류였습니다. 하지만 마이크로서비스 아키텍처(MSA)가 도입되고 배포 파이프라인이 수십 개의 스테이지로 복잡해지면서, 더 이상 GUI 화면만으로는 분기 처리나 예외 처리 같은 고도화된 로직을 감당할 수 없게 되었습니다. 그래서 등장한 것이 바로 '코드로 파이프라인을 작성(Pipeline as Code)'하는 방식입니다. 이번 [Jenkins 실무 완벽 가이드] 시리즈에서는 젠킨스 파이프라인의 양대 산맥인 Scripted Pipeline과 Declarative Pipeline의 차이점, 장단점, 그리고 왜 실무에서는 후자를 99% 채택하는지에 대해 3,000자 분량으로 아주 깊이 있게 딥다이브 해보겠습니다.

📜 1. Scripted Pipeline (초창기의 자유로움과 혼돈)

파이프라인 플러그인이 처음 세상에 나왔을 때 도입된 1세대 문법이 바로 Scripted Pipeline입니다. 이는 순수한 Groovy(그루비) 프로그래밍 언어의 문법을 거의 100% 그대로 차용했습니다.

장점 (무한한 자유도): 일반적인 프로그래밍 언어와 같으므로 if-else 분기문, for 반복문, try-catch-finally를 통한 정교한 예외 처리가 가능합니다. 심지어 파이프라인 도중에 별도의 Groovy 클래스를 정의하거나 외부 라이브러리를 임포트하여 복잡한 문자열 파싱이나 알고리즘 로직까지 구현할 수 있습니다. "안 되는 것이 없다"는 것이 가장 큰 장점입니다.

단점 (유지보수의 지옥): 자유도가 높다는 것은 반대로 말하면 정해진 뼈대나 규격이 없다는 뜻입니다. 개발자 A가 짠 스크립트와 B가 짠 스크립트의 구조가 완전히 다릅니다. 에러가 났을 때 어디서 터졌는지 파악하기 어렵고, 코드가 수천 줄로 길어지면 이른바 '스파게티 코드'가 되어버립니다. 또한, 구문 오류(Syntax Error)를 젠킨스가 사전에 완벽히 캐치하지 못해 빌드를 돌려봐야만 에러를 알 수 있는 경우가 많습니다.

💻 Scripted Pipeline 기본 구조: node 블록으로 시작하며, 그 안에 순차적인 명령어를 기입합니다.

node('master') { // 워커 노드 지정
    stage('Checkout') {
        git 'https://github.com/my-repo.git'
    }
    stage('Build') {
        try {
            if (env.BRANCH_NAME == 'main') {
                sh 'npm run build:prod'
            } else {
                sh 'npm run build:dev'
            }
        } catch(Exception e) {
            echo "빌드 중 치명적 에러 발생: ${e.message}"
            currentBuild.result = 'FAILURE'
        }
    }
}

🏗️ 2. Declarative Pipeline (현대 실무의 압도적 표준)

Scripted 방식의 복잡성에 지친 개발자들의 원성을 수렴하여, 젠킨스 측에서 새롭게 발표한 2세대 문법이 바로 Declarative(선언적) Pipeline입니다. 이름 그대로 "어떻게(How) 동작할지가 아니라 무엇을(What) 할 것인지 선언"하는 구조입니다.

장점 (엄격한 규격과 놀라운 가독성): pipeline 블록으로 시작하여, stages -> stage -> steps로 이어지는 매우 엄격하고 정형화된 블록 구조를 강제합니다. 이 덕분에 누가 코드를 짜든 똑같은 뼈대를 갖게 되어 유지보수성과 가독성이 미친 듯이 상승합니다. 또한 when(특정 조건에만 실행), post(성공/실패 시 후처리), environment(환경변수 세팅)와 같은 매우 편리한 내장 지시어(Directive)들을 제공하여 복잡한 Groovy 로직을 쓰지 않아도 됩니다.

단점 (다소 제한적인 로직 구현): 엄격한 뼈대 안에서만 움직여야 하므로, 순수 Groovy 스크립트처럼 자유로운 반복문이나 복잡한 클래스 선언을 블록 한가운데에 우겨넣을 수 없습니다. (물론 script { ... } 블록을 열어서 그 안에서 Scripted 문법을 섞어 쓸 수는 있습니다.)

💻 Declarative Pipeline 기본 구조: 오늘날 대기업과 유니콘 실무의 99%는 이 방식을 표준으로 채택하고 있습니다.

pipeline {
    agent any // 빌드를 수행할 노드 지정 (추후 상세히 다룸)
    
    environment {
        // 전역으로 사용할 환경변수 선언
        APP_VERSION = '1.0.0'
    }
    
    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/my-repo.git'
            }
        }
        stage('Build') {
            // when 지시어: main 브랜치일 때만 이 stage를 실행하라
            when { branch 'main' }
            steps {
                sh 'npm run build:prod'
            }
        }
    }
    
    // post 지시어: 전체 파이프라인의 결과에 따른 후처리 자동화
    post {
        always {
            echo "성공하든 실패하든 무조건 실행되는 청소 작업"
            cleanWs() // Workspace 비우기
        }
        success {
            echo "🎉 빌드 성공! 슬랙 알림 발송"
            // slackSend ...
        }
        failure {
            echo "🚨 빌드 실패! 담당자에게 메일 발송"
            // mail to: ...
        }
    }
}

⚖️ 3. 두 문법의 결정적 차이 요약 및 트렌드 분석

두 문법의 차이를 쉽게 비유하자면, Scripted Pipeline은 찰흙과 같습니다. 손재주가 좋다면 무엇이든 빚어낼 수 있지만 모양이 제각각입니다. 반면 Declarative Pipeline은 레고 블록입니다. 정해진 홈에 맞춰서만 끼울 수 있지만, 설명서만 보면 누구나 똑같이 멋진 성을 조립할 수 있습니다.

CI/CD 인프라를 운영하다 보면 파이프라인 코드를 작성한 담당자가 퇴사하거나 팀을 이동하는 일이 빈번합니다. 이때 후임자가 수천 줄의 Scripted 코드를 물려받으면 로직을 파악하느라 엄청난 시간을 허비하게 됩니다. 하지만 Declarative 구조로 짜여 있다면 stages 블록만 쭉 훑어봐도 이 빌드가 어떤 흐름으로 흘러가는지 1분 만에 파악이 가능합니다.

젠킨스 공식 문서(Jenkins Documentation)에서도 새로 시작하는 프로젝트는 무조건 Declarative 문법을 사용할 것을 강력하게 권고하고 있으며, 최근 나오는 젠킨스 플러그인들의 가이드 문서들도 모두 Declarative 예제를 최우선으로 제공하고 있습니다.


🎯 4. 마무리 및 다음 단계

지금까지 Jenkins Pipeline의 두 가지 핵심 문법인 Scripted와 Declarative의 차이점, 구조, 그리고 실무 트렌드에 대해 3,000자에 가까운 깊이 있는 분량으로 다루어 보았습니다. 이제 여러분은 왜 수많은 기업들이 Declarative 방식을 채택하는지 완벽하게 이해하셨을 것입니다.

그런데 이렇게 멋지게 작성한 Declarative 코드를 젠킨스 웹 UI 설정창에 그대로 복사해서 붙여넣고 저장하면 될까요? 아닙니다! 웹 UI에 코드를 욱여넣는 것은 구시대적인 방식이며, 코드가 날아갔을 때 복구할 방법이 없습니다. 이어지는 다음 8단계 포스팅에서는 이 파이프라인 코드를 `Jenkinsfile`이라는 파일로 만들어 애플리케이션 소스코드와 함께 Git으로 버전 관리(형상 관리)하는 진정한 의미의 IaC(Infrastructure as Code) 실현 방법에 대해 아주 치밀하게 파헤쳐 보겠습니다!

반응형