본문 바로가기
CI.CD/Jenkins

[Jenkins] Jenkinsfile로 파이프라인 형상관리하기 (IaC의 실현)

반응형

CI/CD 파이프라인을 코드로 작성(Pipeline as Code)하는 문법을 익혔다면, 이제 그 코드를 '어디에, 어떻게 보관하고 실행할 것인가'를 고민해야 합니다. 젠킨스 웹 브라우저를 열어 Job 설정창의 텍스트 박스 안에 수백 줄의 코드를 복사하고 붙여넣는 방식을 생각하셨다면, 아직 진정한 실무의 자동화 트렌드에 합류하지 못하신 겁니다. 이번 [Jenkins 실무 완벽 가이드] 시리즈에서는 인프라 코드를 텍스트 박스가 아닌 `Jenkinsfile`이라는 물리적 파일로 만들어 Git에 함께 커밋함으로써 완벽한 형상 관리(버전 관리)를 달성하는 방법에 대하여 3,000자 분량으로 깊이 있게 딥다이브 해보겠습니다. 이 방식은 선택이 아닌 필수입니다.

🚫 1. 웹 UI(텍스트 박스) 편집의 치명적 단점

젠킨스의 Pipeline Job 설정에 들어가면 기본적으로 `Pipeline script` 항목이 선택되어 있고, 거대한 텍스트 박스가 입을 벌리고 있습니다. 이곳에 코드를 짜는 것은 다음과 같은 세 가지 치명적인 리스크를 동반합니다.

  • 히스토리(버전) 관리 불가: 누군가 코드를 실수로 지우고 저장(Save) 버튼을 눌러버리면? 이전에 어떤 코드가 적혀 있었는지 되돌릴(Rollback) 방법이 전혀 없습니다. 수십 시간 공들여 짠 파이프라인이 클릭 한 번에 날아가는 대참사가 벌어집니다.
  • 협업 불가능 및 블라인드 배포: 여러 명의 데브옵스 엔지니어나 개발자가 동시에 UI 창을 열어 코드를 수정하다 보면, 마지막에 저장(Save) 버튼을 누른 사람의 코드만 남게 됩니다. 또한 누가, 언제, 왜 이 파이프라인 로직을 변경했는지 코드 리뷰를 거칠 수도 없습니다.
  • 브랜치별 파편화 대응 불가: main 브랜치의 배포 로직과 develop 브랜치의 배포 로직이 완전히 달라야 할 때, UI에 적힌 단일 스크립트 하나만으로는 if-else 떡칠을 하지 않고서는 감당할 수 없게 됩니다.

📄 2. Jenkinsfile 이란 무엇인가? (구원자 등장)

이러한 모든 문제를 단번에 해결하는 방법이 바로 Jenkinsfile입니다. Jenkinsfile은 이름 그대로 젠킨스의 파이프라인 로직이 담긴 순수 텍스트 파일입니다. (확장자는 따로 없습니다.) 이 파일을 개발하는 애플리케이션 소스 코드의 최상단 디렉토리(루트 디렉토리)에 함께 위치시키고 Git으로 commitpush하는 것이 핵심 사상입니다.

즉, "이 애플리케이션을 빌드하고 배포하는 방법(명세서)은, 애플리케이션 소스코드 바로 옆에 매뉴얼처럼 동봉되어 있다"는 것을 의미합니다. 이를 인프라 코드를 형상 관리한다는 뜻의 IaC (Infrastructure as Code)라고 부르며, 현대 CI/CD의 가장 기본적이고 훌륭한 패턴입니다.

💻 디렉토리 구조 예시 (Node.js 프로젝트 기준)

my-awesome-project/
├── src/                # 실제 애플리케이션 소스 코드
│   ├── index.js
│   └── components/
├── package.json        # 의존성 관리 파일
├── README.md           # 프로젝트 설명서
├── Dockerfile          # 컨테이너화 명세서
└── Jenkinsfile         # 🌟 빌드 및 배포 파이프라인 명세서 (이 곳에 파이프라인 코드를 작성!)

⚙️ 3. Pipeline from SCM 설정하기 (Jenkins 세팅)

이제 로컬에서 Jenkinsfile을 작성하여 Github에 푸시(Push)해 두었다고 가정하겠습니다. 이제 젠킨스에게 "웹 UI에 적힌 코드를 보지 말고, Github 저장소 안에 있는 파일을 읽어서 실행해라!"라고 알려주어야 합니다.

  1. 젠킨스 대시보드에서 해당 Pipeline Job을 클릭하고 좌측의 [구성(Configure)] 메뉴로 진입합니다.
  2. 맨 하단의 [Pipeline] 섹션으로 스크롤을 내립니다.
  3. Definition (정의) 드롭다운 메뉴를 클릭합니다. 기본값인 Pipeline script 대신, Pipeline script from SCM을 선택합니다. (SCM은 Source Control Management의 약자로, Git을 의미합니다.)
  4. SCM: Git을 선택합니다.
  5. Repository URL: Github 주소를 입력하고, 필요하다면 Credentials를 선택하여 프라이빗 저장소 접근 권한을 줍니다.
  6. Branches to build: 빌드할 타겟 브랜치를 입력합니다. (예: */main)
  7. Script Path (매우 중요): 이 항목에는 젠킨스가 저장소를 클론받은 뒤, 어떤 경로에 있는 어떤 이름의 파일을 읽어야 하는지 지정합니다. 기본값으로 Jenkinsfile이 적혀 있습니다. 만약 파일을 특정 폴더 안에 넣었다면 ci/Jenkinsfile 처럼 적어주면 됩니다.
  8. 저장(Save) 버튼을 누릅니다.

🔥 4. 형상 관리(Jenkinsfile) 도입 시 얻게 되는 엄청난 이점들

이렇게 젠킨스 웹 UI에서 코드를 분리해내어 소스코드와 함께 Git으로 관리하게 되면, 실무에서 다음과 같은 막강한 이점들을 누릴 수 있습니다.

1. 완벽한 버전 관리와 롤백(Rollback) 능력: 파이프라인 코드도 이제 일반 소스코드처럼 git commit 히스토리에 고스란히 남게 됩니다. 만약 누군가 파이프라인 로직을 수정했는데 배포가 터졌다면? 고민할 필요 없이 이전 커밋으로 git revert만 날려주면 과거의 완벽했던 파이프라인 설정으로 1초 만에 복구됩니다.

2. 코드 리뷰(Code Review) 문화 정착: 파이프라인 수정 사항을 main 브랜치로 바로 푸시하지 않고, feature/pipeline-update 브랜치를 따서 수정한 뒤 Pull Request(PR)를 올릴 수 있습니다. 인프라 팀 리더가 PR 변경 사항을 보고 "이 쉘 스크립트 부분은 보안에 취약하니 고쳐라"라고 피드백을 줄 수 있어, 인프라 코드의 품질이 극적으로 상승합니다.

3. 브랜치(Branch)별 독립적인 배포 로직 구성: 개발(develop) 브랜치에서는 테스트 서버로 배포하고, 메인(main) 브랜치에서는 운영 서버로 배포해야 한다고 쳐봅시다. develop 브랜치의 Jenkinsfile에는 테스트 배포 로직을 적어두고, main 브랜치의 파일에는 운영 배포 로직을 적어두기만 하면 끝입니다. 젠킨스는 각 브랜치에 있는 파일을 독립적으로 읽어 들이므로, 더 이상 코드가 충돌하거나 복잡한 if문으로 분기를 칠 필요가 없어집니다.


🎯 5. 마무리 및 다음 단계

지금까지 Jenkinsfile을 도입하여 웹 UI 텍스트 박스의 한계를 벗어나 진정한 의미의 파이프라인 형상 관리(IaC)를 구현하는 방법과 그 압도적인 장점들에 대해 3,000자의 밀도 높은 내용으로 다루어 보았습니다. 이제 여러분의 인프라는 개발팀의 소스코드만큼이나 안전하고 체계적으로 관리될 수 있습니다.

코드를 보관하고 읽어 들이는 방법까지 완벽히 세팅했으니, 이제 남은 것은 "실제 그 Jenkinsfile 내부에 어떤 코드를 어떻게 작성할 것인가"입니다. 그중에서도 가장 기본이자 빌드의 성패를 좌우하는 첫 번째 관문이 바로 어떤 서버(환경)에서 빌드를 돌릴지 결정하는 agent 지시어입니다. 이어지는 9단계 포스팅에서는 실무에서 겪는 의존성 충돌의 지옥을 피하기 위한 고도의 Agent 설정 노하우(Docker Agent 도입기)에 대해 아주 치밀하게 파헤쳐 보겠습니다!

반응형