프로그래머의 블로그: gamer.ru의 뒷모습

content auto translated from {from}

작은 역사적 배경

사이트 gamer.ru는 벌써 세 번째 (어쩌면 네 번째) 완전한 코드 재작성 과정을 겪고 있습니다. 처음 프로젝트는 먼 과거의 2000년대 초에 Ruby-on-Rails로 작성되었습니다. 아키텍처는 모놀리틱했기 때문에, 사용자 요청 하나가 대량의 추가 데이터베이스 요청 및 가능한 모든 라이브러리 로드를 요청하게 되었습니다. 하루에 10만 명의 방문자를 수용하기 위해서는 총 다섯 대의 강력한 서버를 사용하고, memcached, Redis를 사용하며 여러 서버에 데이터베이스를 복제해야 했습니다. 이를 통해 2018년까지 간신히 버틸 수 있었고, 그 후 회사에 재정 문제가 발생하고 개발팀이 흩어졌습니다.

2020년경, 사이트의 SSL 인증서가 만료되었습니다. 오래된 Ruby-on-Rails 버전이 오래된 openssl 버전에 의존했기 때문에 인증서를 업데이트하는 것이 불가능했습니다. 새 인증서들은 더 최신 버전을 요구했습니다. 아무도 특별히 걱정하지 않았습니다 — 사이트는 간신히 작동을 유지했습니다. 2015년부터 2025년까지 방문자는 하루 10만에서 1천명으로 점차 감소했습니다. 숨겨진 블로그와 댓글에는 무수한 스팸이 등장했고, 그 중에는 그리 품위 있는 내용도 아닌 것들이 있었습니다. Yandex는 우리에게 대한 관심을 완전히 잃었고, 웹마스터에는 치명적인 오류가 가득했습니다.

문제 해결을 위한 우리의 조치

사이트는 더 이상 현실에 부합하지 않는 오래된 아키텍처로 인해 심각한 최적화가 필요했습니다. 데이터베이스에는 약 10만 개의 게시물과 160만 개의 댓글이 누적되어, 이를 새로운 엔진으로 신중히 이전해야 했습니다. 우리는 백엔드와 프론트엔드 모두에서 마이크로서비스 아키텍처로 전환하기로 결정하고, 현대 기술을 동시에 도입했습니다.

프로젝트는 제3자 라이브러리 없이 NodeJS로 처음부터 완전히 다시 작성되었습니다. 이는 향후 10-20년 동안 우리의 안정적인 운영을 보장합니다. ExpressJS나 React와 같은 최신 라이브러리의 업데이트가 전체 사이트를 망가뜨려 거대한 리팩토링을 요구할 일도 없게 되었습니다. 그러므로 게시물의 시각적 편집기를 직접 작성해야 했습니다. 우리의 소박한 요구를 충족시킬 수 있는 기존 솔루션을 찾을 수 없었습니다. 이제 엔진은 구형 장치와 검색 엔진을 위해 HTML 페이지를 렌더링하고, 사용자에게는 AJAX를 통해 콘텐츠를 제공합니다.

현재 사이트는 초당 150개의 요청을 성공적으로 처리하고 있으며, 이 중 대다수의 트래픽은 검색봇과 기타 크롤러에 의해 발생합니다. 특히 semrush와 openai 봇의 동작이 활발하여, 하루에 사이트 전체를 다운로드하려고 하는 것처럼 보입니다. Yandex가 느릿느릿 요청하여 초당 1-2번 인덱싱하는 반면, 이 친구들은 50번 요청할 수 있습니다.

하지만 엔진은 매우 최적화되어 있어서 이러한 봇 군단은 겨우 한 대의 저렴한 가상 서버에서 월 500 루블 정도의 비용으로 쉽게 처리됩니다.

물론, 사이트는 가끔 502 및 504 오류로 우리에게 상기시켜주며, 이러한 오류는 점진적으로 발견되고 수정되고 있습니다. 때때로 누군가가 데이터베이스에 인덱스를 추가하는 것을 잊거나, 너무 복잡한 요청을 여러 개의 간단한 요청으로 나눠야 할 때도 있고, 서버의 공간이 단순히 부족해지는 경우도 있습니다. 하지만 우리는 포기하지 않습니다 — 작업은 계속 진행되며, 과정은 '통제하에' 있다고 할 수 있습니다.