[AWS] vue + nginx + spring boot를 EC2 인스턴스에 배포하기

sangwoo·2024년 2월 7일
0

AWS

목록 보기
3/4

들어가기 전...

정말 간단한 프로젝트를 개발했는데 경험 삼아 배포까지 진행하기로 결정했다. 프론트 엔드는 vue를 사용했고, 백엔드는 spring boot를 사용했다.

vue를 배포하는 방법을 알아보니 여러가지 방법이 있는 듯 했다.

  1. github pages, s3를 통한 웹 호스팅
  2. nginx 웹 서버를 통해 실행하기

내가 알아본 방법 중 두가지가 대표적인거 같다? 아닐 수도 있음....

그래서 한참을 고민한 결과 아래와 같이 배포 하기로 결정했다.

  • 하나의 EC2 인스턴스에 vue와 spring boot를 배포한다.
  • nginx로 vue를 띄우고, proxy? 기능을 통해 spring boot의 API를 호출한다.

이제 천천히 배포를 진행 해 보자.

아래에 나오는 CLI는 WSL위에서 Ubuntu를 사용했다.

vue와 spring boot 코드 수정 하기

1) spring boot의 CORS 부분 수정하기

기존에 스프링 부트에서 vue 요청 시 발생하는 CORS를 해결하기 위해 개발 시 사용하는 포트 번호를 허락해주었다. 이제 vue를 ec2에서 실행하기 때문에 URL을 변경해주어야 한다.

이때, ec2의 퍼블릭 도메인:80 포트를 선택해준다. 왜냐? nginx의 기본 포트는 80 포트이다. 80포트는 생략 가능하다.

2) vue의 proxy, axios 부분 수정

  1. vite.config.js의 server 부분을 수정한다. 원래 target이 http:localhost:8080 이었다.

  2. axios의 디폴트 URL을 수정해주자.

EC2 인스턴스의 포트번호 열어주기

spring boot의 포트 번호를 열어주기로 하자. 8080 포트를 사용한다.

aws 콘솔에 로그인한다. -> ec2 서비스로 이동 -> 왼쪽 사이드바에서 인스턴스 클릭 -> 현재 실행중인 인스턴스를 선택하고 해당 인스턴스 창으로 이동 -> 보안 탭에서 보안 그룹 클릭

인바운드 규칙 편집 버튼을 클릭한다.

8080 포트를 열어주자. 근데 이렇게 하면 모든 IP에서 스프링 부트를 접근할 수 있는데 이게 맞는지 고민이 든다. 그래서 해당 포트를 열지 않고 CORS만 설정했을 때는 요청이 들어가지 않아서 일단 해당 포트 번호를 열어 주었다.

그래서 생각한 것이 포트번호는 접근가능하게 열어주고, 스프링 부트의 CORS를 통해 접근 IP를 제한해야 하는 건가? 라고 생각 중이다. 조금 더 알아봐야 겠다.

1. Spring Boot Build 하기

우선 배포를 하기 위해선 프론트, 백엔드 각각의 build 파일이 필요하다. Spring boot 부터 Build 해보기로 하자.

./gradlew build

스프링 부트 프로젝트로 이동해 위의 명령어를 입력하여 프로젝트의 Build 파일을 생성하자. 코드에 이상이 없고 테스트 코드도 모두 통과했다면 정상정으로 Build가 수행될 것이다.

정상적으로 수행되었다면 /build/libs 에 확장자가 .jar인 build 파일이 만들어져 있을 것이다. 이때 -plain.jar 파일도 있을 텐데, plain이 붙지 않은 파일을 실행 하자. 이제 해당 파일을 실행하여 스프링 부트를 띄울 수 있게 되었다.

참고로 .jar 파일을 실행하는 명령어는 아래와 같다.

java -jar {jar 파일 이름.jar}

2. vue Build 하기

다음으로 vue를 build 해보자. vue 프로젝트로 이동하여 아래의 명령어를 입력한다.

npm run build

위의 명령어를 입력하면 프로젝트에 dist라는 폴더가 생성되고 안에 assetsindex.html이 생성되어 있을 것이다.

이 파일들로 vue를 실행할 수 있게 되었다.

3. 인스턴스로 Build 파일들 전송하기

파일 전송 기본

이제 Spring boot build 파일과 vue buil 파일을 EC2 인스턴스로 전송해야 한다. 여기서는 SCP 명령어를 사용해서 데이터를 전송하기로 결정했다.

명령어는 아래와 같다.

scp -i "사용자 키페어" [전송할 파일 이름] [ec2 user]@[ec2 public IP]:[경로]

위의 명령어를 보면 전송할 파일 이름을 입력하고 마지막에 경로를 입력하면 EC2 인스턴스의 해당 위치에 데이터가 전송되어 진다.

이때, 당연히 명령어 실행 위치가 해당 파일이 위치한 곳이라면 경로를 붙일 필요가 없지만 같은 경로 상이 아니라면 파일 경로 까지 작성해주자.

폴더 내부 파일 전송하기

그리고 폴더 내부의 데이터를 모두 전송하고 싶다면 아래의 명령어로 입력하자.

spc -i "사용자 키페어" -r [전송할 폴더 이름] [ec2 user]@[ec2 public IP]

4. EC2 인스턴스 SSH로 접속하기

이제 전송된 Build 파일들을 EC2 인스턴스에서 사용하기 위해 원격으로 접속해보자. SSH를 사용해 접속 할 것이다.

명령어는 아래와 같다.

ssh -i "사용자 키페어" [ec2 user]@[ec2 public IP[

사용자 키페어 입력시 위치에 따라 경로를 붙여주자.

5. EC2 인스턴스 세팅 하기

1) java 설치

sudo yum install java-17-correto

현재 Aws Linux를 사용하고 있다. 위의 명령어를 입력해서 17 버전의 자바를 설치해 주자. 아래 명령어를 입력해서 자바 버전을 확인해주자.

java --version

2) nginx 설치

sudo yum install nginx

위의 명령어를 입력해 nginx 설치를 진행한다.

sudo service nginx start

위 명령어를 입력하고 퍼블릭 IP:80으로 접속하면 welcom 페이지가 나오면 정상적으로 실행된 것이다.

6. spring boot 실행하기

이제 로컬에서 전송한 .jar 파일을 실행하자.

java -jar [jar 파일이름.jar]

터미널이 종료되어도 spring boot 실행하기

만약 터미널이 종료되어도 실행되고 싶게 하고싶다면

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

위의 명령어를 입력해서 실행시켜주자. 실행 중 모든 출력 로그들은 nohup.out에 저장된다고 한다.

7. Nginx 설정하고 실행하기

현재 Nginx는 80포트로 접속하면 기본 페이지를 출력하게 되어 있다. 해당 페이지를 vue 페이지로 변경해보자.

우선 설정 파일을 들어갈건데, 찾아본 바로는 sites-available이라는 폴더가 있다는데 현재 내 상황에서는 존재하지 않았다. 그래서 여러 블로그를 찾아본 결과 etc/nginx/nginx.conf를 수정하는 내용을 찾을 수 있었다.

다른 방법도 있겠지만 nignx.conf파일을 수정해보기로 하자. 아래의 명령어를 입력하자.

sudo vi /etc/nginx/nginx.conf

위 사진에서, listen은 해당 포트로 접속 할 경우를 말한다.
root 파일을 /var/www로 설정해주고 우리가 로컬에서 전송한 dist 파일들을 해당 디렉토리로 전송해주자.

나는 www 디렉토리 구조를 assets, index.html 이렇게 설정하였다. 즉, www 디렉토리에서 ls -l 명령어를 실행하면 assets, index.html 이 출력된다.

그리고 /etc/nginx/nginx.conf.default 파일도 존재하는데 해당 파일을 /etc/nginx/nginx.conf에 incould 해서 사용할 수 있는 듯하다?

그래서 해당 파일의 server 부분도 수정해 주었다. 아래의 명령어를 입력하자.

sudo vi /etc/nginx/nginx.conf.default

root는 /var/www, index는 index.html으로 설정해주자.

이렇게 설정을 마친뒤 nginx를 실행해주자.

sudo service nginx start

위의 과정을 진행한다면 vue와 spring boot의 통신도 정상적으로 수행 될 것이다.

정리

  1. spring boot와 vue 프로젝트에서 설정한 proxy, 요청 URL, CORS url을 수정해주었다.

  2. 8080 포트를 EC2 인스턴스 보안 그룹에서 인바운드 규칙을 편집하여 열어주었다.

  3. vue와 spring boot의 build 파일을 로컬에서 생성하고 ec2 인스턴스 서버로 전송시켰다.

  4. .jar을 실행시키기 위해 java를 설치하고 webserver를 사용하기 위해 nginx를 설치하고 설정을 해주었다.

  5. spring boot를 실행하고, nginx를 실행하여 vue 또한 띄어 서로 통신하게 만들어 주었다.

고민해 볼 것

  1. EC2 인스턴스에서 8080 포트를 여는 것이 올바른 방법인지 고민해 봐야할 것같다.
    8080 포트를 열어 준다면 모든 IP에서 접근이 가능한데 나는 vue의 URL로만 접속하고 싶다. 이렇게 열어줘도 스프링 부트의 CORS를 통해 접근 제한을 걸었기 때문에 괜찮은 걸까?

  2. vue와 spring booot는 같은 서버 내에서 실행되기 때문에 서로 localhost로 통신이 될수 있지 않을까?
    vue는 사용자가 보는 화면 단이기에 URL 도메인이 필요하고 퍼블릭 IP가 필요하지만, spring boot 서버의 rest API는 vue만이 접근 할 수 있도록 했다. 그렇다면 spring boot는 localhost:8080으로 개발 시 설정했던 것처럼 요청할 수 없을까?

  3. nginx의 역할에 대해서 좀 더 알아볼 필요가 있을 것 같다. proxy를 통해 URL을 재설정 해준다는데 확실하게 알 수 있게 공부하자.

  4. 무중단 배포도 공부해보자. 잠깐 알아봤는데 s3와 jenkins? 이라는 것을 통해 무중단 배포도 할수 있다고 한다.

  5. 현재 프로젝트를 수정하면 재 빌드해서 로컬에서 ec2 인스턴스 서버로 직접 전송해주는 상황인데 로컬에서 프로젝트 수정 후 main 브랜치에 push 후 ec2 인스턴스에서 해당 프로젝트를 clone 하여 ec2 인스턴스에서 빌드하도록 하는 방법을 생각중이다.

  6. 5번 처럼 git을 통해 빌드를 업데이트 한다면, 운영 브랜치와 개발 브랜치를 나누어야 할것 같다. 가끔 가다 블로그들을 보면 운영와 개발을 분리해야한다는게 이런 뜻일까?, 로컬 서버 URL들은 운영 URL와 다르고 이것 저것 세팅이 달라지다 보니 개발용으로 브랜치를 파는 것이 좋다고 생각이 들었다.

  7. https를 적용하자 ssl 인증서를 통해 보안성을 높이도록 해보자. vue url와 spring boot url 둘다 설정을 해주어야 하는 건지 고민이 필요할 것 같다. ssl 개념도 정리해 둘 필요가 있다.

0개의 댓글