EC2 단일 서버 환경에서 DB 서버 분리 및 시스템 안정화

김상진 ·2025년 4월 23일

Problem Solving

목록 보기
8/10
post-thumbnail

초기에는 모든 서비스를 EC2 인스턴스 한 대에 구성하여 운영하고 있었습니다.
Spring 애플리케이션, HAProxy, Nginx Proxy Manager, MySQL, Redis까지 모두 하나의 인스턴스에 올려둔 구조였습니다.

이러한 구성은 초기 개발 및 테스트 단계에서는 빠르게 서비스를 구축할 수 있다는 장점이 있었지만,
JMeter 부하 테스트를 진행하면서 심각한 성능 저하 문제를 발견하게 되었습니다.


문제 인식: 단일 인스턴스의 리소스 한계

부하 테스트 결과, 다음과 같은 문제가 발생했습니다.

  • Spring 애플리케이션의 처리 속도 불안정
  • MySQL, Redis, HAProxy 간 리소스 간섭 발생
  • CPU 및 디스크 I/O 병목으로 인한 TPS(초당 처리 요청 수) 급감
DB 분리 전 TPS 측정 결과

당시 측정된 TPS는 최대 약 120이었지만,
이는 서버 자원이 과부하된 상태에서 비정상적으로 부하를 받아낸 결과였습니다.
(실제 응답 지연 및 503 오류가 빈번하게 발생했습니다.)


테스트 시나리오

테스트는 JMeter를 이용해 다음과 같은 설정으로 진행했습니다.

JMeter 테스트 시나리오
  • Start Threads Count : 4
  • Initial Delay, sec : 0
  • Startup Time : 5초
  • Hold Load For : 300초
  • Shutdown Time : 5초

개선 방향: DB 서버 분리 및 시스템 최적화

성능 문제의 핵심 원인은
단일 인스턴스에 과도하게 많은 역할이 집중되어 리소스 경합이 심했던 점이었습니다.

따라서 다음과 같은 개선 작업을 수행했습니다.

  1. DB 서버 분리

    • MySQL과 Redis를 별도의 EC2 인스턴스로 이전
    • Spring, HAProxy, Nginx Proxy Manager는 기존 인스턴스에 유지
  2. 애플리케이션 서버 튜닝

    • HikariCP 커넥션 풀 max size를 10 → 5로 축소
      (CPU 코어 수가 2개이기 때문에, 과도한 동시 처리를 제한하여 안정성 확보)
    • 서버 모니터링 구축 (CPU, Memory, Disk 사용량 실시간 확인)

Terraform 코드 예시

DB 서버용 보안 그룹과 EC2 인스턴스는 다음과 같이 정의했습니다.

resource "aws_security_group" "sg_db" {
  name   = "${var.prefix}-sg-db"
  vpc_id = aws_vpc.vpc_1.id

  ingress {
    description = "MySQL"
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Redis"
    from_port   = 6379
    to_port     = 6379
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

⚠️ 주의: 현재는 더미 데이터 삽입 및 테스트를 위해 퍼블릭 접속을 허용했지만,
운영 환경에서는 반드시 VPC 내부 통신만 허용하는 것이 좋습니다.


인스턴스 생성 시 user_data를 이용해 다음 작업을 자동화했습니다.

  • Docker 및 Docker Compose 설치
  • Git 클론 및 DB용 Docker Compose 파일 실행
  • .env 파일 작성 및 환경변수 설정
docker-compose -f db-docker-compose.yml up -d

AMI 고정

초기에는 Amazon Linux 2023의 최신 AMI를 자동으로 조회하여 사용했습니다.

data "aws_ami" "latest_amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
}

그러나 이 방식은 Terraform을 적용할 때마다 새로운 AMI로 인해 인스턴스가 교체되는 문제가 발생했습니다.
따라서 특정 AMI ID를 고정하여 인프라를 안정적으로 관리할 수 있도록 개선했습니다.


DB 마이그레이션

mysqldump 명령어를 이용해 기존 인스턴스의 데이터를 백업한 뒤,
신규 DB 서버로 복원 작업을 진행했습니다.

Spring 애플리케이션 설정 파일(application.yml)의
DB 호스트 및 포트 정보도 신규 인스턴스 기준으로 수정하여 재배포를 완료했습니다.


결과: 시스템 안정화 및 TPS 변화

DB 서버 분리와 함께 HikariCP 커넥션 풀 최적화, 모니터링 시스템 구축을 완료한 후,
동일한 조건으로 부하 테스트를 재진행했습니다.

DB 분리 후 및 시스템 안정화 후 TPS 결과
  • 최대 TPS: 약 37
  • 응답 안정성: 503 오류 없이 안정적인 응답 유지
  • CPU 사용률: 과도한 급등 없이 안정적으로 관리
  • 전체 시스템 리소스: 균형 있게 분산됨

TPS 수치는 이전보다 낮아졌지만,
서버는 이제 지속 가능한 처리량을 안정적으로 유지할 수 있는 상태로 개선되었습니다.


핵심 요약

항목DB 분리 전 (튜닝 전)DB 분리 후 + 시스템 튜닝
TPS12037
응답 안정성불안정 (오류 빈발)안정적 (오류 없음)
CPU 사용률급등, 불안정정상 범위 유지
Connection Pool 설정max size 10max size 5
모니터링 시스템미구축구축 완료

최종 결론

  • DB 서버 분리를 통해 리소스 경합 문제를 해소하고,
  • HikariCP 커넥션 풀 최적화모니터링 시스템 구축을 통해
    시스템의 안정성과 지속 가능한 처리 능력을 확보할 수 있었습니다.
  • 이번 경험을 통해,
    TPS 수치 그 자체보다는, 지속 가능한 성능과 서버 안정성 확보가 더 중요하다는 것을 실감할 수 있었습니다.
profile
알고리즘은 백준 허브를 통해 github에 꾸준히 올리고 있습니다.🙂

0개의 댓글