[πŸ˜ƒ λ°°ν¬μ™„λ£Œ] welcome-game-server λ°°ν¬ν•˜κΈ° (Github Actions, SCP, MySQL)

meyameΒ·2025λ…„ 1μ›” 15일

welcome-game κ°œλ°œμΌμ§€

λͺ©λ‘ 보기
2/2

https://github.com/haeunsong/welcome-game-back

기초적인 배포 κ°•μ˜λ“€μ„ λ“£κ³  λ‚˜λ‹ˆ mysql 을 μ‚¬μš©ν•œ ν”„λ‘œμ νŠΈλ„ 배포할 수 μžˆμ„ 것 κ°™λ‹€λŠ” 생각이 λ“€μ—ˆλ‹€.
GitHub Actions λ₯Ό μ΄μš©ν•˜μ—¬ CI/CD λ₯Ό κ΅¬μ„±ν•˜κ³ , 배포 μžλ™ν™”λ₯Ό μ„€μ •ν•œλ‹€. μ‹œμž‘!

λ‹¨κ³„λ³„λ‘œ μ­‰ νšŒκ³ ν•΄λ³΄λ©° λ§ˆμ£Όν•œ λ¬Έμ œλ“€μ„ μ μ–΄λ³΄μž.

0. 큰 흐름

  1. AWS EC2 λ₯Ό μ΄μš©ν•œ μΈμŠ€ν„΄μŠ€ 생성 (이건 μ•žμ„œ μž‘μ„±ν•œ κΈ€λ“€ μ°Έκ³ )
  2. λ‘œμ»¬μ— μžˆλŠ” μ½”λ“œλ₯Ό Github λ ˆν¬μ§€ν† λ¦¬μ— PUSH (ν”„λ‘œμ νŠΈ 상단에 .github/workflows/deploy.yml νŒŒμΌλ„ μΆ”κ°€ν•˜μ—¬ Github Actions μ‚¬μš©)
  3. ν™˜κ²½λ³€μˆ˜ μ €μž₯ (Github - Settings - Secrets and variables - Actions - New repository secret)
  4. λ°°ν¬λŠ” deploy.yml 의 λ‹¨κ³„λŒ€λ‘œ μžλ™ μ‹€ν–‰
    1. github λ ˆν¬μ§€ν† λ¦¬μ˜ νŒŒμΌλ“€ 뢈러였기
    2. JDK 17 μ„€μΉ˜
    3. application.yml 파일 생성
    4. MySQL μ„€μ •
    5. gradle 을 μ‚¬μš©ν•˜μ—¬ λΉŒλ“œ
    6. λΉŒλ“œλœ νŒŒμΌμ„ SCP λ₯Ό μ΄μš©ν•˜μ—¬ .jar νŒŒμΌμ„ EC2 둜 전솑
    7. SSH 둜 EC2 에 접속
    8. EC2 에 μ ‘μ†ν•΄μ„œ java, mysql λ“± κΈ°λ³Έ ν™˜κ²½μ„€μ • ꡬ성
    9. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹€ν–‰(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
profile
μœ ν•œν•œ κ°€μΉ˜λ₯Ό λ‚˜λˆ„μ–΄ λ¬΄ν•œν•œ κ°€μΉ˜λ₯Ό μƒμ„±ν•΄λ‚΄μž!

0개의 λŒ“κΈ€