이번 포스팅에서는 AWS의 EC2
를 이용한 Spring Boot
서버 배포 방법을 글로 정리해보겠습니다.
우선, 서버를 왜 개인PC를 활용한 On-premises
환경으로 배포하지 않고 AWS
환경을 사용하는지에 대해서 정리해보겠습니다.
On-premises
방법을 채택한다면, 개인 pc
혹은 회사용 서버 pc
를 이용하게 될 텐데요. 이러한 경우, 서버 pc는 365일 24시간 켜져 있어야 합니다. 서버 운영자는 pc 설정이 자유롭지만 관리 또한 운영자의 몫입니다.
서버를 확장하기 위해선 pc를 구매하고, 임시적인 서버 확장
이었다면 pc를 구매했다가 보관하거나 중고로 판매해야 하죠.. 서버 담당자가 신경써야 할 부분이 상당합니다.
반면에 AWS를 비롯한 Cloud Service
는 설정에 따라 서버 담당자가 관리해야 하는 부분을 양도할 수 있습니다. 책임을 분리
할 수 있는 것이죠. 원한다면 간단한 설정 변경과 과금으로 스케일 업
혹은 스케일 아웃
이 가능합니다. 일시적인 트래픽 밀집을 대비할 수 있는 것입니다.
저는 위와 같은 이유 중, 클라우드 서비스의 서버와 네트워크 관리 책임을 전가할 수 있는 AWS EC2
를 선택하게 되었습니다.
저희 러닝하이 팀은 현재 Spring Boot 3.2.3
버전으로 개발을 진행해왔습니다. 프론트엔드 분들께서 서버를 테스트해볼 수 있도록 개발 서버도 배포가 필요했습니다.
Spring Boot 프로젝트
를 서버에 옮기는 방법은 두 가지가 있습니다.
jar
파일로 빌드를 진행하고 jar
파일을 배포된 서버에 전달git
설치 후 프로젝트 clone
그 중 저는 더 간간한 jar
파일을 이용한 프로젝트 전달 방법을 사용하겠습니다.
(EC2 인스턴스 생성, 탄력적 IP 설정은 참고 자료가 많으므로 생략하겠습니다.)
EC2 OS
는 Ubuntu
를 사용하였습니다.
EC2 생성 간 발급받은 ssh pem key
는 잘 보관해주셔야 합니다.
* SSH - Secure Shell의 줄임말로, 원격 호스트에 접속하기 위해 사용되는 보안 프로토콜입니다. (*Shell(쉘): 명령어와 프로그램을 사용할 때 쓰는 인터페이스를 말합니다.)
우선, 발급받은 ssh pem key
를 이용해서 배포된 EC2 서버에 원격 접속합니다. 터미널에 접속해주세요!
pem key
가 저장된 경로로 이동 후 권한을 변경해주어야 합니다.
chmod 400 {PEM KEY 파일명}
ssh 원격 접속 하기.
ec2 - 인스턴스 - 연결 - ssh 클라이언트
에 있는 명령어를 복사해 실행합니다.
ssh -i "{pem key 파일 명}" {사용자 ID}@{퍼블릭 IP 혹은 도메인}
pem key는 RSA 알고리즘 방식으로 생성된 aws에서 제공해주는 공개키입니다.
진입 성공 시 {사용자ID}@{퍼블릭 IP 혹은 도메인}
으로 명령어 창이 변경됩니다.
가장 많이 실패하는 이유가 보안 그룹 인바운드 설정
입니다.
ssh 접속이 사용하는 기본 포트는 22포트
입니다. 해당 포트가 인바운드 규칙에 포함되지 않으면 보안그룹에서 막히는 것입니다.
ec2 인스턴스 - 보안 그룹 - 인바운드 규칙
위 사진처럼 모든 IP에서 22번 포트로 접속이 가능하도록 설정합니다.
(보안을 위해서 추후에 서버 ip만을 허용하도록 변경해야 합니다.)
다음으로 많이 되는 실패 사유가 인스턴스를 재생성한 경우
입니다.
기존에 접속한 ip의 서버가 달라지면 에러가 발생합니다.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
2이 경우에는 아래의 명령어를 입력하면 해결된다. {접속했던 ip 주소} 에는 현재 컴퓨터의 ip 주소, 이전에 접속했던 EC2의 ip 주소, 이전에 접속했던 EC2의 도메인을 입력하여 각각 실행해야 한다.
ssh-keygen -R {접속했던 ip 주소}
앞으로도 ssh로 서버 원격접속을 진행할 것이기 때문에, 22번 포트
에 대해서 방화벽 허용 설정을 해주어야 합니다. 미설정 시 time out
처리가 되므로 복잡한 과정을 거쳐 다시 설정해야 합니다.
# 22번 포트 방화벽 허용
sudo ufw allow 22
# 방화벽 실행
sudo ufw enable
# 방화벽 상태 확인
sudo ufw status
저희 서버에서 사용할 데이터베이스를 설치해줍니다.
데이터베이스의 경우, ec2 내부 pc에서 설치
해 사용하거나 RDS
를 설정하여 외부 통신을 하기도 합니다.
(그러면 아웃바인드 규칙도 데이터베이스 포트(3306)을 추가해주어야 합니다.)
RDS는 비싸기 떄문에 저희는 우선 ec2 내부에 설치하겠습니다.
저희 서버는 현재 MySQL
을 사용했으므로 해당 데이터베이스를 설치하겠습니다.
MySQL APT Repository를 설정합니다. MySQL의 APT Repository 패키지를 다운로드합니다.
wget -P {원하는 위치} https://dev.mysql.com/get/mysql-apt-config_0.8.22-1_all.deb
다운로드한 패키지를 설치합니다.
sudo dpkg -i {설치한 위치}/mysql-apt-config_0.8.22-1_all.deb
여기서 mysql server를 8.0으로 선택하고 OK를 선택해줍니다.
sudo apt-get update
MySQL Server 패키지 설치
sudo apt-get install mysql-server
설치하면 root
계정의 비밀번호를 설정하는 창이 나옵니다.
비밀번호를 설정해주고, 권장 설정을 해줍니다.
버전 확인 및 서비스 실행
mysql --version
sudo systemctl start mysql
sudo systemctl enable mysql // Ubuntu 서버 재시작시 MySQL 자동 재시작
mysql 서버 연결 테스트
sudo /usr/bin/mysql -u root -p
// 또는
sudo mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.38 MySQL Community Server - GPL
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
비밀번호를 누르고 root계정으로 로그인 시 연결되는 것을 확인할 수 있습니다.
MySQL을 설치했지만 외부에서 직접 MySQL
로 접근이 가능하도록 방화벽 설정을 해주어야 합니다.
sudo ufw allow mysql // 또는 3306
3306 포트에 대한 외부 접근이 가능하도록 모든 IP에 대해서 허용을 해주겠습니다.
우선, 계정을 생성하기 위해 관리자 계정인 root
계정으로 로그인합니다.
sudo mysql -u root -p
사용할 계정 & 스키마 생성
CREATE USER 'new ID'@'%' IDENTIFIED BY 'Password'; -- 'localhost' 대신 '%'를 쓰면 외부 ip로 접속 가능하다.
CREATE DATABASE {스키마};
스키마에 대한 계정 권한 부여
GRANT ALL PRIVILEGES ON {스키마}.* TO '{계정}'@'%';
FLUSH PRIVILEGES;
SHOW GRANTS FOR '{계정}'@'%'; // 권한 확인
이제 로컬 PC에서 접근이 되는지 확인해보겠습니다.
인텔리제이 프로젝트를 열겠습니다.(아무 프로젝트나 괜찮습니다.)
우측에 메뉴 중에 database를 설정하고 사용하는 데이터베이스에 맞게 설정합니다.
입력창이 나올텐데요!!
이제 Host
부분에 EC2 서버 IP 혹은 도메인
을 입력해줍니다.
User/Password
는 이전에 원격 서버에서 설정한 아이디와 패스워드를 입력해줍니다!
Database
부분은 사용하실 schema
를 적어주셔도 되구, 공란으로 두고 콘솔 창에서 use {스키마}
를 입력해주셔도 됩니다.
모두 입력했다면 Test Connection
을 눌러서 잘 되는지 확인이 가능합니다.
sudo apt update
sudo apt upgrade
sudo apt install openjdk-17-jdk
java --version
이제 모든 준비는 마쳤습니다.
프로젝트를 Build
해서 생성된 jar
파일을 ec2 서버로 전송해주면 됩니다.
배포하실 프로젝트로 이동해서 아까와 같은 메뉴의 gradle - task - build - build
를 실행해주시면 됩니다.
빌드가 성공되면, /build/libs
에 jar파일이 두 개 생성됩니다.
💡 파일이 하나가 생성되게 하려면,
build.gradle
에jar.enabled = false
를 추가해주세요.
이제 파일을 EC2 서버로 보내겠습니다.
scp -i "{PEM KEY 명}.pem" "{jar파일 위치&파일명}.jar" {사용자명}@{AWS EC2 도메인 명 or 탄력적 IP 주소}:/home/ubuntu
다시 EC2 서버로 원격 접속합니다.
/home/ubuntu
위치에 파일이 잘 전송되었는지 확인합니다.
이제 명령어로 jar 파일을 실행하면 성공입니다!
실행 시에 백그라운드로 실행하지 않으면, ssh 접속이 끊기는 순간 프로세스가 종료됩니다.
즉, 서버 백그라운드로 실행해야 ssh 접속이 끊겨도 실행이 지속됩니다.
# 사용 중인 포트를 차지하고 있는 프로세스가 있다면 종료
sudo fuser -k {프로젝트 설정 포트}/tcp
# 로그 디렉토리가 없다면 생성
mkdir -p /home/ubuntu/logs
# nohup을 사용하여 JAR 파일을 백그라운드에서 실행하고 로그를 /logs/nohup.out 파일에 기록
nohup sudo java -jar ~.jar > /home/ubuntu/logs/nohup.out 2>&1 &