BLC Project 배포 level.5

한강섭·2025년 7월 1일

BLC 프로젝트

목록 보기
6/9
post-thumbnail

최종 목표

  • EC2에서 Docker 환경으로 Spring Boot (백엔드) + Vue.js (프론트엔드) 배포
  • 포트 분리 및 환경별 설정 파일 관리
  • 팀 협업을 위한 표준화된 배포 프로세스 구축

저번에는 아무것도 모르고 호기롭게 도전했다가 t2.micro 1GB 메모리를 터트려버렸다.. 그래서 이번에는 3-Tier 아키텍처를 활용해서 계층을 분리시켜서 배포해볼 것이다.

프론트엔드는 Firebase, 백엔드 + Redis는 EC2, MySQL DB는 AWS RDS로 진행해서 3 tier!


무료를 위해..

각각 플랫폼을 선택한 이유를 먼저 설명드리자면

Firebase : 10GB 대역폭/월, Organization 지원
AWS EC2 t2.micro : 750시간/월 30GB EBS
AWS RDS : 750시간/월, 20GB SSD, 20GB 백업 스토리지, 2천만 I/O/월

혹시 모르니 CloudWatch 알람까지 해놓자!


AWS RDS

그 후 표준 생성, MySQL, 가장 중요한 프리 티어로 설정해야 한다! (무료)

그 후 인스턴스 식별자, 사용자 이름, 암호 (자체관리)를 해준다

중요! 인스턴스 구성을 db.t3.micro로 설정, 버스터블 클래스 선택

이것도 중요! 스토리지 자동 조정을 꺼야 자동으로 과금될 위험을 없앨 수 있음!

네트워크 설정에서는 퍼블릭 액세스만 예로 바꿔주기

그리고 VPC 보안 그룹은 새로 생성해주고

데이터베이스 포트 3306 (추가구성에 있음)

그리고 추가 구성에서 데이터베이스 이름 설정하고 백업 보존 기간을 1일로 해준다 (비용절감)

마지막 확인까지 해주면 데이터베이스 생성하면된다

혹시 비용이 표시되면 설정을 다시 재 검토해야한다!


RDS 보안 그룹 설정 및 테스트

이제 RDS의 보안 그룹을 설정해야 한다.

EC2로 돌아와서 보안 그룹에서 "blc-mysql-sg" 내가 만든 보안 그룹을 선택하고 소스를 수정한다.

0.0.0.0/0으로 만들어서 일단 어디서든지 테스트와 개발을 할 수 있도록 변경!

그럼 MySQL Workbench에서 테스트를 해보자

Connection Name: BLC AWS RDS
Connection Method: Standard (TCP/IP)
Hostname: 복사한 RDS 엔드포인트
Port: 3306
Username: admin
Password: 설정한 패스워드
Default Schema: blc_db

설정한 내용으로 연결해주면

원격 DB를 생성해서 로컬에서 연결하고 테스트할 수 있다!


AWS EC2

이제 DB는 설정이 완료 되었고 백엔드 서버를 작동시켜보자!

사실 AWS EC2 설정은 전 포스팅에서 다 해버려서 간단히 설명하겠습니다.

blc-backend-server 라고 이름 설정하고
t2.micro 선택하고
키페어 생성하고
보안규칙 생성하고
스토리지 30GB gp2로 선택하고

인스턴스 시작!

그리고 EC2 서버 환경 설정 (이것도 다 포스팅 되어있습니당)

PuTTYgen 실행
.pem 키를 ppk 로 저장
PuTTY 키고 Session, Auth 설정


시스템 설정

여기까지 되었다면 이제 Backend 서버에 시스템들을 설정해주어야 한다!

시스템 업데이트 및 Java 설치

# 시스템 업데이트
sudo yum update -y

# Java 17 설치
sudo yum install java-17-amazon-corretto -y

# Java 설치 확인
java -version
# 출력 예시: openjdk version "17.0.9"

complete!

Redis 설치 및 설정

# Redis 설치
sudo yum install redis6 -y

# Redis 설정 파일 편집
sudo nano /etc/redis6/redis6.conf

설정 수정

# 다음 내용을 밑으로 끝까지 내려서 추가 
maxmemory 200mb
maxmemory-policy allkeys-lru
save ""

Redis 서비스 시작

# Redis 시작 및 자동 시작 설정
sudo systemctl start redis6
sudo systemctl enable redis6

# Redis 상태 확인
sudo systemctl status redis6

# Redis 연결 테스트
redis-cli ping
# 출력: PONG

백엔드 애플리케이션 설정

백엔드 코드 수정이 필요하다

  1. application.properties 를 대체해서 원격 DB와 호환되는 application 만들기

spring.datasource.url 을 AWS RDS의 엔드포인트에 맞춰서 수정한다!

  1. CORS 를 방지해서 corsConfigurationSource 수정
cfg.setAllowedOrigins(List.of(
                "http://localhost:5173",           // 로컬 개발
                "https://localhost:5173",          // 로컬 HTTPS (필요시)
                "http://13.209.49.84:8080",        // EC2 직접 접근
                "https://blc.ai.kr",               // 본인 도메인
                "https://*.web.app",               // Firebase 호스팅
                "https://*.firebaseapp.com"        // Firebase 호스팅 추가 도메인
        ));
  1. 그리고 보안을 spring.datasource.password=${DB_PASSWORD} 라고 해놓고 EC2 환경변수로 설정하기
# PuTTY에서 실행
export DB_PASSWORD="DB 암호"

# 영구 저장 (재부팅 시에도 유지)
echo 'export DB_PASSWORD="DB 암호"' >> ~/.bashrc
source ~/.bashrc

# 확인
echo $DB_PASSWORD

이렇게 환경변수로 설정해놓으면 된다!


로컬 빌드 + JAR 업로드

저번에는 EC2에서 git으로 빌드해서 메모리가 터져버렸다 그래서 이번에는 로컬에서 빌드하고 JAR 파일을 업로드해서 간단하게 배포를 진행해볼 것이다.

추후 Github Actions CI/CD 파이프라인
코드 푸시 -> 자동 빌드 -> 자동 배포
무중단 배포
이렇게 업그레이드 할 수 있다!

빌드

./mvnw clean package -DskipTests

EC2로 업로드

# 권한 설정
chmod 400 /c/Users/user/Desktop/blc-backend-key/blc-backend-key.pem

# scp 실행
scp -i /c/Users/user/Desktop/blc-backend-key/blc-backend-key.pem target/blc_backend-0.0.1-SNAPSHOT.jar ec2-user@13.209.49.84:~/blc-backend.jar

scp 명령어를 통해 키 위치랑 jar 파일을 13.209.49.84로 보내기 (네트워크 불안정하면 한번씩 실패할 수 있음)

EC2에서 실행

# 백그라운드에서 실행
nohup java -Xms256m -Xmx600m \
           -Dspring.profiles.active=prod \
           -jar blc-backend.jar > app.log 2>&1 &

# PID 저장
echo $! > app.pid
echo "Application started with PID: $(cat app.pid)"

-Dspring.profiles.active=prod \
이 부분을 통해 아까 우리가 만들어준 application-prod.properties를 사용해서 실행될 수 있었다!


DataBase 설정

아까 원격 DataBase를 Workbench로 연결 해두었기 때문에 여기서 설정하면 바로 연결 가능하다 여기서 우리의 기본틀 kbo의 팀들의 정보와 임시 채팅방들을 넣어주면 된다

여기서 모르던 걸 알게되었는데 내가 데이터를 insert 하는 걸 실패하고 성공을 했는데 AUTO_INCREMENT 되어버린 것이다 왜 그럴까?

입력에 실패해도 Auto Increment 되는 이유 :
1. 트랜잭션 격리 : 동시성 환경에서 AUTO_INCREMENT 충돌 방지
2. 롤백 비용 절약 : AUTO_INCREMENT 되돌리기는 비용이 크다
3. 일관성 보장 : 여러 테이블 간 참조 무결성을 유지하기 위해

그렇게 이제 데이터를 넣어주고 API를 호출해주면

백엔드에서 요청한 데이터들을 잘 보내준다!
(roomId가 21부터인 이유는 insert 두번 실패해서.. ㅎㅎ)

또한 commit 이 필요할 때는 새로운 API가 추가되거나 Entity 클래스가 수정이 될 때 이럴 때 commit을 하는 것이고 데이터 추가, 입력, 수정, 삭제 에서는 commit 할 필요 없다!


Firebase 프론트엔드 배포

이제 프론트엔드에서 데이터들을 받아서 뿌려주기만 하면 된다!

.env.production

배포용 환경설정을 해준다

VUE_APP_API_BASE_URL=http://13.209.49.84:8080
VUE_APP_SOCKET_URL=http://13.209.49.84:8080

환경설정을 push!

참고로
npm run serve로 local 개발 시에는 .env.development를 사용하고
firebase deploy -> npm run build 는 .env.production을 사용한다!

Firebase

Firebase CLI 설치

npm install -g firebase-tools

Google에 로그인

firebase login

프로젝트 시작

firebase init

init을 하면 이제 선택할 수 있게 나온다

  1. Hosting: Configure files for Firebase Hosting (스페이스바로 선택)
  2. Create a new project
  3. blc-frontend (이름 입력)
  4. BLC Frontend (별칭 입력)
  5. dist (호스팅 설정)
  6. yes (SPA 설정)
  7. no (자동 빌드 no)
  8. no (기존 파일 덮어쓰기 no)

완료 후 배포

firebase deploy

https://blc-frontent.web.app/

헉 https로 배포가 되었는데 백엔드는 http만을 지원한다...


EC2 HTTPS 업그레이드 및 도메인 설정

진짜 최종장.. EC2 HTTPS로 설정하기 위해서는

  1. 도메인 구매 및 DNS 설정
  2. EC2에 SSL 인증서 설정
  3. Nginx 리버스 프록시 설정

을 해야한다!

도메인 DNS 설정

Type: A, Name: @, Value: 13.209.49.84, TTL: 600
Type: A, Name: www, Value: 13.209.49.84, TTL: 600

다시 오랜만에 PuTTY로 가서

Nginx를 설치하고 리버스 프록시를 설정

# Nginx 설치
sudo yum install nginx -y

# Nginx 시작 및 자동 시작 설정
sudo systemctl start nginx
sudo systemctl enable nginx

# 상태 확인
sudo systemctl status nginx

Nignx 설정 파일 생성

# 기본 설정 백업
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup

# 새 설정 파일 생성
sudo nano /etc/nginx/conf.d/blc.conf

파일을 열고 밑에 내용으로 수정

server {
    listen 80;
    server_name 13.209.49.84;

    # Spring Boot 프록시 설정
    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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket 프록시 설정
    location /chat-socket {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Nginx 설정 테스트 및 재시작

# 설정 문법 확인
sudo nginx -t

# Nginx 재시작
sudo systemctl reload nginx

# 테스트: 80포트로 접근
curl http://13.209.49.84/api/chat-rooms

Let's Encrypt SSL 인증서 설치

# Certbot 설치
sudo yum install certbot python3-certbot-nginx -y

# DNS 확인 후 다시 인증서 발급 시도
sudo certbot --nginx -d blc.ai.kr -d www.blc.ai.kr

HTTPS 설정 추가

# Nginx 설정 파일 수정
sudo nano /etc/nginx/conf.d/blc.conf

밑의 내용으로 수정..

# HTTP to HTTPS 리다이렉트
server {
    listen 80;
    server_name 13.209.49.84;
    return 301 https://$server_name$request_uri;
}

# HTTPS 서버
server {
    listen 443 ssl;
    server_name 13.209.49.84;

    # SSL 설정
    ssl_certificate /etc/nginx/ssl/blc.crt;
    ssl_certificate_key /etc/nginx/ssl/blc.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Spring Boot 프록시 설정
    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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # WebSocket 프록시 설정  
    location /chat-socket {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

EC2 보안 그룹 수정

AWS EC2 콘솔에서:
1. 인스턴스 → 보안 그룹 클릭
2. 인바운드 규칙 편집
3. 새 규칙 추가:

  • 유형: HTTPS
  • 포트: 443
  • 소스: 0.0.0.0/0
  1. 규칙 저장

이거 되어 있는지 확인.. 까지 하면 이제 마지막으로

.env.production 에서 https 랑 도메인으로

VUE_APP_API_BASE_URL=https://blc.ai.kr
VUE_APP_SOCKET_URL=https://blc.ai.kr

npm run build
firebase deploy

하면 이제 끝!

https://blc-frontent.web.app/

(이제 도메인 적용만 하면 된다!)


시행착오..

가장 힘들었던 시행착오는

요청이 분명 잘 되게 백엔드를 해놓았는데 프론트에서 받으니 html 코드가 오는 것이었다..

그래서 원인도 모르고 한참 해매다가 이게 CORS 오류였다는 것을 알게되었다.

원인은 SecurityConfig 에서 CORS 처리하는 곳에 있었는데

CorsConfiguration 의 setAllowedOrigins 는 단일 구체적인 도메인이어야 한다.
여기에다가 "https.*.web.app" 적었다가 혼났다.
setAllowedOriginPatterns 에다가 패턴을 적어야 인식한다..

이 부분은 나중에 실수 안할 것 같다 ㅎㅎ

profile
기록하고 공유하는 개발자

0개의 댓글