[Jenkins] Jenkins로 처음 구축해본 CI/CD 파이프라인1

2026. 3. 22. 20:53·Infra
더보기
인프런-애플리케이션 배포 자동화와 CI/CD 강의를 듣고 작성된 글입니다.

백엔드 개발을 공부하면서 API를 만들고 기능을 구현하는 경험은 많이 해봤지만, 배포는 제대로 해본 적이 없었다. 프로젝트를 진행하며 배포 환경 때문에 예상치 못한 문제를 겪기도 했고 실제 서비스가 어떻게 서버에서 실행되는지 궁금하기도 했다. 그래서 이번에는 Jenkins를 이용한 자동 배포 강의를 따라가며 직접 CI/CD 환경을 구축해보았다.

1. Jenkins 서버 구축

Jenkins 서버 생성

먼저, Jenkins를 설치할 서버를 생성한다. 서버 위에 Jenkins를 설치하고 접속한다.

https://github.com/lleellee0/application-deploy-advanced/blob/main/1_0_jenkins_setting_cmd

그다음 서버 ip:8080으로 브라우저에 접속해서 초기 비밀번호를 입력하면 된다.

 

2. SSH Key 기반 인증 구성

Jenkins가 서버에 자동으로 접속하려면 비밀번호 입력 없이 SSH 인증이 가능해야 한다.

이를 위해 공개키(Public Key)와 개인키(Private Key)를 생성한다.

Jenkins 서버에서 SSH Key 생성

Jenkins 컨테이너에 접속한다.

// 컨테이너 접속
docker exec -it {컨테이너id} /bin/bash
// 키 생성 rsa 알고리즘, 4096bit로
ssh-keygen -t rsa -b 4096
 

생성 후 공개키를 확인한다.

cat /var/jenkins_home/.ssh/id_rsa.pub
 

Application Server에 공개키 등록

Application Server에서 다음 파일을 연다. 위에서 확인한 공개키를 추가한다.

vi ~/.ssh/authorized_keys
 

왜 공개키를 등록해야 하는가?

SSH 공개키 인증 방식은 다음과 같이 동작한다.

Jenkins
 ├─ Private Key 보유
 └─ SSH 접속 시도

Application Server
 └─ Public Key 보유
 

서버는 Jenkins가 제시한 개인키가 자신이 저장한 공개키와 쌍이 맞는지 검증한다.

즉, authorized_keys 파일은 "이 공개키를 가진 사용자의 접속을 허용한다"는 의미이다. 따라서 Jenkins가 비밀번호 없이 SSH 접속할 수 있게 된다.

 

3. 파이프라인 생성

item을 생성해서 pipeline을 선택해서 만들어주면 된다. Pipeline은 빌드·배포 과정을 코드로 관리할 수 있어서 버전 관리와 재사용이 쉽고 복잡한 CI/CD 흐름을 구성하기 편하기 때문에 사용한다. 

그 다음 코드를 작성해주면 된다. 

4. Jenkins Credentials 등록

SSH 설정 후에도 빌드가 실패할 수 있다. 대표적으로 다음과 같은 오류가 발생한다.

sshagent step requires a credential

이를 해결하기 위해 Jenkins Credential에 개인키를 등록해야 한다.

Jenkins 개인키 확인

cat /var/jenkins_home/.ssh/id_rsa
 

전체 내용을 복사한다.

-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
 

Jenkins Credential 생성

Jenkins에서 credential을 설정해줘야한다. 설정 이모티콘을 눌러서 jenkins 관리에 들어오면 Security - Credentials 가 있다.

Domains: Global에 들어가서 Add 버튼을 누르고 SSH Username with private key를 선택하면 된다. 

입력해야할 값은 아래와 같다.

ID : deploy_ssh_key
Username : root
Private Key : id_rsa 내용 전체
 

sshagent 사용

파이프라인에서 등록한 Credential을 사용한다.

sshagent(['deploy_ssh_key']) {
    sh "ssh root@$serverIp"
}

이렇게 하면 Jenkins가 해당 개인키를 사용해 SSH 인증을 수행한다.

5. Java 설치

Spring Boot 애플리케이션을 실행하려면 Java가 설치되어 있어야 한다.

sudo dnf install java-17-openjdk
 

6. 방화벽 설정

Spring Boot는 기본적으로 8080 포트를 사용한다. 외부에서 접근하려면 해당 포트를 열어야 한다.

sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
 

왜 Application Server는 포트를 열어야 하는가?

Application Server는 외부 사용자의 요청을 받아야 한다.

따라서

Client
 ↓
8080
 ↓
Application Server

형태로 접근이 가능해야 한다.

 

7. SCP를 이용한 파일 전송

Jenkins는 빌드된 JAR 파일을 Application Server로 복사해야 한다. 이때 사용하는 명령어가 SCP이다.

scp app.jar root@server:/root/

 

SCP는 SSH 프로토콜을 이용해 파일을 안전하게 전송한다. 

 

8. 애플리케이션 실행

초기에는 다음과 같이 실행하였다.

java -jar app.jar

이렇게 되면 Spring Boot는 종료되지 않는 프로세스인데 Jenkins는 명령이 끝날 때까지 기다리기 때문에 Jenkins가 영원히 대기하게 된다.

nohup 사용

따라서 백그라운드로 실행해야 한다.

nohup java -jar app.jar > app.log 2>&1 &

의미는 다음과 같다.

nohup  : 터미널 종료 후에도 실행 유지
>      : 로그 파일 저장
2>&1   : 에러 로그도 함께 저장
&      : 백그라운드 실행
 

9. 배포 성공 여부 검증

애플리케이션을 실행했다고 해서 배포가 성공한 것은 아니다. 실제로는 실행 직후 예외가 발생하거나 설정 문제로 인해 정상적으로 기동되지 않을 수도 있다. 따라서 배포 후에는 애플리케이션이 정상적으로 실행되었는지 확인하는 과정이 필요하다.

 

이번 실습에서는 로그 파일에 특정 문자열이 존재하는지 확인하는 방식으로 배포 성공 여부를 검증했다.

grep "Started" app.log

 

Spring Boot는 정상 실행 시 다음 로그를 출력한다. 

Started Application in 5.123 seconds

Jenkins는 해당 문자열 존재 여부를 확인해 성공 여부를 판단할 수 있다.

 

현재 방식의 한계

현재 파이프라인에서는 애플리케이션 실행 후 일정 시간 동안 대기한 뒤 로그를 확인한다.

sleep 20

하지만 애플리케이션 규모나 서버 상태에 따라 실행 완료까지 걸리는 시간은 달라질 수 있다.

예를 들어 애플리케이션이 정상적으로 실행되기까지 30초가 걸리는 경우, Jenkins는 20초 후 로그를 확인했을 때 아직 시작 로그를 찾지 못해 배포 실패로 판단할 수 있다. 하지만 실제로는 이후 정상적으로 기동될 수 있으므로 고정된 대기 시간만으로 배포 성공 여부를 판단하는 것은 한계가 있다.

 

 

이를 보완하기 위해 2가지 방식을 사용할 수 있다. 

Health Check

응답

curl localhost:8080/actuator/health
확인
{
  "status":"UP"
}
 

반복 Polling

for i in {1..30}
do
  curl localhost:8080/actuator/health && break
  sleep 5
done
 

10. GitHub Webhook 설정

현재는 Jenkins에서 직접 빌드를 실행해야 한다. 하지만, GitHub Push 이벤트를 이용하면 자동 배포가 가능하다.

Webhook 등록

GitHub

Repository
 → Settings
 → Webhooks

추가

Payload URL

http://{jenkins-url}/github-webhook/

Content Type

application/json

이후 Push 이벤트를 선택한다.

Jenkins 설정

아까 개인키를 입력해줬던 것과 같이 이번에도 Credential에서 github token을 입력해주면 된다. 

Username : GitHub ID
Password : Personal Access Token
ID : github-token
 
그 다음 구성에 들어가서 Github project를 선택해서 해당 레포의 url을 입력하고
Trigger에서도 Github hook trigger ~ 을 체크해주면 된다.

11. 기존 프로세스 종료 문제

배포를 여러 번 수행하면 다음 오류가 발생한다. 이미 이전 애플리케이션이 실행 중이기 때문이다.

Web server failed to start.
Port 8080 was already in use.

따라서 기존 프로세스를 종료하고 새 프로세스를 실행할 수 있도록 해줘야한다. 

 

lsof -ti:8080
 

PID 확인 후

kill -9 PID

또는

pkill -f app.jar

를 사용하여 기존 프로세스를 종료할 수 있다.

 

하지만 이 방식은 또 다른 문제를 발생시킨다.

 

12. 무중단 배포

현재 방식은 다음 순서로 동작한다.

기존 애플리케이션 종료
↓
새 애플리케이션 실행
↓
사용자 접속 가능

기존 프로세스를 종료한 시점부터 새로운 애플리케이션이 완전히 실행될 때까지는 요청을 처리할 수 없다. 이를 다운타임(Downtime)이라고 한다.

 

이를 보완하기 위해 아래와 같은 방식이 있다고 한다. 

  • Blue-Green Deployment
  • Rolling Deployment
  • Canary Deployment
  • Kubernetes Deployment
  • Nginx Reverse Proxy 기반 무중단 배포

예를 들어 Blue-Green 방식은 다음과 같이 동작한다.

8081 버전 실행
↓
정상 확인
↓
Nginx 트래픽 전환
↓
8080 종료

기존 서비스가 동작하는 상태에서 새로운 버전을 먼저 실행한 뒤 트래픽을 전환하기 때문에 사용자는 서비스 중단을 거의 느끼지 못한다.

 

현재 Jenkins + SCP + nohup 방식은 가장 기본적인 자동 배포 구조이다. 이후 Docker, Nginx, Kubernetes 등을 도입하면 무중단 배포까지 확장할 수 있다.

정리

이번 실습에서는 Jenkins를 이용해 다음 과정을 자동화하였다.

  • GitHub 소스코드 다운로드
  • Maven 빌드
  • SCP를 이용한 JAR 파일 전송
  • SSH 원격 실행
  • 배포 성공 여부 검증
  • GitHub Webhook 기반 자동 배포

 

'Infra' 카테고리의 다른 글

[CI/CD] Jenkins로 처음 구축해본 CI/CD 파이프라인3  (0) 2026.03.27
[NGINX] Jenkins로 처음 구축해본 CI/CD 파이프라인2  (3) 2026.03.24
[k8s] 로컬로 쿠버네티스 구축하기 - minikube, kubectl  (0) 2026.03.08
[k8s] 쿠버네티스란?  (0) 2026.03.04
[AWS] Elastic Beanstalk로 FastAPI + Redis CRUD API 배포하기(2)  (1) 2025.06.07
'Infra' 카테고리의 다른 글
  • [CI/CD] Jenkins로 처음 구축해본 CI/CD 파이프라인3
  • [NGINX] Jenkins로 처음 구축해본 CI/CD 파이프라인2
  • [k8s] 로컬로 쿠버네티스 구축하기 - minikube, kubectl
  • [k8s] 쿠버네티스란?
지-토리
지-토리
  • 지-토리
    지토리의 개발이야기
    지-토리
  • 전체
    오늘
    어제
    • 분류 전체보기 (46)
      • [AND] 사용자 정의 지표 기반 실시감 감지 및.. (13)
        • 기획 (4)
        • 기술 (8)
      • [Linkompany] 뉴스와 공시를 통합 기업 .. (4)
      • [Candly] 차트 공부 및 예측 웹 프로젝트 (2)
      • JAVA (4)
        • 코딩테스트 (1)
      • 대규모 시스템 설계 (1)
      • Infra (12)
      • ELK (3)
      • AI (2)
      • FrontEnd (1)
      • TIP (2)
      • 자격증 (1)
  • 블로그 메뉴

    • 홈
    • Github
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    K8S
    And
    신투
    K디지털트레이닝
    부트캠프
    Issue
    kpt
    쿠버네티스
    인증/인가
    Firebase
    프로디지털아카데미
    알파코
    kdt교육
    SpringSecurity
    프로젝트
    EC2
    알파코캠퍼스
    신한투자증권
    인프런
    프디아
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
지-토리
[Jenkins] Jenkins로 처음 구축해본 CI/CD 파이프라인1
상단으로

티스토리툴바