기존 인프라에 대한 모니터링 진단

스토어 심사가 들어간 시점에서 서비스가 안정적으로 운영될 수 있을지에 대한 검증이 필요했다. 실제 운영 서버 대상으로 일어날 수 있는 부하 상황을 재현해 점검을 진행했다.
  • VM : EC2 t3.Small (vCPU 2개, 메모리 2GB), Ubuntu 24.04 LTS
  • 서버 1대 : Spring Boot 3.4.9, Kotlin, Java 21
  • DB : MySQL 8.0, Redis 7.0
사용자가 가장 많이 사용하는 API 흐름을 기준으로 시나리오를 구성했고, 10분 동안 100 VU까지 점진적으로 부하를 증가시키며 테스트를 진행하였다.

1. 응답 지연 증가

notion image
부하 증가에 따라 일부 API의 응답 시간이 지속적으로 증가하는 경향이 확인되었다.
특히 긴 트랜잭션을 포함한 API에서 지연이 빠르게 증가하며, 부하에 비례해 응답 시간이 함께 상승하는 구조를 보였다.

2. 메모리 및 Swap 사용 증가

notion image
테스트 진행 중 메모리 사용률이 약 85.8%까지 상승하였으며, 동시에 Swap 메모리 사용도 함께 증가하는 패턴이 확인되었다.
이는 요청 처리 과정에서 생성된 객체가 즉시 해제되지 않고 누적되며, 메모리 회수 지연과 처리 효율 저하로 이어질 수 있는 상태로 판단하였다.
 

3. GC 부담 증가 — 직접적인 병목은 아님

notion image
부하 증가에 따라 minor GC 발생 횟수와 누적 GC 시간이 증가하였다.
다만 STW로 인한 응답 정체는 확인되지 않아, GC는 직접적인 병목이 아닌, 메모리 사용 증가의 결과로 발생한 현상으로 판단하였다.
 

4. 스레드 및 CPU 상태

전체 스레드 수
전체 스레드 수
스레드 상태별 수치
스레드 상태별 수치
스레드 수는 부하에 따라 정상 증가했으나 사용 가능한 runnable 스레드는 제한적이였고, 대부분 timed-waiting 상태로 관측되었다.
이는 CPU 부족이 아닌 I/O 대기 중심의 병목 구조임을 의미한다.
 

테스트 결론

부하 증가에 따라 응답 지연, 메모리 사용률, GC 부담이 함께 증가하는 경향이 확인되었다.
특히 메모리 사용률이 85.8%까지 상승하고 Swap 사용이 동반된 점에서, 단일 인스턴스 환경에서 장시간 실행되는 요청이 누적될 경우, 리소스 고갈과 성능 저하가 동시에 발생할 수 있는 구조임을 확인하였다.
또한 I/O 대기 중심의 처리 구조로 인해, 일부 요청 지연이 전체 처리량 저하로 이어질 가능성이 존재했기에, 성능뿐 아니라 가용성 확보 관점에서도 멀티 인스턴스 구조로의 전환이 필요한 상태로 판단하였다.
 

Claude를 IaC 검토 도구로 활용하기 — 인프라 마이그레이션에서 AI를 활용한 방법

Terraform을 먼저 익히는 방식이 아니라, 구성할 인프라를 자연어로 정의하고 이를 코드로 변환하는 방식으로 빠른 설계를 진행했다.
또한 Claude를 IaC 검토 도구로 활용하여, 보안 취약점과 설정 누락, 접근 제어 오류를 반복적으로 점검할 수 있도록 검토 프로세스를 구성했다. 기존처럼 사람이 수동으로 체크리스트를 확인하는 방식이 아니라, 변경 자체가 자동 검토로 이어지는 구조로 전환했다.
그 결과, IaC 경험이 많지 않은 상태에서도 설계 → 코드 생성 → 검증이 하나의 흐름으로 연결되었고, 설정 누락과 보안 오류를 사전에 차단할 수 있었다.
 

1. 자연어 기반으로 인프라를 정의

가장 중요한 것은 구축하려는 인프라의 최종 상태를 명확히 정의하는 것이였기에, 필요한 아키텍처의 의도를 자연어로 먼저 서술하고 Claude가 이를 HCL 코드로 번역하게 했다.
단일 ↔ 멀티 서버 전환 역시 동일한 기준으로 설계했다. “롤백 시 즉시 단일 서버로 복귀할 수 있어야 한다”는 요구를 기준으로, 인스턴스 수를 변수 하나로 제어하는 구조로 구성했다.
이처럼 인프라 설계 의도(롤백 가능성)를 변수로 명시하고, 운영 판단을 코드 수정 없이 제어할 수 있도록 분리했다.
 

2. Claude를 IaC 정적 분석기로 활용

두번째로, 자연어 요구사항을 기반으로 작성된 IaC 코드가 항상 설계 기준에 맞는지 검증이 필요하였다.
기존에는 필요할 때마다 검토를 요청하는 방식이였다면, 이번에는 코드 변경 자체가 검토 트리거가 되도록 흐름을 구성했다.

Claude가 체크하는 주요 포인트 예시

  • 분산 환경 안정성: 멀티 인스턴스 구조에서 Redis가 단일 장애점(SPOF)이 되지 않는지, Subnet 분리가 적절한지 검토
  • 리소스 고갈 방지: 인스턴스 확장 시 DB 커넥션 풀(HikariCP) 설정이 Max Connection을 초과하지 않는지 확인
  • 버전 호환성: MySQL 8.0 기준 Deprecated 구문(VALUES()) 사용 여부 및 Upsert 로직 유효성 검증
  • 보안 표준 준수: EC2 IMDSv2 강제, 스토리지 암호화, 삭제 방지 설정 등 기본 보안 정책 점검
이 파일은 모든 IaC 작업에서 공통 기준으로 참조되는 컨텍스트 역할을 했다.
notion image
실제로 RDS 백업 기간을 변경하며, 인스턴스 유형 때문에 terraform apply에 실패하였고, 아래 에러가 발생했다.
Claude는 자동으로 에러 메시지를 읽고 판단한 뒤, 값을 1로 되돌리면서 의도가 사라지지 않도록 주석으로 이유를 남겼다.
notion image
terraform apply 실패 → 원인 파악 → 코드 수정까지, 별도 검색이나 문서 확인 없이 하나의 흐름으로 처리됐다.
 

Hook 기반 자동 검토 — 변경 시점에 검증 수행

파일이 수정될 때마다 자동으로 Claude의 검토가 수행되도록 Hook을 구성했다. 사람이 수동으로 체크리스트를 대조할 필요 없이, 아래 시나리오에서 즉각적인 피드백을 받는다.
  • 리소스 생성 시 → 기본 보안 설정 누락 여부 확인
  • 보안그룹 변경 시 → 접근 범위 검증
  • 신규 리소스 추가 시 → 정책 위반 여부 검사
실제로 코드가 변경됐는데 ADR이 그대로인 경우를 함께 감지하여, 낡은 문서(ADR-012, 014)를 폐기 및 대체(Superseded) 상태로 분류하고, 새로운 설계 의도를 담은 신규 문서(ADR-016, 017)의 구성을 제안 하게 했다.
notion image
notion image
notion image
코드가 맞고 문서가 틀린 경우, 코드가 틀리고 문서가 맞는 경우 — 두 방향 모두 잡아낼 수 있다.  IaC 감사의 범위가 코드에서 설계 문서까지 확장되는 지점이다.
 

/iac-audit — 배포 전 전체 검증

부분 변경 검토와 별개로, 배포 전에는 전체 IaC 구성을 한 번에 점검하는 흐름을 추가했다.
  1. 의도하지 않게 외부로 노출된(Public) 리소스의 존재 여부
  1. 분산 환경에서의 가용성(HA) 확보 및 장애 전파 방지 구조
  1. 리소스 간 의존성 문제로 인한 배포 순서 오류 가능성
이 과정을 통해 부분적으로는 정상이나 전체적으로 잘못된 구성을 사전에 제거했다.
 

Terraform 실행 이후 작업까지 Claude가 이어서 정리

아래와 같이 현재 작업의 취약점이나 빠뜨린 부분, 남은 태스크 등을 IaC 실행 결과와 함께 후속 태스크를 자동으로 정리하도록 프로세스를 구성했다.
notion image
이를 통해,
  • 인프라 생성 이후 필요한 작업을 별도로 기억하거나 문서에서 찾을 필요가 없어짐
  • 설정 누락이나 순서 오류로 인한 배포 실패 가능성을 줄일 수 있었음
Terraform은 리소스를 생성하는 도구였고, Claude는 그 위에서 작업 흐름을 끊기지 않게 이어주는 역할을 했다.
 

3. Claude로 인프라 운영 자동화

IaC 검증을 넘어, 운영 중 발생하는 이벤트에 자동으로 반응하는 구조로 확장했다.
배포 실패, 컨테이너 장애, 메모리 위기 등 상황별 대응을 이벤트 기반 자동 진단·복구 흐름으로 자동화했다.

1. 배포 실패 → 자동 진단

롤링 배포 중 실패가 발생하면 SSH 접속 후 로그를 확인해야 했고, 그 사이 부분 장애 상태가 지속되는 문제가 있었다. 이를 해결하기 위해 배포 실패 시 Claude가 자동 진단을 수행하도록 Job을 추가했다.
실패한 인스턴스에만 조건부로 실행되며, 컨테이너 상태, 로그, 메모리, Docker 지표, 디스크 사용량를 즉시 수집하여, SSH 접속 없이도 원인 파악이 가능하게 된다.
 

2. Route53 헬스체크 실패 → 컨테이너 자동 복구

Route53은 장애 인스턴스를 DNS에서 제외하지만, 컨테이너 자체는 복구하지 않는다. 이로 인해 정상 응답이 돌아오기 전까지는 수동 개입이 필요한 공백이 존재했다.
이를 보완하기 위해 health-recovery.sh를 구성하고, 모든 인스턴스에서 5분 주기로 실행되도록 했다.
  • 컨테이너 미존재 → 오류 로그 후 종료
  • 컨테이너 중지 상태 → docker start 후 상태 확인
  • 실행 중이나 비정상(unhealthy + HTTP 미응답) → docker restart
  • 정상 상태 → 무음 종료
Route53이 DNS 레벨 격리, 스크립트가 컨테이너 복구를 담당하도록 분리하여, 격리 이후 복구까지 자동으로 이어지게 된다.
 

3. Sentry 에러 → 매일 자동 분석

notion image
notion image
ssolv는 외부 API 의존성이 높아 에러 노이즈가 많다. Sentry 이슈를 매일 직접 확인하고 우선순위를 판단하는 과정은 컨텍스트 전환 비용이 컸다.
Claude 스케줄 태스크를 구성해 매일 09:00에 Sentry 신규 이슈를 자동으로 수집하고, 소스 코드와 스택 트레이스를 연결해 우선순위별 원인 분석 리포트를 생성하도록 했다.
  • 각 이슈에 대해 영향 파일:라인, 원인 분류, 우선순위(HIGH/MEDIUM/LOW)를 출력
  • 외부 API 장애와 코드 버그를 자동으로 구분
  • 별도 Sentry 대시보드 접속 없이 분석 결과를 바로 확인 가능
 

4. Terraform 드리프트 → 주간 자동 감지

notion image
notion image
Terraform 상태 파일은 로컬에서 관리되며, 콘솔에서 직접 변경한 설정이 IaC와 조용히 벌어질 수 있다. 이 드리프트는 다음 terraform apply 시 예상치 못한 변경을 일으키는 원인이 된다.
Claude 스케줄 태스크를 구성해 매주 월요일 10:00에 terraform plan을 실행하고, 실제 인프라와 코드 간의 차이를 리포트하도록 했다.
  • 변경 사항이 없으면 → 정상 확인으로 종료
  • 예상치 못한 변경이 감지되면 → HIGH 우선순위로 분류해 보고
  • terraform apply는 실행하지 않음 — 감지와 보고에만 집중
 

5. 전체 인스턴스 메모리 경보 → 자동 진단 및 복구

인스턴스들의 부하 급증 시 OOM 위험이 존재하지만, Grafana 알림은 메트릭 수집 주기에 의존하기 때문에 즉각적인 대응에는 한계가 있었다.
이를 보완하기 위해 스크립트를 작성하고,  두 인스턴스에서 5분 주기로 실행되도록 구성했으며, 상태 수집 ⇒ 대응까지 Cluade가 하게 된다.
  • 메모리 사용률 80% 이상 → free -h, docker stats, JVM heap(actuator), 상위 5개 프로세스를 로그에 기록
  • 메모리 사용률 90% 이상 + 컨테이너 unhealthy → docker restart app-server 자동 실행
Grafana와 독립적으로 동작하기 때문에, 모니터링 스택 자체가 다운된 상황에서도 메모리 이상을 감지하고 대응할 수 있다.
또한, 이 과정에서 수집된 로그와 상태 정보는 이후 분석에 바로 활용될 수 있도록 정리되며, 해당 진단·복구 흐름은 Claude가 지속적으로 검토·보완하는 운영 데이터로 업데이트 되도록 구성했다.
 

자동화 이전에는 장애 발생 시 SSH 접속, 상태 확인, 재시작까지 모두 수동으로 처리해야 했지만, 현재는 이상 징후 감지 → 대응 → 진단 로그 확보까지가 자동으로 이어지는 구조로 전환되었다.
결과적으로 운영 개입 시점을 줄이고, 개입이 필요한 경우에도 이미 원인 분석에 필요한 정보가 확보된 상태에서 대응 가능하도록 했다.