이 글에서는 Jenkins로 CI/CD를 구축한 과정에 대해서 다루겠습니다.
글의 목차는 다음과 같습니다.
1) CI/CD를 구축한 이유
2) Jenkins vs Github Actions
3) Jenkins란?
4) Jenkins로 CI/CD 구축하기
1) CI/CD를 구축한 이유

- CI/CD란 Continuous Integration, Continuous Delivery의 줄임말로, 우리나라 말로 번역하면 지속적인 통합, 지속적인 서비스 제공, 지속적인 배포입니다. CI/CD는 애플리케이션 개발 단계를 자동화하여 애플리케이션을 더욱 짧은 주기로 고객에게 제공하는 것을 가능하게 합니다.
- CI/CD가 없다면, 개발자는 자신이 작성한 코드를 Github에 push하면, 해당 코드를 빌드하고, 배포하는 과정을 직접 해야 합니다. 이 과정은 반복적인 작업이므로, 계속해서 직접 배포하는 것은 개발 생산성의 관점에서 볼 때 비효율적입니다. 따라서 CI/CD를 통해 이 과정을 자동화함으로써 개발 생산성을 향상시킬 수 있습니다.
2) Jenkins vs Github Actions
- CI/CD 툴로서 많이 사용하는 것에는 대표적으로 Jenkins와 Gtihub Actions가 있습니다.
각각의 특징은 다음과 같습니다.
| Jenkins | Github Actions |
| 서버 설치 필요 | 클라우드가 있으므로, 별도 설치 필요 없음 |
| 자체 플러그인 지원 | 플러그인 없음 |
| 전세계 많은 사람들이 이용하여 문서가 많음 | 문서가 상대적으로 적음 |
| 자체 UI 제공 | 자체 UI 따로 없음 |
| 설정이 다소 복잡 | 설정이 간단 |
- 저는 개발하는데 참고할 문서가 많음, 자체 UI 제공 등을 고려해 Jenkins를 선택했습니다.
3) Jenkins란?

- Jenkins는 소프트웨어 구축, 테스트, 제공 또는 배포와 관련된 모든 종류의 작업을 자동화하는데 사용할 수 있는 독립형 오픈 소스 자동화 서버입니다. Jenkins는 기본 시스템 패키지, Docker를 통해 설치하거나, JRE(Java Runtime Environment)가 설치된 모든 시스템에서 독립형으로 실행할 수도 있습니다.
- Jenkins를 이해하는데 있어서, Jenkins 파이프라인을 이해하는 것이 중요합니다. Jenkins 파이프라인은 지속적 전달 파이프라인을 Jenkins에 구현하고 통합하는 것을 지원하는 플러그인 모음입니다.
- CD(Continous Delivery) 파이프라인은 소프트웨어를 버전 제어에서 사용자와 고객에게 바로 전달하는 프로세스를 자동화한 표현입니다. 소프트웨어에 대한 모든 변경 사항(소스 제어 - 커밋)은 출시되기까지 복잡한 프로세스를 거칩니다. 이 프로세스에는 신뢰할 수 있고 반복 가능한 방식으로 소프트웨어를 구축하는것 뿐만 아니라 여러 단계의 테스트 및 배포를 통해 구축된 소프트웨어(=빌드)를 진행하는 작업을 포함합니다.
4) Jenkins로 CI/CD 구축하기
- Jenkins로 CI/CD를 구축하는 단계는 다음과 같습니다.
1) Jenkins 아이템 생성 및 설정
2) Github Webhook 설정
3) Jenkins 서버에서 ssh로 배포 서버 접속
4) Jenkins 서버에 있는 빌드 스크립트를 배포 서버에서 실행
5) 테스트
각각의 단계에 대해서 구체적으로 살펴보겠습니다.
1) Jenkins 아이템 생성 및 설정
(1) 새 아이템 생성
- Jenkins 빌드를 위해서는 우선, Jenkins에서 새로운 Item을 생성해줘야 합니다.

- Item 이름은 프로젝트 명으로 정하고, Freestyle project로 생성합니다.

-
(2) Jenkins Item 설정
- 그리고 생성한 아이템 -> Configuration을 선택합니다.
Configuration 페이지에 들어가면 3가지 설정을 해야 합니다.
그것은 Github Repo 등록, Github hook 등록, Gradle 설정입니다.
(2-1) Github Repo 등록
- 내가 소스 코드를 가져올 Github Repo와 브랜치를 등록합니다.
저는 브랜치는 main 브랜치로 등록하였습니다.


(2-2) Github Hook 등록
- Github에서 Hook이 왔을 때, 빌드가 될 수 있도록 'Github hook trigger for GITScm polling'을 선택합니다.

(2-3) Gradle 설정
- 프로젝트의 빌드를 Gradle로 하기 때문에, 마찬가지로 Jenkins에서 빌드를 하려면 Gradle 설정을 해줍니다.
Use Gradle Wrapper와 Make gradlew executable을 선택합니다.

2) Github Webhook 설정
- Github Webhook은 Github에서 이벤트가 발생했을 때, 다른 URL로 API 호출을 할 수 있게 설정하는 것입니다.
(1) Github Webhooks 페이지 접속
- 우선 Github Webhooks 페이지에 접속합니다.

(2) Github Webhooks 페이지 설정
- Github Webhooks 설정을 합니다. Payload URL에는 Jenkins 서버 URL/github-webhook/을 추가하고, Content-Type은 application/json으로 설정합니다.

(3) Secret 설정
- 이 때, secret에 입력할 값은 Jenkins 서버에서 발급합니다.
Jenkins 서버의 사용자명 -> 설정으로 들어가면 API Token을 발급 받을 수 있습니다.
발급 받은 API Token을 Github Webhooks 페이지의 Secret에 입력합니다.

(4) 기타 설정 및 설정 완료
- 그리고 Which events would you like to trigger this webhook?은 Just the push event를 선택한 후에,
Update Webhook을 클릭합니다.

(5) 최종 결과
- 최종적으로 Github과 Jenkins가 잘 연동되었음을 확인할 수 있습니다.
이제 Github의 main 브랜치에 push가 발생하면, Github Webhook이 Jenkins로 전달됩니다.

- 이 과정에서 주의할 점이 있는데, 처음에 바로 연결을 하면 다음과 같은 403 에러가 발생합니다.
에러를 읽어보면 ERROR 403 No valid crumb was included in the request 라는 내용을 확인할 수 있습니다.
여기서 Crumb이란 Jenkins에서의 토큰을 의미하는데, 이것이 필요한 이유는 CSRF 공격을 막기 위함입니다.

※ CSRF(Cross-Site Request Forgery) 공격이란?
- CSRF는 인증된 사용자가 웹 애플리케이션에 특정 요청을 보내도록 유도하는 공격 행위를 말합니다.
크로스 사이트 요청 위조는 생성된 요청이 사용자의 동의를 받았는지 확인 할 수 없는 웹 애플리케이션의
CSRF 취약점을 이용합니다. 공격자의 요청이 사용자의 요청인것처럼 속이는 공격 방식이기에
크로스 사이트 요청 위조라는 명칭이 붙었습니다.
- 위의 문제를 해결하기 위해서는, Jenkins에서 Strict Crumb Issuer 플러그인을 설치해야 합니다.
해당 플러그인을 설치한 후에, Jenkins의 Security 탭에서 설정해줄 수 있습니다.
이 때, Check the session ID는 해제하여야 합니다.

Jenkins 서버에서 ssh로 배포 서버 접속부터는 다음 글에서 살펴보겠습니다.
참고 자료
CI/CD(CI CD, 지속적 통합/지속적 배포): 개념, 툴, 구축, 차이 (redhat.com)
Jenkins vs Github Action 어떤걸 쓰는게 좋을까? (velog.io)
Jenkins - Github 웹훅 설정 에러(HTTP ERROR 403 No valid crumb was included in the request) (tistory.com)
'interviewPrep 프로젝트' 카테고리의 다른 글
| Jenkins로 CI/CD 구축하기 (2) (0) | 2023.10.25 |
|---|---|
| 단위 테스트 및 인수 테스트 작성 (0) | 2023.09.30 |
| 로그인 시 JWT Access Token, Refresh Token 적용하기(with Redis) - 1부 (0) | 2023.09.12 |
| Mysql Named Lock으로 좋아요 기능에 대한 동시성 처리하기 (0) | 2023.09.11 |
| SSE 댓글 알림 기능 개발(with Redis) (0) | 2023.09.11 |