Spring boot AWS 배포, 나도 할 수 있을까?
이 글은 배포 과정을 자꾸 까먹는 나를 위해 포스팅 하려한다.
준비물
☕ Java v17
🚀 Kotlin v1.9.22
🌿 Spring boot v3
🐘 Postgresql v16
🧱 Redis v7
🐋 Docker v26
Step 1. AWS 구성
프로젝트 아키텍처의 일부를 발췌
AWS 구성은 구글링하면 나오지만 순서랑 주의점 정도만 적어본다.
1. EC2 인스턴스 생성
- EIP 연결
- Public IP 할당
- 보안그룹 지정
- 역할 지정 ( SSM 연결용 )
- 키페어 지정 x ( SSM 연결 할거니까 )
- AMI 고를 때 Amazon SSM Manager 있는 거로 골라야됨 ( amazon linux 엔 대부분 있다 )
- SSM 연결하려면 인스턴스 만들고 4~5시간은 지나야 연결됨, 참을성을 가지자
- SSM 대신 SSH 쓸거면 키페어 생성하고 저장만 잘 해두면 됨
2. RDS 생성
- RDS - Postgres 이용 ( Aurora 하면 지갑 다털림 )
- 파라미터 그룹 지정 ( Timezone )
3. S3 생성
- ACL 권한 조정
4. VPC
- 잘 안되는거 있다 싶으면 VPC 의심하자
- private vpc, endpoint 사용하면 지갑 다털림
간단하게만 나열했는데 모르겠는 부분이 있으면 찾아보자
Step 2. EC2 접근
매우 간단쓰하게 설치 가능
우선 EC2 접근
ssh 연결 시
ssh -i "pem 파일" 유저명@EC2_Public_IPv4_DNS
ssm 연결 시
1. aws-cli 설치
2. aws-cli 용 ssm-plugin 설치
3. 아래명령어 사용
aws ssm start-session --target <ec2-id>
혹은
그냥 AWS Console 에서 접속
EZPZ
Step 3. EC2 에 JDK 설치
sudo yum install java-17-amazon-corretto-devel.x86_64
Package Manager 는 뭘 쓰던 상관없다
설치 후
java --version
// OpenJDK Runtime Environment Corretto-17.0.11.9.1 (build 17.0.11+9-LTS)
// OpenJDK 64-Bit Server VM Corretto-17.0.11.9.1 (build 17.0.11+9-LTS, mixed mode, sharing)
이렇게 나오면 된다.
EC2에 Spring Boot Project 옮기기
여러가지 방법 중 한가지를 사용하면 된다
1. git 을 이용하여 clone을 한다.
2. ftp or sftp 를 사용하여 jar를 넘긴다
3. docker 로 이미지화 해서 넘긴다.
여기서는 2번 방법으로 진행한다.
장단점을 따지자면
방법 | 장점 | 단점 |
git | 코드 관리가 매우 편리 | 받아야 하는 파일 크기가 너무 커진다. |
ftp / sftp | jar 파일 그냥 넘기면 되는거라 용량 차지가 적고 빠르게 배포 가능 | sftp를 사용해야하고 ssh 키 관리를 해야한다. |
docker | 일관성, 확장성이 있고 컨테이너화 해서 하기 좋다 | dockerfile 잘못다루면 더 힘들어진다. |
jar 파일로 하는게 작은 크기의 ec2에 적합하다고 생각해서 sftp 방식을 사용할 예정이다.
Step 4. sftp 로 파일 옮기기
1. cli로 옮기기
2. 툴 사용하기
cli 로 사용하는게 간지는 나지만 이래저래 툴이 편리함이 있기에 2번을 사용하고자 한다.
cli 접속 방법 참고용
sftp -i pem파일경로 -P 포트 접속계정@접속IP
툴은 보통 2가지 중 하나를 사용한다.
1. putty
2. filezilla
실무를 할 때 On-Premis 를 사용하는 기업들 대부분 putty 를 사용했는데 ec2를 사용할 때는 filezilla를 사용하는 경우가 많았어서 filezilla로 하고자한다. 사실 뭐 두개 별 다른거 없다.. UI 차이라고 보면되겠는데 난 filezilla를 선호
filezilla 설치 페이지
https://www.filezilla-project.org/download.php?type=client
설치하고 실행하면 이렇게 뜨는데, 왼쪽 상단 PC 3대가 있는 버튼(사이트 관리자 열기) - 새 사이트 버튼을 누르고
설정을 기입하면 된다.
호스트에 ec2 public ip 를 입력하면 되고 포트는 기본으로두되 안되거나 특정 포트를 사용할 거라면 22 혹은 지정한 포트를 기입하면 된다.
좌측 (로컬) , 우측 (ec2) 가 된다.
이제 끌어다 옮기던~ 더블클릭으로 옮기던 맘대로 옮기면 된다.
Step 5. 실행
실행은 간단하다.
jar 파일을 옮겨놓은 jar 파일 경로에가서 아래 명령어 수행하면 끝이다.
java -jar <jar파일명>
하지만 위 명령어는 터미널을 끄게 되면 spring boot 도 같이 내려가버린다.
다음은 백그라운드에 작업을 올려놓는 방식이다.
nohup java -jar <jar파일명>
그러면 정상적으로 올라갈 것이고 지정해둔 url , port 등을 통해서 접근 가능해질 것이다.
보안그룹 조건, ec2 설정 등에 따라서 접근 방식은 다양하고 복잡하니 접근 방식까진 얘기 안할랍니더..
Step 6. 트러블 슈팅
1. 환경변수
대부분의 환경 변수는 application.yml 에서 관리하고있다.
하지만 port 만은 실행 단계에서 주입하도록 하였었다.
intellij로 치면 아래와 같은 부분
실행 시 환경변수를 주입해 주기위해서는 여러가지 방법이 있다.
1. os 자체에 환경변수를 설정한다.
2. 실행 시 환경변수를 같이 준다.
1번이 맞다고 생각은 하지만, 인스턴스를 하나뿐이 쓰지 못하는 나의 상황에선 이 인스턴스를 요리 굴리고 저리 굴릴것이기에 실행 시 환경변수를 같이 주려고 한다
아래 명령어를 통해서 수행하면 된다.
<환경변수 key=value> nohup java -jar <jar파일명>
나는 아래의 명령어를 이용했다.
SERVER_PORT=8080 nohup java -jar test.jar
포트가 잘 들어갔다.
2. DB 연동
기존에 로컬에서 테스트할 때 db를 rds 에 올리고 그 설정을 그대로 가져다 쓰면 얼마나 좋을꼬..
하지만 돈이 없는 나는 테스트를 할 때 로컬에 db를 만들어둔 상태였고 연결또한 그렇게 했었다.
기존 설정대로 하려면 그냥 ec2에 postgres 를 띄우고 유저명, 비밀번호만 맞춰주면 그만이었다.
하지만 t2.micro 라는 프리티어 인스턴스가 spring boot , react, postgres, redis 등을 한번에 버티기엔 부담이 클거라 생각했고 db 위치를 RDS 로 옮기기로 생각했다.
정석대로라면 db dump를 떠서 dump 뜬 db 를 rds 에 importing 해야한다.
안그러면 데이터가 없자네..
하지만 죄다 더미데이터일 뿐더러 클라우드에 올리는 db 는 release용 db 로 쓸 것이기에 이 참에 새로 만들기로 했다.
순서,
2-1. rds 생성
생성하는건 어렵지 않지만 주의점이 몇가지 있다.
2-1-1.엔진 옵션
aurora 쓰면 내 지갑은 반드시 죽는다.
2-1-2. 템플릿
default 가 프로덕션으로 되어있으니 반드시 프리티어로 변경해줘야한다.
2-1-3. 연결
컴퓨팅 리소스에서 EC2 컴퓨팅 리소스에 연결
이걸 해버리게 되면 EC2 내에서만 rds 에 접근 가능하도록 되어버려서 intellij 같은 곳에서 연결 할 수 없게 되어버린다.
실제 release db 라면 이렇게하는게 보안적으로 매우 좋겠지만, testDB 가 따로 없는 이 시점에는 애매하긴 하다..
실제 product 라면 vpc 안에서 ec2 - rds 간에 연결만을 뚫어놓고 외부를 차단해서 안전하게 사용하겠지만 지금은 스터디 단계이기에 굳이 그렇게까진 하지 않으려고 ec2 연결 안했으며 퍼블릭 액세스를 열어두었다.
2-1-4. 추가 구성
반드시 반드시 반드시 추가 구성 탭에서 초기 데이터베이스 이름을 지정해주어야한다.
안그러면 cli 로 rds에 접속하여 초기 db 이름을 만들어 주어야만 intellij든 어디든 연결할 수 있다.
이렇게하면 다 생성 되는데 마지막 하나 더 수정해야한다.
2-1-5. 파라미터그룹
파라미터 그룹을 postgres 버전에 맞춰서 생성하고 timezone 을 검색하여 UTC+9로 변경해줘야만 우리나라와 시간이 맞아진다.
안그러면 tuple 생성 시 db의 timezone 을 가져다 쓰는 경우나 jpa 에서 now를 사용하는 경우 db 의 시간을 기준으로 해버리기에 UTC 기준으로 잡혀버린다.
이렇게 까지하면 전부 생성 완료 된다.
application.yml 을 변경해주고 다 시 bootjar 를 통해서 jar 파일을 만들고 실행시켜봤다.
잘 연결이 되었다.
3. redis 연결
아아... 레디스는 연결이 안되도 컴파일 단계에서 문제가 생기지 않는다..
그로인해 놓쳤던 redis 연결!
redis 는 ec2 내부에 docker 로 띄우려고 한다.
3-1. docker 설치
sudo yum install docker -y
설치 완료
docker 서비스를 띄워줘야한다.
sudo service docker start
sudo usermod -aG docker ec2-user (sudo로 service 를 띄웠기에 ec2-user에서 사용 시 permission denied가 뜬다)
다 했으면 ec2 재접속 한다.
docker 로 아무 명령어 쳤을 때 permission denied 안뜨면 된다.
docker pull redis:latest
이미지 파일을 받아준다.
아래 명령어를 통해서 이미지를 컨테이너로 올린다.
docker run [옵션] 이미지명[:태그명][인수]
// docker run -d -p 6379:6379 redis:latest
아래 명령어를 통해서 컨테이너 잘 올라갔는지 본다
docker ps
아래 명령어를 통해서 컨테이너에 접속한다.
docker exec -it [컨테이너ID] /bin/bash
아래 명령어를 통해서 redis-cli를 들어가는 겸 잘 돌아가는지 본다.
redis-cli
info
다 잘 올라갔다,
테스트
배포 끄읕
나도 spring boot 배포 할 수 있다!