본문 바로가기
스프링부트와 AWS로 혼자 구현하는 웹서비스

EC2 서버에 프로젝트 배포하기 - EC2에 프로젝트 Clone 및 배포 스크립트 작성(외부 Security 파일 등록)

by 초이사 2023. 3. 27.

이 글은 '스프링부트와 AWS로 혼자 구현하는 웹 서비스 - 이동욱(jojoldu)'을 공부하며 작성한 글로 생략된 내용은 책을 구매해서 확인하는 것을 권장합니다.

참고 소스코드 깃허브 https://github.com/jojoldu/freelec-springboot2-webservice

http://www.yes24.com/Product/Goods/83849117

 

스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - YES24

가장 빠르고 쉽게 웹 서비스의 모든 과정을 경험한다. 경험이 실력이 되는 순간!이 책은 제목 그대로 스프링 부트와 AWS로 웹 서비스를 구현한다. JPA와 JUnit 테스트, 그레이들, 머스테치, 스프링

www.yes24.com

 

이 책의 8장에 해당하는 EC2 서버에 프로젝트 배포 과정 중 EC2에 프로젝트 Clone 및 배포 스크립트 작성(외부 Security 파일 등록)에 대해 정리하고자 한다.

 

 

EC2에 프로젝트 Clone 받기

깃허브에서 코드를 받아올 수 있도록 EC2에 깃을 설치해주어야 한다.

1. putty로 EC2로 접속하여 깃 설치

git 설치 및 설치 상태 확인

sudo yum install git //깃 설치
git --version //설치 버전 확인

설치 상태 확인.

제대로 설치되었다면 현재 git 버전이 나온다

 

2. git clone으로 프로젝트를 저장할 디렉토리 생성

디렉토리 생성

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

디렉토리로 이동

cd ~/app/step1

3. 본인 깃허브 웹페이지로 가서 https 주소 복사 후 git clone 진행

git clone 복사한주소

프로젝트 클론 성공

4. 프로젝트가 있는 폴더로 이동, 복사된 파일 확인 및 코드 테스트

폴더로 이동 및 복사된 파일 확인

cd springboot-webservice
ll

코드가 잘 수행되는지 테스트

./gradlew test

오류가 발생했다.

Permission denied 오류 발생

gradlew파일이 ./gradlew를 실행할수 있는 권한이 없어서 발생하는 오류 권한을 주고 실행하면 된다.

chmod +x ./gradlew test //권한 주기
./gradlew test //테스트 실행

테스트가 잘 실행될 줄 알았으나 FAILURE: Build failed with an exception. Execution failed for task ':compileJava'. 가 발생했다. 오류 해결 과정은 아래 글에 작성해두었다.

첫번째 오류 - Execution failed for task ':compileJava

2023.03.23 - [spring] - [spring] ./gradlew test 오류 Execution failed for task ':compileJava'. 에러 해결

 

위 오류를 해결하고 다시 테스트하니 85%까지 진행되다가 test 폴더에 있는 테스트들이 실패하는 문제가 발생했다.

두번째 오류 - Execution failed for task ':test'.

오류 해결과정은 아래 글에 작성해두었다.

2023.03.23 - [spring] - [spring] ./gradlew test 오류 Execution failed for task ':test'. There were failing tests. 해결

 

 

 

 

배포 스트립트 만들기

*배포: 작성한 코드를 실제 서버에 반영하는 것

이 책에서 진행하는 프로젝트에서 배포는

  • git clone 혹은 git pull을 통해 새 버전의 프로젝트 받기
  • Gradle 혹은 Maven을 통해 프로젝트 테스트와 빌드
  • EC2 서버에서 해당 프로젝트 실행 및 재실행

위 3가지를 포괄하는 의미인데, 이 과정을 새로 배포할 때마다 하나하나 명령어를 실행하는 것은 불편함이 많다.

-> 그래서 이를 쉘 스크립트로 작성해서 스크립트만 실행하면 위 3가지가 차례대로 실행되도록 스크립트 작성 필요!

 

참고사항 - 빔과 쉘 스크립트의 역할 차이

쉘스크립트

  •  .sh라는 파일 확장자를 가진 파일로 노드 JS가 .js라는 파일을 통해 서버에서 작동하는 것 처럼 리눅스에서 기본적으로 사용할 수 있는 스크립트를 말한다.

빔(Vim)

  • 리눅스 환경과 같이 GUI(윈도우와 같이 마우스를 사용할 수 있는 환경)이 아닌환경에서 사용할 수 있는 편집 도구
  • 리눅스에서 지원하는 도구 중 가장 대중적인 도구

 

1. ~/app/step1/에 deploy.sh 파일 생성

vim ~/app/step1/deploy.sh

 

2. 파일 생성 후 스크립트 작성

i 또는 insert를 눌러서 편집모드로 진입 후 작성

*글자색이 진한 파란색으로 잘 보이지 않는 이슈가 있어 색 수정해서 사용

아래글 참고

https://www.runit.cloud/2020/04/putty-blue-color.html

 

PuTTY 환경 설정에서 파란색 색상 변경하기

리눅스 서버에 ssh 접속 시 터미널 창의 디렉터리와 주석이 파란색으로 표시되는데, 색이 어두워서 알아보기 쉽지 않습니다. putty의 설정을 변경해서 리눅스 터미널의 파란색의 색을 알아보기 쉽

www.runit.cloud

 

색 변경후 아래 명령어로 다시 스크립트 접속

cd ~/app/step1
vi deploy.sh

쉘 스크립트 작성

#!/bin/bash

REPOSITORY=/home/ec2-user/app/step1
PROJECT_NAME=springboot-Webservice

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 &
  • REPOSITORY=/home/ec2-user/app/step1: 프로젝트 디렉토리 주소는 스크립트 내에서 자주 사용하는 값이기에 변수로 저장한다. 쉘에서는 타입없이 선언하여 저장한다.

쉘에서는 $변수명으로 변수를 사용한다.

  • cp ./build/libs/*.jar $REPOSITORY/: build의 결과물인 jar 파일을 복사해 jar 파일을 모아둔 위치로 복사
  • CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar): 기존에 수행중이던 스프링 부트 애플리케이션을 종료한다.
    • pgrep: process id만 추출하는 명령어
    • -f 옵션: 프로세스 이름으로 찾는다.
  • if ~ else ~fi: 현재 구동중인 프로세스가 있는지 판단해서 기능 수행, process id 값을 보고 프로세스가 있다면 해당 프로세스 종료
  • JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1): 새로 실행할 jar파일을 찾는다. 
    • tall -n: 여러 jar파일이 생기기 때문에, tall -n으로 가장 나중의 jar 파일을 변수에 저장하도록 한다.
  • nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 &: 찾은 jar 파일명으로 해당 jar 파일을 nohup으로 실행한다.
    • 스프링부트의 장점으로 외장 톰캣 설치할 필요x
    • 내장 톰캣을 사용해서 jar 파일만 있으면 바로 웹 어플리케이션 서버 실행 가능
    • 애플리케이션 실행자가 터미널을 종료해도 애플리케이션은 계속 구동되도록 nohup 명령어 사용
      • 일반적으로 자바 실행시 사용하는 java -jar은 사용자가 터미널 접속을 끊을 때, 애플리케이션도 같이 종료된다.

작성이 끝난 후 esc를 누른 뒤, :wq를 해서 저장하고 종료한다.

 

3. 생성한 스크립트에 권한 주기

chmod +x ./deploy.sh //권한주기
ll //권한 추가되었는지 확인

ll 명령어 실행결과

4. 스크립트 실행

./deploy.sh

스크립트 실행 결과

readme를 작성하면서 일부 수정한 사항이 있었는데, git pull로 클론된 프로젝트에도 성공적으로 반영됐다.

 

5. nohub.out 파일로 로그 확인해보기

vim nohup.out

파일로 들어가 i또는 insert를 눌러 편집모드로 들어가 제일 아래로 내려가면

ClinetRegistrationRepository를 찾을 수 없는 에러 발생

ClinetRegistrationRepository를 찾을 수 없다는 에러가 발생한다.

 

 

 

 

외부 Security 파일 등록

ClinetRegistrationRepository를 찾을 수 없다는 에러 발생 이유

  • ClinetRegistrationRepository를 생성하려면 clientId 와 clientSecret이 필수로 로컬 PC에서 실행할 때는 application-oauth.properties가 있었기 때문에 생성이 가능했다. 하지만 이 파일은 .gitignore로 git에서 제외 대상으로 등록했기에 클론된 프로젝트에는 없는 파일이다.

 

애플리케이션 실행을 위해 공개된 저장소에 ClientId와 ClientSecret을 올릴 수는 없기에 서버에서 직접 이 설정들을 가지고 있게 해야 한다.

1. app 디렉토리에 properties 파일 생성(step1 디렉토리가 아님)

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

2. 생성한 파일에 로컬에 있는 application-oauth.properties 파일 내용 복붙한 뒤, 저장하고 종료

3. 방금 생성한 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 &
  •  -Dspring.config.location: 스프링 설정 파일 위치를 지정한다. 
    • 기본 옵션들을 담고 있는 application.properties와 OAuth 설정들을 담고 있는 application-oauth.properties의 위치를 지정한다.
    • classpath가 붙으면 jar안에 있는 resources 디렉토리를 기준으로 경로 생성
    • application-oauth.properties는 외부에 파일이 있어 절대 경로를 사용한다.

댓글