-
Notifications
You must be signed in to change notification settings - Fork 1
[BE] GitAction 학습 정리
-
유연성
다양한 플러그인과 모듈을 통해 거의 모든 환경에 맞춰 설정할 수 있습니다. 필요에 따라 커스터마이징이 가능합니다.
-
다양한 지원 언어
여러 프로그래밍 언어와 빌드 도구를 지원하며, 거의 모든 언어에 대해 사용 가능한 플러그인이 존재합니다.
-
독립성
자체 서버에서 운영되기 때문에 외부 서비스에 의존하지 않고 독립적으로 실행할 수 있습니다.
-
강력한 커뮤니티
오랜 역사와 많은 사용자 기반으로 인해 풍부한 문서와 커뮤니티 지원이 존재합니다.
-
설정 복잡성
초기 설정과 구성이 복잡할 수 있으며, Jenkins 서버 및 플러그인 관리가 번거롭습니다.
-
자원 소모
자체 서버를 운영해야 하므로 인프라 비용과 관리 부담이 큽니다.
-
스케일링 문제
대규모 프로젝트에서 확장성이 제한적일 수 있으며, 여러 노드에서 실행하려면 복잡한 설정이 필요합니다.
-
통합된 환경
GitHub와 원활하게 통합되어 있으며, 레포지토리와 관련된 작업을 쉽게 설정할 수 있습니다. 코드 변경이 발생하면 자동으로 트리거됩니다.
-
간단한 설정
YAML 파일을 통해 간단히 설정할 수 있으며, UI에서 쉽게 수정할 수 있습니다.
-
무료 사용
GitHub의 무료 플랜에서 일정량의 실행 시간이 제공되어 소규모 프로젝트에 적합합니다.
-
빠른 시작
새로운 프로젝트를 시작할 때 즉시 사용할 수 있으며, 초기 설정이 필요 없습니다.
-
제한된 유연성
Jenkins와 비교할 때 커스터마이징과 유연성이 제한적입니다. 기본 제공되는 Action 외에 커스터마이즈가 필요한 경우 적합하지 않을 수 있습니다.
-
GitHub에 의존
GitHub 레포지토리와 연동하여만 사용할 수 있으며, 타깃이 GitHub이 아닐 경우 불리합니다.
-
리소스 제한
무료 플랜의 경우 시간 제한이 있어 대규모 프로젝트에는 비효율적일 수 있습니다.
확장성을 고려하면 Jenkins를 선택하는 것이 좋아보입니다.
하지만 Github Actions만의 고유한 특징들이 너무 매력적입니다.
- Github와 원할하게 통합되어 있고, repository와 관련된 작업을 쉽게 설정할 수 있습니다.
- 간단한 yaml파일 설정을 통해 작성이 가능하고 무료로 사용이 가능합니다.
- 초기 설정이 따로 필요하지 않아서 진행하고 있는 소규모 프로젝트에 적합하다고 판단했습니다.
단점을 살펴봤을 때 커스터 마이즈가 필요한 action이 필요할 경우 추후에 도구를 변경하는 판단을 하면 될 것 같습니다. 또한 리소스 제한 같은 경우에도 저희에게는 넉넉한 양이기 때문에 큰 문제가 되지않을 것 같습니다.
그렇기에 일단 Github Actions를 이용해서 CI/CD를 시작하는 것이 좋다고 생각했습니다.
on:
push or pull_request:
branches:
- main
- develop
push, pull_request같은 트리거를 작성하여 워크플로를 실행합니다.
on:
schedule:
- cron: "0 0 * * *" # 매일 자정에 실행
설정한 일정에 따라 워크플로를 주기적으로 실행합니다.
on:
issues:
types: [opened, closed]
release:
types: [published]
issue, release의 타입에 따라 워크플로를 실행할 수 있습니다.
on:
workflow_dispatch:
inputs:
environment:
description: "Choose the environment to deploy to"
required: true
default: "staging"
version:
description: "Specify the version to deploy"
required: false
default: "latest"
- 매개변수 설명
-
on: workflow_dispatch
- 이 설정을 통해 워크플로가 수동으로 실행될 수 있음을 나타냅니다.
-
inputs
- 수동으로 워크플로를 실행할 때 사용자에게 제공할 수 있는 입력값을 정의합니다.
-
input_name
- 입력값의 이름을 정의합니다. 사용자가 입력할 수 있는 변수의 이름입니다.
-
description
- 입력값에 대한 설명을 제공하는 문자열입니다. 사용자가 입력할 때 어떤 값을 넣어야 하는지를 안내합니다.
-
required
- 입력값이 필수인지 여부를 지정합니다.
true
로 설정하면 사용자가 해당 입력값을 반드시 입력해야 합니다.
- 입력값이 필수인지 여부를 지정합니다.
-
default
- 입력값의 기본값을 설정합니다. 사용자가 값을 입력하지 않을 경우 이 값이 사용됩니다.
-
environment는 필수 입력값, 배포할 환경을 선택하는 것입니다. 기본값은 staging
version은 선택 입력값, 배포할 버전을 지정할 수 있습니다. 기본값을 latest입니다.
코드 빌드 및 컴파일을 처리하는 작업입니다. 주로 애플리케이션의 소스 코드를 빌드하고, 필요한 패키지를 설치하는 등의 단계가 포함됩니다.
-
build작업의 기본 단계
환경 설정 → 종속성 설치 → 소스 코드 컴파일 → 자원 준비 → 테스트 실행 → 아티팩트 생성
💡아티팩트란 ??
아티팩트(artifact)란, 소프트웨어 개발 및 CI/CD(지속적 통합/지속적 배포) 과정에서 생성되는 모든 파일과 데이터를 의미합니다. 이에는 빌드 결과물, 테스트 결과, 로그 파일, 문서, 구성 파일 등이 포함될 수 있습니다. 아티팩트는 여러 가지 목적을 위해 사용됩니다:
-
예시: 컴파일된 바이너리 파일, 패키지(예:
.jar
,.war
,.zip
등). - 빌드 프로세스에서 생성된 최종 산출물로, 배포를 위해 사용됩니다.
- 예시: JUnit XML 파일, HTML 형식의 테스트 리포트.
- 자동화된 테스트의 결과를 기록하여, 테스트가 성공했는지 실패했는지를 확인할 수 있게 합니다.
- 예시: 빌드 또는 테스트 과정에서 생성된 로그.
- 디버깅이나 모니터링을 위해 유용하게 사용됩니다.
- 예시: API 문서, 사용자 매뉴얼.
- 소프트웨어에 대한 설명이나 사용 방법을 기록한 문서입니다.
-
예시: 컴파일된 바이너리 파일, 패키지(예:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: '20.x'
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
코드의 테스트를 실행하는 작업입니다. 유닛 테스트, 통합 테스트 등을 수행하며, 코드의 품질을 검증하는 데 사용됩니다.
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: '20.x'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
build:
runs-on: ubuntu-latest
needs: test # test job이 성공적으로 완료된 경우에만 실행
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: '20.x'
- name: Install dependencies
run: npm install
- name: Build the application
run: npm run build
위의 build에서도 test를 진행할 수는 있지만 각 작업의 역할을 분리하기 위해 test따로 두는 것이 좋아보입니다. 이런식으로 test가 성공적이라면 build를 진행하는 워크플로를 작성할 수 있습니다.
- 테스트 보고서 생성방법
-
테스트 프레임 워크 설정
npm install --save-dev jest jest-junit
-
package.json 설정
{ "jest": { "reporters": [ "default", [ "jest-junit", { "outputDirectory": "./reports/junit", "outputName": "test-results.xml" }] ] } }
-
github actions 워크플로 설정
- name: Upload test report uses: actions/upload-artifact@v2 with: name: test-results path: ./reports/junit/test-results.xml
-
결과 확인
테스트가 실행이 되면 test-result.xml 파일이 github actions의 아티팩트로 업로드됩니다.
-
HTML 리포터로도 사용할 수 있습니다.(추가기능)
-
애플리케이션을 서버나 클라우드 서비스에 배포하는 작업입니다. 이 과정에서 Docker 이미지 빌드, 서버에 파일 전송, 환경 설정 등이 포함될 수 있습니다.
-
runs-on
runs-on
은 GitHub Actions에서 각 작업(job)이 실행될 환경을 지정하는 데 사용됩니다. 이 속성은 해당 작업이 실행될 운영 체제와 환경을 설정합니다. -
name
각 단계의 이름을 지정합니다. 이 이름은 워크플로우 실행 시 사용자에게 보여지며, 어떤 작업이 수행되고 있는지를 쉽게 이해할 수 있도록 도와줍니다.
-
uses
다른 GitHub Actions 또는 액션을 사용할 때 지정합니다. 이 속성은 미리 정의된 액션을 참조하여 재사용할 수 있게 해줍니다.
uses
는 액션의 경로(예: 레포지토리와 태그)를 지정합니다.- uses: actions/checkout@v2
위의 예시는
actions/checkout
액션의 v2 버전을 사용하여 코드 리포지토리를 체크아웃합니다. -
with
-
uses
로 지정된 액션에 인수를 전달합니다. 이 인수들은 액션의 동작을 구성하는 데 필요한 설정값들을 포함합니다.
- uses: actions/setup-node@v1 with: node-version: '20.x'
위의 예시는 Node.js의 버전을
20.x
로 설정하는 데 필요한 인수를 전달하고 있습니다. -
-
run
쉘 명령어나 스크립트를 실행하는 데 사용됩니다. 이 속성을 통해 사용자 정의 명령을 직접 입력할 수 있으며, 리포지토리에서 소스 코드를 빌드하거나 테스트하는 등의 작업을 수행할 수 있습니다.
deploy:
runs-on: ubuntu-latest
needs: build # build 작업이 완료되어야 이 작업이 실행됨
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PASSWORD }}
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /app
docker-compose down
docker-compose up -d
코드 스타일 검사 및 정적 분석을 수행하는 작업입니다. ESLint, Prettier와 같은 도구를 사용하여 코드 품질을 유지합니다.
jobs:
lint:
runs-on: ubuntu-latest
steps:
...(test, build와 동일한 패턴)
- name: Run linter
run: npm run lint
이 단계를 통해서 코드를 자동으로 검사하여 스타일과 문법 문제를 찾아내고, 개발자가 코드 품질을 향상시킬 수 있도록 지원합니다.
- name: Upload Lint Report
uses: actions/upload-artifact@v2
with:
name: lint-report
path: path/to/lint-report-file
결과 요약: Lint 보고서에는 다음과 같은 정보가 포함될 수 있습니다.
- 발견된 문제의 개수
- 각 문제의 유형 및 심각도
- 각 문제의 위치(파일명 및 줄 번호)
- 권장 수정 사항
코드 빌드와 배포를 동시에 처리하는 작업입니다.
build
와deploy
단계를 연속으로 실행하여 빌드 후 바로 배포를 진행합니다.
build_and_deploy
는 build
와 deploy
작업을 결합한 것으로, 전체 CI/CD 파이프라인의 일부분을 구성합니다. 이 작업은 소스 코드를 빌드하고, 테스트한 후, 최종적으로 결과물을 배포하는 과정을 포함합니다.
-
Build:
- 애플리케이션의 소스 코드를 컴파일하고, 필요한 의존성을 설치하며, 테스트를 실행하는 단계입니다.
- 이 단계에서 오류가 없으면 최종 제품을 만들기 위한 준비가 완료됩니다.
-
Deploy:
- 빌드가 완료된 애플리케이션을 실제 서버나 클라우드 환경에 배포하는 단계입니다.
- 이는 컨테이너화된 이미지를 서버에 푸시하고, 새로운 버전의 애플리케이션을 실행하는 과정을 포함합니다.
- 효율성: 빌드와 배포를 한 번의 작업으로 처리하여 시간을 절약하고, 여러 단계를 동시에 관리할 수 있습니다.
- 일관성: 동일한 워크플로우를 통해 빌드와 배포가 이루어지므로, 배포 과정에서의 일관성을 유지할 수 있습니다.
- 간편한 관리: CI/CD 파이프라인을 관리하는 측면에서 빌드와 배포를 하나의 작업으로 묶으면 관리가 용이해집니다.
CI/CD 프로세스에서 생성된 임시 파일이나 컨테이너를 정리하는 작업입니다. 필요 없는 파일을 삭제하거나, 종료된 Docker 컨테이너를 정리하는 등의 역할을 합니다.
-
임시 파일 삭제:
- 빌드 및 테스트 과정에서 생성된 임시 파일, 캐시, 로그 파일 등을 삭제하여 디스크 공간을 확보합니다.
-
종속성 정리:
- 특정 작업이 완료된 후 필요 없는 라이브러리나 종속성을 정리합니다. 이는 프로젝트의 경량화를 도와줍니다.
-
Docker 이미지 및 컨테이너 정리:
- Docker를 사용하는 경우, 더 이상 필요하지 않은 이미지와 컨테이너를 삭제하여 Docker 환경을 정리합니다.
-
리소스 해제:
- 클라우드 리소스를 사용하는 경우, 사용이 끝난 리소스(예: 테스트 서버, 데이터베이스 등)를 종료하거나 삭제하여 비용을 절감합니다.
-
상태 초기화:
- 빌드 환경을 초기 상태로 되돌려 다음 빌드를 위해 준비된 상태를 유지합니다.
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Remove temporary files
run: |
rm -rf ./temp/*
- name: Cleanup Docker images
run: |
docker system prune -af
(작성해야함)
- 환경 설정 체크
- 의존성 설치
- 코드 빌드
- 테스트 실행
- 릴리스 또는 배포
- 클린업(정리)
테스트보다 왜 빌드를 먼저할까요??
-
장점:
- 빨리 피드백: 빌드가 성공하면 즉시 테스트를 진행할 수 있어, 문제가 있는 코드가 쉽게 추적됩니다.
- 의존성 문제: 빌드가 먼저 완료되면, 그 후의 테스트에서 의존성 문제나 코드 결함을 확인할 수 있습니다.
-
단점:
- 자원 낭비: 빌드가 실패해도 불필요하게 빌드하는 과정이 발생할 수 있습니다.
-
장점:
- 자원 효율성: 테스트가 통과해야만 빌드가 진행되므로, 실패한 코드에 대한 자원 낭비를 줄일 수 있습니다.
- 빠른 피드백: 코드가 빌드되지 않더라도, 개발자는 테스트 결과를 통해 코드의 품질을 즉시 확인할 수 있습니다.
-
단점:
- 복잡한 설정: 일부 경우에서는 테스트가 빌드에 의존할 수 있어, 환경 구성이 더 복잡해질 수 있습니다.
on:
pull_request:
branches:
- dev-be
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
run: actions/checkout@v2
- name: Docker Hub login
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Build and Push Docker images
run: |
docker-compose -f ./docker-compose.yml build
docker-compose -f ./docker-compose.yml push
- name: send files & deploy script
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
source : ${{ secrets.DOCKER_IMAGE }}
target: /corinee
overwrite: true
- name: docker run
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
script: |
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/corinee-server}
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/corinee-client}
docker-compose down
docker-compose up -d
rm -rf docker-compose.yml
- name: Generate Error Report
if: failure()
run: |
echo "Deployment Report" > report.txt
echo "===================" >> report.txt
echo "Commit SHA: ${{ github.sha }}" >> report.txt
echo "Branch: ${{ github.ref }}" >> report.txt
echo "Deployment Status: Failed" >> report.txt
echo "Error Details: ${{ job.status }}" >> report.txt # 오류 상태 추가
echo "===================" >> report.txt
cat report.txt
- name: Upload Error Report
if: failure()
uses: actions/upload-artifact@v2
with:
name: deployment-error-report
path: report.txt
- name: Deploy with SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd /app
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-fe:${{ github.sha }}
docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/web16-b1g1-be:${{ github.sha }}
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker-compose up -d
rm -rf .env docker-compose.yml
- Checkout repository
- docker hub 로그인
- docker build
- ssh 접속 후 이미지 전송
- docker run
main.yml
name: Build and Deploy
on:
push:
branches:
- feature-be-10
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: '20.x'
- name: Install yarn
run: npm install -g yarn
- name: Docker Hub login
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build and Push Docker images
run: |
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/corinee-server -f ./dockerfile-server .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/corinee-server
docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/corinee-client -f ./dockerfile-client .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/corinee-client
- name: Send files & deploy script
uses: appleboy/scp-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
source: ${{ secrets.DOCKER_IMAGE }}
target: /corinee
overwrite: true
- name: Docker run
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
password: ${{ secrets.SSH_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
script: |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/corinee-server
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/corinee-client
cd /corinee
docker-compose down
docker-compose up -d
- name: Generate Error Report
if: failure()
run: |
echo "Deployment Report" > report.txt
echo "===================" >> report.txt
echo "Commit SHA: ${{ github.sha }}" >> report.txt
echo "Branch: ${{ github.ref }}" >> report.txt
echo "Deployment Status: Failed" >> report.txt
echo "Error Details: ${{ job.status }}" >> report.txt
echo "===================" >> report.txt
cat report.txt
- name: Upload Error Report
if: failure()
uses: actions/upload-artifact@v3
with:
name: deployment-error-report
path: report.txt
docker-compose.yml
services:
# db:
# image: mysql:5.7
# environment:
# MYSQL_ROOT_PASSWORD: root
# MYSQL_DATABASE: mydb
# MYSQL_USER: user
# MYSQL_PASSWORD: password
# volumes:
# - db-data:/var/lib/mysql
# networks:
# - app-network
server:
build:
context: .
dockerfile: dockerfile-server
image: seunggwan/corinee-server
ports:
- "3000:3000"
# environment:
# # DB_HOST: db
# # DB_USER: user
# # DB_PASSWORD: password
# # DB_DATABASE: mydb
networks:
- app-network
client:
build:
context: .
dockerfile: dockerfile-client
image: seunggwan/corinee-client
ports:
- "80:80"
depends_on:
- server
networks:
- app-network
volumes:
db-data:
networks:
app-network:
- [FE] TailwindCSS @apply
- [FE] 캐러셀 구현
- [FE] 사이드 바 상태관리 도전기
- [FE] axios interceptor로 로그인 필요한 api 개선하기
- [FE] Tanstack Query API 최적화 도전기
- [FE] Tanstack Query로 구현하는 무한 스크롤 차트 도전기
- [FE] 차트 무한 스크롤링 최적화 도전기
- [FE] 차트 실시간 등락 구현 도전기
- [FE] 검색 구현 및 검색 API 호출 최적화 도전기
- [FE] 고차 컴포넌트를 활용한 인증 접근 제어
- [FE] 코드 스플릿팅으로 최적화 도전기
- [BE] Server 생성
- [BE] CI/CD
- [BE] GitAction 학습 정리
- [BE] ssh터널링으로 db연결
- [BE] 배포환경에서 DB 연결 및 테스트 완료
- [BE] https 적용
- [BE] upbit api 연결 및 SSE api
- [BE] SSE 구현
- [BE] SSE 에러
- [BE] redis 설치 및 연동
- [BE] 트랜잭션 락 구현과 최적화
- [BE] Oauth CORS
- [BE] QueryRunner 사용 시 발생한 문제점과 해결방안
- [BE] Git Action 학습 정리
- [BE] NestJS 학습 정리
- [BE] 로그인 기능 및 리프레시토큰
- [BE] 비회원 체험 기능
- [BE] Nginx 학습 정리
- [BE] Mixed Content와 HTTPS 보안 구현하기
- [BE] 매수/매도 로직 구현 및 개선 과정
- [BE] Queue, Load Balancing, Redis