| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
- SSL
- HTTP 상태 코드
- 서버
- 마이그레이션
- springboot
- REST
- restful
- EC2 인스턴스 생성
- 프리티어
- DDos
- RDS
- API
- 백업
- EC2
- RDS생성
- CRUD
- postgresql
- 인증
- log
- nginx
- REST API 설계
- aop
- 자동 배포
- CD
- AWS
- ec2 rds 연결
- Prometheus
- spring
- Grafana
- 복구
- Today
- Total
SU_DING_GI
[AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 3. CI/CD 코드 및 여러 설정 파일 수정하기 본문
2025.02.06 - [INFRA] - [AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 2. EC2 인스턴스 생성하기
[AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 2. EC2 인스턴스 생성하기
2025.02.04 - [INFRA] - [AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 1. RDS 생성 및 백업 [AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 1. RDS 생성 및 백업기존에 운영하던 알고리즘
sua-su-ding-gi.tistory.com
이전 글에서 EC2와 RDS 연결까지 완료했었다. 원래 우리는 깃 action을 통해 CI/CD를 구현해놨지만 내가 그 설정을 담당하지 않았어서.. 처음 부터 다시 공부하면서 EC2 서버에 배포할 수 있도록 설정해 보겠다!
1. CI/CD란?
CI(Continuous Integration)/CD(Continuous Deployment)는 소프트웨어 개발 및 배포를 자동화하는 과정이다.
CI/CD를 적용하면 코드 변경이 자동으로 테스트 되고, 빌드되며, 배포까지 자동으로 이루어질 수 있기 때문에 이를 통해 개발 속도를 높이고, 오류를 줄이며, 운영 효율성을 개선할 수 있다.
1-1. CI(Continuous Integration, 지속적 통합)
CI는 코드 변경이 생길 때마다 자동으로 테스트하고 빌드하는 과정이다.
✅ CI의 핵심 목표
- 코드 변경 사항을 빠르게 검증하여 오류를 미리 발견
- 여러 개발자가 동시에 작업하더라도 코드 충돌을 최소화
- 자동화된 테스트로 안정적인 코드 유지
✅ CI 동작 방식
- 코드 변경 사항을 Git에 푸시
- Github Actions, Jenkis, GitLab CI/CD같은 CI 서버가 자동으로 실행
- 코드가 자동으로 빌드되고, 테스트 실행
- 테스트를 통과하면 배포를 준비, 실패하면 즉시 개발자에게 알림
1-2. CD(Continuous Deployment, 지속적 배포)
CD는 CI이후, 테스트를 통과한 코드를 자동으로 서버에 배포하는 과정이다
CD는 Continuous Deployment라는 지속적 배포외에도 추가로 Continuous Delivery라는 지속적 전달 방식도 있다.
- Continuous Delivery(지속적 전달)
- 배포 준비까지 자동화되지만, 배포는 사람이 승인 후 진행
- 일반적으로 "배포 버튼"을 눌러야 실제 서버에 반영됨
- 대기업에서는 주로 이 방식을 사용하여 실수를 방지
- Continuous Deployment(지속적 배포)
- 완전히 자동으로 배포까지 진행
- 사람이 개입할 필요 없음
- 스타트업이나 DevOps 환경에서 많이 사용됨
✅ CD의 핵심 목표
- 코드가 안전하게 배포될 준비가 되었는지 확인
- 배포 프로세스를 자동화하여 운영 부담 감소
- 코드 변경이 빠르게 실제 서비스에 반영
✅ CD에서 수행하는 작업 (aloc 웹서버 기준)
- CI 단계를 통과한 코드르 자동으로 Docker 이미지로 빌드
- Docker 이미지를 업로드
- EC2 서버에서 최신 Docker 이미지를 받아 실행
2. CI/CD 스크립트 및 EC2 서버 초기 설정하기
2-1. CI/CD 스크립트 수정
우선, 우리 CI 관련 스크립트는 프로젝트 폴더에 .github/workflows/gradle.yml에 작성되어있다.
기존에는 lightsail로 사용하고 있어서 PostgreSQL을 로컬로 설치하고 있었는데, 이제는 RDS를 사용해야 하므로 해당 내용을 수정해보겠다.
✅ application.yml 수정
application.yml의 db관련 설정(url, username, password) 정보를 반영한다.
그외에는 gradle.yml을 그대로 사용해도 되기때문에 특별한 수정은 안했다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Make gradlew executable
run: chmod +x gradlew
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Create application.yml
run: |
mkdir -p ./src/main/resources
cd ./src/main/resources
echo "${{ secrets.APPLICATION }}" base64 -d > application.yml
echo "${{ secrets.JWT_APPLICATION }}" base64 -d > application-jwt.yml
echo "${{ secrets.TEST_APPLICATION }}" base64 -d > application-test.yml
- name: Install PostgreSQL client
run: sudo apt-get install -y postgresql-client
- name: Build with Gradle Wrapper
run: ./gradlew build --parallel --daemon
✅ CD 스크립트를 수정
우리 CD 관련 스크립트는 프로젝트 폴더에 .github/workflows/deploy.yml에 작성되어있는데,
기존 코드에 수정해야될 점은
- CI/CD 스크립트로 수정 및 작업 분리
- lightsail 에서 EC2로변경
- EC2에서는 필요없는 네트워크 설정을 제거
이다. 따라서 해당 수정사항을 반영해서
name: CI/CD
on:
push:
branches: [ "develop" ] # develop 브랜치에 푸시되면 실행
jobs:
build:
name: CI - Build & Test
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Make gradlew executable
run: chmod +x gradlew
- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Create application.yml
run: |
mkdir -p ./src/main/resources
cd ./src/main/resources
echo "${{ secrets.APPLICATION }}" base64 -d > application.yml
echo "${{ secrets.JWT_APPLICATION }}" base64 -d > application-jwt.yml
echo "${{ secrets.TEST_APPLICATION }}" base64 -d > application-test.yml
- name: Install PostgreSQL client
run: sudo apt-get install -y postgresql-client
- name: Build with Gradle Wrapper
run: ./gradlew build --parallel --daemon
- name: Save JAR Artifact
uses: actions/upload-artifact@v4
with:
name: built-jar
path: build/libs/*.jar
deploy:
name: CD - Deploy to EC2
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4
- name: Download JAR Artifact
uses: actions/download-artifact@v4
with:
name: built-jar
path: build/libs/
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/aloc-spring:latest
# 🔥 SSH 키 설정 (base64 디코딩 없이 원본 그대로 저장)
- name: Setup SSH Key
run: |
echo "${{ secrets.EC2_SSH_KEY }}" > key.pem # 🔴 디코딩 없이 저장
chmod 600 key.pem
# ✅ SSH 연결 테스트
- name: Test SSH Connection
run: ssh -i key.pem -o StrictHostKeyChecking=no ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} "echo '✅ SSH 연결 성공!'"
# ✅ SSH 실행 시 key_path 사용
- name: Deploy to EC2
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key_path: key.pem # 🔥 key_path로 직접 지정
script: |
echo "🔄 Starting Deployment on EC2..."
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
echo "🛑 Stopping and removing old container..."
if [ "$(docker ps -q -f name=aloc-spring)" ]; then
docker stop aloc-spring
docker rm aloc-spring
fi
echo "📦 Pulling the latest image..."
docker pull ${{ secrets.DOCKER_USERNAME }}/aloc-spring:latest | exit 1
echo "🚀 Running new container..."
docker run -d --name aloc-spring \
-e TZ=Asia/Seoul \
-p 8080:8080 \
-v /home/ubuntu/upload/user:/app/upload \
${{ secrets.DOCKER_USERNAME }}/aloc-spring:latest
echo "✅ Deployment completed!"
- name: Send deployment status to Discord
if: success()
uses: tsickert/discord-webhook@v5.3.0
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
content: |
[aloc-spring]
🚀 배포가 성공적으로 완료되었어요!
커밋한 사람 🙋🏻 ${{ github.actor }}
${{ github.event.head_commit.message }}
- name: Send deployment failure to Discord
if: failure()
uses: tsickert/discord-webhook@v5.3.0
with:
webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
content: |
[aloc-spring]
❌ 배포 중 문제가 발생했어요!
확인이 필요합니다. 👀
잘못한 사람 🙋🏻 ${{ github.actor }}
URL: https://github.com/ALOC-UOS/aloc-backend/actions/runs/${{ github.run_id }}
${{ github.event.head_commit.message }}
이렇게 수정해주고 github setting에서 secrets를 업데이트 해줬다.
2-2. EC2 초기 설정
그후, EC2의 보안 그룹에 가서 22, 80, 443, 8080 포트를 개방해주고
EC2에 접속해 docker 와 docker-compose를 설치해준다!
그후 develop 브랜치에 push 해주면

짜잔 완성이다~
이제는 DNS에 EC2 퍼블릭 ip 등록하고 Nginx 사용해서 ssl 설정까지 해주면 진짜 완성~
사실 ssl 인증서 등록하는 것도 작성하려 했지만.. 너무 지친 관계로 작성하지 못했다
생각보다 되게 오래걸렸지만 다음에 또 이런 설정을 하게되면 순차적으로 잘 할 수 있을 것 같다!
'INFRA' 카테고리의 다른 글
| 🤯 뭐? 우리 서버가 공격 받고 있다고? (1) | 2025.04.29 |
|---|---|
| [AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 2. EC2 인스턴스 생성하기 (0) | 2025.02.06 |
| [AWS] 기존 서버에서 새로운 서버로 마이그레이션 하기 - 1. RDS 생성 및 백업 (0) | 2025.02.04 |