[CI/CD] CI/CD와 Jenkins로 구현하는 개인 프로젝트

9north·2024년 10월 20일

CI/CD

앱 개발 단계에 자동화를 통합하는 앱 제공 방식으로, 지속적 통합(Continuous Integration) 및 지속적 제공/배포 (Continuous Delivery/Deployment)를 뜻한다. 애자일 개발 방식에서 발전한 CI/CD는 운영 원칙을 포함하는 포괄적인 용어이며, DevOps 팀이 코드 변경을 앱에 쉽고 빠르게 구현하도록 지원한다.

경험으로 절감하는 CI/CD의 필요성

예전에 회사에서 진행한 프로젝트에서는 CI/CD가 완벽한 자동화를 이루지 못했다. 매번 깃헙에 파일을 올리고 버전만 변경시키는 배포 스크립트를 돌리고, 빌드 인스톨러를 구동시킨 뒤 인스톨 파일을 만든 다음 리눅스 서버에 접속해서 dist 정적 배포 파일을 변경해야 했다. 빌드할 때마다 최소 한 시간 정도 소요되었으며, 테스트를 제대로 거치지 못한 채 많은 과정을 거치느라 실수도 수도 없이 했다.

당시에는 CI/CD에 시간을 투여할 여지가 적었기 때문에 불편함을 감수하고 수동으로 작업을 진행했다. 결과를 돌이켜봤을 때, 만약 제대로 된 CI/CD가 있었다면, 개발 속도는 훨씬 빨라졌을 거란 아쉬움이 남는다.
신규 개인 프로젝트와 팀 프로젝트를 시작하면서, 이런 어려움을 최소화하고자, CI/CD를 구축한 다음에 프로젝트를 진행하고자 한다.

Jenkins vs Github Actions

CI/CD를 위한 대표적 플랫폼으로 JenkinsGithub Actions가 있다.

Jenkins

소프트웨어 빌드, 테스트, CI/CD와 관련된 모든 종류의 작업 자동화에 사용하는 오픈 소스 자동화 서버. 기본 시스템 패키지, Docker를 통해 설치할 수 있으며, JRE가 설치된 모든 시스템에서 단독 실행 가능하다.

Github Actions

빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI/CD 플랫폼. 리포지토리에 대한 모든 pull request를 빌드 및 테스트하거나 merged pull request를 프로덕션에 배포하는 워크플로를 만들 수 있다.

비교분석JenkinsGithub Actions
러닝 커브높음낮음👍
가격무료👍개인만 무료
참고 자료많음👍적음
사용 범위넓음👍Github 한정
온프레미스*유연하게 적용👍기능이 한정적

온프레미스

원격환경에서 서버를 운영하는 클라우드와는 대비되는 개념으로 기업이 서버를 자체적으로 보유하고 직접 설치 및 운영하는 방식

간단한 개인 프로젝트를 구현하기 위해서는 GitHub Actions를 사용하는 것이 좋다. 쉽고 간편하게 원하는 결과를 구현할 수 있기 때문이다.
JenkinsGitHub actions에 비해 사용하기 어려운 단점이 있으나, 가격 측면에서 우위를 가지고 있어 많은 기업에서 사용하고 있다.

나는 CI/CD를 학습하는 입장에서, 더 많은 배움을 위해 Jenkins를 선택했다.

구축하고자 하는 배포 파이프라인

개인 프로젝트 tmdb의 최종 결과물은 웹 사이트, 팀 프로젝트의 최종 결과물은 모바일 어플리케이션으로 나온다. 개인 프로젝트를 제대로 완성시킨 다음 팀 프로젝트에 적용할 것이라, 먼저 개인 프로젝트부터 정리한다.

tmdb의 간단한 파이프라인 설계 플로우차트

Start

   ⬇ Github Push/Pull Request → Webhook Trigger
   ⬇ Frontend Build (Vite + React)
   ⬇ dist 폴더를 Backend로 복사
   ⬇ Backend Build (Spring Boot)
   ⬇ EC2로 배포
   ⬇ EC2 앱 재시작 및 확인
   ⬇ Post-deployment Checks ⬇ Jenkins 성공/실패 알림

End

플로우차트에는 테스트 과정이 빠져 있는데, 위의 과정이 제대로 이루어지고 난 다음 세부 테스트를 추가하려 한다.

tmdb의 Jenkins 파이프라인 플로우

1. Trigger

Github Webhook: repository의 push 또는 pull request 이벤트 감지 
→ Jenkins 파이프라인 실행

2. Frontend Build (Vite + React)

Step 1: cd frontend
Step 2: npm install (필요한 dependencies 설치)
Step 3: npm run build (Vite를 이용해 정적 파일 생성)
Step 4: 생성된 dist/ 폴더를 백엔드 폴더로 복사
Command: cp -r dist ../backend/dist

3. Backend Build (Spring Boot + Gradle)

Step 1: cd backend
Step 2: ./gradlew clean build (gradle로 Spring Boot 빌드)
결과물: backend/build/libs/tmdb.jar 생성

4. Upload to AWS EC2

Step 1: EC2 서버와 SSH 연결
Command: scp -i [pem 파일] target/tmdb.jar 
		 ec2-user@[EC2 주소]:/home/ec2-user/app/
Step 2: EC2 서버에서 기존 앱 중단
Command: ssh -i [pem 파일] ec2-user@[EC2 주소] "pkill -f tmdb.jar || true"
Step 3: 새 앱 실행
Command: ssh -i [pem 파일] ec2-user@[EC2 주소] 
		"nohup java -jar /home/ec2-user/app/tmdb.jar > log.txt 2>&1 &"

5. Post-deployment Checks

Step 1: EC2 서버에서 앱 상태 점검 (포트 확인 등)
Command: curl -I http://[EC2 주소]:[포트]
Step 2: Jenkins에 성공/실패 알림 표시

무중단 서버가 아닌, 업데이트를 할 때에는 서비스가 모두 종료되는 사양이다. 애자일 기반으로, 최소 기능이 완성되고 난 다음 다른 기능을 추가하려 한다.

결론

CI/CD는 개발의 밑바탕이다. 개발 시간의 최소화는 CI/CD에 달려 있다. 이번 프로젝트를 기회 삼아, DevOps의 역량을 키우고 싶다.

참고 자료

Jenkins 공식 문서
GitHub Actions 설명서
온프레미스 VS 클라우드 차이점과 앞으로의 발전방향은?

profile
FE / JAVA 개발자

0개의 댓글