0. 이전
Tripot은 멀티 모듈 프로젝트이다. 처음에 루트 경로의 jar 파일을 실행했다. 하지만 루트 경로에는 Main mehtod를 넘어 소스코드가 존재하지 않으므로 현재 실행 파일이 존재하는 api 모듈을 실행해야 한다. 따라서 start.sh를 다음과 같이 작성하였다.
#!/bin/bash
ROOT_PATH="/home/ubuntu/tripot_cicd"
API_JAR="$ROOT_PATH/api_application.jar"
API_APP_LOG="$ROOT_PATH/api_application.log"
API_ERR_LOG="$ROOT_PATH/api_error.log"
API_START_LOG="$ROOT_PATH/api_start.log"
NOW=$(date +%c)
echo "[$NOW] $API_JAR 복사" >> $API_START_LOG
cp $ROOT_PATH/module-api/build/libs/*.jar $API_JAR
echo "[$NOW] > $API_JAR 실행" >> $API_START_LOG
nohup java -jar -Dspring.profiles.active=prod $API_JAR > $API_APP_LOG 2> $API_ERR_LOG &
SERVICE_PID=$(pgrep -f $API_JAR)
echo "[$NOW] > 서비스 PID: $SERVICE_PID" >> $API_START_LOG
1. 개요
java.lang.RuntimeException: Driver com.mysql.cj.jdbc.Driver claims to not accept jdbcUrl, ${DB_URL}
Tripot을 진행하면서 Git Action을 이용한 CI/CD를 구축하던 중 api 애플리케이션의 로그에서 위의 오류가 발생했다. 해당 게시글은 이를 해결하는 과정을 작성한 글이다.
2. 해결 과정
2-1. DB와의 연결 문제?
https://2vup.com/ubuntu-remove-mysql/
[Ubuntu] Mysql 완전 삭제, 재설치
🪤 Ubuntu에서 Mysql 완전 삭제 mysql 관련 파일들 리스트 확인 위 커맨드로 확인한 mysql 관련 파일 삭제 폴더 및 관련항목 삭제 재설치
2vup.com
우선 해당 게시글을 참고하여 재설치부터 해보았다. 하지만 아무리 해도 오류가 해결되지 않던 중 한 가지 의문이 떠올랐다.
2-2. 에러 메시지의 의미?
이번 프로젝트에서는 git submodule을 사용하였을 때의 복잡함, 멀티 모듈 사용에 따른 여러 개의 application.yml을 가지고 있는 점을 들어 환경 변수를 관리하기로 했다. 이에 따라 .bashrc에 환경 변수를 작성 및 적용하였다.
export AWS_S3_ACCESS_KEY_ID={}
export AWS_S3_SECRET_ACCESS_KEY={}
export DB_URL={}
export DB_USERNAME={}
export DB_PASSWORD={}
export JWT_SECRET_KEY={}
export KAKAO_CLIENT_ID={}
export KAKAO_SECRET_KEY={}
그리고 해당 환경변수가 적용된 것도 확인하였다.
그런데 에러 메시지에는 ${DB_URL}이라고 표기, 해당 변수의 실제 값이 표기되지 않았다. 이에 따라 환경 변수가 스프링부트에 적용되지 않음을 의심하였다. 찾아보던 중 CI/CD 시 ec2의 환경 변수가 적용되지 않음을 확인하고, 실제로 CI/CD를 사용하지 않고 직접 프로그램을 실행하였을 때 정상적으로 실행되는 것을 확인할 수 있었다.
2-3. AWS Parameterstore
이에 대한 해결방법으로 환경 변수 관리의 편리함을 생각하여 Parameterstore을 채택하였다. 이를 적용하는 방법은 다음과 같다.
2-3-1. 환경 변수 등록
AWS 로그인, Parameter Store에 들어간다.
우측에 파라미터 생성을 클릭하여 새 변수를 설정한다.
파라미터 이름은 기본적으로 다음의 양식을 따른다.
- /{prefix}/{name}{profile-separator}{profile}/{환경변수 이름}
- prefix: 파라미터의 접두사
- name: 애플리케이션을 식별할 이름
- profile-separator: name과 profile을 구분할 구분자
- profile: 해당 환경변수가 적용될 profile
- 환경변수 이름
파라미터 이름은 추후 변경할 수 없으므로 주의하도록 하자.
민감 정보라면 유형을 보안 문자열로 설정하여 암호화할 수 있다. 값에 해당 환경변수의 값을 적고 파라미터 생성을 눌러 저장한다.
이렇게 해당 프로젝트의 환경 변수를 저장하였다.
2-3-2. IAM 권한 추가
Parameter Store을 ec2에서 사용하려면 IAM에 해당 권한을 추가해야 한다.
우선 사용자 권한에 아래 2개의 권한을 추가해준다.
- AmazonSSMFullAccess
- AmazonSSMReadOnlyAccess
ec2와 연결되어 있는 역할에도 해당 권한을 추가해준다.
2-3-3. ec2 기본 설정
aws configure을 사용하여 IAM 정보를 등록한다.
2-3-4. 스프링부트 설정
//AWS Parameter Store
implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.2.0")
implementation 'io.awspring.cloud:spring-cloud-aws-starter-parameter-store'
루트 모듈에 위의 의존성을 추가해준다. 해당 프로젝트는 스프링부트 3.3.3을 사용하므로 아래 프로젝트의 Readme를 참고하여 spring-cloud-aws의 버전을 3.2.0으로 설정했다.
https://github.com/awspring/spring-cloud-aws?tab=readme-ov-file
GitHub - awspring/spring-cloud-aws: The New Home for Spring Cloud AWS
The New Home for Spring Cloud AWS. Contribute to awspring/spring-cloud-aws development by creating an account on GitHub.
github.com
application.yml에 Parametestore을 사용하기 위한 설정 정보를 추가해준다.
spring:
config:
import: aws-parameterstore:/config/tripot-prod/
aws:
paramstore:
enabled: true
prefix: /config
name: tripot
profile-separator: '-'
드디어 배포했을 시 스프링부트가 정상적으로 실행되는 것을 확인할 수 있었다.
3. 왜 이런 일이 발생하였는가?
다음 코드는 .bashrc의 상단에 있는 코드이다.
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
interactively하게 돌아간다는 것은 다음의 뜻을 가진다.
this command is to prevent the sourcing of the .bashrc file on a remote shell (rsh) or secure shell (ssh).
즉, SSH에서 해당 스크립트를 실행하는 것을 방지하는 코드이다. CI/CD를 적용하게 되면 원격으로 접속하기 때문에 해당 코드에 걸려 아래에 있는 환경 변수 적용 코드가 적용되지 않는 것이다.
물론 해당 코드 위에 환경변수를 선언하는 방법이 있지만 .bashrc가 실행됨에 있어서 안전하지 않다는 생각이 들었고, Parameter Store을 사용하게 되었다.
4. 여담
2-3-4에서 yml 파일에 Parameter Store 접근 정보를 저장하는데, 처음에는 각 모듈의 yml 파일에 이를 다 기입했었다.
그런데도 처음과 같은 오류가 발생해서(환경변수가 적용되지 않는 오류) 확인해보다
ec2에는 해당 환경변수가 잘 불러와지는 것을 확인, 설정정보에 있다는 것을 확인 후 스프링부트의 코드에 문제가 있다고 판단, 며칠 삽질하여 각 모듈이 아닌 application.yml에 넣어 이를 해결하였다. 이로써 생각해야 할 일이 또 생겼다
왜 다른 모듈의 yml 파일에 넣으면 적용이 되지 않는가? 다 같은 설정 파일이고 모두 읽히는 것도 같지 않은가?
CI/CD를 구축하느라 개발이 좀 늦어져서 이를 연구하는 것은 TODO로 남겨두어야 겠다.
'Proj > Tripot' 카테고리의 다른 글
스프링 시큐리티에서 발생하는 예외 처리하기 (0) | 2024.11.10 |
---|---|
Trouble Shooting: @Value에 값이 불러와지지 않는 문제 (3) | 2024.11.04 |
Spring OAuth2를 사용하여 소셜 로그인 구현하기 (feat.추가 정보 입력) (2) | 2024.11.01 |
프로젝트 DB 보안 간단히나마 관리하기 (1) | 2024.10.31 |
Trouble Shooting: 무한 리다이렉트 현상 (2) | 2024.10.15 |