[Spring Boot] AWS 배포 (2)
1. AWS 배포
1) Git 배포
EC2 인스턴스에 깃허브에서 코드를 받아올 수 있도록 깃을 설치한다. 이 후, 프로젝트를 저장할 디렉토리를 생성하고 해당 디렉토리에 git clone을 진행한다. 모든 프로젝트가 복사가 되고 나서 테스트 검증을 통해 문제가 있는지 확인한다.
// 깃 설치
sudo yum install git
// 깃 확인
git --version
// 프로젝트 디렉토리 생성
mkdir ~/app && mkdir ~/app/step1
cd ~/app/step1
// 깃 클론
git clone [깃 프로젝트 주소]
// 파일 확인
cd [프로젝트명]
ll
// 테스트 검증
./gradlew test
테스트가 실패하여 코드를 수정하고 다시 깃허브에 푸시를 했을 경우, 프로젝트 폴더 내에서 풀을 한다. 만약 gradlew 실행 권한이 없을 경우, 권한을 추가 후 테스트를 진행한다.
chmod +x ./gradlew
2) 배포 스크립트
서버에 배포할 때마다 명령어를 실행하는 불편함을 해결하기 위해 쉘 스크립트(.sh)를 작성하여 진행하도록 설정한다. (쉘 스크립트와 vim은 서로 다른 역할을 한다. vim은 GUI가 아닌 환경에서 사용할 수 있는 편집 도구다.) 프로젝트 디렉토리 내에 deploy.sh 파일을 생성하고, deploy.sh 파일에 실행 권한을 부여한다. 이 후 ./deploy.sh 명령어만으로도 로그가 출력되며 애플리케이션이 실행이 된다.
어노테이션 및 코드 | 설명 |
REPOSITORY=[프로젝트 위치] | 프로젝트 디렉토리 주소를 변수로 저장한다. |
cd $REPOSITORY/[프로젝트명]/ | git clone을 받은 디렉토리로 이동한다. |
git pull | 마스터 브렌치의 최신 내용을 받는다. |
./gradlew build | 프로젝트 내부의 gradlew로 build를 수행한다. |
cp ./build/libs/*.jar $REPOSITORY/ | build 결과물인 jar 파일으르 복사하여 jar 파일을 모아둔 위치로 복사한다. |
CURRENT_PID=$(pgrep -f [프로젝트명]) | 기존에 수행 중인 애플리케이션을 종료한다. |
if - else -fi | 구동중인 프로세스의 유무에 따라 명령을 수행한다. |
JAR_NAME=$ls $REPOSITORY/|grep [프로젝트명]| tail -n 1) | 새로 실행할 jar 파일명을 찾는다. 여러 jar 파일이 생성이 되기에 가장 최신의 jar 파일을 찾는다. |
nohup java -jar $REPOSITORY/$JAR_NAME & | 찾은 jar 파일명으로 jar 파일을 터미널이 종료가 되어도 애플리케이션은 계속 구동될 수 있도록 nohup 명령어로 실행한다. |
※ 만약 안될 경우, 프로젝트 디렉토리 내에 build/libs 디렉토리를 생성한다.
※ 스프링 부트는 외장 톰캣의 설치가 필요없으며 jar 파일만 있다면 서버를 실행할 수 있다.
#!/bin/bash
REPOSITORY=/home/ec2-user/app/step1
cd $REPOSITORY/[프로젝트명]/
echo "> Git Pull"
git pull
echo "> 프로젝트 Build 시작"
./gradlew build
echo "> Build 파일 복사"
cp ./build/libs/*.jar $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f [프로젝트명])
echo "$CURRENT_PID"
if [ -z $CURRENT_PID ]; then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -2 $CURRENT_PID"
kill -9 $CURRENT_PID
sleep 5
fi
echo "> 새 어플리케이션 배포"
JAR_NAME=$(ls $REPOSITORY/ |grep '[프로젝트명]' | tail -n 1)
echo "> JAR Name: $JAR_NAME"
nohup java -jar $REPOSITORY/$JAR_NAME &
chmod +x ./deploy.sh
3) application-oauth.properties
쉘 스크립트로 배포 완료 후, 출력되는 모든 내용을 담은 nohup.out 파일을 열람하면 ClientRegistrationRepository를 찾을 수 없다는 에러를 확인할 수 있다. 이는 application-oauth.properties 파일이 없기 때문에 생기는 문제이다. application-oauth.properties 파일은 보안상 중요한 파일이기에 프로젝트 외부(/app)에 생성하고, 쉘 스크립트에 application-oauth.properties 파일 위치를 등록한다.
어노테이션 및 코드 | 설명 |
-Dspring.config.location | 스프링 설정 파일 위치를 지정한다. classpath가 붙을 경우 jar 내에 resources 디렉토리 기준으로 경로가 생성된다. |
nohup java -jar \
-Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties \
$REPOSITORY/$JAR_NAME 2>&1 &
2. 프로젝트 RDS 설정
1) 프로젝트 설정
프로젝트에서는 h2 데이터베이스를 사용하였기 때문에, MariaDB를 사용하고 있는 RDS에 대한 설정이 필요하다. h2에서 자동 생성해주던 테이블을 MariaDB에서는 직접 쿼리를 이용해 생성해야한다. 그리고 자바 프로젝트가 RDS에 접근하기 위해서는 데이터베이스 드라이버가 필요하기에 MariaDB에서 사용 가능한 드라이버를 프로젝트에 추가해주어야 한다. 마지막으로 EC2 인스턴스에서는 데이터베이스 접속 정보를 관리하도록 설정해야한다.
2) RDS 테이블 생성
JPA가 사용될 엔티티 테이블과 스프링 세션이 사용될 테이블 2가지 종류를 생성해야한다. 테스트 코드 수행 시 찍히는 쿼리 로그와 스프링 세션 테이블은 schema-mysql.sql 파일의 내용을 RDS에 반영한다.
※ Command + Shift + o 단축키로 schema-mysql.sql 파일을 찾는다.
3) build.gradle
MariaDB 드라이버를 build.gradle에 등록한다.
compile('org.mariadb.jdbc:mariadb-java-client')
4) application-real.properties
'src/main/resources/' 하위에 application-real.properties 파일을 추가하여 서버에서 구동될 환경을 구성한다. 이 파일을 생성하면, profile=real인 환경이 구성된다. 실제 운영될 환경이기에 보안/로그상 이슈가 될 만한 설정들을 모두 제거하며 RDS 환경 profile 설정이 추가된다. 파일 구성이 완료가 되면 깃허브에 푸시하도록 한다.
spring.profiles.include=oauth,real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.session.store-type=jdbc
3. EC2 설정
1) application-real-db.properties
OAuth와 동일하게 RDS 접속 정보도 보호해야할 정보이기에 프로젝트 외부 디렉토리(/app)에 application-real-db.properties 파일을 생성한다.
어노테이션 및 코드 | 설명 |
spring.jpa.hibernate.ddl-auto=none | JPA로 테이블이 자동 생성되는 옵션을 비활성화한다. RDS에는 실제 운영으로 사용될 테이블이기에 절대 스프링 부트에서 새로 만들지 않도록 해야한다. 만약 활성화 상태라면, 테이블이 모두 새로 생성이 될 수 있다. |
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mariadb://[RDS 주소]:3306/[데이터베이스명]
spring.datasource.username=[DB 계정]
spring.datasource.password=[DB 계정 비밀번호]
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
2) 배포 스크립트
deploy.sh 쉘 스크립트에 real profile을 사용할 수 있도록 수정해준다.
어노테이션 및 코드 | 설명 |
-Dspring.profiles.active=real | application-real.properties를 활성화한다. |
nohup java -jar \
-Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/application-real-db.properties,classpath:/application-real.properties \
-Dspring.profiles.active=real \
$REPOSITORY/$JAR_NAME 2>&1 &
3) 구현 화면
모든 설정이 끝나면 쉘 스크립트를 실행하고 curl localhost:8080 명령어와 EC2 도메인으로 접속하여 확인해본다.
4. 소셜 로그인 설정
1) 구글 승인된 리디렉션 URL 등록
소셜 로그인 기능을 사용하기 위해서는, EC2에 자동으로 할당된 도메인을 구글 서비스(승인된 리디렉션 URI)에 등록해야한다.
http://ec2-13-124-85-99.ap-northeast-2.compute.amazonaws.com/login/oauth2/code/google
2) 네이버 승인된 리디렉션 URI 등록
소셜 로그인 기능을 사용하기 위해서는, EC2에 자동으로 할당된 도메인을 네이버 서비스(승인된 리디렉션 URI)에 등록해야한다.
항목 | 설명 |
서비스 URL | 로그인을 시도하는 서비스가 네이버에 등록된 서비스인지 판단하는 항목이다. 8080 포트를 제외하고 실제 도메인 주소만 입력한다. 네이버에서 아직 지원되지 않아 하나만 등록이 가능하다. 개발 단계에서는 등록하지 않는 게 좋고, localhost도 테스트를 원할 경우, 네이버 서비스를 하나 더 생성하여 키를 발급받아 진행하면 된다. |
// 서비스 URL
http://ec2-13-124-85-99.ap-northeast-2.compute.amazonaws.com:8080/
// Callback URL
http://ec2-13-124-85-99.ap-northeast-2.compute.amazonaws.com:8080/login/oauth2/code/naver
3) 구현 화면
[참고] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스