1. 배경: 어떤 현상을 발견해서
어느 날 사용자가 대규모 이벤트가 진행되는 웹사이트에 접속할 때, 페이지 로드 시간이 평소보다 급격히 느려지는 현상이 발생했습니다. 특히, API 요청 대기 시간이 길어지면서 사용자 경험이 크게 저하되었습니다.
2. 발단: 이런 장애가 생길 수 있다는 것을 인지했고
장애 분석 중, 특정 API 서버에서 처리 속도가 비정상적으로 느려지는 문제가 발견되었습니다. 트래픽 급증으로 인해 데이터베이스 쿼리 처리 시간이 증가하고, 일부 요청이 타임아웃되는 상황이 발생했습니다. 서버 로그를 확인한 결과, 특정 쿼리가 자주 호출되며 병목 현상이 발생하는 것을 확인했습니다.
3. 전개: 장애를 대응, 해결하던 와중에
우선 문제를 완화하기 위해 다음과 같은 긴급 대응을 수행했습니다:
- 트래픽을 분산하기 위해 API 서버의 인스턴스를 수평적으로 확장(Auto-scaling)하였습니다.
- 타임아웃 발생을 줄이기 위해 클라이언트와 서버의 타임아웃 설정을 늘리고, 요청 재시도 로직을 추가했습니다.
- 데이터베이스 모니터링 도구를 통해 쿼리 성능 병목을 추적했습니다.
일시적으로 성능은 개선되었지만, 쿼리 병목 문제를 근본적으로 해결하지 않는 한 트래픽 급증 시 동일한 문제가 반복될 가능성이 있음을 깨달았습니다.
4. 위기: 또 다른 장애 발견 또는 간단하게 해결할 수 없다는 것을 알게되어서
데이터베이스 성능을 분석한 결과, 주요 병목의 원인은 조인과 정렬이 많은 대규모 데이터 쿼리였습니다. 캐싱을 적용하지 않은 상태에서 동일한 쿼리가 반복적으로 실행되고 있었으며, 트래픽 급증 시 데이터베이스 자원이 빠르게 소진되었습니다.
더 나아가, 일부 쿼리는 인덱스가 제대로 설정되지 않아 풀 테이블 스캔을 발생시키고 있었습니다. 이는 단순히 서버 확장으로 해결할 수 있는 문제가 아니었습니다.
5. 절정: 근본적인 해결을 위해 이런 방법으로 접근하였다
근본적인 해결을 위해 다음과 같은 조치를 계획 및 실행했습니다:
- 쿼리 최적화:
- 병목이 발생한 주요 쿼리의 실행 계획(EXPLAIN)을 분석하고, 필요한 컬럼에 적절한 인덱스를 추가했습니다.
- 자주 사용하는 데이터는 정규화된 테이블 대신 캐싱 테이블을 도입하여 정규화 비용을 줄였습니다.
- Redis를 활용한 캐싱:
- 동일한 쿼리가 반복적으로 호출되는 문제를 완화하기 위해 Redis를 도입하여 자주 사용되는 데이터를 캐싱했습니다.
- 캐싱 정책으로 일정 시간 간격(TTL)을 설정하여 데이터 신뢰성과 효율성을 균형 있게 유지했습니다.
- 읽기/쓰기 분리:
- 데이터베이스의 읽기 작업과 쓰기 작업을 분리하기 위해 읽기 전용 복제본(Read Replica)을 설정했습니다.
- API 서버는 읽기 요청을 복제본으로 라우팅하고, 쓰기 요청은 기본 데이터베이스로 처리하도록 수정했습니다.
- 부하 테스트:
- 개선된 시스템의 안정성을 검증하기 위해 JMeter와 같은 부하 테스트 도구를 활용하여 대규모 트래픽 시뮬레이션을 수행했습니다.
6. 결말: 따라서, 이런이런 방법을 통해 근본적으로 해결 및 앞으로 유지, 보수에 용이하게 개선하게 되었다
이러한 조치의 결과:
- 쿼리 응답 시간이 평균 300ms에서 50ms로 단축되었습니다.
- 트래픽 급증 시에도 데이터베이스 부하가 일정 수준으로 유지되어 서비스 중단 없이 운영이 가능해졌습니다.
- Redis 캐싱으로 API 서버의 요청 처리 속도가 대폭 개선되었고, 읽기/쓰기 분리로 데이터베이스의 확장성이 증가했습니다.
- 최적화된 쿼리와 캐싱 정책 덕분에 향후 유지보수가 용이해졌고, 추가적인 트래픽 증가에 대비할 수 있게 되었습니다.
이번 개선으로 단기적인 문제를 해결했을 뿐만 아니라, 장기적으로 확장 가능한 시스템 기반을 마련할 수 있었습니다. 😊
'REACT' 카테고리의 다른 글
으아 이놈의 next.js (1) | 2024.12.11 |
---|---|
MBTI_TEST 2 (0) | 2024.11.26 |
리액트 심화주차 정리 (1) | 2024.11.22 |
뉴스피드 팀 프로젝트 _ 최최종 (0) | 2024.11.21 |
뉴스피드 팀프 _ 최종 (0) | 2024.11.21 |