2023.02 ~ 2023.03 나의 2023년초는 장애로 얼룩졌다. 주말 시험에 장애가 3주 연속으로 발생했던 것으로 기억하는데, 장애 원인이 정말 다양하게도 있었다. - WebRTC SaaS인 Agora의 API limit에 걸려서 응시자들이 화상 연결에 실패했는데, 계속된 retry로 인해 limit 해제가 되지 않고 결국 시험을 연기했다. 고객사에서 이 장애에 대한 원인 규명과 후속 조치에 대한 계획을 요구해서 그에 대한 대응을 하기도 했고, 보험 처리가 되긴 했지만 배상금도 1억 정도 나왔었다. - 시험의 인원이 등록되지 않아 오토스케일링이 동작하지 않았는데, 마침 당일에 온콜에 익숙하지 않은 엔지니어가 대기하고 있어서 체크하지 못했었다. 그리고 결국 웹서버 부족으로 인해 CPU가 높아져서 장애가 발생했다. - 영업팀의 요청으로 웹서버의 숫자를 평소보다 늘렸는데, 데이터베이스가 연결 과다로 인해 메모리가 부족해져서 죽었다. 이 날 마침 데브옵스팀에서 데이터베이스 증설을 놓친 상태여서 메모리가 더욱 부족했다. 그리고 데이터베이스가 failover되었는데, 웹서버에서 write, read 데이터베이스 정보가 바뀌지 않아서 한참동안 read 데이터베이스에 write 요청을 보내기도 했다. 장애 원인은 다양했지만, 핵심적인 원인은 트래픽에 제대로 대응을 못하게 된 것이었기 때문에 먼저 부하테스트를 자동화하기로 팀 내에서 결정했다. 그냥 부하테스트를 하지 않고 자동화를 한 이유는, 시험의 문제 개수 등에 따라 트래픽 유형이 다를 수도 있고 기능이 추가되었을 때 성능에 미치는 영향을 빠르게 확인하고 싶었기 때문이다. 최종 목표인 부하테스트 자동화를 달성하기 위해 다음과 같이 업무를 작게 쪼개서 진행했다. - 로컬에서 부하테스트 진행할 수 있게 만들기 - 부하테스트 툴을 GitHub Actions로 수행 - 부하테스트 인프라 설정하는 Terraform을 작성하고 GitHub Actions로 수행 - 부하테스트 규모를 GitHub Actions 인자로 받아서 부하테스트 시나리오 선택 - 부하테스트 결과 리포트 자동화 - 부하테스트 시나리오 고도화 업무를 진행하기 전에 먼저 부하테스트 도구를 리서치했다. 팀 내에서 부하테스트를 할 때 ruby-jmeter와 locust를 사용한 경험이 있었지만, 두 도구는 성능이 좋지 않아서 응시자 10000명 규모를 테스트하려면 클러스터를 구성해야했다. 그래서 하나의 인스턴스로 수 만명의 규모를 테스트할 수 있는 k6를 선택했고, 프로젝트가 끝난 지금 생각해도 훌륭한 선택이었던 것 같다. 내가 k6로 부하테스트를 돌리는 작업을 맡았고, 팀 내의 다른 백엔드 개발자 분이 Terraform으로 부하테스트 인프라를 자동으로 설정하는 부분을 담당하셨다. 그렇게 계획대로 차근차근 부하테스트 자동화를 진행하고 있었는데 내가 갑자기 TF로 가게 되었다. 서비스에서 너무 장애가 자주 발생한다고 판단한 CTO님이 안정성 개선하는 TF를 만들어서 CTO 1명, 백엔드 개발자 2명과 데브옵스 1명으로 인원을 구성했고, 백엔드 개발자 중 하나로 내가 들어가게 되었다. TF에서는 기존에 하던 부하테스트 자동화 업무를 이어서 진행한 후에 서버 오토스케일링 개선 및 성능 개선 작업을 진행하기로 했다. TF 시작 전에 부하테스트 자동화 시스템의 기본적인 부분은 거의 완성한 상태여서, 결과 리포트 자동화와 시나리오 고도화 작업 위주로 진행했다. 응사자 입장에서 시험을 진행하며 크롬 개발자 도구에서 요청하는 uri와 think time을 가져와서 시나리오를 고쳤다. 그리고 k6에 WebSocket 테스트 기능도 있어서 WebSocket도 시나리오에 추가했다. 결과 리포트의 경우, k6 가이드의 influxdb와 grafana를 사용한 베스트 프랙티스를 보고 구성해보았는데 원하는 성능을 위해서는 너무 큰 인스턴스가 필요했었다. 그래서 Rails instrument API를 사용해서 redis에 성능 측정 결과를 임시로 저장하는 방식으로 결과를 받았다. 이렇게 부하테스트 자동화를 마친 후에는 AWS RDS Proxy를 적용하는 작업을 진행했다. 웹서버가 늘어나도 데이터베이스의 커넥션이 너무 많아지지 않도록 막고, failover된 후에 write/read 데이터베이스 정보를 빠르게 적용하기 위함이었다. 그리고 다음 날 최대 동시 접속자 수를 계산해서 필요한 웹서버 개수와 데이터베이스 인스턴스 크기대로 스케일링을 설정하는 작업을 진행했다. 웹서버 스케일링은 기존에 있었던 로직에 검증 로직만 더한 정도였지만, RDS 인스턴스의 스케일업을 예약하는 기능은 처음으로 추가한 작업이어서 많이 신경을 썼던 기억이 난다. 데이터베이스 인덱스 최적화와 통계 작업 비동기화 등 성능 개선 작업을 진행하는 것으로 TF 업무는 마무리되었다. 안정성 TF를 마무리한 후 몇 개월 동안 트래픽으로 인한 장애는 한 번도 없었다. 진작에 우선순위를 높여서 진행했으면 좋았겠다는 아쉬움이 들기도 했고, 목적을 잘 달성했다는 성취감도 들었다. 특히 부하테스트 자동화 업무의 경우, 최소 기능부터 애자일하게 진행한 과정도 좋았고 짧은 시간 안에 완성도도 높게 만들어서 만족스러웠다.