sellen

SpringBoot - Big Bang Deployment 본문

DevOps/Deploy

SpringBoot - Big Bang Deployment

sellen 2025. 7. 28. 01:41

빅뱅 배포

빅뱅 배포법은 서버에 전체 시스템을 한 번에 배포하는 방식입니다.

서버에 문제가 생길 경우 롤백을 하기 힘들다는 단점이 존재합니다.

하지만 모든 기능을 한 번에 새 버전으로 배포하므로 빠르게 전체 시스템을 사용자에게 제공한다는 장점이 있으며 준비 및 세팅도 비교적 간단하다는 장점이 있습니다.

EC2에 배포를 할 계획이며 EC2 생성은 하단의 링크를 참고해 주세요.

2025.07.26 - [DevOps/AWS] - AWS - VPC 생성

2025.07.26 - [DevOps/AWS] - AWS - 보안 그룹 생성

2025.07.26 - [DevOps/AWS] - AWS - EC2 생성

2025.07.26 - [DevOps/AWS] - AWS - 탄력적 IP


 

1. EC2에 필요한 패키지 설치

sudo apt update
sudo apt install openjdk-17-jdk

SpringBoot 애플리케이션을 jar로 압축한 후 EC2에서 실행시키기 위해 java를 설치해야 합니다.

# Java 버전 확인
java -version

설치가 완료되면 java 버전을 확인하여 제대로 설치가 되었는지 확인합니다.


2. 스왑 메모리 설정

스왑 메모리는 서버의 RAM이 부족할 때, 디스크 공간을 임시 메모리로 사용하는 기능입니다.

EC2를 생성할 때 micro 같은 프리티어 인스턴스는 메모리가 1GB 미만으로 설정되어 있습니다.

따라서 트래픽이 몰리거나, 큰 애플리케이션을 실행할 경우 메모리가 부족하여 다운될 가능성이 있습니다.

sudo fallocate -l 2G /swapfile  # 2GB 크기 스왑 파일 생성
sudo chmod 600 /swapfile # 스왑 파일의 권한 설정(root 사용자만 읽고 쓰는게 가능)
sudo mkswap /swapfile # 생성한 파일을 스왑 영역으로 초기화
sudo swapon /swapfile # 스왑 파일을 활성화하여 실제로 사용하게 한다.

2GB 크기의 스왑 파일을 생성하여, 스왑 메모리를 설정합니다.

# /swapfile 이라는 이름의 파일이 출력해야 합니다.
sudo swapon --show 

# Mem과 Swap 두개가 출력되어야 합니다.
# 이 때 Swap은 2GB로 설정했으므로 2GB로 출력되어야 합니다.
free -h

스왑 메모리가 정상적으로 설정되었는지 확인합니다.


3. GitHub Secrets 설정

EC2 페어키나 스프링부트 환경변수 같은 노출되면 안 되는 정보는 GitHub Secrets에 저장하여 사용합니다.

  1. GitHub 리포지토리 페이지에서 [Settings] 탭으로 이동합니다.
  2. 좌측 사이드 바에서 [Secrets and variables] > [Actions] 선택합니다.
  3. [New repository secret] 버튼을 클릭합니다.

위 사진처럼 시크릿들을 추가합니다.

Secret 설명
APPLICATION_YML application.yml 내용
EC2_HOST EC2 인스턴스의 퍼블릭 IP 주소
EC2_SSH_KEY EC2 인스턴스 접속에 사용할 프라이빗 키
EC2_USERNAME ubuntu 입력
  • APPLICATION_YML : applicaiton.yml 내용을 그대로 복사 붙여 넣기 하시면 됩니다.
    • properties 파일도 그대로 복사 붙여 넣기 하시면 됩니다.
    • intelliJ에 설정한 환경변수도 yml에 안에 같이 넣으셔야 합니다.
    • 이때 DB 설정을 로컬이 아닌 외부 DB로 변경하셔야 합니다.
    • JPA의 경우 hibernate.hbm2ddl.auto를 create로 설정하여 테이블을 생성한 후 update로 바꾸셔야 합니다.
  • EC2_HOST : EC2 인스턴스의 퍼블릭 IP를 입력하시면 됩니다.
    • 탄력적 IP가 설정되어있지 않을 경우 EC2 재실행 시 퍼블릭 IP가 변경되어 배포가 안됩니다.
  • EC2_SSH_KEY : EC2를 생성할 때 다운로드하였던. pem 파일의 내용을 그대로 넣으시면 됩니다.
-----BEGIN RSA PRIVATE KEY-----
(키 내용)
-----END RSA PRIVATE KEY-----

이런 식으로 되어있습니다.

txt로 변환해서 하셔도 되고 저는 웹사이트에 드래그 드롭해서 복붙 합니다.

  • EC2_USERNAME : 인스턴스 유형을 ubuntu로 했기 때문에 ubuntu를 입력하시면 됩니다.
GitHub Secrets에 저장된 정보는 암호화되며, 설정 후 다시 볼 수 없습니다.

4. GitHub Actions 설정하기

  1. GitHub 리포지토리 페이지에서 [Actions] 탭으로 이동합니다.
  2. Actions 페이지에서 [set up a workflow yourself →] 링크를 클릭합니다.
  3. 아래의 코드를 입력하시면 됩니다.

이때 {server_name}라고 되어있는 부분은 본인의 프로젝트 이름으로 입력하셔야 합니다.

name: CI/CD Pipeline

on:
  pull_request:
    branches: [ main ]
    types: [ closed ]  # main 브랜치에 PR 병합될 때 실행

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3  # 저장소 코드 체크아웃

      - name: Set up JDK 17  # Java 개발 킷 설정
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Make application.yml  # application.yml 파일 생성
        run: |
          cd ./src/main/resources
          echo "${{ secrets.APPLICATION_YML }}" > ./application.yml
        shell: bash
        
      - name: Grant execute permission for gradlew  # gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle  # Gradle을 사용하여 프로젝트 빌드
        uses: gradle/gradle-build-action@v2
        with:
          arguments: build

      - name: Upload build artifact  # 빌드된 아티팩트 업로드
        uses: actions/upload-artifact@v4
        with:
          name: {server_name}  # 본인의 프로젝트 이름으로 변경
          path: build/libs/*.jar

  deploy:
    needs: build  # build 작업이 성공적으로 완료된 후 실행
    runs-on: ubuntu-latest

    steps:
      - name: Download build artifact  # 이전 단계에서 업로드한 아티팩트 다운로드
        uses: actions/download-artifact@v4
        with:
          name: {server_name}  # 본인의 프로젝트 이름으로 변경
          path: build/libs/

      - name: Deploy to EC2  # EC2에 배포
        env:
          EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
          EC2_USERNAME: ${{ secrets.EC2_USERNAME }}
          EC2_HOST: ${{ secrets.EC2_HOST }}
        run: |
          echo "Step 1: Creating private_key.pem"
          echo "$EC2_SSH_KEY" > private_key.pem
          chmod 600 private_key.pem
          
          echo "Step 2: Finding the JAR file"
          jar_file=$(find build/libs -name '*.jar' ! -name '*plain.jar' | head -n 1)
          
          echo "Step 3: Uploading the JAR file to EC2"
          scp -i private_key.pem -o StrictHostKeyChecking=no "$jar_file" $EC2_USERNAME@$EC2_HOST:/home/$EC2_USERNAME/{server_name}.jar  # 본인의 프로젝트 이름으로 변경
          
          echo "Step 4: Stopping old Java process and starting new one"
          ssh -i private_key.pem -o StrictHostKeyChecking=no $EC2_USERNAME@$EC2_HOST "
            pgrep java | xargs -r kill -15  # 기존에 실행 중인 Java 프로세스 종료
            sleep 10
            # 본인의 프로젝트 이름으로 변경
            nohup java -jar /home/$EC2_USERNAME/{server_name}.jar > app.log 2>&1 &  # 새 버전 애플리케이션 실행
          "
          echo "Step 5: Cleaning up"
          rm -f private_key.pem  # 민감한 정보 삭제

on:
  pull_request:
    branches: [ main ]
    types: [ closed ]  # main 브랜치에 PR 병합될 때 실행

이 코드에 의해 main 브랜치에 PR 병합이 되면 GitHub Actions가 실행을 합니다.

on:
  push:
    branches: [ main ]

이렇게 코드를 변경할 경우 main 브랜치에 push를 할 때 실행을 하게 됩니다.

실행 조건은 각자의 프로젝트 환경에 맞춰 변경을 하시면 됩니다.


jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3  # 저장소 코드 체크아웃

      - name: Set up JDK 17  # Java 개발 킷 설정
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Make application.yml  # application.yml 파일 생성
        run: |
          cd ./src/main/resources
          echo "${{ secrets.APPLICATION_YML }}" > ./application.yml
        shell: bash
        
      - name: Grant execute permission for gradlew  # gradlew 실행 권한 부여
        run: chmod +x gradlew

      - name: Build with Gradle  # Gradle을 사용하여 프로젝트 빌드
        uses: gradle/gradle-build-action@v2
        with:
          arguments: build

      - name: Upload build artifact  # 빌드된 아티팩트 업로드
        uses: actions/upload-artifact@v4
        with:
          name: {server_name}
          path: build/libs/*.jar

이 부분은 ubuntu 최신 버전에서 java 17 버전으로 gradle을 통해 jar 파일을 빌드하는 과정입니다.

이때, GitHub Secrets에 저장했던 application.yml 파일을 생성하여 jar 파일에 같이 넣습니다.


  deploy:
    needs: build  # build 작업이 성공적으로 완료된 후 실행
    runs-on: ubuntu-latest

    steps:
      - name: Download build artifact  # 이전 단계에서 업로드한 아티팩트 다운로드
        uses: actions/download-artifact@v4
        with:
          name: {server_name}
          path: build/libs/

      - name: Deploy to EC2  # EC2에 배포
        env:
          EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
          EC2_USERNAME: ${{ secrets.EC2_USERNAME }}
          EC2_HOST: ${{ secrets.EC2_HOST }}
        run: |
          echo "Step 1: Creating private_key.pem"
          echo "$EC2_SSH_KEY" > private_key.pem
          chmod 600 private_key.pem
          
          echo "Step 2: Finding the JAR file"
          jar_file=$(find build/libs -name '*.jar' ! -name '*plain.jar' | head -n 1)
          
          echo "Step 3: Uploading the JAR file to EC2"
          scp -i private_key.pem -o StrictHostKeyChecking=no "$jar_file" $EC2_USERNAME@$EC2_HOST:/home/$EC2_USERNAME/{server_name}.jar
          
          echo "Step 4: Stopping old Java process and starting new one"
          ssh -i private_key.pem -o StrictHostKeyChecking=no $EC2_USERNAME@$EC2_HOST "
            pgrep java | xargs -r kill -15  # 기존에 실행 중인 Java 프로세스 종료
            sleep 10
            nohup java -jar /home/$EC2_USERNAME/{server_name}.jar > app.log 2>&1 &  # 새 버전 애플리케이션 실행
          "
          echo "Step 5: Cleaning up"
          rm -f private_key.pem  # 민감한 정보 삭제

위 코드는 배포하는 단계입니다.

이전의 빌드 단계에서 생성한 jar 파일을 EC2 인스턴스에 업로드합니다.

그 후 이전에 실행하던 서버를 종료하고 새로운 버전의 애플리케이션을 실행하는 과정입니다.


5. 확인하기

배포한 서버가 실제로 동작 중인지 확인하기 위해 EC2 터미널에 원격 접속합니다.

ps aux | grep java

이 코드를 통해 /home/ubuntu/{server_name}.jar 파일이 실행 중인지 확인할 수 있습니다.

head /home/ubuntu/app.log

만약 실행 중이지 않다면 위 코드를 통해 실행 로그를 확인할 수 있습니다.


6. 접속하기

실행 중인 것을 확인하셨다면 http://<EC2_PUBLIC_IP>:8080으로 접속하시면 됩니다.