Search
🛫

배포 시스템 구축(feat. AWS, SpringBoot, React)

1. 서버 설정

가. EC2 생성 시 참고사항

서버 환경: AWS Ubuntu 20.04, Intel CPU
1) EC2 instance 생성 시 참고
Storage의 경우 프리티어 사용자에게 30GB까지 무료로 제공
보안그룹 설정 시, HTTP & HTTPS에 대한 인바운드 정책을 모든 사용자에게 허용 권장
: SSH의 경우, 내 PC의 IP에 대해서만 허용 권장
2) Elastic IP 등록 필요
고정 IP 활용 위해 Elastic IP 할당 받아서 EC2 인스턴스와 연결
Elastic IP는 사용하면 과금 X, 사용하지 않고 방치하면 과금
3) SSH로 EC2 Instacne 접속
ssh key 파일에 대한 접근권한 변경하고 접속
‘EC2/인스턴스/인스턴스에 연결’ 참고할 것
인스턴스 생성 시 기존 보안 그룹 선택 시 SSH 연결이 안될 수 있음
: 포트 및 일부 방화벽 정책에 닫혀 있임
: 새로운 보안 그룹 생성 권장

나. Java & Git & MySQL 설치

1) Ubuntu 패키지 업그레이드 및 한글 설정
패키지 업데이트 & 업그레드
sudo apt update sudo apt upgrade
Bash
복사
locale 설정
sudo apt install language-pack-ko sudo locale-gen ko_KR.UTF-8 sudo update-locale LANG=ko_KR.UTF-8 LC_MESSAGES=POSIX
Bash
복사
재부팅 후 로케일 확인
$ locale LANG=ko_KR.UTF-8 LANGUAGE= LC_CTYPE="ko_KR.UTF-8" LC_NUMERIC="ko_KR.UTF-8" LC_TIME="ko_KR.UTF-8" LC_COLLATE="ko_KR.UTF-8" LC_MONETARY="ko_KR.UTF-8" LC_MESSAGES=POSIX ...
Bash
복사
2) Java 설치
Ubuntu Linux 기준 아래와 같이 설치
: Java Version에 따라 JDK 설치
ex) sudo apt-get install openjdk-8-jdk
sudo apt-get install openjdk-17-jdk
정상 설치 확인(java version 확인)
: java -version
3) Git 설치 및 Clone
패키지 리스트 업데이트
: sudo apt-get install git
Git 설치
: sudo apt install git
Git 정상 설치 확인(버전 확인)
: git --version
레파지토리 Clone
ex) git clone https://githhttps://github.com/skawnkk/sidedish
4) MySQL 설치 및 설정
MySQL 설치
sudo apt install mysql-server sudo mysql
Bash
복사
: local pwd: mysql123456
하나의 서버에 WAS와 DB가 동시에 존재하는 경우 설정
: 사용자 생성 및 권한 부여
CREATE USER 'difs'@'localhost' IDENTIFIED BY 'p#jJIL3432as491!#$'; GRANT ALL PRIVILEGES ON `ocp`.* TO 'difs'@'localhost'; flush privileges;
SQL
복사
CREATE USER 'ocp'@'localhost' IDENTIFIED BY '1234qwer'; GRANT ALL PRIVILEGES ON `image-platform`.* TO 'ocp'@'localhost'; flush privileges;
SQL
복사
: 스키마(또는 데이터베이스) 생성
CREATE SCHEMA `image-platform`; quit
SQL
복사
WAS, DB 서버가 분리되어 있는 경우 설정
: 데이베이스 생성
CREATE SCHEMA `growth_analysis`;
SQL
복사
: 사용자 생성 및 권한 부여
CREATE USER 'airbnb'@'%' IDENTIFIED BY 'MySqlppqweas4565987!#$'; GRANT ALL PRIVILEGES ON airbnb_db.* TO 'airbnb'@'%'; flush privileges; quit
SQL
복사

2. API 배포

배포환경: AWS Ubuntu 20.04

가. 빌드파일 전송(로컬 → 서버)

1) 로컬에서 .jar 파일 생성
Gralde - build - bootJar
.jar 파일 생성 확인
2) scp 활용해서 서버로 .jar 파일 전송
.jar 파일이 위치한 경로에서 터미널 열기
: intelliJ에 내장된 터미널로 접근하면 Operation not permitted 로그 발생하고 접속이 안됨
: 접근권한이 없기 때문임
: .jar 파일 위치에서 터미널 창을 열어서 접근하면 정상 동작
ssh 접속 확인
: ssh -i [pem 파일 경로] [ec2 계정명]@[ec2 intance의 pulbic IP or DNS]
ssh -i "/Users/mj/Documents/ssh-keys/code_squard.pem" ubuntu@ec2-15-164-68-136.ap-northeast-2.compute.amazonaws.com
Bash
복사
scp로 파일 전송
: scp -i [pem 파일 경로] [.jar파일] [ec2 계정명]@[ec2 intance의 pulbic IP or DNS]:[경로]
: .jar 파일이 위치한 경로에서 scp 명령이 내려지므로 .jar 파일의 이름만 추가하면 됨
: 마지막에 :~ 추가, 추가 안하면 로컬의 .jar 파일과 같은 폴더에 생성됨
scp -i "/Users/mj/Documents/ssh-keys/code_squard.pem" "side-dish-0.0.6-SNAPSHOT.jar" ubuntu@ec2-15-164-68-136.ap-northeast-2.compute.amazonaws.com:~
Bash
복사
scp -i "/Users/mj/Documents/keys/child-growth.pem" "childGrowth-0.0.1-SNAPSHOT.jar" ubuntu@ec2-3-37-248-174.ap-northeast-2.compute.amazonaws.com:~
Shell
복사
참고)
.pem 경로 복사
: finder에서 경로 이름 복사 기능 활용
: Reference 참고
.jar 파일 이름 복사
: intelliJ copy path 기능 활용

나. 빌드파일 실행

1) 서버에서 .jar 파일 실행
데몬 백그라운드 없이 실행
: java -jar [.jar 파일]
: java -jar backend-0.0.1-SNAPSHOT.jar
데몬의 형태로 실행
: 데몬이란 사용자가 직접 제어하지 않는 상태에서 작동되는 프로그램
: nohup java -jar [.jar 파일]
: nohup java -jar backend-0.0.1-SNAPSHOT.jar
데몬 + 백그라운드 형태로 실행
: nohup → java -jar [.jar 파일] &
: nohup java -jar backend-0.0.1-SNAPSHOT.jar &
프로세스 종료
프로세스 아이디 알아내기
: ps -ef | grep [빌드 파일]
프로세스 종료 : kill -9 <프로세스 아이디>
포트번호 8080 트래픽 허용
: 웹서버 설정 하지 않았다면 8080포트 트래픽을 인바운드에서 허용하도록 네트워크 설정 필요
2) 서버에서 직접 jar 파일 생성해서 실행
프리티어의 1GB RAM으로는 빌드가 어려움
: 프리티어 환경에서는 직접 jar 파일 생성(빌드)를 권장하지 않음
Gradle 빌드
: ./gradlew build jar
스프링부트 실행
: ./gradlew bootrun

다. 프록시 서버 설정

프록시 서버 사용 목적: 모든 인바운드 트래픽을 80포트의 웹서버를 거침으로써 사용자의 WAS에 직접 접근 방지
1) Nginx 설치
설치
sudo apt-get install nginx -y
Bash
복사
사용
: sudo service nginx start 후에 public ip로 접속 했을 때, Nginx welcome 페이지 확인
: 또는 프로세스 확인해서 실행상태 확인
ps -ef|grep nginx
Nginx 기타 명령
sudo service nginx start sudo service nginx stop sudo service nginx restart
Bash
복사
2) Nginx.conf 수정
기존 설정 파일 제거
sudo rm /etc/nginx/sites-available/default sudo rm /etc/nginx/sites-enabled/default
Bash
복사
'/etc/nginx/sites-available' 경로(Ubuntu의 경우)에 설정파일(**.conf) 생성 및 이하 설정 작업
참고) amazone Linux의 경우 nginx 설정파일의 위치가 '/etc/nginx/nginx.conf' 경로에 있음
8080포트로 들어오는 트래픽을 Nginx에서 80포트로 리다이렉트
: 설정파일 이름은 proxy.conf(예시)로 지정하여 이하 설정 작업 진행
cd /etc/nginx/sites-available sudo vim proxy.conf
Bash
복사
proxy.conf 파일에 이하 설정값 입력
: 80포트로 Nginx 에 요청이 오면 http://localhost:8080/ 경로로 해당 트래픽 전달
: X-Real-IP 에 요청자의 IP 저장
server { listen 80; location / { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } }
Bash
복사
심볼릭 링크 생성
: 웹서버 동작 시 sites-enabled의 설정파일 참조
sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf
Bash
복사
nginx server 재시작
sudo service nginx restart
Bash
복사
3) Web Socket proxy 설정
'/ws' 경로로 들어오는 트래픽에 대한 트래픽 처리
WS은 프로토콜 상 http와 완전히 다르지만 동작 시 http로부터 유도됨
location / { // 생략 } location /ws/ { proxy_pass http://localhost:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; }
Bash
복사

3. React 배포

배포환경: AWS Ubuntu 20.04 + Yarn

가. 주요 프로그램 설치

1) Node, NPM, Yarn 설치
sudo apt-get install nodejs -y sudo apt-get install npm -y sudo npm install -g yarn
Bash
복사
2) Git Clone
git clone -b FE-dev --single-branch https://github.com/JUNGYUN-Daegu/issue-tracker
Bash
복사
3) NPM Module 설치
node_modules의 경우 매우 크기 때문에 버전관리하지 않음
: 서버에서 관련 파일을 다운로드해야 함
위의 명령으로 package의 종속성을 확인하고 설치하는 작업
: 이하 명령은 package.json 파일이 있는 경로에서 실행해야 함
: npm의 경우 npm install
yarn install
Bash
복사
만약 node_modles가 이미 있는데 부분만 다운된 경우, 기존 파일 삭제 후 재설치
: rm -rf node_modules
: yarn install
4) Nginx 설치 및 사용
설치
sudo apt-get install nginx -y
Bash
복사
사용
: nginx start 후에 public ip로 접속 했을 때, Nginx welcome 페이지 확인
: 또는 프로세스 확인해서 실행상태 확인
ps -ef|grep nginx
sudo service nginx start sudo service nginx stop sudo service nginx restart
Bash
복사

나. 빌드파일 생성 및 실행

1) 빌드파일 생성
build 파일 생성
: npm의 경우 npm run build
yarn build
Bash
복사
2) Nginx 설정
Nginx 설정 파일 삭제
: 개인 설정과 겹칠 수 있으므로 에러 예방차원에서 기본 설정값 제거
sudo rm /etc/nginx/sites-available/default sudo rm /etc/nginx/sites-enabled/default
Bash
복사
Nginx 설정 파일 생성
cd /etc/nginx/sites-available sudo vim proxy.conf
Bash
복사
설정값 입력
: listen 인바운드 포트 설정
: root 실행파일(빌드파일) 위치
: index 인덱스 파일 지정
server { listen 80; location / { root /home/ubuntu/airbnb_fe/build; index index.html index.htm; try_files $uri $uri/ /index.html; } }
Bash
복사
API와 함께 Nginx에 빌드파일을 적용하는 경우
: react app의 빌드 파일의 경로를 root 이하에 설정
server { listen 80; location / { root /home/ubuntu/issue-tracker-fe/issue-tracker/build; index index.html index.htm; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; } }
Java
복사
심볼릭 링크 생성
: 웹서버 동작 시 sites-enabled의 설정파일 참조
: 심볼릭 링크: 일종의 바로가기
sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf
Bash
복사
3) Nginx 재시작
sudo systemctl stop nginx sudo systemctl start nginx
Bash
복사

다. 빌드파일 갱신

1) 빌드파일 생성
node_modules 추가 생성
yarn install
Bash
복사
빌드파일 생성
yarn build
Bash
복사
2) Nginx 재시작
nginx server 재시작
→ 설정 정보 반영
sudo service nginx restart
Bash
복사

4. 배포 스크립트

가. 스크립트 파일 설정

1) 권한부여
chmod 755 [script 파일]
chmod 755 re_start_build.sh
2) 실행
sudo ./[script 파일]
sudo ./re_start_build.sh

나. 스크립트 기본

1) 프로세스 중단 및 재실행
echo ">start rerun" PID=$(pgrep java) echo "> check Process ID: $PID" echo "> kill Process" kill -9 $PID echo "> rerun Process" nohup java -jar baseballGameApi-0.0.1-SNAPSHOT.jar &
Bash
복사
2) 빌드 및 빌드파일 복사
#!/bin/bash ./gradlew build aws s3 cp build/libs/issue-tracker-0.0.1-SNAPSHOT.jar s3://issue-tracker-storage
Bash
복사

다. S3 CLI 활용

1) 로컬에 AWS CLI 설치 및 설정
AWS CLI 설치
: unzip이 미설치 시, sudo apt install unzip
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install
Bash
복사
AWS 설정
: aws configure
: AWS IAM의 AWS CLI 부분 참고
2) 로컬의 빌드 파일을 S3로 복사
aws s3 cp <builded_file> s3://honuxkq
3) WAS에 AWS CLI 설치 및 설정
aws s3 cp s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar ./
4) S3의 빌드 파일을 WAS로 복사

라. SLACK BOT 활용

1) 슬랙 알람
curl -X POST --data-urlencode "payload={\"text\": \"msg\"}" https://hooks.slack.com/services/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
2) 슬랙 알람 활용 스크립트
#!/bin/bash IP=`curl -s 169.254.169.254/latest/meta-data/public-ipv4` START="배포 시작" END="배포 완료\n 배포주소: http:/$IP" SLACK_CHANNEL="https://hooks.slack.com/services/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" # real deploy script CK=`aws s3 ls s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar` if [ -z $CK ]; then echo "no need to build" exit 0 fi curl -X POST --data-urlencode "payload={\"text\": \"$START\",\"username\": \"deploy-bot\", \"icon_emoji\": \":ghost:\"}" $SLACK_CHANNEL fuser -k 8080/tcp aws s3 cp s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar ./ nohup java -jar issue-tracker-0.0.1-SNAPSHOT.jar & aws s3 rm s3://issue-tracker-storage/issue-tracker-0.0.1-SNAPSHOT.jar curl -X POST --data-urlencode "payload={\"text\": \"$END\",\"username\": \"deploy-bot\", \"icon_emoji\": \":ghost:\"}" $SLACK_CHANNEL
Bash
복사

5. 이슈 정리

가. ssh 접속 이슈

현상: ssh 접속 시도에 따라 아래와 같은 에러 발생
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ 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. The fingerprint for the ECDSA key sent by the remote host is SHA256:526T1ds6Jf7m3RiIzH4yts0w8q7B86D77O7fuen/Keo. Please contact your system administrator. Add correct host key in /Users/mj/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /Users/mj/.ssh/known_hosts:4 ECDSA host key for ec2-13-209-102-10.ap-northeast-2.compute.amazonaws.com has changed and you have requested strict checking. Host key verification failed.
JSON
복사
원인
: Elastic IP 서비스를 이용해서 여러 인스턴스를 바꿔가며 같은 고정 IP로 연결을 시도함
: 같은 고정 IP에 대해 여러 host가 ssh 접속을 함에 따라 에러 발생
해결
1) 기존 Elastic IP 주소(여러 인스턴스에 연결했던)를 릴리즈하고 새로운 Elastic IP를 할당 받아서 연결함
2) .ssh 파일 내 known_hosts 파일 내 관련 정보 삭제. 대게 최신(맨 아래) host 정보(ip - hash 쌍) 제거 후 해결
cd ~ cd .ssh vim known_hosts
Bash
복사

나. EC2 메모리 부족에 따른 빌드 실패 1

현상: Creating an Opcreating an optimized production build... stuck
원인: ec2 인스턴스의 메모리 부족(RAM 1G)
시도한 방법
1) 기존에 동작 중인 프로세스 중단(API, Nginx 등)
2) frontend 폴더 삭제(rm -rf forntend) 후 원격 저장소에서 다시 클론
3) 1, 2 번 시도 후 인스턴스 재부팅
4) GENERATE_SOURCEMAP 옵션 제거
해결
: 4번째 방법 시도 후 성공
: 관련 링크는 Reference에서 참고

다. EC2 메모리 부족에 따른 빌드 실패 2

현상: 동일
원인: 동일
해결
: 로컬 PC에서 빌드 완료 후 빌드된 파일을 원격 서버로 전송
: 빌드폴더를 압축 후, 압축된 파일을 원격 서버로 전송
: scp -i /Users/mj/Documents/ssh-keys/airbnb_key.pem issue-tracker-fe.zip ubuntu@15.164.68.136:~/issue-tracker-fe
참고 scp -r 옵션으로 디렉토리를 전송할 수 있지만 일반적으로 build 폴더 크기로 인하여 lost connection 에러 발생
: 로컬 PC에서 zip 명령으로 압축 후 원격 서버에서 unzip으로 압축해제하여 사용
: zip 명령 사용 시, test 디렉토리 이하 모든 파일 압축: zip -r test.zip test

라. EC2 메모리 부족에 따른 인스턴스 중지

현상: 평상시에는 CPU 사용률이 13%이지만 갑자기 과부화 현상이 발생함
→ EC2 모니터링 데이터 참고
원인 가능성
1) 메모리 부족에 따른 CPU 과부하
2) 외부에서 해당 CPU 무단 사용 가능
3) EC2 하드웨어 이슈
해결방안
1) SWAP 메모리 설정 또는 수직확장
2) 보안그룹의 인바운드 규칙을 작업공간의 IP에 SSH 연결만 허용
3) 인스턴스 교체
해결
: 평상시 메모리 사용률이 88%에 달하기 때문에 남는 디스크의 일부를 swap으로 설정
# swap 설정 전 메모리 사용률 확인 ~$ free -h total used free shared buff/cache available Mem: 966Mi 557Mi 70Mi 0.0Ki 337Mi 257Mi Swap: 0B 0B 0B # disk 내 2GB를 활용하여 빈 파일 생성 ~$ sudo dd if=/dev/zero of=/root/swapfile bs=1k count=2000000 conv=excl 2000000+0 records in 2000000+0 records out 2048000000 bytes (2.0 GB, 1.9 GiB) copied, 29.9611 s, 68.4 MB/s # swapfile로 사용하기 위한 권한설정 ~$ sudo chmod 600 /root/swapfile ubuntu@ip-172-31-44-138:~$ free -h total used free shared buff/cache available Mem: 966Mi 548Mi 79Mi 0.0Ki 337Mi 260Mi Swap: 0B 0B 0B # swapfile로 지정 ~$ sudo mkswap /root/swapfile Setting up swapspace version 1, size = 1.9 GiB (2047995904 bytes) no label, UUID=3e951b0d-5c38-4242-94dd-687103498d59 # swapfile 실행 ~$ sudo swapon /root/swapfile # swap 동작 확인 ubuntu@ip-172-31-44-138:~$ free -h total used free shared buff/cache available Mem: 966Mi 550Mi 62Mi 0.0Ki 352Mi 261Mi Swap: 1.9Gi 0B 1.9Gi
Shell
복사
결과: 컴퓨팅 자원의 안정화
: 메모리 사용률 감소(88% → 59%)
: CPU 사용률 감소(13% → 4%)

마. EC2 내 DB Server 접근 이슈

현상: 로컬 DB Client에서 EC2 내 DB Server에 접근 이슈 발생
해결: MySQL Workbench로 SSH 베이스로 접근

Reference

서버/API 배포
mac local 환경에 mysql server 설치, https://daimhada.tistory.com/121
finder에서 경로 위치 복사, https://androphil.tistory.com/728?category=640236
nohup & background, https://joonyon.tistory.com/98
Web Socket 프록시 서버 설정, https://www.joinc.co.kr/w/man/12/Nginx/wsproxy
API 배포 중 DB 설정(WAS, DB 서버 분리 시), https://nickjoit.tistory.com/144
React 배포
에러
메모리 부족 현상 해결, https://progdev.tistory.com/26