본문 바로가기

프로그래밍/Spring

[REST API 실습] 4. Springboot 프로젝트 AWS EC2 인스턴스에 배포

본 포스팅은 스터디 모임의 발표 참고자료로 사용하기 위해 작성되었습니다.

 

 

목차

1) Springboot 프로젝트 생성하고 RestController 작성 후 실행하기(Gradle)

2) AWS RDS로 MariaDB 생성해서 워크벤치에 연결하기

3) JPA(Hibernate) + HikariCP로 스프링부트 프로젝트와 RDS MariaDB 연동 후 CRUD 메소드 구현

4) Springboot 프로젝트 AWS EC2 인스턴스에 배포

5) 안드로이드 앱에서 Retrofit을 사용해서 REST API와 통신하기(CRUD 구현)

 

참고사항

1) 부가적인 설명은 최대한 배제하는 대신 모든 과정을 여과 없이 스크린샷으로 남겼습니다. 그래서 대부분의 스크린샷이 창 전체를 포함합니다.

2) 이론적인 이해가 필요한 부분은 해시 태그(#)를 통해 키워드만 남겨놓도록 하겠습니다. 

3) 모든 과정을 정확하게 따르기 위해서는 IntelliJ, Gradle, Putty, AWS 계정, Mysql Workbench, Postman이 필요합니다.(테스트 과정을 패스한다면 Mysql Workbench, Postman은 필요 없습니다.)

 

 

4) Springboot 프로젝트 AWS EC2 인스턴스에 배포

1) Github Repository 생성

- 프로젝트를 깃허브에 업로드하는 방법은 다양하지만 저는 깃허브 데스크탑을 사용했습니다.

- 비공개로 업로드했기 때문에 따로 gitignore 설정은 하지 않지만 만약 공개로 업로드할 경우 업로드 전에 민감한 정보가 노출되지 않도록 gitignore 설정을 반드시 해야합니다.

#gitignore #githubDesktop

 

- File 탭의 add local repository를 클릭합니다.

 

- 프로젝트 폴더를 지정하면 레파지토리를 생성하라는 메시지가 나옵니다.

- create a repository를 클릭합니다.

 

- 레파지토리 이름을 지정해서 생성합니다.

 

- Publish repository를 클릭해서 깃허브에 업로드합니다.

 

- 깃허브 레파지토리 이름을 지정합니다.

- 이렇게 길게 만드실 필요는 없습니다. 저는 공개전환할 예정이기 때문에 검색에 노출될 수 있도록 사용된 기술을 전부 적었습니다.

 

- 깃허브에 업로드된 결과를 확인합니다.

 

2) AWS EC2 인스턴스 생성

- AWS EC2 서비스를 검색하고 인스턴스 시작 버튼을 클릭합니다.

- AWS가 너무 복잡하게 느껴지는 분은 생활 코딩 강좌를 한번 보시는걸 추천합니다. 하루만 투자해도 다 볼 수 있습니다.

https://www.youtube.com/playlist?list=PLuHgQVnccGMC5AYnBg8ffg5utOLwEj4fZ

 

Amazon Web Services (AWS) - YouTube

 

www.youtube.com

 

 

- 이미지를 선택할 수 있습니다. Ubuntu Server 18.04를 선택합니다.(익숙한 다른 OS를 선택하셔도 무관합니다.)

- 이미지마다 설치된 어플리케이션이 조금씩 다를 수 있는데 그때 그때 간단하게 설치할 수 있습니다.

#Linux #Unix #Ubuntu

 

- 인스턴스 유형을 무료인 t2.micro로 설정하고 검토 및 시작을 클릭합니다.

- 프리 티어라도 중첩해서 만들거나 스토리지 용량을 크게 설정하면 과금이 될 수 있습니다.

 

- 세부적인 설정은 건드리지 않고 인스턴스를 시작합니다.

 

- 키 페어를 다운 받습니다. 이름은 크게 중요하지 않습니다.

 

- 인스턴스가 시작됩니다.

 

3) PuttyGen을 이용해서 ppk 파일 생성

- 인스턴스가 시작되는 동안에 접속 환경을 설정합니다. 

- Putty를 설치할때 함께 설치된 Puttygen을 실행해서 Load를 클릭합니다.

 

- 파일 형식을 All files로 변경하고 다운받은 pem 파일을 로드합니다.

 

- 키가 import 되었습니다.

 

- Save private key를 클릭합니다.

 

- 경고창이 나오지만 예를 클릭합니다.

 

- ppk 파일로 저장합니다. EC2 인스턴스 접속시 사용할 파일이니 경로를 잘 기억해두세요.

 

4) EC2 인스턴스에 IP 연결

- EC2 인스턴스가 정상적으로 생성되어 running 상태가 되었습니다.

- 고정된 IP를 사용하기 위해 메뉴창의 탄력적 IP를 클릭합니다.

 

 

- 새 주소 할당을 클릭해서 특별한 설정 없이 할당을 클릭합니다.

 

- IP주소가 할당되었습니다.

 

- 우클릭 후 주소 연결을 클릭합니다.

 

- 생성한 인스턴스에 연결합니다.

 

- IP 주소가 연결되었습니다.

- 이제 putty를 이용해서 인스턴스에 접속해보겠습니다. IPv4 퍼블릭 IP 주소를 복사합니다.

 

- Putty를 실행한 후 Host Name에 복사한 IP주소를 입력합니다.

 

- 카테고리에서 Connection - SSH - Auth를 클릭하고 Browse를 클릭해서 ppk 파일을 로드한 후 Open을 클릭합니다.

- Session 카테고리에서 설정을 저장해두면 추후 재접속시 편리합니다.

 

- 보안 알림창이 뜨는데 그냥 예를 클릭합니다.

 

- ubuntu로 로그인합니다.

- CentOS 계열의 이미지를 선택한 경우 ec2-user를 입력하면 됩니다.

 

- EC2 인스턴스에 정상적으로 접속되었습니다.

 

5) 프로젝트 파일 가져오기

 

- 깃허브에서 파일을 클론해오기 위해 클론 URI를 복사합니다.

 

- git clone 명령어를 통해 프로젝트를 클론합니다.

git clone "주소"

 

- 프라이빗 레파지토리에서 클론해오는 경우에는 깃허브 계정의 유저네임과 패스워드를 입력해야합니다.

 

- 클론이 정상적으로 완료되었습니다.

 

6) 자바8 설치

- Ubuntu 18.04 이미지에는 자바11이 내장되어있으나 에러 발생의 소지가 있어서 자바8을 설치합니다.

sudo apt-get update

 

- 혹시 아래 명령어로 자바가 설치되지 않는다면 구글에 java8 install을 검색해서 패키지명을 알맞게 입력해주시면 됩니다.

sudo apt install openjdk-8-jdk

 

- 자바 버전을 확인해서 설치가 잘 되었는지 확인합니다.

java -version

 

7) 프로젝트 빌드하기

- gradlew 파일에 권한을 부여합니다.

- ls 명령어를 쳤을 때 초록색으로 표시가 되어야 합니다.

#chmod

sudo chmod 777 ./gradlew

 

- 아래 명령어를 통해 빌드합니다.

#GradleWrapper

sudo ./gradlew build

 

- 빌드를 하려는데 에러가 발생했습니다. 잘 읽어보니 테스트 코드에서 문제가 생긴 것 같습니다. REST API이기 때문에 index.html 파일은 필요 없습니다.

- EC2에서 삭제하거나 프로젝트를 생성한 PC에서 삭제하고 깃을 통해 업데이트 하는 방법이 있습니다.

- 후자를 선택했습니다. 다시 인텔리제이로 돌아가서 test/java/ 안의 테스트 코드를 삭제합니다.

 

- 깃 커밋 후 푸시합니다.

 

 

- EC2 인스턴스에서 pull해온 후 빌드를 재시도합니다.

sudo git pull
sudo ./gradlew build

 

- 빌드가 정상적으로 완료되고 build 폴더가 생성되었습니다. 

- ./build/libs 폴더 안에 jar 파일이 생성되었습니다.

- 스프링부트에는 톰캣 서버가 내장되어있기 때문에 빌드된 파일만 실행하면 서버가 가동됩니다.

#톰캣 #jar #war

java -jar 파일명.jar

 

- IDE의 콘솔창에서 보던 익숙한 화면이 등장합니다.

- 커넥션 풀 연결 에러가 발생합니다. 

 

- 이전 글에서 RDS 생성할 때 얘기했던 부분입니다.

- 보안 그룹 설정이 인스턴스를 생성 요청한 PC의 IP로만 제한되어 있는 상태인데 다른 IP의 EC2로는 접근이 불가능합니다. 

- RDS 서비스로 돌아가서 인스턴스 정보에 VPC 보안그룹을 클릭합니다.

 

- 인바운드 -> 편집을 클릭합니다.

 

- EC2 인스턴스의 프라이빗 IP로 지정합니다.

- 보안상의 문제가 없거나 여러 위치에서 테스트해야하는 경우 위치 무관으로 지정합니다.

 

- EC2로만 이용을 제한할 경우 인스턴스에 접근했던 퍼블릭 IP가 아닌 프라이빗 IP로 지정해야 합니다.

 

- 그리고 다시 실행하자 정상적으로 실행됩니다.

 

8) 프로젝트 접속 테스트

- 이 전의 작업이 EC2 -> RDS로의 접근을 설정하는 작업이었다면 이번 작업은 클라이언트 -> EC2(서버)로의 접근을 설정하는 작업입니다.

- EC2 대시보드로 이동해서 인스턴스의 보안그룹을 클릭합니다.

 

- 스프링부트 프로젝트가 가동되는 포트를 위치 무관으로 열어줍니다.

 

- 퍼블릭 IP를 복사합니다.

 

- 퍼블릭IP:3333으로 요청을 보내자 정상적으로 응답이 돌아옵니다.

 

- API도 DB와 연동되어서 잘 작동합니다.

 

9) 배포용 코드 작성

- 서버가 백그라운드에서 실행될 뿐만 아니라 git pull, 가동 확인까지 해주는 코드를 작성합니다.

sudo nano deploy.sh

- nano가 아닌 다른 편집기를 사용해도 됩니다. nano를 사용할 경우 작성을 완료하고 Ctrl+O를 클릭해서 저장 후 Ctrl+X로 빠져나오면 됩니다.

- 아래 TODO가 표시된 부분만 맞게 변경해서 저장하면 됩니다. Putty에서 붙여넣기를 하려면 Ctrl+V가 아니라 마우스 우클릭을 하면 됩니다.

#!/bin/bash
REPOSITORY=/home/ubuntu/Springboot-JPA-hikariCP-restAPI-CRUD-example # TODO 경로 수정
cd $REPOSITORY
echo "> Git Pull"
git pull
echo "> 프로젝트 Build 시작"
sudo ./gradlew build
echo "> Build 파일 복사"
sudo cp ./build/libs/*.jar $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f Springboot-JPA-hikariCP-restAPI-CRUD-example) # TODO 피드명 수정
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 'restapi-0.0.1-SNAPSHOT.jar' | tail -n 1)
echo "> JAR Name: $JAR_NAME"
nohup java -jar $REPOSITORY/$JAR_NAME &

코드 출처: https://jojoldu.tistory.com/263

 

- 작성한 코드에 권한을 부여한 후 실행합니다.

sudo chmod 775 ./deploy.sh
./deploy.sh

 

- nohup.out이라는 파일이 생성되고 콘솔에서 출력되던 내용들이 해당 파일에 저장됩니다.

- 아래 명령어를 통해 실시간 확인도 가능합니다.

tail -f nohup.out

 

- curl 명령어를 이용해서 서버가 정상구동중인지 테스트합니다.

curl localhost:3333/member/select

 

 

10) 포트 리다이렉트

 

- 주소에 포트까지 연결하기가 번거롭다면 포트를 리다이렉트 시킬 수 있습니다.

- http는 80포트로 연결됩니다. 80 포트에 접근할 경우 3333으로 리다이렉트 시킴으로써 포트번호를 입력하지 않아도 됩니다.

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3333

 

- 인스턴스의 보안그룹에서 80 포트를 열어줍니다.

 

- 이제 IP주소로만 접속해도 정상적으로 연결이 됩니다.

 

이제 도메인을 설정하고 SSL 인증서를 통해서 https 443 포트로 접속할 수 있도록 만들면 좋습니다.

다음에 시간이 나면 아래 사항에 대해서 따로 포스팅하겠습니다.

 

- AWS의 ELB와 ROUTE 53을 통해 도메인을 구매, 인증서 발급, 연결하는 방법

- Auto Scaling과 AMI, systemctl을 이용해서 서비스 자동 실행 및 안정적인 서버 운영

 

 

5장에서는 간단한 안드로이드 앱을 만들어서 배포한 REST API 서버와의 통신을 통해 CRUD를 하는 실습을 진행합니다.