시간이 조금 많이 늦었지만,
현재는 배포 완료 이후 트래픽 경험(부하/동시성 테스트)을 진행하고 있다.
배포는 “Docker로 Docker Hub에 push → AWS에서 pull받아 EC2에서 컨테이너를 실행”하는 방식으로 구성했다. 애플리케이션은 EC2의 vCPU 2, 메모리 8GB(프리티어) 인스턴스에서 운영 중이며, PostgreSQL은 AWS RDS를 사용하고 있다.
이번 프로젝트의 배포 환경은 `docker-compose.yml` 기준으로 다음 구성으로 동작한다.
웹(`web`)은 Django + Gunicorn(gevent worker)로 실행되고, 컨테이너 시작 시 `python manage.py migrate`, `collectstatic`을 함께 수행한다. 또한 `/app/logs/access.log`, `/app/logs/error.log`로 로그를 남기고, 호스트 로그 경로는 `${TREND_LOGS_DIR:-.}/logs:/app/logs` 마운트를 통해 EC2에서 확인할 수 있게 해두었다.
캐시는 `redis` 컨테이너를 사용하고, Celery 비동기 작업 처리를 위해 `celery_worker`(큐: `celery,embedding`)와 스케줄러 `celery_beat`(DatabaseScheduler)가 함께 올라간다.
임베딩/벡터 관련 데이터는 `chroma_data:/app/chroma_db` 볼륨으로 영속화되어, 재배포가 일어나도 데이터가 유지된다.
서버 배포를 하면서 매번
`github에 push → docker image build → docker hub push → ec2에서 pull → docker compose up -d`
를 수작업으로 반복하는 건 기다리는 시간도 크고, 실수 가능성도 높아서 비효율적이라고 생각했다. 그래서 GitHub Actions를 이용해 배포 자동화를 진행했다.
이제 `main` 브랜치에 push가 발생하면, GitHub Actions가 Docker Hub 푸시와 EC2 배포까지 자동으로 수행한다.
구체적으로는 GitHub Actions에서 Docker 이미지를 빌드한 뒤 `limsunoh/trend:latest` 태그로 Docker Hub에 push하고, EC2에는 SSH로 접속해서 `docker compose down`, `docker system prune -af`로 정리한 다음, 최신 이미지를 `docker pull`로 내려받아 `docker compose up -d`로 실행한다.
배포 흐름 중 문제가 생기면 Actions 로그에서 즉시 에러 원인 확인이 가능하고, 작업이 얼마나 걸렸는지도 확인할 수 있어 “배포 속도 + 재현성”이 크게 좋아졌다.
또한 배포 전에 코드 품질을 점검하는 CI도 구성해두었다. `main` push/PR 기준으로 `black`, `isort`, `flake8` 같은 린트와 `pip audit` 취약점 점검을 진행하다.
즉, 배포에 들어가기 전 단계에서 기본적인 안전장치를 추가한 셈이다.
배포가 안정적으로 동작하는지와 트래픽 경험 중 병목을 찾기 위해, 단순히 “서버가 켜졌다”에서 끝내지 않고 상태 확인도 함께 보고 있다. `docker-compose.yml`의 healthcheck과 `depends_on` 조건을 사용해서 Redis/웹 준비 상태가 갖춰진 뒤 Celery가 올라오도록 했고, 웹 컨테이너가 직접 접근 가능한 상태인지도 확인한다.
동시에 `gunicorn` 접근/에러 로그와 함께 RDS의 성능 지표를 보면서 응답 지연과 에러율이 어디서 발생하는지 추적한다.
트래픽 테스트 과정에서는 Locust 같은 방식으로 동시 사용자 수를 단계적으로 올리면서, 응답 시간(특히 상위 지연 구간)과 에러율을 관찰한다.
서버를 약 2달 동안 무료로 운영할 수 있는 기간 동안 이 인프라 위에서 배포를 반복하면서, 실제 대용량 트래픽에 가까운 조건으로 성능과 안정성을 점검해보려 한다.
목표는 “자동 배포가 끊김 없이 동작하는지”와 “부하 상황에서 어떤 부분(웹 동시성, Celery 작업, Redis 캐시, DB 쿼리)이 병목이 되는지”를 데이터로 확인하는 것이다.
추가로 운영 단계에서 “눈으로 상태를 확인”하기 위해 AWS CloudWatch를 붙였다.
단순히 서버가 살아있는지 여부만 보는 게 아니라, 로그와 시스템 지표를 함께 보면서 배포 이후 상태를 확인하는 방식이다.
CloudWatch Logs에는 Gunicorn 로그를 분리해서 올리고 있다.
- `trend/web-access`: access.log (요청/응답 흐름 확인)
- `trend/web-error`: error.log (예외/실패 원인 확인)
로그 수집은 Docker 기본 json 로그가 아니라, EC2 호스트에 마운트된 파일 로그를 CloudWatch Agent가 수집하도록 구성했다.
컨테이너 재생성 시 경로가 바뀔 수 있는 Docker 내부 로그보다 운영 관점에서 추적이 안정적이고, CloudWatch에서 검색/필터링도 더 편하다.
메트릭도 함께 수집해서 대시보드처럼 확인하고 있다.
- CPU 사용률(`cpu_usage_user`, `cpu_usage_system`, `cpu_usage_idle`)
- 메모리 사용률(`mem_used_percent`)
- 디스크 사용률(`/`의 `used_percent`)
- 네트워크 트래픽(`bytes_sent`, `bytes_recv`, `packets_sent`, `packets_recv`)
이렇게 구성해두니 배포 직후에
“에러가 발생했는지”, “리소스가 급격히 올라가는지”, “트래픽이 정상적으로 유입되는지”
를 CloudWatch에서 바로 확인할 수 있었다.

추가로 장애 대응 속도를 높이기 위해 Sentry도 연결했다.
CloudWatch가 서버/로그 중심 모니터링이라면, Sentry는 “애플리케이션 에러 단위”로 추적하는 역할이다.
에러가 발생하면 스택 트레이스, 발생 시점, 영향 범위(사용자/환경)를 바로 확인할 수 있어서
“어디서 깨졌는지”를 코드를 빠르게 파악할 수 있다.
또한 Sentry MCP를 함께 연결해, 이슈를 대화형으로 조회하고 원인 분석 흐름을 쉽게 알 수 있다.
즉, CloudWatch로 인프라 상태를 보고, Sentry(+MCP)로 애플리케이션 에러를 깊게 확인하는
2단 모니터링 체계를 갖춘 상태다.
정리하면 배포 자동화는 GitHub Actions,
운영 지표/로그 확인은 CloudWatch,
실제 애플리케이션 에러 추적은 Sentry와 MCP로 담당하도록 구성했다.
덕분에 배포 이후 문제가 생겨도 탐지-원인파악-대응까지 걸리는 시간이 확실히 줄었다.
'AI_RSS_트래픽 프로젝트' 카테고리의 다른 글
| AI_RSS_분석_대용량트래픽 프로젝트 cpu2,8Gib 단일 인스턴스 성능 개선기 (0) | 2026.03.31 |
|---|---|
| 모르는 상태로 하는 RSS&분석&RAG 프로젝트(19) 트렌드 분석 (0) | 2026.01.14 |
| 모르는 상태로 하는 RSS&분석&RAG 프로젝트(18) 트러블슈팅2 analyze_time_lag (0) | 2026.01.09 |
| 모르는 상태로 하는 RSS&분석&RAG 프로젝트(17) 시간차 분석 (뉴스 ↔ SNS 전파 패턴) (0) | 2026.01.09 |
| 모르는 상태로 하는 RSS&분석&RAG 프로젝트(16) 크로스 플랫폼 키워드 추출 및 빈도 분석 (0) | 2026.01.02 |