이 글은 이동욱 님의 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 책을 읽으며 정리한 글입니다.
1. EC2에 프로젝트 clone
2. 배포 스크립트 만들기
3. RDS 접근하기
ssh aws_apupu_ec2 # EC2 터미널 접속하기
1. EC2에 프로젝트 clone 받기
sudo yum install git
git --version
# 프로젝트를 저장할 디렉토리 생성
mkdir ~/app && mkdir ~/app/step1
cd ~/app/step1
git clone 깃허브 주소
2. 프로젝트 테스트
# 테스트
./gradlew test
테스트를 돌리니 아래와 같이 오류가 발생했다. application-oauth.properties 파일은 보안상의 문제로 깃허브에 올리지 않았었는데, 이 파일 없이 테스트를 돌리니 오류가 발생했던 것이다. 파일을 FileZilla를 통해 전송해 주었다.
PostsRepositoryTest > 게시글저장_불러오기() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98
Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:658
Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:185
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException at DefaultListableBeanFact
3. 배포 스크립트 만들기
- git clone 혹은 git pull을 통해 새 버전의 프로젝트를 받는다.
- Gradle이나 Maven을 통해 프로젝트를 테스트하고 빌드 한다.
- EC2 서버에서 해당 프로젝트를 실행 및 재실행한다.
VIM을 다루는 방법은 이 링크를 참조했다.
vim ~/app/step1/deploy.sh # 파일 생성
#!/bin/bash
REPOSITORY=/home/ec2-user/app/step1 # 프로젝트 디렉토리 주소를 변수로 저장
PROJECT_NAME=Apupu
cd $REPOSITORY/$PROJECT_NAME/ # git clone 받은 주소로 이동
echo "> Git Pull"
git pull
echo "> 프로젝트 Build 시작"
./gradlew build # 프로젝트 내부의 gradlew로 build 수행
echo "> step1 디렉토리로 이동"
cd $REPOSITORY
echo "> Build 파일 복사"
cp $REPOSITORY/$PROJECT_NAME/build/libs/*.jar $REPOSITORY/ # build 결과물인 jar 파일을 복사
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar) # 기존 수행 중이던 애플리케이션을 종료 / -f: 프로세스 이름으로 찾는다
echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"
# 현재 구동 중인 프로세스가 있는지 판단
if [ -z "$CURRENT_PID" ]; then
echo "> 현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID"
kill -15 $CURRENT_PID
sleep 5
fi
echo "> 새 애플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1) # 새로 실행할 jar 파일 찾기 / tail -n: 최신 파일을 변수에 저장
echo "> JAR Name: $JAR_NAME"
nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 & # 찾은 jar 파일을 nohup으로 실행
# nohup: java -jar 명령어는 터미널 접속을 끊으면 종료되지만 nohup은 계속 구동된다
chmod +x ./deploy.sh # 스크립트에 실행 권한 부여하기
ll
./deploy.sh # 스크립트 실행
vim nohup.out # 로그 보기
위에서 application-oauth.properties 파일을 src/main/resources 위치에 넣었었는데, 상위 폴더인 step1에서만이 아닌 step2에서도 사용하기 위해서 그 상위 폴더인 app로 위치하고, 이 파일을 사용하도록 deploy.sh를 수정했다.
nohup java -jar \
-Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties \
$REPOSITORY/$JAR_NAME 2>&1 &
- -Dspring.config.location: 스프링 설정 파일 위치를 지정한다. classpath가 붙으면 jar 안에 있는 resources 디렉토리를 기준으로 경로가 생성된다. application-oauth.properties는 외부에 파일이 있으므로 절대 경로를 사용한다.
4. RDS 접근하기
현재 RDS는 MariaDB를 사용하고 있다. 스프링 부트 프로젝트를 실행하기 위해서 아래 작업이 필요하다.
- 테이블 생성: H2에서는 자동 생성해 주던 테이블을 직접 쿼리를 위해 생성해 주어야 한다.
- 프로젝트 설정: 데이터베이스 드라이버를 프로젝트를 추가해야 한다.
- EC2(리눅스 서버) 설정: 데이터베이스 접속 정보를 외부에 노출하지 않고 EC2 내에서만 관리하도록 해야 한다.
🍓 RDS 테이블 생성
- JPA가 사용할 엔티티 테이블: 테스트 코드 수행 시 로그로 생성되는 쿼리를 사용하면 된다.
- 스프링 세션이 사용될 테이블: schema-mysql.sql 파일에서 확인할 수 있다.
create table posts (
id bigint not null auto_increment,
created_date datetime(6),
modified_date datetime(6),
author varchar(255),
content TEXT not null,
title varchar(500) not null,
primary key (id)
) engine=InnoDB
create table users (
id bigint not null auto_increment,
created_date datetime(6),
modified_date datetime(6),
email varchar(255) not null,
name varchar(255) not null,
picture varchar(255),
role varchar(255) not null,
primary key (id)
) engine=InnoDB
🍓 MariaDB 드라이버 등록
# build.gradle
implementation("org.mariadb.jdbc:mariadb-java-client")
위의 설정 후 서버에서 구동될 환경을 구성하기 위해 src/main/resources/에 application-real.properties 파일을 추가한다. 실제 운영될 환경이기 때문에 보안/로그상 이슈가 될 만한 설정을 모두 제거하며 RDS 환경 profile 설정이 추가된다.
spring.profiles.include=oauth,real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.session.store-type=jdbc
🍓 EC2 설정
RDS 접속 정보는 보호해야 할 정보이니 서버에 직접 설정 파일을 두어야 한다.
vim ~/app/application-real-db.properties
spring.jpa.hibernate.ddl-auto=none # DB 테이블 자동 생성을 막는다
spring.jpa.show_sql=false
spring.datasource.hikari.jdbc-url=jdbc:mariadb://☆RDS 주소☆:☆포트명(기본 3306)☆/☆DB 이름☆
spring.datasource.hikari.username=☆DB 계정☆
spring.datasource.hikari.password=☆DB 비밀번호☆
spring.datasource.hikari.driver-class-name=org.mariadb.jdbc.Driver
설정 파일을 만들고, deploy.sh가 real profile을 쓸 수 있도록 개선한다.
nohup java -jar \
-Dspring.config.location=classpath:/application.properties,classpath:/application-real.properties,/home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/application-real-db.properties \
-Dspring.profiles.active=real \
$JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
deploy.sh를 실행한 뒤 nohup.out 파일을 열어서 성공적으로 수행되는지 확인한다. 8080 포트로 톰캣 서버가 실행되었는지 확인하고, 아래 명령어로 html 코드가 정상적으로 보이면 된다.
curl localhost:8080
🤔 no main manifest attribute in 에러
나는 로그를 확인하니 아래의 문구가 떠 있었다. 검색해 보니 jar파일에서 처음 호출할 Main 메소드를 찾지 못했다는 에러라고 한다. jar 파일이 잘 생성되었는지 확인하고, 잘 복사되는지 확인했는데 문제가 없었다.
no main manifest attribute in
이 문제는 Spring Boot 2.5.0 버전 이상부터 나타날 수 있는 문제다. gradle로 빌드를 할 때 아래와 같이 jar 파일이 두 개가 생성되기 때문이다. Apupu-1.0-SNAPSHOT.jar 파일이 배포가 되어야 하는데 Apupu-1.0-SNAPSHOT-plain.jar가 배포되었던 것이다.
이를 해결하기 위해 build.gradle에 빌드 시 plain.jar 파일이 생성되지 않도록 하는 명령어를 추가했다. 추가한 이후에 EC2에 남아 있던 plain.jar 파일을 jar 파일이 생성되는 곳과 복사된 곳 두 위치에서 삭제해 주자!
jar {
enabled = false
}
6. EC2에서 소셜 로그인하기
- AWS 보안 그룹 변경: 스프링 부트 프로젝트가 8080 포트로 배포되었으니 8080 포트가 보안 그룹에 열려 있는지 확인한다.
- AWS EC2 도메인으로 접속: http://ec2-☆.ap-northeast-2.compute.amazonaws.com:8080/
- 구글에 EC2 주소 등록: https://console.cloud.google.com/
- 네이버에 EC2 주소 등록: https://developers.naver.com/apps/#/myapps
- 서비스 URL: 로그인을 시도하는 서비스가 네이버에 등록된 것인지 확인한다.
- Callback URL: 전체 주소를 등록한다. http://ec2☆.ap-northeast-2.compute.amazonaws.com:8080/login/oauth2/code/naver
'Book > 스프링 부트와 AWS 웹 서비스' 카테고리의 다른 글
[AWS] 배포 자동화 중 발생한 문제 해결 (0) | 2023.03.02 |
---|---|
[배포 자동화] Github Actions & S3 & CodeDeploy (0) | 2023.02.26 |
[AWS] 데이터베이스 환경 구성하기 - RDS (0) | 2023.02.24 |
[AWS] 서버 환경 구성하기 - EC2 (0) | 2023.02.22 |
JUnit 테스트에 Spring Security 적용하기 (0) | 2023.02.22 |
댓글