Skip to content

Project Information

KIM DONGJUN edited this page Jul 2, 2023 · 6 revisions

📚 System Architecture

전체 시스템 구성도는 다음과 같습니다.

시스템 구성도

프론트엔드 서버는 AWS Amplify를 통해서 배포되어있습니다. 프론트엔드 서버와 백엔드 서버는 REST API를 통해서 데이터를 주고 받습니다.

백엔드 아키택쳐에 대한 자세한 설명입니다.

  • 먼저 가장 앞단에는 Nginx Web 서버가 실행중입니다.
    • Nginx Web 서버는 요청을 받으면 해당 요청을 두개의 Spring Was 서버로 로드밸런싱 합니다.
  • Spring Was 서버에는 총 4개의 데이터베이스가 붙어있습니다.
    • 1개의 Redis, 3개의 MySql
      • Redis 데이터베이스는 이메일 인증, 멤버 알림, 사용자 토큰 정보 저장에 쓰입니다.
      • MySql 데이터베이스는 그외 애플리케이션 실행에 필요한 멤버, 가계부, 가계부 데이터 등에 대한 정보를 저장합니다.
    • MySql은 1개의 마스터, 2개의 슬레이브로 이루어져있습니다.
      • 읽기 작업은 슬레이브에서 이루어지고, 그외 생성, 업데이트, 삭제 작업은 마스터에서 이루어집니다.

📚 CI/CD

프로젝트에서 구현한 CI/CD 프로세스에 대한 자세한 설명입니다.

CI/CD 프로세스는 다음과 같은 흐름으로 실행됩니다.

Screenshot 2023-07-02 at 15 25 17

프로젝트에서 사용한 깃허브 액션 CI/CD yml 파일의 일부 입니다.

build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
    - uses: actions/checkout@v3
    - name: make application.yml
      run: |
        # create application.yml
        cd ./src/main/resources
        
        # application.yml 파일 생성
        touch ./application.yml
      
        # GitHub-Actions 에서 설정한 값을 application.yml 파일에 쓰기
        echo "${{ secrets.APPLICATION }}" >> ./application.yml

      shell: bash

    - name: Build with Gradle
      run: |
        ./gradlew build

    - name: Save test result
      uses: EnricoMi/publish-unit-test-result-action@v1
      if: always()
      with:
        files: '**/build/test-results/test/TEST-*.xml'
        token: ${{ secrets.TOKEN_GITHUB }}

    - name: Saves check comment when test fails
      uses: mikepenz/action-junit-report@v3
      if: always()
      with:
        report_paths: '**/build/test-results/test/TEST-*.xml'
        token: ${{ github.token }}

    - name: web docker build and push
      run: |
        docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
        docker build -t ${{ secrets.DOCKER_REPO }}/uliga_backend .
        docker push ${{ secrets.DOCKER_REPO }}/uliga_backend
  deploy_was1:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - name: was1 무중단 배포
      uses: appleboy/ssh-action@v0.1.7
      with:
        host: ${{ secrets.WAS1_HOST }}
        username: ubuntu
        key: ${{ secrets.WAS1_PEM_KEY }}
        port: 22
        script: |
          sudo docker pull ${{ secrets.DOCKER_REPO }}/uliga_backend 
          bash deploy.sh
  deploy_was2:
    needs: deploy_was1
    runs-on: ubuntu-latest
    steps:
      - name: was2 무중단 배포
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.WAS2_HOST }}
          username: ubuntu
          key: ${{ secrets.WAS2_PEM_KEY }}
          port: 22
          script: |
            sudo docker pull ${{ secrets.DOCKER_REPO }}/uliga_backend 
            bash deploy.sh
  deploy_web1:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: was1 nginx 무중단 배포
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.WEB_HOST }}
          username: ubuntu
          key: ${{ secrets.WEB_PEM_KEY }}
          port: 22
          script: |
            bash deploy_was1.sh
  deploy_web2:
    needs: deploy_web1
    runs-on: ubuntu-latest
    steps:
      - name: was2 nginx 무중단 배포
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.WEB_HOST }}
          username: ubuntu
          key: ${{ secrets.WEB_PEM_KEY }}
          port: 22
          script: |
            bash deploy_was2.sh

build

  • build 작업에서는 application.yml 파일을 생성하고 깃허브 액션 시크릿으로 부터 읽어온 내용을 applcation.yml 파일에 씁니다.
  • 작성된 application.yml 파일을 포함해서 ./gradlew build 명령어가 실행되며 작성해둔 테스트 코드가 실행되며 jar 파일이 만들어집니다.
  • 테스트 결과를 깃허브 액션에서 볼 수 있게 테스트 결과를 저장한 다음 docker image를 빌드해서 docker hub에 푸쉬하는 것으로 build 작업은 마무리 됩니다.

deploy_was1 & deploy_web1

  • build 작업이 종료되면 실행되는 작업들입니다.
  • deploy_was1deploy_web1은 병렬적으로 실행됩니다.
  • deploy_was1deploy_web1은 각각 ssh로 was, web 서버 인스턴스로 접근해서 미리 작성해둔 deploy.sh, deploy_was1.sh라는 스크립트를 실행합니다.
  • deploy.sh, deploy_was1.sh는 각각 무중단 배포를 위해 작성해둔 스크립트입니다.
    • deploy.sh는 was 서버 인스턴스에서 실행되는 스크립트로 플로우는 아래와 같습니다.
      • 8081 포트로 pull한 도커 이미지를 실행시킵니다.
      • 8081 포트에 curl 명령어를 이용해 응답 값을 확인합니다.
      • 8081 포트에 서버가 올라온 것이 확인되면, 8080 포트에 실행중인 도커 컨테이너를 kill 합니다.
      • 8080 포트로 새로 pull한 도커 이미지를 실행시킵니디ㅏ.
      • 8080 포트에 마찬가지로 curl 명령어를 이용해 응답 값을 확인하다가 실행중인 것이 확인되면 8081 포트에 실행중인 컨테이너를 kill 합니다.
    • deploy_was1.sh는 web 서버 인스턴스에서 was1 서버의 무중단 배포를 위한 스크립트로 플로우는 아래와 같습니다.
      • was1 서버의 8081 포트로 지속적으로 curl 명령어를 통해 서버가 올라온 것을 확인합니다.
      • 서버가 올라온 것이 확인되면 nginx가 바라보는 was1의 포트를 8081로 변경합니다.
      • nginx를 재시작하고, was1 서버의 8080 포트로 지속적으로 curl 명령어를 통해 서버가 올라온 것을 확인합니다.
      • 8080 포트에 서버가 올라온 것이 확인되면, nginx가 바라보는 was1의 포트를 8080으로 변경합니다.

deploy_was2 & deploy_web2

  • deploy_was1, deploy_web1 작업이 종료되면 실행되는 작업들입니다.
  • 마찬가지로 병렬적으로 실행되고, 실행되는 작업 내용은 was2에 대하여 위와 같은 작업을 수행합니다.

총 실행된 작업들은 아래와 같습니다.

Screenshot 2023-07-02 at 15 23 50
Clone this wiki locally