본문 바로가기
개발/스프링

[혼자 구현하는 웹서비스] 8-1. EC2 서버에 프로젝트를 배포해 보자 (MariaDB)

by 카펀 2022. 2. 3.

* 이 글은 '스프링 부트와 AWS로 혼자 구현하는 웹 서비스' (프리렉, 이동욱 저) 를 공부하며 내용을 정리한 글입니다.

* 내용을 따라가며 쓴 글이라 책과 흐름이 겹칠 수 있으나, 최대한 내용을 이해한 후 저의 글로 옮겼습니다.

* 이 글은 7-1. AWS에 데이터베이스 환경을 만들어보자 - AWS RDS (MariaDB) 에서 이어집니다.

 

이전 글에서 밝혔던 대로, 일단은 MariaDB로 진행할 예정이다.

글 제목은 이전 글과 같이 챕터-1 의 형식을 유지하려고 한다. 나중에 PostgreSQL로 이어서 작성하게 된다면 그때 넘버링을 이어 갈 예정이다.

 

앞서 1~5장에서는 스프링 부트를 이용해 웹 서비스를 담당할 코드를 작성했고, 6~7장에서는 웹 서비스를 올릴 서버 환경을 세팅했다. 여기서부터는 이 둘을 결합하여 실제 웹 서비스가 서비스되도록 진행해 보겠다.

 

목차

1. EC2에 프로젝트 Clone 받기

2. 배포 스크립트 만들기

3. 외부 Security 파일 등록하기

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

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

 

1. EC2에 프로젝트 Clone 받기

앞서 설정해 둔 EC2 서버에 접속한다.

우선 개발의 형상관리의 기본이 되는 Git을 설치하자.

 

sudo yum install git

 

성공적으로 Git을 설치하고 나면 아래와 같이 설치여부 및 버전을 확인할 수 있다.

 

 

다음으로 우리의 프로젝트를 담을 디렉토리를 만들자.

app 디렉토리를 만들고, 그 아래에 step1 디렉토리를 만든다.

 

mkdir ~/app && mkdir ~/app/step1

 

 

디렉토리가 생성된 것을 확인할 수 있다.

step1 디렉토리로 이동해 보자.

 

cd ~/app/step1

 

그리고 여기에 우리의 프로젝트를 clone하겠다.

본인의 GitHub 주소에 들어가서 주소를 복사해 오자.

 

 

git clone '복사한 주소'

 

 

성공적으로 clone 하였으면 아래의 명령어를 입력해 보자.

 

cd '프로젝트명'
ll

 

 

IntelliJ에서 보던 우리 프로젝트가 잘 옮겨져 온 모습이다.

 

잘 수행되는지 테스트를 통해 확인해 보자.

 

./gradlew test

 

앞에서 5장의 "기존 테스트에 Security 적용하기" 까지 잘 진행했다면 테스트 역시 성공적으로 진행된다.

 

 

소요 시간은 편차가 크다 (EC2의 성능 문제 같은데 정확하지는 않다). 

 

2. 배포 스크립트 만들기

우리가 배포를 한다고 하면, 여러 가지 의미를 내포하고 있다. 보통은 다음과 같은 의미를 가진다.

  • git clone 또는 git pull을 통해 새 버전의 프로젝트를 내려받는다
  • Gradle / Maven을 통한 프로젝트 테스트 및 빌드를 수행한다
  • EC2 서버에서 프로젝트를 실행한다

이런 과정을 Linux terminal 환경에서 매번 직접 치는 것은 개발자에게 매우 수고로운 일이 아닐 수 없다.

다행히 이를 파일 하나에 적어 두고, 파일을 실행하는 것으로 한 번에 모든 과정이 진행되도록 할 수 있다. 이를 '쉘 스크립트' 라고 한다.

쉘 스크립트는 .sh 확장자를 가지며, Linux 환경에서 사용할 수 있다.

 

아쉽지만 우리의 EC2 환경에서는 VS Code와 같은 텍스트 에디터는 없다.

하지만 terminal 환경만 있다면 언제나 사용할 수 있는 vi (vim)이 있다. 이를 통해 스크립트를 작성해 보자.

 

vim ~/app/step1/deploy.sh

 

#!/bin/bash

REPOSITORY=/home/ec2-user/app/step1
PROJECT_NAME=springboot-web-practise

cd $REPOSITORY/$PROJECT_NAME/

echo "> Git Pull"

git pull

echo "> 프로젝트 Build 시작"

./gradlew build

echo "> step1 디렉토리로 이동"

cd $REPOSITORY

echo "> Build 파일 복사"

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_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)

echo "> JAR Name: $JAR_NAME"

nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 &

 

작성한 스크립트 파일에 실행 권한을 추가해 주자.

 

chmod +x ./deploy.sh

 

 

파일에 실행 권한이 추가되었다.

 

이 스크립트를 실행해 보자.

 

./deploy.sh

 

 

 

실행 결과는 같은 디렉토리의 nohup.out 파일을 열어 보면 확인할 수 있다.

맨 밑을 확인해 보면 아래와 같은 결과가 나온다.

 

 

oauth2 관련 문제 때문에 구동에 실패했다는 메세지이다.

 

3. 외부 Security 파일 등록하기

앞서 5장에서, oauth2 관련 값을 담을 application-oauth.properties 파일을 만들고, 이 파일을 .ignore 파일에 추가했었다.

oauth2 인증에 관련된 중요한 정보를 담고 있기 때문인데, 우리의 프로젝트 구동에는 이 파일에 담긴 내용이 필수적이다.

따라서 이 내용을 EC2 내부로 수동으로 옮겨야 한다.

 

먼저 app 디렉토리 아래에 properties 파일을 만들자.

 

vim /home/ec2-user/app/application-oauth.properties

 

그리고 로컬에 있는 application-oauth.properties 파일 내에 있는 내용을 복사해서 붙여넣기 하고 저장하자.

이후 이 파일을 deploy.sh에서 읽을 수 있도록 약간 수정해 준다.

 

~

nohup java -jar \
	-Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties \
    $REPOSITORY/$JAR_NAME 2>&1 &

 

다음 deploy.sh 파일을 다시 실행해 본다.

 

 

Spring Boot가 성공적으로 구동되었음을 확인할 수 있다.

 

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

사실 이 부분 때문에 PostgreSQL에서 MariaDB로 바꿨다.

MariaDB에서 스프링부트 프로젝트를 실행하기 위해서는 몇 가지 작업이 필요하다.

  • 테이블 생성 - H2에서는 자동으로 생성해 줬지만, MariaDB는 직접 생성해 주어야 한다.
  • 프로젝트 설정 - Java 프로젝트가 MariaDB에 접근하려면 DB 드라이버가 필요하다.
  • EC2 설정 - EC2 서버 내부에서 접근 정보를 관리하도록 설정한다.

 

RDS 테이블 생성

MariaDB 내에 테이블을 생성해 보자. JPA가 사용될 엔티티 테이블과 스프링 세션이 사용할 테이블 두 가지를 만든다.

 

아까 실행한 로그를 보면, 중간에 아래와 같은 로그가 있다.

 

Hibernate: 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
Hibernate: 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

 

여기서 create table 부터 복사해서 쿼리를 입력해 주자.

 

 

나는 DBeaver를 사용했다.

 

다음은 스프링 세션 테이블이다.

 

CREATE TABLE SPRING_SESSION (
    PRIMARY_ID CHAR(36) NOT NULL,
    SESSION_ID CHAR(36) NOT NULL,
    CREATION_TIME BIGINT NOT NULL,
    LAST_ACCESS_TIME BIGINT NOT NULL,
    MAX_INACTIVE_INTERVAL INT NOT NULL,
    EXPIRY_TIME BIGINT NOT NULL,
    PRINCIPAL_NAME VARCHAR(100),
    CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);

CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);

CREATE TABLE SPRING_SESSION_ATTRIBUTES (
    SESSION_PRIMARY_ID CHAR(36) NOT NULL,
    ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
    ATTRIBUTE_BYTES BLOB NOT NULL,
    CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
    CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
);

 

이것 역시 마찬가지로 반영해 주면 된다.

 

프로젝트 설정

build.gradle 파일을 열고, MariaDB 드라이버를 추가해 주자.

 

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

 

그리고 서버에서 읽을 환경을 하나 구성한다.

src/main/resources/ 아래에 application-real.properties 파일을 만든다.

 

 

실제 구동될 환경이기 때문에 보안/로그상 이슈가 되는 내용은 지우고, RDS 환경 프로파일이 추가된다.

 

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

 

저장하고, GitHub에 푸시합니다.

 

 

EC2 설정

oauth와 마찬가지로, RDS 접속 정보 역시 보호해야 할 정보이므로 서버에 직접 설정 파일을 두도록 하자.

 

app 디렉토리에 application-real-db.properties 파일을 생성한다.

 

vim ~/app/application-real-db.properties

 

그리고 아래 내용을 추가한다.

 

spring.jpa.hibernate.ddl-auto=none
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

 

oauth 때와 같이, 이 파일을 읽을 수 있도록 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 \
    $REPOSITORY/$JAR_NAME 2>&1 &

 

다시 deploy.sh 파일을 실행해 주자.

 

 

nohup.out 파일을 보면 잘 실행된 것 같다.

 

로컬 환경에서 톰캣을 구동했을 때는 localhost:8080으로 접속했다.

마찬가지로 한번 접속해 보자.

 

curl localhost:8080

 

 

위처럼 HTML 코드가 나오면 정말로 제대로 실행되었다는 뜻이다.

 

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

정말로 배포 끝! 이라고 하기 전에, 한 가지 단계가 더 남았다. 직접 접속해서 확인해 보자.

 

접속을 위해서는 일단 AWS 보안 그룹 변경이 필요하다. EC2에 스프링 부트 프로젝트가 8080 포트로 배포되었으니, 8080 포트가 보안 그룹에 열려 있는지 확인하자.

 

 

EC2 -> 보안 그룹 -> 인바운드 규칙을 확인하자.

열려 있다면 넘어가고, 그렇지 않다면 직접 추가해 주자.

 

이후 왼쪽 사이드바의 '인스턴스' 메뉴를 클릭하면, 퍼블릭 DNS를 확인할 수 있다.

 

이 주소 뒤에 8080을 붙이면 우리의 웹 서비스에 접속할 수 있다.

 

우리의 서비스가 잘 배포된 것을 확인할 수 있다.

그렇다면 무엇이 문제일까?

 

OAuth2를 이용한 소셜 로그인을 구현할 때, 도메인을 입력하는 칸이 있었다.

당시에는 로컬 환경에서 테스트 중이었으므로 localhost:8080을 입력했다.

이걸 수정해 주어야 한다.

 

https://console.cloud.google.com/home/dashboard

 

API 및 서비스 > 사용자 인증 정보 에서 아래와 같이 입력해 주면 된다.

 

도메인:8080/login/oauth2/code/google

 

이러면 구글 로그인 설정은 끝이다!

 

 

성공적으로 로그인 되었다.

 

네이버도 마찬가지로 설정하러 가 보자.

 

https://developers.naver.com/apps/#/myapps

 

위의 순서로 들어가서, 서비스 URL과 네이버 로그인 Callback URL을 등록해 주면 된다.

네이버 로그인: 8080을 제외한 도메인 주소를 입력한다.

CallBack URL: 도메인 주소:8080/login/oauth2/code/naver

 

성공적으로 로그인 화면으로 넘어간다!

 

이렇게 성공적으로 우리의 서비스를 배포하였다.

이제 남은 과정은 배포 자동화와 무중단 배포 환경 구축이다.

댓글