
์ด ๊ธ์ ์ ์ ๋ฌด์งํจ์ผ๋ก ์ธํด ๋ฐ์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ณผ์ ์ ๋ํด ๋ค๋ฃจ์ง๋ง, github actions workflow์์์ env variable ์ค์ ๋ฐ ์ ์ฉ์ ๋ํ ๋ด์ฉ์ ์ฃผ๋ก ๋ค๋ฃน๋๋ค.
๋ถ๋ช
ํ ์ฒ์ CI/CD pipeline์ Github actions๋ก ๊ตฌ์ถํ ํ ์ ๋๋ก ๋์ํ๋ ๊ฒ์ ํ์ธํ๋ค. ๊ทธ๋ฐ๋ฐ ์ธ์ ๊ฐ๋ถํฐ dev branch์ mergeํ ๋ ๊ฐํ์ ์ผ๋ก failure ๋ฉ์ธ์ง๊ฐ ๋จ๋ ๊ฒ์ ๋ณด์๋ค. ๋ชจ์ข
์ ์ด์ ๋ก ํ๋ก ํธ ๊ฐ๋ฐ์ด ์ด๋ฃจ์ด์ง๊ณ ์์ง ์์ ์ํฉ์ด์๊ธฐ ๋๋ฌธ์ ๋น์ฅ ํ์ํ์ง ์๋ค๊ณ ํ๋จํด ๋ฐฉ์นํ๋๋ฐ, 3๋ฒ์ 1๋ฒ์ ๋จ๋ success ๋ฉ์ธ์ง๋ง์ ์ฌ๋ผ์ ธ ํด๊ฒฐํด์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ๋ญ๊ฐ ์ค์ ํ๋ ๊ณผ์ ์์ ์๋ชป๋ ๊ฒ ๊ฐ๋ค.
์ฐธ๊ณ ๋ก ์ด์ ์ ๋จ๋ failure๋ ๋ค๋ฅธ ๋ฐฑ์๋ ๊ฐ๋ฐ์์ ํ์
ํ๋ฉด์ ๋ฐ์ํ build ๋ฌธ์ ์๊ธฐ ๋๋ฌธ์ ์ค๋ง CI/CD ํ์ดํ๋ผ์ธ์ด ์๋ชป๋์ด์์ ๊ฑฐ๋ผ๋ ์๊ฐ์ ๋ชปํ๋ค.
์ด๋์๋ถํฐ ์๋ชป๋ ๊ฑด์ง๋ฅผ ์๊ธฐ ์ํด Github actions workflow๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉฐ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ์ฝ์๋ค. ๋ด๊ฐ ํ์ ํ ์์ธ์ ๋ค์์ 2๊ฐ์ง์๋ค.
1. RDS datasource connection url์ด ์ค์ ๋์ง ์์ ๊ฒ
2. Github secret variable ๊ฐ์ด ์ ๋๋ก ์ ์ฉ๋์ง ์์ ๊ฒ
์ฒซ ๋ฒ์งธ ๋ฌธ์ ๋ ๋ด ์ค์๋ก ์ธํด ๋ฐ์ํ ๊ฒ์ด๋ผ ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์์ผ๋, ๋ ๋ฒ์งธ ๋ฌธ์ ๋ ์ ์ ์ฉ๋์ง ์์ ๊ฒ์ธ์ง ๋ชฐ๋๊ธฐ์ ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์๋ค. ์ฌ๋ฌ ๋ฐฉ๋ฒ์ ์๋ํด๋ณด๊ณ ๋์ ๋ฉ์ฒญํจ์ ๊นจ๋ฌ์๋๋ฐ ๊ฐ์ ์ค์๋ฅผ ํ์ง ์๊ธฐ๋ฅผ ๋ฐ๋ผ๋ฉฐ ํด๊ฒฐ ๊ณผ์ ์ ๊ธฐ๋กํด๋๋ค. ์ฌ์ค ๊ฐ์ ์ค์๋ ๋ค์ ์ํ ๊ฒ ๊ฐ๋ค ์ด๋ฒ์ ๋๋ฌด ์ฝ์ง์ ํด์
์์ ๋งํ๋ฏ ์ด ๋ฌธ์ ๋ RDS datasource๋ฅผ ๋ฐฐํฌ์ฉ application.yml์ ์ค์ ํด๋์ง ์์ ๊ฒ์ด ์์ธ์ด์๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ถ๊ฐํด ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์๋ค.
...
spring:
config:
activate:
on-profile: dev
datasource:
url: jdbc:mysql://{RDS datasource url}:3306/{schema}?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Seoul
username: admin
password: {password}
driver-class-name: com.mysql.cj.jdbc.Driver
...
datasource๋ฅผ ์ค์ ํ๋ ๋ถ๋ถ ์ธ์๋ ์๋ตํ๋ค. application.yml ์์ ํ local ํ๊ฒฝ์์ dev profile ์ ์ฉ ํ ์ ์์ ์ผ๋ก RDS์ ์ฐ๊ฒฐ๋๋ ๊ฒ์ ํ์ธํ๋ค.
๊ฐ๋ฐ์๋ผ๋ฉด ๋๊ตฌ๋ ์๊ฒ ์ง๋ง, AWS IAM ์ฌ์ฉ์์ access key์ secret key๋ ์ธ๋ถ์ ๋
ธ์ถํ๋ฉด ์๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด๋ผ? ์ด๊ฑธ ๋ ํฌ์งํ ๋ฆฌ์ ์ฌ๋ ค๋ฒ๋ฆฐ ์ฌ๋์ด ์๋ค? ๊ทธ๊ฒ ๋๋ค.
๋ก์ปฌ ํ
์คํธ ์ฉ๋๋ก ์ฌ์ฉํ๋ ํ๊ฒฝ ํ์ผ(application.yml)์ ์ค์๋ก ์ปค๋ฐํด๋ฒ๋ ธ๋ค. ์๋ฌด ์๊ฐ ์์ด ์ปค๋ฐ์ ํ๋๋ฐ, ๊ฐ์๊ธฐ ์ปค๋ฐ์ด ์๋๋ค๊ณ ๋ง๊ธธ๋ ๊ธฐ๋ถ์ด ์ ์ข์๋์ง "๋๊ฐ ๋ด ์ปค๋ฐ์ ๋ง์!" ํ๋ฉด์ ๊ฒฝ๊ณ ๋ฉ์ธ์ง๋ฅผ ๋๊ณ ๊ทธ๋ฅ ์ปค๋ฐํด๋ฒ๋ ธ๋ค.. ๋ฌผ๋ก ์ด๋ฌ๋ฉด ์ ๋ ์๋๋ค
๋ณ ์๊ฐ ์์๋๋ฐ ๊ฐ์๊ธฐ AWS์์ ๋ฉ์ผ์ด ์ค๊ณ , ๋ญ๊ฐ ์๋ชป๋์๋ค๋ ๊ฒ์ ์ธ์งํด ์ด๋ฅผ secret ํ๊ฒฝ ๋ณ์๋ก ์ค์ ํด ํด๊ฒฐํ์๋ค. ๊ทธ ๊ณผ์ ์ ๐ ๏ธ CI/CD pipeline ๊ตฌ์ถ, ๊ทผ๋ฐ secret ํ๊ฒฝ ๋ณ์๋ฅผ ๊ณ๋ค์ธ..์์ ํ์ธํ ์ ์๋ค. ๋ฌผ๋ก ์ ๊ธ์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋ฒ์ ์ผ๋ก ์
๋ฐ์ดํธ ๋์ด์๋ค.
secrete variable์ ๋ถ๋ช ํ๊ฒฝ ๋ณ์๋ก ์ค์ ํด์คฌ๋๋ฐ, ์๋ฌ ๋ฉ์ธ์ง๋ก ๋ฏธ๋ฃจ์ด ๋ณด์ ์ ๋๋ก ์ ์ฉ๋์ง ์์ ๊ฒ ๊ฐ๋ค.
...
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'AWS_ACCESS_KEY_ID' in value "${AWS_ACCESS_KEY_ID}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180) ~[spring-core-6.1.5.jar!/:6.1.5]
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126) ~[spring-core-6.1.5.jar!/:6.1.5]
...
ํ๊ฒฝ ๋ณ์๊ฐ ์ ๋๋ก ์ค์ ๋์ง ์์ ๊ฒ ๊ฐ์ EC2 ์๋ฒ์์ ํ๊ฒฝ ๋ณ์๋ฅผ ๋ณ๋๋ก ์ค์ ํ๊ณ , ํ ์คํธํ์ผ๋ ์คํจํ๋ค. EC2 ๋ด๋ถ์์๋ ํ๊ฒฝ ๋ณ์๊ฐ ์ ์ค์ ๋ ๊ฒ์ ํ์ธํ ์ ์์๊ธฐ์ EC2์ ๋ฌธ์ ๊ฐ ์๋๋ผ๋ ๊ฒ์ ์ ์ ์์๋ค. local์์ docker image๋ฅผ ๋ฐ์ ์คํ์์ผฐ์ผ๋ ๊ฐ์ ์๋ฌ ๋ฉ์ธ์ง๊ฐ ๋ ์ ์ฌ์ ํ env variable์ด ์ ๋๋ก ์ ์ฉ๋์ด ์์ง ์๋ค๋ ๊ฒ์ ํ์ธํ๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก env variable์ build ๊ณผ์ ์์ ์ด๋ฏธ ์ค์ ๋์ด ์์ด์ผ ํ๊ณ , ์ด๋ฅผ ํฌํจํด build๊ฐ ์ด๋ฃจ์ด์ ธ์ผ ํ๋ค. ์์งํ ๋๋ฌด ๋น์ฐํ ๋ง์ด๋ผ์ ์ด์ด๊ฐ ์์ ์๋ ์์ง๋ง, ๊ทธ ๋น์ฐํ ๊ฑธ ์๊ณ ์์๋ค.
Github actions workflow์์ ์ฌ์ฉํ๋ ๋น๋ ํ๊ฒฝ์ ํ ๋น ๋ฐ์ vm์ด์๊ธฐ ๋๋ฌธ์ ํ๊ฒฝ ๋ณ์๊ฐ ์๋์ผ๋ก ์ค์ ๋์ง ๋ชปํ๋ค. ๋ฐ๋ผ์ secret.{env variable}์ ์ง์ application.yml์ ์ ์ฉํ๋ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ๋ค.
์๋ ์ฝ๋๋ฅผ Gradle build ๊ณผ์ ์ ์ ๋ฃ์ด ์ง์ yml ํ์ผ์ ์๋ ๋ณ์๋ฅผ secret์ผ๋ก๋ถํฐ ๊ฐ์ ธ์ ์ ์ฉํด์คฌ๋ค.
# yml ํ์ผ์ ์๋ ๋ณ์๋ค์ secrets๋ก๋ถํฐ ๊ฐ์ ธ์์ yml ํ์ผ์ ์ ์ฉ
- name: Set yml file
uses: microsoft/variable-substitution@v1
with:
files: 'src/main/resources/application.yml'
env:
cloud.aws.credentials.access-key: ${{ secrets.AWS_ACCESS_KEY }}
cloud.aws.credentials.secret-key: ${{ secrets.AWS_SECRET_KEY }}
ํด๋น ์ฝ๋๋ฅผ ์ ์ฉํด ๋ค์ ๋น๋ํ๋ ์ ์์ ์ผ๋ก ๋์ํ๋ ๊ฒ์ ํ์ธํ๋ค. ํด๊ฒฐํ๊ณ ๋๋ ๋๋๋๋ก ํ๋ฌดํ๋ฐ ๋ด ๋ฉ์ฒญํจ์ด ์ด๋๊น์ง ๊ฐ ์ ์๋ ์ง ๋๋ ์ข ๊ธฐ๋๊ฐ ๋ ์ ๋์๋ค.
local ํ๊ฒฝ์์ ํ ์คํธํ๊ธฐ ์ํด์๋ intellij์์ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ๊ณ ์ ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ค. ์์ธํ ๋ฐฉ๋ฒ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋๋ค.
์ฒ์ CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ ๋์๋ ๊ทธ๋ ๊ฒ ๋ง์ ์๋ฃ๋ฅผ ์ฐพ์๋ณด์ง ์์๋ ์ฝ๊ฒ ๊ตฌ์ถํ ์ ์์๋ค. ์ฌ์ค Github actions๋ฅผ ์จ๋ณด๋๊ฒ ์ฒ์์ด์ง, ์ด์ ์ ๋ค๋ฅธ ํด์ ํ์ฉํด์ CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํด๋ณธ ๊ฒฝํ์ด ์์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ ์๋ฌด ์๊ฐ ์์ด ์ฝ๋๋ง ์งฐ๋๋ฐ, ์ด๊ฒ ๋ฌธ์ ๊ฐ ๋์๋ค. ๋ค๋ฅธ ์ฌ๋์ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํด ๊ตฌํํ ๋๋ ์ดํด๋ฅผ ํ๊ณ ๊ฐ์ ธ์ ์ฌ์ฉํ๋ ์ต๊ด์ ๋ค์ด์๐ป ๋ฌด์์ ๊ฐ์ ธ์ ์ฐ๋ฉด ๋ GPT์ ๋ค๋ฅผ ๋ฐ๊ฐ ์๋ค. ์ฌ์ค ๊ทธ๋ณด๋ค ๋ชปํ ๊ฐ๋ฅ์ฑ์ด ๋๋ค. ๊ทธ๋๋ ์ด ๊ณผ์ ์ ํตํด์ CI/CD ํ์ดํ๋ผ์ธ๊ณผ ํ๊ฒฝ ๋ณ์, ๋น๋ ๊ณผ์ ์ ๋ํด ๋ ์ ์ดํดํ๊ณ ์ฝ๋๋ฅผ ์งค ์ ์๊ฒ ๋์ด ์ข์๋ค. ์์ผ๋ก๋ ๊ฐ์ ์ค์ ๋ฐ๋ณตํ์ง ๋ง์.