Group Study (2021-2022)/Spring Boot

[Spring Boot] 6주차 스터디 - EC2 서버에 프로젝트 배포하기

smjan27 2021. 11. 25. 02:46

[08장] EC2 서버에 프로젝트를 배포해 보자

 

1. EC2에 프로젝트 Clone 받기

sudo yum install git                //EC2에 git 설치
git --version                       //git 버전 확인
mkdir ~/app && mkdir ~/app/step1    //프로젝트를 저장할 디렉토리 생성
cd ~/app/step1                      //생성된 디렉토리로 이동

github에서 프로젝트 링크 복사하기

git clone 복사한 주소     //프로젝트 Clone
git clone -b 브랜치 이름 --single-branch 복사한 주소  //특정 브랜치만 Clone하고 싶다면

cd 프로젝트명             //프로젝트로 이동
ll                       //파일들이 잘 복사되었는지 확인

chmod +x ./gradlew       //gradle 실행 권한 부여

./gradlew test           //코드들이 잘 수행되는지 테스트로 검증

테스트 통과

 

2. 배포 스크립트 만들기

배포: 작성한 코드를 실제 서버에 반영하는 것으로, 다음의 과정을 모두 포괄하는 의미라고 볼 수 있다.

  1. git clone 또는 git pull을 통해 새 버전의 프로젝트를 받음
  2. Gradle이나 Maven을 통해 프로젝트 테스트 및 빌드
  3. EC2 서버에서 해당 프로젝트 실행 및 재실행

앞선 8-1 과정을 배포할 때마다 하나하나 명령어를 실행하는 불편함을 해소하기 위해, 앞의 과정을 자동으로 실행시켜주는 쉘 스크립트(.sh)를 작성해준다.

vim ~/app/step1/deploy.sh     // ~/app/step1/ 에 deploy.sh 스크립트 파일 생성
// deploy.sh

#!/bin/bash

//프로젝트 디렉토리 주소, 프로젝트 이름를 변수로 저장
REPOSITORY=/home/ec2-user/app/step1
PROJECT_NAME=freelec-springboot2-webservice

//프로젝트를 복사했던 디렉토리로 이동
cd $REPOSIROTY/$PROJECT_NAME/

echo "> Git Pull"
git pull  //최신 내용 받기

echo "> 프로젝트 Build 시작"
./gradlew build  // 프로젝트 내부의 gradlew로 build를 수행

echo "> step1 디렉토리 이동"
cd $REPOSITORY

echo "> Build 파일 복사"
//빌드 결과물인 jar 파일을 복사
cp $REPOSITORY/$PROJECT_NAME/build/libs/*.jar $REPOSITORY/

echo "> 현재 구동중인 애플리케이션 pid 확인"
//기존에 수행 중이던 스프링부트 애플리케이션을 종료
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)

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 파일명(최신 버전)을 변수에 저장
JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)
echo "> JAR Name: $JAR_NAME"

//해당 jar 파일을 nohup으로 실행 (외장 톰캣 필요 없음, 터미널 종료해도 애플리케이션 구동됨)
nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 &
chmod +x ./deploy.sh   //생성한 스크립트에 실행 권한 추가
./deploy.sh            //스크립트 실행

스크립트 실행 결과

vim nohup.out   //실행되는 애플리케이션에서 출력되는 내용을 담고 있는 로그 파일

ClientRegistrationRepository가 없어 애플리케이션 실행 실패

ClientRegistrationRepository를 생성하려면, clientIdclientSecret가 필요한데, 해당 파일은 .gitignore의 제외 대상에 속해있어 깃허브에 올라가지 않았다. 애플리케이션을 실행하기 위해 공개된 저장소에 해당 파일을 올릴 수는 없으므로 서버에서 직접 이 설정들을 가지고 있게 해준다.

 

3. 외부 Security 파일 등록하기

vim /home/ec2-user/app/application-oauth.properties   //properties 파일 생성

파일 내용은 로컬에 있는 application-oauth.properties 와 동일하다. 그리고 해당 파일을 쓰도록 deploy.sh 파일을 수정한다.

// deploy.sh
...
//스프링 설정 위치 지정
nohup java -jar \
	-Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties \
    $REPOSITORY/$JAR_NAME 2>&1 &
  • application.properties(기본 옵션), application-oauth.properties(OAuth 설정) 파일의 위치 지정
  • classpath가 붙으면 jar 안에 있는 resources 디렉토리를 기준으로 경로가 생성됨
cd ~/app/step1
./deploy.sh   //스크립트 실행
vim nohup     //로그 확인

애플리케이션이 정상적으로 실행되었다.

 

4. 스프링 부트 프로젝트로 RDS 접근하기

RDS에서 사용하는 MariaDB에서 스프링 부트 프로젝트를 실행하기 위해 필요한 작업은 다음과 같다.

  1. 테이블 생성: H2에서는 테이블을 자동 생성해 주었지만, MariaDB에선 직접 쿼리를 이용해 생성한다.
  2. 프로젝트 설정: MariaDB에서 사용 가능한 데이터베이스 드라이버를 프로젝트에 추가한다.
  3. EC2(리눅스 서버) 설정: EC2 서버 내부에서 접속 정보를 관리하도록 설정한다.

 

✔ RDS 테이블 생성

JPA가 사용될 엔티티 테이블, 스프링 세션이 사용될 테이블 2가지 종류를 생성한다.

① JPA가 사용될 엔티티 테이블은 테스트 코드 수행 시 로그로 생성되는 쿼리를 사용한다.

create table posts (id bigint not null auto_increment, created_date datetime, modified_date datetime, author varchar(255), content TEXT not null, title varchar(500) not null, primary key (id)) engine=InnoDB
create table user (id bigint not null auto_increment, created_date datetime, modified_date datetime, email varchar(255) not null, name varchar(255) not null, picture varchar(255), role varchar(255) not null, primary key (id)) engine=InnoDB

# 인텔리제이에서 오류가 발생하여 MySQL WorkBench를 사용하는 경우, SQL 문법으로 변경하여 반영한다.
create table posts (
	id bigint not null auto_increment, 
    created_date datetime, 
    modified_date datetime, 
    author varchar(255), 
    content TEXT not null, 
    title varchar(500) not null, 
    primary key (id)
) engine=InnoDB

create table user (
	id bigint not null auto_increment, 
    created_date datetime, 
    modified_date datetime,
    email varchar(255) not null, 
    name varchar(255) not null,
    picture varchar(255), 
    role varchar(255) not null, 
    primary key (id)
) engine=InnoDB

② 스프링 세션 테이블은 schema-mysql.sql 파일을 확인하여 RDS에 반영한다. (Ctrl+Shift+N으로 탐색, 내용 생략)

 

✔ 프로젝트 설정

인텔리제이 build.gradle 파일에 MariaDB 드라이버를 등록한다.

compile("org.mariadb.jdbc:mariadb-java-client")

src/main/resources/에 application-real.properties 파일을 생성하여 서버에서 구동될 환경(스프링의 profile)을 하나 구성한다. profile=real인 RDS 환경 profile 설정이 추가된다.

// application-real.properties

spring.profiles.include=oauth,real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.session.store-type=jdbc

모든 설정이 완료되면 깃허브로 푸시한다.

 

✔ EC2 설정

EC2 서버에 RDS 접속 정보를 설정할 파일을 생성하고 다음 내용을 추가한다.

vim ~app/application-real-db.properties   //app 디렉토리에 application-real-db.properties 파일 생성
// application-real-db.properties

spring.jpa.hibernate.ddl-auto=none     //JPA로 테이블 자동 생성하지 않도록 설정
spring.datasource.url=jdbc:mariadb://rds주소:3306/db이름
spring.datasource.username=db계정
spring.datasource.password=db계정 비밀번호
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver

deploy.sh가 real profile을 사용하도록 마지막 코드를 다시 수정한다.

// deploy.sh
...
//스프링 설정 위치 지정
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 \      //application-real.properties 활성화
	$REPOSITORY/$JAR_NAME 2>&1 &

이제 deploy.sh를 실행하고 nohup.out를 열어 다음과 같은 로그가 보인다면 성공적으로 수행된 것이다. 또한 curl 명령어를 입력했을 때 html 코드가 정상적으로 보인다면 성공이다.

cd ~/app/step1
./deploy.sh   //스크립트 실행
vim nohup     //로그 확인
curl localhost:8080

 

5. EC2에서 소셜 로그인하기

EC2에 배포된 서비스를 브라우저에서 확인하기 전, EC2 보안 그룹에 8080 포트가 있는지 확인한다. (스프링 부트 프로젝트는 8080 포트로 배포되었기 때문)

EC2 인스턴스를 선택하면 나오는 퍼블릭 DNS 주소가 EC2에 자동으로 할당된 도메인이다. 해당 도메인 주소에 :8080 포트를 붙여 브라우저에서 접속한다.

마지막으로 구글, 네이버 로그인을 지원하기 위해 해당 도메인 주소를 반영해준다.

  1. 구글
    1. API 및 서비스 - OAuth 동의 화면 - "승인된 도메인"에 http://를 제외한 퍼블릭 DNS 주소 등록
    2. API 및 서비스 - 사용자 인증 정보 - 서비스 이름 클릭 - "승인된 리디렉션 URI"에 퍼블릭 DNS 주소:8080/login/oauth2/code/google 주소 추가
  2. 네이버
    1. 서비스 이름 클릭 - API 설정 - PC 웹 - 서비스 URL을 퍼블릭 DNS 주소로 수정 (로그인을 시도하는 서비스가 네이버에 등록된 서비스인지 판단)
    2. 서비스 URL 하단의 Callback URL에 퍼블릭 DNS 주소:8080/login/oauth2/code/naver 등록

지금까지 구축한 Spring Boot 프로젝트를 EC2 서버에 배포하는 것을 끝으로 스터디를 마무리하였습니다. 지금까지 스터디에 참여하신 모든 분들, 그리고 스터디를 진행해주신 리드님 수고 많으셨습니다!👏👏