Jenkins는 소프트웨어 개발 과정에서 반복적으로 수행하는 빌드, 테스트, 배포 작업을 자동화하는 CI/CD 서버다.
GitHub Actions와 비슷한 역할을 하지만 구조가 조금 다르다.
GitHub Actions는 GitHub Repository와 강하게 결합된 자동화 플랫폼이고, Jenkins는 별도의 서버를 설치하고 직접 운영하면서 다양한 개발 환경과 도구를 연결하는 자동화 서버에 가깝다.
GitHub Actions -> GitHub / Workflow / Runner / Actions
Jenkins -> Jenkins Server / Pipeline / Agent / Plugin / 외부 Repository / Build Tool / Deploy System
Jenkins는 오래전부터 사용되어 온 CI/CD 도구라서 대규모 조직이나 사내 인프라에서 여전히 많이 볼 수 있다.
Jenkins가 필요한 이유
개발자가 코드를 수정할 때마다 직접 다음 작업을 한다고 생각해보자.
코드 수정 -> Build -> Test -> Package -> 서버 접속 -> 배포 -> 서비스 재시작
한두 번이면 문제가 없지만 개발자가 계속 반복해야 한다.
Jenkins를 사용하면 이런 작업을 자동화할 수 있다.
Git Push -> Jenkins -> Build -> Test -> Package -> Deploy
개발자는 코드 변경에 집중하고 Jenkins가 정해진 절차를 수행한다.
Jenkins의 기본 구조
Jenkins를 이해할 때는 다음 구조를 먼저 잡는 것이 좋다.
Developer -> Git Repository -> Jenkins Controller -> Jenkins Agent -> Build / Test / Package / Deploy
각 역할을 나누면 다음과 같다.
Controller -> 작업을 관리하고 Pipeline을 조정
Agent -> 실제 Build / Test / Deploy 작업을 실행
Pipeline -> 자동화 Workflow 정의
Plugin -> 외부 시스템과 Jenkins를 연결
Jenkins Controller
Jenkins의 중심이 되는 서버다.
과거에는 Master라는 용어를 사용했지만 현재는 Controller라는 용어를 사용한다.
Controller가 모든 작업을 직접 실행하는 구조도 가능하지만, 규모가 커지면 Agent를 별도로 두는 방식이 일반적이다.
Controller는 다음과 같은 작업을 담당한다.
Job 관리 / Pipeline 관리 / Build 예약 / Build 결과 관리 / Agent 관리 / Credential 관리 / Plugin 관리
중요한 점은 Controller가 작업을 지시하고 관리하는 역할이라는 것이다.
실제 빌드는 Agent에서 수행할 수 있다.
Jenkins Agent
Agent는 실제 작업을 실행하는 머신이다.
Jenkins Controller -> Agent 1 / Agent 2 / Agent 3
예를 들어 프로젝트마다 필요한 환경이 다를 수 있다.
Agent 1 -> Linux / C++ / GCC
Agent 2 -> Windows / Visual Studio / C++
Agent 3 -> Linux / Node.js / Docker
이렇게 Agent를 나눠 사용할 수 있다.
게임 개발에서도 활용할 수 있다.
Windows Agent -> Unreal Build / Unity Build
Linux Agent -> Game Server Build / Docker Build
Jenkins Pipeline
Jenkins에서 자동화 Workflow를 정의하는 핵심 개념이다.
예를 들어 다음과 같은 Pipeline을 만들 수 있다.
Checkout -> Build -> Test -> Package -> Deploy
Pipeline은 Jenkinsfile이라는 파일로 코드화할 수 있다.
pipeline {
agent any
stages {
stage('Build') {
steps {
sh './build.sh'
}
}
stage('Test') {
steps {
sh './test.sh'
}
}
stage('Deploy') {
steps {
sh './deploy.sh'
}
}
}
}
이렇게 Pipeline을 코드로 관리하는 방식을 Pipeline as Code라고 한다.
Jenkinsfile
Jenkinsfile은 Jenkins Pipeline을 정의하는 파일이다.
보통 Repository에 함께 저장한다.
project -> src / tests / Dockerfile / Jenkinsfile
이렇게 하면 CI/CD 설정도 소스 코드와 함께 버전 관리할 수 있다.
Git -> Source Code / Test / Dockerfile / Jenkinsfile
Jenkins 서버에 Pipeline 설정을 수동으로 작성하는 것보다 변경 이력을 관리하기 쉽다.
Declarative Pipeline
Jenkins Pipeline은 크게 Declarative와 Scripted 방식으로 나눌 수 있다.
일반적으로 처음 접한다면 Declarative Pipeline부터 이해하는 편이 좋다.
pipeline {
agent any
stages {
stage('Build') {
steps {
sh './build.sh'
}
}
}
}
구조는 다음과 같이 이해할 수 있다.
pipeline -> agent / stages -> stage -> steps
Stage
Stage는 Pipeline의 논리적인 작업 단위다.
예를 들어
Build / Test / Package / Deploy
를 각각 Stage로 만들 수 있다.
stages {
stage('Build') {
steps {
sh './build.sh'
}
}
stage('Test') {
steps {
sh './test.sh'
}
}
}
Jenkins UI에서도 Stage별 결과를 확인할 수 있기 때문에 어떤 단계에서 실패했는지 파악하기 쉽다.
Step
Stage 안에서 실제 명령을 실행하는 단위가 Step이다.
steps {
sh './build.sh'
sh './test.sh'
}
Linux에서는 sh, Windows에서는 bat 등을 사용할 수 있다.
steps {
bat 'build.bat'
}
결국 Jenkins는 개발자가 기존에 터미널에서 실행하던 명령을 자동화된 Pipeline 안에서 실행하는 것이라고 볼 수도 있다.
Jenkins와 Git
Jenkins는 Git과 함께 사용하는 경우가 많다.
Developer -> Git Push -> Jenkins -> Checkout -> Build
Jenkins가 Git Repository에서 코드를 가져온 다음 Pipeline을 실행한다.
Jenkinsfile이 Repository에 있다면
Git Repository -> Source Code / Jenkinsfile
Jenkins가 해당 파일을 읽어서 Pipeline을 실행할 수 있다.
Trigger
Jenkins가 언제 Pipeline을 실행할 것인지 결정해야 한다.
대표적인 방식은 다음과 같다.
Git Push / Pull Request / Webhook / Schedule / Manual
예를 들어 GitHub에서 Push가 발생하면 Webhook을 통해 Jenkins에 이벤트를 전달할 수 있다.
GitHub -> Webhook -> Jenkins -> Pipeline 실행
Polling
Jenkins가 Git Repository를 주기적으로 확인해서 변경사항이 있는지 검사하는 방식도 있다.
Jenkins -> 일정 시간마다 -> Git Repository 확인 -> 변경 없음 / 변경 있음 -> Build 실행
하지만 Repository에서 변경이 발생했을 때 바로 Jenkins에 알려주는 Webhook 방식이 더 효율적인 경우가 많다.
CI Pipeline
일반적인 CI Pipeline은 다음과 같다.
Git Push -> Checkout -> Build -> Unit Test -> Integration Test -> Static Analysis -> Build Success
예를 들어 C++ 프로젝트라면
Checkout -> CMake Configure -> Build -> Unit Test -> Package
같은 Pipeline을 만들 수 있다.
Node.js라면
Checkout -> npm ci -> npm run build -> npm test -> Package
처럼 구성할 수 있다.
CD Pipeline
CI가 코드의 품질을 검증한다면 CD는 결과물을 실제 환경에 전달하는 역할을 한다.
Build -> Package -> Artifact -> Deploy
Docker를 사용한다면
Git Push -> Jenkins -> Docker Build -> Docker Image -> Registry Push -> Server Deploy
같은 구조가 된다.
Jenkins와 Docker
Jenkins는 Docker와 함께 사용하는 경우가 많다.
Jenkins Agent 자체를 Docker Container로 실행할 수도 있고, Pipeline에서 Docker Image를 빌드할 수도 있다.
Jenkins -> Docker Build -> Image -> Registry -> Production
환경을 Docker Image로 고정하면 CI 환경 차이로 발생하는 문제를 줄일 수 있다.
Jenkins Plugin
Jenkins의 강력한 부분 중 하나가 Plugin 시스템이다.
Jenkins 자체가 모든 기능을 직접 구현하기보다는 Plugin을 통해 다양한 외부 시스템과 연결한다.
예를 들어
Git / GitHub / GitLab / Docker / Kubernetes / AWS / Slack / SonarQube
등과 연동할 수 있다.
구조를 보면 다음과 같다.
Jenkins -> Git Plugin / Docker Plugin / Kubernetes Plugin / Slack Plugin / Cloud Plugin
그래서 Jenkins는 특정 개발 환경에 맞춰 상당히 자유롭게 구성할 수 있다.
다만 Plugin이 많아질수록 관리해야 할 의존성도 증가한다.
Jenkins와 Kubernetes
대규모 CI/CD 환경에서는 Jenkins Agent를 Kubernetes에서 동적으로 생성하는 구조도 사용할 수 있다.
Jenkins Controller -> Kubernetes -> Agent Pod / Agent Pod / Agent Pod
Build 요청이 들어오면 필요한 Agent Pod를 생성해서 작업을 수행하고 작업이 끝나면 제거하는 방식이다.
Build 요청 -> Agent 생성 -> Build -> Test -> 결과 저장 -> Agent 제거
이렇게 하면 작업량에 따라 실행 환경을 유동적으로 확장할 수 있다.
Artifact
Build 결과물을 다음 단계에서 사용해야 한다면 Artifact로 관리할 수 있다.
예를 들어
Build -> game-server / game-client / installer
같은 결과물이 만들어질 수 있다.
Pipeline에서는
Build -> Artifact 저장 -> Test -> Deploy
같은 구조를 만들 수 있다.
Artifact Repository를 별도로 사용하는 경우도 있다.
Jenkins -> Artifact -> Nexus / Artifactory -> Deploy
Jenkins Credential
CI/CD에서는 Git 인증정보, SSH Key, Cloud Credential, API Token 같은 민감한 값이 필요하다.
이 값을 Jenkinsfile에 직접 넣으면 안 된다.
// 잘못된 방식
sh 'deploy --token=abc123'
Jenkins에서는 Credential을 별도로 관리하고 Pipeline에서 참조하도록 구성할 수 있다.
Jenkins -> Credentials -> SSH Key / API Token / Username / Password / Cloud Credential
Pipeline은 Credential의 실제 값을 직접 코드에 작성하지 않고 필요한 작업에서 사용할 수 있다.
Jenkins와 GitHub Actions의 차이
둘 다 CI/CD에 사용할 수 있지만 운영 방식에서 차이가 있다.
| 구분 | Jenkins | GitHub Actions |
|---|---|---|
| 형태 | 별도 CI/CD 서버 | GitHub 기반 CI/CD |
| 운영 | 직접 운영 | GitHub가 기본 인프라 제공 |
| Pipeline | Jenkinsfile | YAML Workflow |
| 실행 환경 | Agent | Runner |
| 확장 | Plugin | Action |
| GitHub 연동 | 별도 구성 가능 | 매우 자연스러움 |
| Self-hosted | 가능 | 가능 |
| 커스터마이징 | 매우 높음 | 높음 |
| 유지보수 | 직접 관리 필요 | 상대적으로 적음 |
구조적으로 비교하면 다음과 같다.
Jenkins -> Git -> Jenkins Controller -> Jenkins Agent -> Build / Test / Deploy
GitHub Actions -> GitHub -> Workflow -> Runner -> Build / Test / Deploy
다만 둘의 역할 자체는 상당히 겹친다.
Jenkins를 사용하는 이유
Jenkins의 장점은 자유도와 기존 시스템과의 통합 능력에 있다.
특히 다음과 같은 환경에서 의미가 있다.
사내 인프라 / 폐쇄망 / 복잡한 Build 환경 / 커스텀 CI/CD / 기존 Jenkins Pipeline / 대규모 Plugin 생태계 / 여러 종류의 Agent
예를 들어 회사 내부에 이미
GitLab / Jenkins / Nexus / Docker Registry / Kubernetes / AWS
가 구축되어 있다면 Jenkins를 중심으로 전체 Pipeline을 연결할 수 있다.
Jenkins의 단점
반대로 Jenkins는 직접 운영해야 하는 부분이 많다.
Jenkins Server 관리 / Plugin 관리 / Agent 관리 / Credential 관리 / 백업 / 보안 / 업데이트 / 장애 대응
특히 Plugin 의존성이 많아지면 Jenkins 자체가 하나의 운영 시스템이 된다.
Jenkins -> Plugin A / Plugin B / Plugin C / Plugin D -> Dependency / Version / Compatibility
그래서 단순한 GitHub 프로젝트라면 GitHub Actions가 더 편한 경우도 많다.
실무에서 Jenkins를 바라보는 방법
Jenkins를 단순히 “빌드 자동화 프로그램”이라고 생각하면 범위가 너무 좁다.
실제로는 다음과 같은 Pipeline을 관리하는 자동화 Orchestrator에 가깝다.
Git -> Jenkins -> Checkout -> Build -> Test -> Static Analysis -> Package -> Artifact Repository -> Docker -> Kubernetes -> Cloud -> Production
Jenkins 자체가 모든 작업을 수행하는 것이 아니라 각 개발 도구를 연결하고 정해진 순서와 조건에 따라 작업을 실행시키는 역할을 한다.
실무 Jenkins Workflow
일반적인 팀 개발 환경을 하나로 연결하면 다음과 같다.
개발자 -> Feature Branch -> Commit -> Push -> Pull Request -> Jenkins -> Checkout / Build / Test / Lint -> Code Review -> Merge -> main -> Jenkins -> Build / Package / Docker Build / Registry Push -> Deploy -> Production
이 구조에서 Jenkins는 코드가 변경된 이후 실제 서비스에 반영될 때까지의 자동화 흐름을 실행하는 역할을 한다.
정리
Jenkins의 핵심 개념은 많지 않다.
Controller -> Pipeline을 관리
Agent -> 실제 작업을 실행
Pipeline -> CI/CD Workflow
Jenkinsfile -> Pipeline을 코드로 정의
Stage -> Pipeline의 작업 단계
Step -> 실제 실행 작업
Plugin -> 외부 시스템과 연결
Credential -> 인증정보 관리
Artifact -> Build 결과물 관리
전체 구조는 다음과 같이 이해하면 된다.
Git Repository -> Jenkins Controller -> Jenkins Agent -> Build / Test / Package / Deploy
그리고 Jenkins의 본질은 개발자가 반복적으로 수행하던 Build, Test, Package, Deploy 과정을 Pipeline으로 정의하고 자동 실행하는 것이다.
GitHub Actions와 비교하면 GitHub Actions는 GitHub에 붙어 있는 관리형 CI/CD에 가깝고, Jenkins는 직접 서버와 Agent를 운영하면서 필요한 도구들을 조합하는 범용적인 CI/CD 자동화 서버에 가깝다.
실무에서는 둘 중 하나가 절대적으로 우월하다기보다 현재 조직의 Repository, 인프라, 보안 정책, Build 환경, 운영 방식에 맞는 쪽을 선택하는 문제다.