node.js 서버에서 캐싱으로 최적화 진행하기
개요
이번에 진행했던 프로젝트에서 서버 쪽을 담당해서 개발을 진행했습니다. 그렇게 개발을 진행하다보니 런칭 전에 서버에 얼만큼 투자를 할지 결정해야 하는 시기가 도달했고, 현재 시스템 상 얼마 만큼의 동접을 버틸 수 있는지 체크를 하기로 결정했습니다.
부하 테스트
부하 테스트는 K6로 진행하기로 결정했습니다. k6는 JavaScript 기반으로, Node.js 와의 호환성이 뛰어나며, 도시 접속자수 테스트를 수행하기 편리한 도구로 보였습니다.
문제점 발견
부하 테스트를 진행하는 과정에서 예상보다 낮은 동시 접속자 수를 기록했습니다. 로그 및 실시간 모니터링, 프로파일링을 통해 확인해본 결과 두가지 주요 문제점을 발견할 수 있었습니다.
로그 기록의 지연 : 로그를 기록하는 IO 과정에서 상당한 지연이 발생했습니다
데이터베이스 접근 지연 : 데이터베이스 접근 후 데이터를 검색하는 과정이 비효율적이었습니다.
테스트를 할 때는 1명이 접속하는 것이니 해당 지연이 채감되지 않았는데 많은 인원이 한번에 요청하니 심각할 정도로 느려졌죠.
해결
이러한 문제들을 해결하기 위해서 다음과 같은 조취를 취했습니다.
winston 라이브러리를 활용해서 로그를 콘솔이 아닌 파일로 비동기적으로 기록하도록 변경했습니다. 이를 통해 IO 지연을 줄였습니다.
MemoryCache를 도입해 동일한 URL을 호출하면 1분에 한 번씩만 데이터베이스에 접근하도록 제한했습니다. 그리고 그 외의 시간에는 캐싱된 데이터를 반환하도록 수정했습니다.
테스트 및 문제 해결
성능 개선 이후, 테스트를 진행하면서 특정 API 에서 특정 유저의 개인 정보를 1분간 반환하는 문제가 발견되었습니다. 이는 개발 과정에서 발견되지 않고 다른 사람들과 진행한 테스트 과정에서 발견되었는데, 처음 데이터베이스에 접근한 유저의 데이터를 캐싱시켜서 반환했기 때문에 제가 혼자 테스트할 때는 발견하지 못하고 다른 사람이 테스트 할 때 그 사람은 데이터베이스에 접근하지 않고 다른 유저의 캐싱된 데이터를 받아서 발생한 문제였습니다.
결국 캐싱 매커니즘에 개인 액세스 토큰을 포함시켜 사용자별로 캐시를 관리하는 방식으로 수정해서 해결했습니다.
결과
이러한 최적화 작업 덕분에 개발 서버에서 동시 접속자 1000명을 유지하는 경우, 응답 속도가 기존 13초에서 최대 100ms로 대폭 개선되었습니다. 물론 이 경우는 쉴 틈 없이 데이터 교환을 테스트한 결과고 서버 특성 상 정보 교환이 자주 있는 편이 아니라 더 많은 인원을 수용할 것으로 예상되었습니다.
이 결과를 바탕으로 라이브 서버 사양을 고르게 되었죠.
지금 생각해 보면 그냥 멍청한 짓 해놓고 테스트하면서 수정한 것 같아 보이네요
Leave a Reply
Want to join the discussion?Feel free to contribute!