Published:
Updated:

나는 동시 접속자를 최대 1500명으로 생각하고 워스트 케이스를 잡았다.
프론트엔드는 Vercel로 배포했으므로 이 글에서는 생략하겠다.

인프라 환경

  • EC2 Auto Scaling Group (SpringBoot Server Scale-out)
  • ElastiCache for Valkey (Redis)
  • AmazonMQ for ActiveMQ (Message Broker)
  • RDS for MySQL (DB)
  • Atlas for MongoDB (DB for Message)

EC2 - 시작 템플릿

AMI 생성

  1. 새로운 EC2 인스턴스를 Ubuntu로 하여 새로 생성
  2. 인스턴스의 SSH에 접속하여 Docker와 Docker Compose 설치
# OS 패키지 최신화
sudo apt-get update
sudo apt-get upgrade -y

# Docker 설치
sudo apt-get install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker ubuntu

# Docker Compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
  1. 이미지 생성

Screenshot 2025-08-28 at 09 51 27

EC2 인스턴스용 IAM “정책” 생성

Screenshot 2025-08-28 at 09 57 44

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ssm:GetParameter",
            "Resource": "arn:aws:ssm:ap-northeast-2:789665426799:parameter/lionchat/be/application-local-yml"
        }
    ]
}
  • 이름은 Read-Lionchat-App-Config-Policy으로 생성
  • 789665426799는 우측 최상단에 보이는 계정 ID를 넣으면 됨

EC2 인스턴스용 IAM “역할” 생성

Screenshot 2025-08-28 at 09 59 56

  • 이름은 EC2-Lionchat-App-Role로 생성
  • 위에서 만든 Read-Lionchat-App-Config-Policy를 권한 정책에 추가
    • AmazonSSMManagedInstanceCoreAmazonSSMManagedEC2InstanceDefaultPolicy도 추가

AWS Systems Manager에 yml 파일 추가

Screenshot 2025-08-28 at 10 05 23

Screenshot 2025-08-28 at 10 06 09

  • 부분에 서버용 application.yml을 넣으면 됨

시작 템플릿 생성

Screenshot 2025-08-28 at 09 52 15

Screenshot 2025-08-28 at 09 53 07

Screenshot 2025-08-28 at 10 02 36

Screenshot 2025-08-28 at 10 02 55

#!/bin/bash -xe

# 스크립트 실행 과정을 로그 파일로 남겨서 디버깅을 쉽게 합니다.
exec > >(tee /home/ubuntu/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1

# apt가 사용자에게 질문하는 것을 방지합니다.
export DEBIAN_FRONTEND=noninteractive

# 1. 시스템 패키지 목록 업데이트
apt-get update -y

# 2. 필수 패키지 (curl, unzip, docker) 설치
# 'awscli'는 apt 목록에서 제거하고, AWS CLI 설치에 필요한 'unzip'을 추가합니다.
apt-get install -y apt-transport-https ca-certificates curl unzip software-properties-common docker.io

# 3. AWS CLI v2 공식 설치 (가장 중요한 변경점)
echo "Installing AWS CLI v2..."
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install
rm -rf aws awscliv2.zip
echo "AWS CLI v2 installation complete."

# 4. Docker 서비스 시작 및 활성화
systemctl start docker
systemctl enable docker

# 5. 'ubuntu' 사용자가 sudo 없이 docker 명령어를 사용하도록 권한 추가
usermod -aG docker ubuntu

# 6. 설정 파일 저장 디렉토리 생성
CONF_DIR="/home/ubuntu/conf"
mkdir -p "$CONF_DIR"

# 7. SSM Parameter Store에서 설정 파일 가져오기
# 이제 aws 명령어가 정상적으로 작동할 것입니다.
aws ssm get-parameter --name "/lionchat/be/application-local-yml" --with-decryption --query "Parameter.Value" --output text --region ap-northeast-2 > "$CONF_DIR/application-local.yml"

# 8. 생성된 파일 및 디렉토리의 소유자를 ubuntu로 변경
chown -R ubuntu:ubuntu "$CONF_DIR"
chown ubuntu:ubuntu /home/ubuntu/user-data.log

# 9. Docker Hub에서 최신 이미지 가져오기
docker pull won4885/lionchat_be:latest

# 10. 기존 컨테이너가 있다면 삭제 후 실행
docker stop be-app || true
docker rm be-app || true

# 11. Docker 컨테이너 실행
docker run -d --name be-app \
-p 8080:8080 \
-v /home/ubuntu/conf/application-local.yml:/app/application-local.yml \
-e SPRING_CONFIG_ADDITIONAL_LOCATION=file:/app/application-local.yml \
--restart always \
won4885/lionchat_be:latest
  • won4885/lionchat_be:latest는 Docker Hub에서 생성해준 레포지토리다.
  • 아래 사진은 같이 Docker Hub에 레포지토리 생성 후 latest까지 버전을 붙여줘야 한다.

Screenshot 2025-08-28 at 10 09 05

Auto Scaling 그룹

Screenshot 2025-08-28 at 10 18 51

Screenshot 2025-08-28 at 10 19 18

Screenshot 2025-08-28 at 10 23 55

Screenshot 2025-08-28 at 10 24 15

Screenshot 2025-08-28 at 10 20 49

  • 로드 밸런서는 ALB로 8080 포트로 이동하는 대상 그룹을 선택했다.
  • 그룹 크기는 “원하는 용량”으로 “기본 크기”를 설정하고, “크기 조정”으로는 늘어날 미니멈과 맥시멈 값을 조정할 수 있다.
    • 현재는 기본적으로 인스턴스 2개로 돌아가면서, CPU 사용률이 60%가 넘었을 때 최대 4개까지 늘어나게끔 설정했다.

Github Actions용 IAM “사용자” 생성

Screenshot 2025-08-28 at 10 27 55

Screenshot 2025-08-28 at 10 32 33

  • “권한 추가”를 눌러서 Github-Actions-ASG-Refresh-Policy 이름의 권한을 아래와 같이 생성한다.

Screenshot 2025-08-28 at 10 34 02

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "autoscaling:StartInstanceRefresh",
            "Resource": "*"
        }
    ]
}

Screenshot 2025-08-28 at 10 37 55

  • 여기에서 액세스 키를 만들고, 아래의 환경 변수에 넣어줄 거다.

CI/CD 연동

name: be-cd
on:
  push:
    branches:
      - dev
    paths:
      - '**'
env:
  ROOT_PATH: $
  MAIN_RESOURCE_PATH: $/src/main/resources
  TEST_RESOURCE_PATH: $/src/test/resources

jobs:
  be-cd:
    runs-on: ubuntu-latest
    steps:
      - name: 레포지토리를 체크아웃한다
        uses: actions/checkout@v4
      - name: 자바를 설치한다
        uses: actions/setup-java@v3
        with:
          distribution: 'corretto'
          java-version: '17'
      - name: 설정파일을 추가한다
        run: |
          cd $
          printf '%s' "$" > application-test.yml
          
          # 생성 후 파일 확인 명령어 추가
          ls -l $/application-test.yml
          stat $/application-test.yml
      - name: 어플리케이션을 빌드한다
        run: |
          chmod +x gradlew
          echo "::group::Gradle Build Logs"
          ./gradlew clean build --info
          echo "::endgroup::"

        working-directory: $
      - name: 도커 허브에 로그인한다
        uses: docker/login-action@v2
        with:
          username: $
          password: $
      - name: 어플리케이션의 도커 이미지를 빌드하고 도커 허브에 푸시한다
        uses: docker/build-push-action@v4
        with:
          context: .
          file: ./Dockerfile.be
          push: true
          tags: $
      - name: AWS 자격 증명 설정
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: $
          aws-secret-access-key: $
          aws-region: ap-northeast-2

      - name: Auto Scaling Group 인스턴스 새로고침 시작
        run: |
          aws autoscaling start-instance-refresh \
            --auto-scaling-group-name tokit-asg \
            --strategy "Rolling" \
            --preferences "MinHealthyPercentage=50"
  • .github/workflows/be-cd.yml 파일이다.
  • secrets.$환경변수로 찍혀있는 부분은 깃허브 레포의 Settings -> Security -> Secrets and variables -> Actions에서 Repository secrets에 추가하면 된다.

Screenshot 2025-08-28 at 10 53 05

  • APPLICATION_TEST_YML: 테스트 코드용 yml 파일
  • AWS_ACCESS_KEY_ID: Github Actions IAM 사용자를 만들 때 생성한 액세스 키에서 받은 key id
  • AWS_SECRET_ACCESS_KEY: Github Actions IAM 사용자를 만들 때 생성한 액세스 키에서 받은 secret key
  • BE_DOCKER_IMAGE_NAME: Docker hub의 레포지토리 네이밍 (won4885/lionchat_be)
    • 혹시 잘 안 되면 won4885/lionchat_be:latestlatest 태그 추가
  • DOCKER_HUB_USERNAME: docker hub의 id
  • DOCKER_HUB_PASSWORD: docker hub의 access key

실제 서비스 경험

8월 23일 18시 ~ 8월 25일 12시: 사전예약 기간
8월 25일 12시 ~ 8월 26일 05시: 본 서비스 기간

접속자 수

스크린샷 2025-08-27 오전 10 51 03

EC2 인스턴스

Screenshot 2025-08-26 at 20 35 06

RDS for MySQL

Screenshot 2025-08-26 at 20 57 58

ElastiCache for Valkey

Screenshot 2025-08-26 at 20 53 57

Screenshot 2025-08-26 at 20 54 13

Screenshot 2025-08-26 at 20 54 21

AmazonMQ for ActiveMQ

Screenshot 2025-08-26 at 20 55 17

추가 정보

Route 53

Screenshot 2025-08-29 at 12 00 29

  • A 타입(별칭): 위 이미지를 참고하여, 백엔드용 api.google.com으로 api 서브 도메인을 사용하여 연결
    • A 타입(값): Vercel에서 발급 받은 A 타입 주소
  • NS 타입: 가비아와 같은 도메인 사이트에서 발급받은 네임서버 넣기
  • CNAME 타입(AWS): 아래의 Certificate Manager 참고
    • CNAME 타입(Vercel): Vercel에서 CNAME 값을 받고, 레코드 이름에 www.google.com과 같이 www도 지정하기

Certificate Manager

Screenshot 2025-08-29 at 11 59 42

  • 정규화 도메인을 *.google.com과 같이 설정
  • 이렇게 한다면 www.google.comapi.google.com 둘 다 커버 가능

ALB

Screenshot 2025-08-29 at 11 54 38

Screenshot 2025-08-29 at 11 55 28

Screenshot 2025-08-29 at 11 55 43

대상 그룹

Screenshot 2025-08-29 at 11 56 13

Leave a comment