이전까지 졸업작품이나 사이드 프로젝트를 진행했을 때는 .jar파일을 수동으로 빌드하여 Elastic Beanstalk 또는 EC2에 직접 수동배포를 진행했습니다.
그러다보니 매번 Github에 Build하여 확인 및 하는 과정, Github에 Push 이후 배포하는 과정이 통합되어있지 않아 귀찮기도 하고 비효율적이라는 생각이 들어 다음에 하는 프로젝트에서는 꼭 CI/CD를 적용해 자동화해보고 싶었습니다.
특히나 이번 프로젝트는 애자일 방법론을 채택함에 따라 빠르게 만들고, 빠르게 dev브랜치에 merge하고, 빠르게 테스트하는 과정이 요구되어 더욱 지속적인 통합, 지속적인 배포의 필요성이 대두되었고 이번 Clothstar 팀프로젝트에 CI/CD를 적용하여 빠른 빌드테스트 & 배포를 진행해보기로 했습니다.
실무에서는 비록 Jenkins를 많이 사용하고 있지만 모든 설정을 구축하기까지 꽤나 복잡합니다.
따라서 현재 프로젝트에서 빠르게 CI/CD를 도입하여 테스트를 하는 것에 있어 Jenkins를 통한 구축은 오버스펙일 수도 있다고 판단했습니다.
또한 Github Action은 비교적 친숙한 YAML파일로 직접 작성할 수 있고, 코드 호스팅 플랫폼인 Github의 해당 Repository에서 직접 관련한 모든 설정이 가능하며, CI/CD를 위한 서버를 직접 제공하여 현재 우리 프로젝트에 빠르게 적용해볼 수 있겠다는 생각이 들어 채택하게 되었습니다.
Jenkins와 Github Actions의 차이점에는 아래와 같은 사항들이 있습니다.
(출처 : https://choseongho93.tistory.com/)
GitHub Actions는 빌드, 테스트 및 배포 파이프라인을 자동화할 수 있는 CI/CD(연속 통합 및 지속적인 업데이트) 플랫폼입니다. 리포지토리에 대한 모든 PR 요청을 빌드 및 테스트하거나 mergede된 PR을 Production 환경에 배포하는 워크플로를 만들 수 있습니다.
GitHub Actions은(는) 단순한 DevOps 수준을 넘어 리포지토리에서 다른 이벤트가 발생할 때 워크플로를 실행할 수 있도록 합니다. 예를 들어 누군가가 리포지토리에서 새 이슈를 만들 때마다 워크플로를 실행하여 적절한 레이블을 자동으로 추가할 수 있습니다.
Github Action에 관한 자세한 설명은 아래 공식 문서에서 확인할 수 있습니다.
GitHub Actions 설명서
Docker는 컨테이너 기반 가상화 플랫폼으로, 애플리케이션과 그 종속성을 함께 패키지화하여 어디서나 일관되게 실행할 수 있는 큰 장점이 있습니다.
Docker를 선택한 이유는 다음과 같습니다:
일관된 환경 제공: Docker는 애플리케이션과 그 종속성을 컨테이너 이미지로 패키징하여 어떤 환경에서도 동일하게 실행될 수 있습니다. 이를 통해 “개발 환경에서는 잘 동작했는데, 운영 환경에서는 문제가 발생하는” 상황을 방지할 수 있습니다.
이식성(Portability): Docker 컨테이너는 운영 체제에 독립적이므로, 애플리케이션이 클라우드, 온프레미스 서버, 로컬 개발 환경 등 다양한 환경에서 일관되게 동작할 수 있습니다.
격리된 환경: 컨테이너는 애플리케이션과 그 환경을 다른 애플리케이션으로부터 격리시킵니다. 이를 통해 의존성 충돌을 방지하고, 여러 애플리케이션이 동시에 실행될 때도 안정성을 유지할 수 있습니다.
빠른 배포와 스케일링: 컨테이너는 경량화되어 있어 가상 머신보다 빠르게 시작하고 중단할 수 있습니다. 이를 통해 배포 시간을 단축하고, 필요에 따라 애플리케이션을 빠르게 확장할 수 있습니다.
효율적인 리소스 사용: Docker는 가상 머신과 달리 호스트 운영체제의 커널을 공유하기 때문에, 리소스 사용이 더 효율적이며, 더 많은 애플리케이션을 동시에 실행할 수 있습니다.
풍부한 에코시스템: Docker Hub와 같은 공개 레지스트리에는 수많은 공식 및 비공식 이미지가 있어, 개발에 필요한 다양한 서비스를 빠르게 설정하고 사용할 수 있습니다.
Docker Compose와 Kubernetes는 모두 컨테이너화된 애플리케이션의 오케스트레이션 도구입니다.
특히 Kubernetes는 대규모의 클러스터 관리와 복잡한 배포에 적합하고 그 구성이 꽤나 복잡합니다.
현재 프로젝트는 규모가 작고 사이드 프로젝트의 성격을 띠고 있기 때문에, 간단한 설정 파일로 여러 개의 Docker 컨테이너를 정의하고 실행할 수 있어 작은 팀 프로젝트나 테스트 환경에서 더 빠르고 쉽게 사용할 수 있는 Docker Compose를 사용해 보기로 했습니다.
상세한 Flow 과정은 아래와 같습니다.
기존에 테스트코드 빌드를 확인하기 위한 Github Action코드가 있었는데요, 테스트와 배포의 책임을 명확하게 분리하기 위해 AWS 배포를 위한 CI/CD 파이프라인과 테스트코드 빌드를 위한 파이프라인을 분리하기로 결정했습니다.
dev-aws-CI-CD.yml
gradle.yml
테스트 빌드와 배포의 책임을 분리했을 때의 장점은 아래와 같습니다.
[AWS CI/CD] 에서는 GitHub Actions를 통해 자동으로 배포 프로세스를 트리거하고, 새로운 코드가 푸시되면 이미지를 build하고 AWS 인프라에 배포하는 전체 CI/CD 파이프라인을 관리합니다.
코드가 푸시되면 Spring Boot와 Nginx Docker 이미지를 빌드 및 Docker hub에 push합니다.
AWS EC2 인스턴스에서 Docker Compose를 통해 서버에 배포된 컨테이너를 자동으로 업데이트하고 실행합니다.
[Test Build] 에서는 전체 프로젝트를 빌드하고, 테스트 코드(유닛 테스트)를 실행하여 코드가 올바르게 작동하는지 확인합니다.
코드가 develop 브랜치에 푸시되거나 PR(Pull Request)이 생성될 때 트리거되며, Gradle을 사용해 프로젝트를 빌드 및 테스트를 수행하고 테스트 결과를 report합니다.
다음 포스팅부터는 EC2 생성 및 환경 세팅부터 시작하여 실습 및 CI/CD에 필요한 파일/코드들을 작성해보도록 하겠습니다.