https://github.com/haeunsong/welcome-game-back
GitHub - haeunsong/welcome-game-back
Contribute to haeunsong/welcome-game-back development by creating an account on GitHub.
github.com
기초적인 배포 강의들을 듣고 나니 mysql 을 사용한 프로젝트도 배포할 수 있을 것 같다는 생각이 들었다.
GitHub Actions 를 이용하여 CI/CD 를 구성하고, 배포 자동화를 설정한다. 시작!
단계별로 쭉 회고해보며 마주한 문제들을 적어보자.
0. 큰 흐름
- AWS EC2 를 이용한 인스턴스 생성 (이건 https://velog.io/@meyame/posts 참고)
- 로컬에 있는 코드를 Github 레포지토리에 PUSH (프로젝트 상단에 .github/workflows/deploy.yml 파일도 추가하여 Github Actions 사용)
- 환경변수 저장 (Github - Settings - Secrets and variables - Actions - New repository secret)
- 배포는 deploy.yml 의 단계대로 자동 실행
- github 레포지토리의 파일들 불러오기
- JDK 17 설치
- application.yml 파일 생성
- MySQL 설정
- gradle 을 사용하여 빌드
- 빌드된 파일을 SCP 를 이용하여 .jar 파일을 EC2 로 전송
- SSH 로 EC2 에 접속
- EC2 에 접속해서 java, mysql 등 기본 환경설정 구성
- 애플리케이션 실행(nohup 으로 백그라운드 실행)
1. 깃허브 레포지토리 설정 문제
원래는 welcome-game 이라는 큰 틀 안에 welcome-game-front 와 welcome-game-server 이런식으로 깃을 관리하려고 했다. 하지만, Github Actions 을 쓰다보니 프론트 따로, 백 따로 레포지토리를 관리하는게 편할 것 같다는 생각이 들었다.
처음에는 기존의 구조를 유지한 채, welcome-game 프로젝트의 최상단에 .github/workflows/deploy.yml 파일을 만들고 working directory 를 추가하여 github actions 경로를 설정해보려했지만, 생각보다 복잡해지는 것 같아서 결국 레포지토리를 분리했다.
2. application.yml 파일 관리
기본적으로 .gitignore 파일에 application.yml 을 등록해두었다. 그리고 기존에는 인텔리제이에서 환경변수로 따로 설정해둔 부분이 있었는데,
1. 어차피 내 컴퓨터에서만 이 프로젝트를 진행하게 될 것 같아서
2. github 에는 해당 파일을 올리지 않을 것이기 때문에
환경변수를 지우고 mysql 과 관련된 부분을 모두 하드코딩 해두었다.
(But, 이건 추후에 변경하는게 좋을 듯)
그리고 deploy.yml 파일에서 사용되는 ${{ secrets.MYSQL_PASSWORD }} 와 같은 부분들은 Github - Settings - Secrets and variables - Actions - New repository secret 에 저장해두었다.
설정한 변수들은 아래와 같다.
EC2_HOST: EC2 퍼블릭 IP
EC2_USERNAME: EC2 사용자 이름(예: ubuntu).
EC2_PRIVATE_KEY: .pem 파일 내용.
MYSQL_USERNAME, MYSQL_PASSWORD: MySQL 접속 정보.
APPLICATION_PROPERTIES: application.yml 내용.

3. 3306 포트 열어주는 인바운드 보안그룹 추가
지금까지 한 배포에서는 MySQL 을 추가하지 않았기 때문에 아래 사진의 보안그룹으로 충분했다.

하지만 MySQL 은 localhost:3306 을 사용하기 때문에 추가적으로 3306 포트도 열어주어야했다.

이렇게 총 5개의 인바운드 보안그룹을 사용한다.
(아웃바운드 보안그룹은 디폴트로 전체 포트/프로토콜/대상 열어주는 1개 존재)
4. pem 의 접근 권한 수정
로컬에서 $ ssh -i pem/welcome-game-server.pem ubuntu@13.124.172.186 명령어로 ec2 에 접근하려했는데 아래와 같은 오류가 발생했다.
WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'pem/welcome-game-server.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "pem/welcome-game-server.pem": bad permissions
이건 pem 파일의 권한 설정이 현재 0644로 너무 느슨해서 생기는 문제였다.
아래 명령어로 pem 파일의 권한을 0600으로 설정하였다.
$ chmod 600 pem/welcome-game-server.pem
5. 빌드 전에 mysql 설정 코드 추가
MySQL 설정
현재 배포 방식은 빌드 후 생성되는 jar 파일을 SCP 로 EC2 로 전송하는 방식을 사용하고 있다. 그렇기에 너무도 당연한 이야기지만, 빌드하기 전에 mysql 설정을 해주어야한다. Github Actions 의 mirromutth/mysql-action@v1.1 라이브러리를 사용했다.
- name: MySQL 설정하기
uses: mirromutth/mysql-action@v1.1
with:
host port: 3306
container port: 3306
mysql database: 'welcome_game_db'
mysql root password: ${{ secrets.MYSQL_PASSWORD }}
나는 현재 사용자 이름이 root 이기 때문에 이렇게 적어주었다.
6. SSH(원격접속)로 EC2 에 접속하기
EC2_HOST, EC2_USERNAME, EC2_PRIVATE_KEY 로 EC2 에 접속하면 기본적으로 java, mysql 을 설정해주어야한다. 처음에는 이걸 하지 않아서 오류가 났다. deploy.yml 파일의 script 부분에 추가한 코드이다.
script: |
sudo apt update
sudo apt install -y openjdk-17-jdk
sudo apt install -y mysql-server
java -version
sudo systemctl start mysql || true
7. MySQL 에 접속하여 auth_socket -> mysql_native_password 플러그인으로 수정
오류
서버를 실행하다가 만난 오류 중에 다음과 같은 오류를 만났다.
[welcome-game-back] [main] o.h.engine.jdbc.spi.SqlExceptionHelper : Access denied for user 'root'@'localhost'
사실 이 오류는 상당히 자주 만나는 오류인데, 때마다 이유는 달랐지만 이번에는 명쾌한 해답이 있었다.
원인
MySQL 이 auth_socket 플러그인을 사용하도록 설정되어있으면, 비밀번호 인증이 아닌 Unix 소켓 기반 인증만 허용된다.
스프링부트 애플리케이션은 일반적으로 비밀번호 기반 인증을 통해 데이터베이스에 연결한다. 하지만, auth_socket 설정은 비밀번호가 아닌 Unix 소켓 인증을 사용하기 때문에 문제가 발생한다.
스프링부트나 원격 클라이언트는 auth_socket 방식을 지원하지 않는다!
해결
auth_socket 플러그인을 mysql_native_password 플러그인으로 수정해주면 된다.
# mysql 접속
$ sudo mysql -u root
# 현재 root 사용자 설정 확인
> SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
# 출력 예시
+------+-----------+-------------+
| user | host | plugin |
+------+-----------+-------------+
| root | localhost | auth_socket |
+------+-----------+-------------+
# 만약 auth_socket 로 되어있다면 mysql_native_password 로 바꾸어야한다.
> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
> FLUSH PRIVILEGES;
# 변경 후 사용자 확인
> SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
# 출력 예시
+------+-----------+-----------------------+
| user | host | plugin |
+------+-----------+-----------------------+
| root | localhost | mysql_native_password |
+------+-----------+-----------------------+
8. EC2의 MySQL 내에서 DB가 자동으로 생성되도록 설정
당연한 말이지만 현재 EC2 의 mysql 에는 내가 생성한 DB 가 없다. 직접 생성해줘도 되지만, application.yml 파일을 수정하여 자동으로 생성되도록 설정하는 방식이 더 편해보여서 택했다.
spring:
datasource:
url: jdbc:mysql://localhost:3306/welcome_game_db?createDatabaseIfNotExist=true
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
createDatabaseIfNotExist=true 이 옵션을 붙이면 DB 가 없을경우 자동으로 생성된다.
9. 오류 찾아내는 방법
deploy.yml 코드에 최종적으로 nohup 을 통해 서버를 실행시킬 때 아래와 같은 명령어를 사용한다.
nohup java -jar project.jar > ./output.log 2>&1 &
이는 project.jar 파일을 실행시키고, 그 표준출력 및 오류를 output.log 파일에 입력하는 명령어다.
output.log 파일을 확인하며 오류를 찾아내어갔다.
10. 결과
인스턴스를 생성하고 탄력적 IP 를 받았는데 IP주소:포트번호 이렇게 해서 접속하면 된다.
나는 swagger 를 사용했기 때문에, swagger 페이지를 띄웠다.

11. 추가 궁금증
Q. Github Actions 에서 JDK 설치(actions/setup-java) VS EC2 서버에서의 Java 설치(appleboy/ssh-action)의 차이는?
전자의 목적은 Github Actions의 빌드 환경에서 자바를 사용하기 위해 설치하는 것이다. 이 때는 EC2 서버가 아니라 GitHub 의 가상머신에 설치된다. Gradle 빌드를 실행하기 위해 필수적이다.
후자의 목적은 Spring Boot 애플리케이션을 실행하기 위해 JDK 를 설치한다. 빌드된 .jar 파일이 java 로 실행되기 때문에 당연히 있어야한다. EC2 서버에 JDK 가 설치된다.
GitHub Actions는 빌드 머신, EC2 서버는 애플리케이션이 실제로 배포되고 실행되는 환경이라고 생각하면 된다.
12. 코드
가장 핵심역할을 하는 application.yml 파일과 deploy.yml 은 아래와 같다.(민감한 정보 제외)
application.yml
spring:
application:
name: welcome-game-back
datasource:
url: jdbc:mysql://localhost:3306/welcome_game_db?createDatabaseIfNotExist=true
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jackson:
date-format: yyyy-MM-dd
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: true
format_sql: true
dialect: org.hibernate.dialect.MySQLDialect
open-in-view: false
deploy.yml
name: EC2 로 배포하기
on:
push:
branches:
- main
jobs:
Deploy:
runs-on: ubuntu-latest
steps:
- name: Github Repository 에 올린 파일들을 불러오기
uses: actions/checkout@v4
- name: 잘 되고 있는지 Test 하기
run: |
ls
pwd
- name: JDK 17버전 설치
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- name: application.yml 파일 만들기
run: |
pwd
mkdir -p src/main/resources
echo "${{ secrets.APPLICATION_PROPERTIES }}" > src/main/resources/application.yml
- name: MySQL 설정하기
uses: mirromutth/mysql-action@v1.1
with:
host port: 3306
container port: 3306
mysql database: 'welcome_game_db'
mysql root password: ${{ secrets.MYSQL_PASSWORD }}
- name: 테스트 및 빌드하기
run: |
./gradlew clean build
- name: 빌드된 파일 이름 변경하기
run: |
mv ./build/libs/*SNAPSHOT.jar ./project.jar
- name: SCP로 EC2에 빌드된 파일 전송하기
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
source: project.jar
target: /home/ubuntu/welcome-game-server/tobe
- name: SSH(원격 접속)로 EC2에 접속하기
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_PRIVATE_KEY }}
script_stop: true
script: |
sudo apt update
sudo apt install -y openjdk-17-jdk
sudo apt install -y mysql-server
java -version
sudo systemctl start mysql || true
rm -rf /home/ubuntu/welcome-game-server/current
mkdir /home/ubuntu/welcome-game-server/current
mv /home/ubuntu/welcome-game-server/tobe/project.jar /home/ubuntu/welcome-game-server/current/project.jar
cd /home/ubuntu/welcome-game-server/current
sudo fuser -k -n tcp 8080 || true
nohup java -jar project.jar > ./output.log 2>&1 &
rm -rf /home/ubuntu/welcome-game-server/tobe
'IT' 카테고리의 다른 글
spring security 403 에러 해결!!! (0) | 2024.06.05 |
---|---|
Chatbot App?? 난 무엇을 유료결제했는가? (2) (2) | 2024.06.03 |
ChatGPT-3.5 vs GPT-4o vs Google PaLM 2 vs Google Gemini (0) | 2024.06.03 |
Chatbot App?? 난 무엇을 유료결제했는가? (1) (0) | 2024.06.03 |
아이패드 9세대 스펙 및 가격 (0) | 2021.09.22 |
댓글