Spring Security + JWT + React - 08. AWS EC2 Spring 백엔드 배포

june·2022년 9월 26일
2
post-thumbnail

AWS

백엔드와 프론트엔드 모두 제작 과정이 끝났으니 배포를 해보도록 하자.

AWS 프리티어를 사용해서 EC2를 통해 배포를 진행할 예정이다.

EC2 인스턴스 생성

먼저 리전을 서울로 설정한 다음 인스턴스를 생성한다.

os는 ubuntu로 설정했다. 다른 것으로 해도 무방하나 문법이 약간 다르다.

인스턴스는 프리티어인 t2.micro로 설정했고, 보안 그룹에서는 모든 곳에서 ssh를 허용했다.

물론 이러면 보안상의 문제가 될 수 있지만, 여러곳에서 ssh를 사용할 예정이기 때문에 허용해놓았고, 추후에 수정할 예정이다.

자신이 쓸 IP만 설정해놔도 무방하다.

키페어 설정은 중요한데, 여기서 받은 키는 더 발급 받을 수 없기 때문이다. 따라서 생성을 누르고 다운받아진 키페어 파일은 중요한 곳에 저장해놔야 한다.

윈도우의 PuTTYCygwin 기준으로는 ppk가 필요하고, 여기서도 ppk를 사용하지만, pem으로 다운받아도 무방하다. PuTTYGen같은 프로그램으로 충분히 변환이 가능하다.

스토리지는 10G로 설정해놨다. 더 적게 해도 무방하다.

포트 연결

생성이 다 되었다면 포트를 열어주기 위해 보안규칙으로 가자. 인스턴스를 클릭한다.

이후 보안 탭에서 보안그룹을 클릭한다.

보안 그룹에서 인바운드 규칙 편집을 클릭한다.

이전의 설정했던 ssh를 위한 22번 포트 이외에 Tomcat의 포트인 8080포트와, 80포트를 열어주면 된다. 이 또한 나중에 프론트엔드 측에서만 열람 가능하게 IP를 설정하는 것이 좋다.

탄력적 IP주소 설정 (고정 IP)

해당 인스턴스는 고정 IP가 없기 때문에 만약 인스턴스가 재부팅이 된다면 IP주소가 변하고 만다.

그렇게 되면 서비스 도중 통신이 제대로 되지 않고, 과정마다 수정을 해야하므로 고정IP를 설정해주도록 하자.

해당 인스턴스를 들어가 작업에 네트워킹을 클릭하면 IP주소 관리가 있다. 클릭하자.

그러면 탄력적 IP 주소를 할당하라고 하는데 저 할당 부분을 클릭하자.

그러면 탄력적 IP 페이지로 나오게 되고, 여기서 탄력적 IP 주소 할당 버튼을 클릭한다.


그러면 이 페이지가 나오는데, 해당 설정 그대로 할당 버튼을 누르면 된다. 추가적인 과정을 거쳐도 무방하다.


그러면 탄력적 IP 주소가 할당 된다. 이제 이것을 인스턴스와 연결하자. 참고로 할당하기만 하고 인스턴스를 연결하지 않을 시 AWS에서 요금이 부과된다. 주의하자!


인스턴스 부분에서 연결할 인스턴스를 선택하고 연결 버튼을 누르면 된다.


성공적으로 되었다면 이런 화면이 뜨게 된다.


인스턴스를 확인해도 마찬가지로 해당 IP주소로 IPv4주소가 바뀌었다.

SSH 연결

SSH 연결을 위해 SSH 프로그램을 설치하자.

많은 곳에서 PuTTY를 사용하지만, 여기서는 MobaXterm을 사용할 것이다.

설치 후 세션 모양 아이콘을 클릭해주자.

이후 SSH 아이콘을 클릭한다.

여기서 Remote host에는 자신의 ec2 인스턴스의 퍼블릭 IPv4 DNS를 넣으면 된다.

AWS EC2의 인스턴스 페이지를 들어가서 해당 인스턴스를 클릭했을때 퍼블릭 IPv4 DNS를 알 수 있다.

이후 Specify username에는 체크하고 ubuntu라고 작성하면되고

Use private key 또한 체크하고, 발급 받았던 ppk 키를 넣으면 된다. (앞서 말했듯이 pem으로 발급 받았으면 변환하면 된다.)

설정을 다 하고 OK 버튼을 누르면 이런 화면이 나올 것이다.

ubuntu 세팅

$ sudo apt-get update

먼저 설치 가능한 패키지 리스트를 최신화 해주자.

메모리 스와핑

이후 해야할 과정은 메모리 스와핑이다. 이는 하드디스크를 가상 메모리로 전환시켜 램처럼 사용하는 것을 뜻한다.

이건 다른 블로그나 책 등에서 배포할 때 잘 설명하지 않는 부분인데, 만약 자기가 AWS의 프리티어를 사용하고 있다면 난 메모리 스와핑이 필수라고 생각된다.

왜냐하면 실제 빌드를 할 때 이 부분에서 램 부족 문제로 진행되지 않는 경우가 부지기수기 때문이다.

우리가 프리티어에서 설정한 인스턴스는 t2.micro인 경우가 많은데, 이는 램이 1기가 밖에 되지 않는다.

실제 내가 빌드 과정을 거쳤을 때 많이 겪었던 오류로, 80% EXECUTING 이후 더이상 나가질 못했다.

따라서 이 글을 보고 문제를 깨닫게 되었으며, 메모리 스와핑 또한 이 글을 참고로 진행하기로 한다.

먼저 AWS가 제시한 이 우분투 공식 글에서는, 1기가 이상에서는 최소 램과 같거나 2배까지라고 했으니, 2기가로 설정하여 진행해보자.

먼저 스와핑을 진행할 파일을 생성해주자.

$ sudo dd if=/dev/zero of=/swapfile bs=128M count=16

리눅스의 dd 명령을 사용해서 파일을 생성했으며, 2기가를 설정했으므로 블록크기는 128MB, 블록수는 16개로 설정했다. (2GB = 2048MB)

$ sudo chmod 600 /swapfile

파일에 대한 읽기 및 쓰기 권한을 업데이트 해주자.

$ sudo mkswap /swapfile

이제 해당 파일을 인스턴스 리눅스의 스왑 영역을 설정한다.

$ sudo swapon /swapfile

스왑 영역을 활성화 시켜준다.

$ sudo swapon -s

이후 절차가 성공했는지 확인해보자.

정상적으로 스와핑이 성공했다.

$ sudo vi /etc/fstab

이후 /etc/fstab파일을 vi편집기로 편집하여, 부팅시 스와핑을 활성화하도록 하자.

/swapfile swap swap defaults 0 0

vi 편집기를 통해 파일 맨 마지막 줄에 이 부분을 추가하고 파일을 저장한 다음 종료하면 된다.

이후 free를 입력하여 메모리를 확인해보면 스와핑이 제대로 진행되고 있는지 확인이 가능하다.

정상적으로 진행된다.

Java 설치

이제 자바를 설치해보자.

$ sudo apt list | grep openjdk

먼저 apt의 list에 있는 openjdk를 모두 찾아보자. (openjdk는 Java 환경에서 돌아가는 프로그램을 개발하는 데 필요한 툴들을 모아놓은 소프트웨어 패키지를 오픈소스로 구현해 놓은 것이다.)

내가 이번 버전에서 진행한 프로젝트에서 자바는 17버전이므로 버전에 맞게 설치해주면 된다.

$ sudo apt-get install openjdk-17-jdk

환경변수

이제 윈도우에서도 자바를 사용하기 위해 환경변수를 설정했던 것처럼, 리눅스에서도 환경변수를 설정해보자.

$ which java
/usr/bin/java

$ readlink -f /usr/bin/java
/usr/lib/jvm/java-17-openjdk-amd64/bin/java

먼저 자바의 절대경로를 알아내보자.

vi /etc/profile

이제 vi 편집기를 통해 프로필 파일을 수정해준다.

맨 마지막 줄에 아래 3줄을 추가하면 된다.

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=$CLASSPATH:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar

저장 후 종료한다.

이제 환경변수가 설정되었는지 확인해보자.

$ echo $JAVA_HOME

다음과 같이 입력했을 때 절대경로가 나오면 환경변수가 설정되었다는 뜻이다.

gradle 설치

이제 gradle을 설치하자.

gradle을 설치하기에는 먼저 약간의 준비과정이 필요한데, 먼저 유닉스 환경에서 sdk들을 관리하는 sdkman을 설치해야하며,

sdkman을 설치하기 위해서는 압축파일을 관리하기 위한 zip도 설치되어야 한다. (ec2의 ubuntu는 zip이 설치되어 있지 않다!)

차근차근 진행해보도록 하자.

$ sudo apt install zip

zip부터 설치해 주자.

$ curl -s "https://get.sdkman.io" | bash

설치가 완료되었으면 sdkman도 설치한다.

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

이후 source 명령어를 통해 환경설정을 바로 적용시킨다.

$ sdk version

제대로 설치되었는지 버전을 통해 확인해본다.

제대로 설치가 되었다.

이제 gradle을 설치해보자

$ sdk list gradle

내 프로젝트의 gradle은 7.4.1 버전이므로 맞는 버전을 설치해준다.

$ sdk install gradle 7.4.1

배포

$ git clone [프로젝트 코드 주소]

배포를 하기 위해, github에 있는 프로젝트를 클론해오자

$ cd ./프로젝트 디렉토리

다음 프로젝트 디렉토리로 이동한다.

$ sudo chmod +x ./gradlew

이후 ./gradlew에 권한을 준다.

테스트 및 실제 배포

이제 테스트 빌드를 먼저 시행해보자.

$ sudo ./gradlew clean test

이런 결과가 나왔으면 성공한 것이다.

이제 실제 빌드를 거쳐보자

$ sudo ./gradlew build

마찬가지로 성공했다. 이제 java를 실행해보자.

$ sudo java -jar [jar파일명]

익숙한 화면이 등장한다. 성공적으로 된 것이다.

이제 postman을 통해 호출도 해보자.

REST API를 통한 호출도 제대로 된다.

포트포워딩

그런데 앞서 실행했던 과정과 같이 항상 url 뒤에 8080을 붙여서 통신해야하는 과정이 번거롭다.

따라서 http의 기본 포트인 80포트를 자동으로 8080포트로 바꿔서 통신하게 해주는 포트포워딩 과정을 거쳐보자.

간단하게 아래의 명령어만 입력하면 된다.

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

출처

이제 8080을 빼도 제대로 실행 된다.

백그라운드 배포

앞의 과정에서 배포의 문제점은 만약 우리가 ssh를 종료하고 나가면, java 또한 종료된다는 점에 있다.

따라서 이러한 점을 막기 위해 ssh가 종료되어도 실행될 수 있도록 백그라운드 배포를 해보자.

이 또한 별로 어렵지 않다.

$ nohup java -jar [파일이름].jar &

이렇게 실행하면, 서버는 알아서 돌아가게 된다.

이후 실행되고 있는 자바 프로세스를 종료시키려면

$ ps -ef | grep java

이 명령어를 통해 pid를 찾아낸 다음

$ kill -15 [pid]

를 사용하면 된다.

여기서는 pid가 27914이므로

$ kill -15 27914

가 되겠다.

만약 이걸로도 종료가 안된다면 kill -9 pid를 사용하면 된다.

profile
초보 개발자

0개의 댓글