프로젝트aws셋업

프론트+백엔드 프로젝트 aws로 서비스하기

1. 프로젝트 소개

학원 운영을 하며 여러가지 관리할것들이 쌓이다보니, 상당히 복잡해져 웹서비스로 준비하게 되었다.

프론트엔드: DevExtreme 리액트 라이브러리

개인은 무료다.
DataGrid, Shceduler, 기본 template으로 다 했다.
jsp mvc에서는 화면을 전적으로 백엔드에서 통제를 하지만, 리액트에서는 별개로 돌아가기 때문에 강제로 로그인 이후 화면으로 진입한다면 리소스 제한만 했다.
Doc를 보면서 화면을 제작하다보니 가장 많은 시간이 들어갔고, 컴포넌트 안에 컴포넌트를 반복해서 집어넣다보니 상태관리나 변수 조절이 까다로웠다.

백엔드: 스프링부트

JPA로 여러 엔티티를 모조리 관계를 맺었다.
useYn 과 레코드 삭제(cascade)까지 사용했다. cascade 설정 시 customId를 사용하면 생성시기가 늦어 삭제가 안되므로 cascade적용 엔티티는 기본 id생성규칙을 따랐다.
RDS로 설정했다가 비용이 많이나와서 ec2에 직접 mysql8을 설치해서 사용하는것으로 변경했다. 로컬 개발환경의 mysql과 ec2 의 것을 일치시키면 편하다.
스프링 시큐리티 로그인(jwt)을 적용했다.

2. aws으로

인스턴스 설정

처음 ami 고를 때 amazon linux 2023으로 했더니 mysql8설치가 귀찮아졌다. 빠르게 인스턴스 세팅을 다시 amazon linux 2로 하다가 인스턴스 유형을 x86 t2.micro에서 arm t4g.micro로 변경했다. 이유는 속도는 비슷하고 조금 더 싸다.
온디맨드 시간당 t2.micro : 0.0116USD, t4g.micro : 0.0084USD
프리티어는 날아가서 없다.

보안그룹

처음에 인스턴스 생성 시 보안그룹을 만들거나 기존것을 고른다.
인바운드: http로 들어오니 80포트 모두에게
쉘로 붙어야 하니 22포트 내 ip만
로컬에서 DB 넣어야 하니 3306포트 내 ip만, 아웃바운드는 다 허용

자바 설치

1
sudo yum list *java* 

검색해서 원하는 것으로 설치한다.
나는 java-17-amazon-corretto-headless.aarch64
으로 설치했다.

1
2
3
4
5
java -version

openjdk version "17.0.7" 2023-04-18 LTS
OpenJDK Runtime Environment Corretto-17.0.7.7.1 (build 17.0.7+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.7.7.1 (build 17.0.7+7-LTS, mixed mode, sharing)

잘 나오니 환경변수 설정은 패스한다.

nginx 설치

인스턴스로 http를 타고 들어오면 80포트로 들어온다.
리액트를 빌드해서 스프링부트에 넣고 다시 war로 감싸서 8080포트로 들어가야 하므로 리버스 프록시 설정을 해줄 nginx를 설치한다.

1
2
sudo yum install nginx
sudo vi /etc/nginx/nginx.conf

80포트를 8080으로 물려주는 세팅을 한다. (###안 부분)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
################################################
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For proxy_add_x_forwarded_for;
################################################
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

대개는 location 안쪽만 수정을 하면된다.

1
2
sudo systemctl start nginx
sudo systemctl enable nginx

시작하고 시작프로그램으로 등록한다.

mysql8 설치 (amazon linux 2)

amazon linux 2023은 잘 안됐다. 그래서 인스턴트 다시 생성

1
sudo amazon-linux-extras install epel -y

epel repo 설치

1
sudo yum install https://repo.mysql.com/mysql80-community-release-el7-5.noarch.rpm

MySql Community Repo 설치(최신버전있는데 이걸로하는게 설치 잘됌)

1
2
sudo yum install mysql-community-server
sudo yum install mysql-community-client

둘째줄은 이미 설치됐다고 나왔다.
출처: https://blog.mevi.tech/install-mysql-8-client-on-amazon-linux-2-arm-and-x86_64/

1
sudo systemctl start mysqld@

mysql을 실행한다.

1
mysql -u root -p

mysql8은 초기비밀번호가 있단다. 찾으러간다.

1
2
3
sudo cat /var/log/mysqld.log

2023-06-30T04:13:52.839282Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: 13KI1ddFdJ-(

비밀번호는 13KI1ddFdJ-( 이다.

다시 mysql 에 로그인해서 root 계정 비밀번호를 바꾼다.

1
ALTER USER 'root'@'localhost' IDENTIFIED BY '새비번';

프로젝트에 쓸 DB를 만든다.

1
CREATE DATABASE ssbDB;

프로젝트용 계정을 만들고 권한을 부여한다.

1
2
CREATE USER '아이디'@'접속위치(ip)' IDENTIFIED BY '비번';
GRANT ALL PRIVILEGES ON ssbDB.* TO '아이디'@'접속위치(ip)';

프로젝트에서 테스트하니 Public Key Retrieval is not allowed 발생.

방법1. url 에 allowPublicKeyRetrieval=true 붙이기

방법2. 사용자 인증 플러그인 native_password로 바꾸기

1
ALTER USER 'User'@'%' IDENTIFIED WITH mysql_native_password BY '비번';

나는 방법 2로 했다.

젠킨스 설치(패스)

젠킨스 설치는 다른데도 많으니 생략한다.
리액트를 eirslett 라이브러리를 써서 프로젝트 빌드시
리액트빌드-> resources/static으로 파일 이동 -> 스프링부트 빌드 -> target에 war 생성 순으로 설정했다.
그러나 리액트 빌드 도중 메모리 부족으로 실패.

package.json에서 빌드 명령어 수정

1
"build": "set NODE_OPTIONS=--max_old_space_size=4096&&set GENERATE_SOURCEMAP=false&&react-scripts build",

스왑 메모리 설정

1
2
3
4
5
6
7
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo swapon --show
sudo nano /etc/fstab
/swapfile none swap sw 0 0

결과: 계속 실패(돈많으면 가능…)

젠킨스 사용 보류

war 시작 파일 만들기(옵션)

파일 위치는 변경 후 사용해야한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/bin/bash

# WAR 파일 경로
WAR_FILE="./dscheduler-0.0.1-SNAPSHOT.war"

# 포트 설정
PORT=8080

# Java 실행 명령어
JAVA_CMD="java"

# JVM 옵션
JAVA_OPTS="-Xmx512m -Xms256m"

# 로그 폴더 경로
LOG_FOLDER="./logs"

# 백그라운드에서 WAR 파일 실행
start() {
echo "Starting the application..."
LOG_FILE="$LOG_FOLDER/ssbScheduler-$(date +'%Y-%m-%d').log"
nohup $JAVA_CMD $JAVA_OPTS -jar $WAR_FILE --server.port=$PORT > "$LOG_FILE" 2>&1 &
echo "Application started. Logs are being saved to: $LOG_FILE"
}

# 실행 중인 프로세스 종료
stop() {
echo "Stopping the application..."
PID=$(pgrep -f $WAR_FILE)
if [ -n "$PID" ]; then
kill $PID
echo "Application stopped."
else
echo "Application is not running."
fi
}

# 명령어 파라미터에 따라 실행
case $1 in
start)
start
;;
stop)
stop
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
;;
esac

탄력적 IP 설정 및 연결

ec2 > 탄력적IP -> 주소할당-> 주소연결(인스턴스로)

이렇게 인스턴스 세팅은 끝이다. 다음은 aws 세팅이다.

aws 설정

도메인(route53)

aws 콘솔>Route53>등록된 도메인>도메인 등록
도메인 골라서 결제(꽤비쌈)
route53에서 도메인을 구매했더니 대기중인 요청에 한 10분정도 있다가 호스팅영역에 자동으로 추가되고 네임서버도 자동으로 등록이 되어있었다.

호스팅영역에서 ip를 연결한다. https인증서를 쓸려면 로드밸런서를 연결한다.
나는 1인 유저기때문에 바로 ip에 연결했다.

호스팅영역->레코드 생성. 아래와 같이 작성

레코드 이름: 원하는 이름
레코드 유형: A
값: 연결할 ip 입력.
TTL: 300
라우팅 정책: 지리적위치(한국에서만)
위치: 한국
레코드ID: 내맘대로

RDS(적용취소)

db.t3.small 싱글 인스턴스 가격 0.063USD/h 이 나와서 인스턴스 내 db를 설치해서 사용하기로 노선변경
가장 싼 db.t4g.micro 를 사용하면 0.025USD/h 한달에 3만원가량
-> 이건 무려 프리티어지만 나는 프리하지 않다..
그 외 저장 비용등은 낮아서 생략한다.

SPOT인스턴스(적용취소)

RDS -> 로컬DB 사용으로 패스
RDS를 사용한다면 SPOT으로 변경하고 때때로 서비스 불량이 있을 수 있지만
가격이 낮아져 t4g.small을 사용할수도 있을 것 같다.
그러면 메모리가 2기가로 높아지고 속도가 올라가 리액트 빌드가 가능해지고
젠킨스를 사용할 수 있게 될것으로 예상
비용은 4만원/월 정도 예상

접속 순서 정리:
브라우저에서 설정한 도메인 입력
탄력ip로 연결
인스턴스 보안그룹 통과
nginx가 8080으로 연결
스프링부트에서 로컬 db 접근
스프링부트 내 index.html 으로 안내