이번 포스팅에서는 가장 대중적인 클라우드인 AWS EC2에 가장 대중적인 웹 프레임워크 조합인 스프링 부트 + 리액트 개발환경 구축하는 법을 다뤄보겠다.
➕
AWS 세팅
인스턴스 생성하기
aws의 ec2 대시보드에 들어가 인스턴스 시작 버튼을 눌러준다.
인스턴스 이름을 작성하고,
OS 이미지로는 ubuntu 22.04 LTS를 선택해준다. (용도에 따라 이미지를 선택하면 된다.)
인스턴스 유형을 선택해준다.
비교적 최근에 나온 유형이 저렴하므로, t3 micro 버전을 선택해주었다.
프리티어를 사용할 경우 t2.micro를 선택해주어야 과금요소가 추가되지 않는다.
키페어를 생성해준다.
키페어는 후에 EC2 인스턴스에 원격으로 접속하기 위해 필수적으로 필요하고, 한 번 생성하면
다시는 다운할 수 없으므로 잘 저장해두자.
혹시 이를 분실했다면 걱정말고 다음 글을 참고하자.
2023.07.21 - [🛠️TOOL/🔶AWS] - [AWS] - pem 파일 없이 EC2 인스턴스 SSH로접속하기
보안 그룹은 방화벽에 관한 내용으로, 추후에 따로 생성해서 세팅해줄 예정이니 넘어가고 기존에 보안 그룹을
생성해두었다면 그대로 사용해도 된다.
SSH 접속을 위해 허용을 체크한다.
스토리지 설정은 기존으로 두고, 인스턴스 시작 버튼을 누른다.
프리티어에서는 최대 30기가까지 설정이 가능하다.
인스턴스 생성이 완료된 모습이다.
보안 그룹 수정하기
보안 그룹이란?
AWS 에서 제공하는 방화벽으로 인바운드 규칙, 아웃바운드 규칙이 존재합니다.
- 인바운드 규칙(inbound) : 외부에서 EC2나 RDS 등의 내부로 접근할때 사용되는 방화벽 규칙
- 아웃바운드 규칙(outbound) : EC2나 RDS 등의 내부에서 외부로 접근할때 사용되는 방화벽 규칙
외부에서 인스턴스에 접속해 서버를 띄우기 위해서는, 인바운드 규칙을 수정해주어야 한다.
인스턴스를 누르고 보안탭 -> 보안 그룹에 들어간다.
현재는 22번 포트인 SSH 접속 포트만 열려있는 모습인데,
다음과 같이 필요한 포트들을 세팅해준다.
1. ssh 접속은 어디서도 가능하게하고, 22번 포트를 사용한다.
2. 스프링 부트 서버는 8080포트를 사용한다.
pem 키를 이용해 SSH 서버로 인스턴스 접속하기
1.pem 키가 위치한 폴더로 이동한다.
2.다음 명령어로 권한을 부여한다.
chmod 400 sshKey.pem
3. 다음 명령어로 인스턴스에 접속한다.
ssh -i sshKey.pem ubuntu@퍼블릭ipv4주소
Elastic IP (탄력적 IP) 설정
EIP(Elastic IP Address)는 내 인스턴스에 인터넷을 통해 접속할 수 있는 고정적인 공인 IP 주소를 할당할 수 있는
서비스이다. 만약 EIP를 설정해주지 않는다면, 인스턴스가 실행될 때마다 다른 공인 IP 주소를 할당받게 된다.
모든 인스턴스 또는 네트워크 인터페이스에 탄력적 IP 주소를 연결 가능하다.
또한, EIP를 할당받고 삭제하기 전까지 IP 주소를 쭉 유지할 수 있다.
네트워크 및 보안 탭 -> 탄력적 IP 에 접속후, 탄력적 IP 주소 할당 버튼을 누른다.
기본 설정은 건드리지 않고, 할당을 해준다.
탄력적 IP를 할당하고 나면, 이렇게 탄력적 IP 주소를 연결할지에 대한 메시지가 뜨게 된다.
인스턴스를 미리 생성했으니, 바로 연결 해주자.
인스턴스와 프라이빗 IP 주소는 이 IP를 사용하고자 하는 인스턴스로 설정해주고, 연결을 누른다.
연결 정보를 확인가능하다.
해당 IP로 연결도 잘 되는 모습이다.
Spring Boot 배포 환경 구축
스프링 서버는 start.spring.io 에서 1분이면 만들 수 있기에, 생략하고
이미 만들어진 스프링 서버가 있다고 가정하겠다.
git 설치
위 예시에서는 ubuntu 이미지를 설치했지만, 현재 AMI 이슈로 aws linux 이미지를 사용중이다.
aws linux는 centOs기반이므로 다음 명령어로 git을 설치해준다.
sudo yum install git
만약 우분투 이미지를 사용중이라면 다음처럼 apt-get으로 설치해주면된다.
sudo apt-get install git
프로젝트 Clone
설치가 완료되었음을 확인 후, 내 스프링 프로젝트가 올라간 깃 주소를 clone 해준다.
(현재 gitLab을 사용중인데, gitLab은 아직 id/pw로 작업이 가능하다. github는 반드시 토큰을 발급받거나 ssh를 사용)
빌드 후 jar 파일을 실행시켜 스프링 부트 서버 배포
우선 다음 명령어로 java 11버전을 설치해준다.
sudo yum install openjdk-11-jdk
우분투는 다음 명령어
sudo apt update
sudo apt install openjdk-11-jdk
이제 프로젝트 폴더로 이동하여, 다음 명령어로 빌드를 실행한다.
chmod +x ./gradlew
./gradlew build
빌드가 완료되면, jar 파일이 있는 폴더로 이동한다.
cd build
cd libs
jar 파일이 정상적으로 생성되어있다면, 다음 명령어로 서버를 실행시킬 수 있다.
java -jar [프로젝트이름]-0.0.1-SNAPSHOT.jar
ssh 접속을 끊어도 서버를 켜주고 싶다면, nohup을 이용해 백그라운드로 실행시켜줄 수도 있다.
nohup java -jar [프로젝트 이름]-0.0.1-SNAPSHOT.jar &
백그라운드로 서버가 실행되면, 해당 경로에 nohup.out이 생성되어있다.
cat nohup.out
위 명령어를 통해 서버 로그도 확인 가능하다.
현재 백그라운드에서 실행중인 작업들은 jobs를 통해 확인가능하다.
jobs
현재 실행중인 작업을 끄고싶다면, 다음 명령어로 백그라운드 프로그램을 가져온뒤,
ctrl+c로 종료도 가능하다.
fg %실행중인 작업의 인덱스번호
React + Spring 개발환경 구축
리액트를 설치 및 코드 작성하는 부분은 이미 되어있다고 가정하고, 어떻게 React로 만든 페이지를
Spring으로 구축한 서버 위에 띄우는 지 알아보자.
파일 계층 구조
우선 다음처럼 프로젝트 폴더 안에서, 리액트 프로그램을 front 폴더 밑에 두고, 스프링은 server 폴더 밑에 둔다.
Proxy 설정을 통한 CORS 에러 방지
CORS 에러란 동일 출처 정책을 지키지 않을경우 발생하는 에러이다.
동일 출처 정책 (Same-Origin Policy)
웹 브라우저는 보안상의 이유로 스크립트가 다른 도메인에서 리소스를 로드하거나 요청하는 것을 제한한다. 이는 기본적으로 웹 페이지가 자신의 원래 출처에서만 리소스를 가져오는 것을 허용하는 보안 기능이다.
다른 도메인 간 요청
클라이언트(브라우저)가 원래 출처와 다른 도메인에 있는 서버로 요청을 보낼 때 CORS 에러가 발생한다. 이는 기본적으로 브라우저의 보안 기능으로, 서버는 명시적으로 다른 도메인에서의 요청을 허용해야 한다.
src/main/front 폴더에서 프록시 설정에 필요한 모듈을 설치해준다.
npm install http-proxy-middleware --save
src/main/front/src 폴더에서 setProxy.js 파일을 생성하고, 아래의 코드를 붙여넣기하자.
// src/main/front/src/setProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:8080', // 서버 URL or localhost:설정한포트번호
changeOrigin: true,
})
);
};
- 프록시 서버 설정: 위에서 제공한 코드에서 /api 경로로 오는 요청을 백엔드 서버의 8080 포트로 프록시 설정을 했다. 이로써 클라이언트는 프록시 서버와 동일한 도메인에서 요청을 보내게 된다.
- 프록시 서버는 다른 도메인에서 요청: 프록시 서버는 클라이언트의 요청을 받은 후, 백엔드 서버로 요청을 보내는데, 이때는 백엔드 서버와의 도메인이 동일하므로 CORS 에러가 발생하지 않는다.
- 프록시 서버 응답 전달: 백엔드 서버가 응답을 보내면 프록시 서버는 해당 응답을 클라이언트로 전달한다. 이 과정에서 프록시 서버의 도메인과 클라이언트의 도메인이 동일하기 때문에 브라우저는 CORS 에러를 발생시키지 않는다.
빌드하기
server 폴더의 build.gradle 파일 하단에 코드를 추가한다. 해당 스크립트는 SpringBoot 프로젝트가 build 될 때 React 프로젝트가 먼저 build되고, 결과물을 SpringBoot 프로젝트 build 결과물에 포함시킨다는 스크립트입니다.
def frontendDir = "$projectDir/src/main/front"
sourceSets {
main {
resources { srcDirs = ["$projectDir/src/main/resources"]
}
}
}
processResources { dependsOn "copyReactBuildFiles" }
task installReact(type: Exec) {
workingDir "$frontendDir"
inputs.dir "$frontendDir"
group = BasePlugin.BUILD_GROUP
if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
commandLine "npm.cmd", "audit", "fix"
commandLine 'npm.cmd', 'install' }
else {
commandLine "npm", "audit", "fix" commandLine 'npm', 'install'
}
}
task buildReact(type: Exec) {
dependsOn "installReact"
workingDir "$frontendDir"
inputs.dir "$frontendDir"
group = BasePlugin.BUILD_GROUP
if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
commandLine "npm.cmd", "run-script", "build"
} else {
commandLine "npm", "run-script", "build"
}
}
task copyReactBuildFiles(type: Copy) {
dependsOn "buildReact"
from "$frontendDir/build"
into "$projectDir/src/main/resources/static"
}
spring 프로젝트 빌드와 실행은 앞서 설명했던 방법을 따라서 하면 된다.
이제 빌드 시에 리액트 파일도 같이 빌드가 될 것이고, 서버 실행 후 8080포트로 접속하면 정상적으로 배포가 되는 모습을 볼 수 있다.
EC2에서 리액트 프로젝트를 빌드 시 주의사항
EC2에서 프리티어를 사용하는 경우, t2.micro 를 사용하게 되는데, 해당 이미지는 램을 1GB만 제공한다.
따라서 해당 인스턴스에서 리액트 프로젝트를 빌드할 경우, 램이 딸려서 힘들어하는 모습을 보이기 때문에..
(심할 경우엔 ssh 접속 상태에서 인스턴스가 멈춘다.)
미리 빌드를 하고 빌드 파일을 올리거나, 램을 올리자.
Axios를 이용한 API 통신은 다음번에 알아볼 예정.
'🛠️TOOL > 🔶AWS' 카테고리의 다른 글
[AWS] - EC2 인스턴스 SSH 접속 시 error : Permission denied (publickey) (1) | 2024.02.14 |
---|---|
[AWS] - EC2 프리티어 사용시 메모리 부족 현상 해결 (0) | 2023.11.29 |
[AWS] - EC2에 mongoDB 설치하기 (0) | 2023.09.27 |
[AWS] S3 버킷 생성하고 보안 정책 설정하기 (0) | 2023.09.07 |
[AWS] - pem 파일 없이 EC2 인스턴스 SSH로접속하기 (0) | 2023.07.21 |