GeoDirectory

wp-rankings.com 구축 방법: GeoDirectory로 60,000개 리스팅과 1,600만 행 처리

지난주, 우리는 wp-rankings.com 를 공개했습니다.

WordPress.org 저장소의 모든 플러그인을 추적합니다: 성장세, 설치 추정치, 순위, 모멘텀, 키워드 포지션, 경쟁사 비교까지.

이 사이트의 구성 요소는 다음과 같습니다:

이 모든 것이 GeoDirectory 위에서 돌아갑니다.

검색은 자체 Elasticsearch 익스텐션을 통해 처리됩니다. 이 규모의 사이트를 위해 직접 만든 GeoDirectory 애드온입니다. 왜 필요했는지는 나중에 더 설명하겠습니다.

사람들은 GeoDirectory가 얼마나 확장 가능한지를 끊임없이 묻습니다. 예전 답변은

이 글은 사이트가 어떻게 구축되었는지를 다룹니다.

이 사이트가 존재하는 이유

WordPress.org는 예전에 모든 플러그인 페이지에 활성 설치 성장 차트를 보여줬습니다. 어느 시점에 이를 없앴고, 복원을 요청하는 Trac 티켓인 #6511은 아직도 열려 있습니다.

그 차트는 플러그인이 실제로 성장하고 있는지를 확인할 수 있는 유일한 방법이었습니다.

이것 없이는 버킷 안의 숫자, 즉 "10,000+ active installs"만 보일 뿐, 그게 빠르게 오르고 있는 10,000인지 아니면 조용히 무너지고 있는 19,000인지 전혀 알 수 없습니다.

그래서 4년 전, 저희는 매일 WordPress.org 플러그인 API를 수집하고 결과를 저장하기 시작했으며, wp-rankings V1을 만들었습니다.

그 이후로 하루도 빠진 적이 없습니다.

전체 저장소에 걸쳐 4년간의 일별 스냅샷. 이것은 나중에 돌아가서 만들 수 없는 유일한 것입니다.

V2는 그 진화된 버전으로, 훨씬 더 많은 통계를 제공하며, 데이터를 위한 세계적 수준의 프런트엔드를 마침내 구축했을 때 탄생한 결과물입니다.

리스팅 구조

저장소의 모든 플러그인은 GeoDirectory 리스팅입니다. A gd_place 포스트로, 데이터는 GeoDirectory의 detail 테이블에 저장됩니다. wp_geodir_gd_place_detail.

각 플러그인에는 커스텀 필드가 40개 있습니다. 활성 설치 수, 다운로드 수, 평점, 평가 수, 지원 스레드, 해결된 스레드, 버전, 테스트 완료 버전, WordPress.org 순위, 그리고 저희가 직접 계산하여 기록한 값들이 포함됩니다.

이 부분을 사람들이 과소평가합니다.

GeoDirectory 커스텀 필드는 실제 테이블 안의 실제 스키마로, 실제 컬럼 타입을 가집니다. 저희가 계산한 성장률은 FLOAT 컬럼에 저장됩니다.

인덱싱, 정렬, 필터링이 됩니다. 데이터베이스 컬럼처럼 동작하는 이유는, 실제로 그것이기 때문입니다.

규모가 있는 사이트에서 post meta 값으로 WordPress 아카이브를 정렬해본 적이 있다면, 이것이 왜 중요한지 알 것입니다.

Post meta는 스키마 코스튬을 입은 키-값 저장소이며, 흥미로운 질문을 던지기 시작하는 순간 정확히 무너집니다.

이 포스트의 다른 모든 내용은 이 하나의 결정에 달려 있습니다. 데이터를 커스텀 필드에 제대로 넣으면, 나머지는 가능해집니다.

검색과 정렬, 그리고 저희가 저지른 실수

이 포스트에서 한 섹션만 읽는다면, 바로 이 섹션을 읽으세요.

저희는 트렌딩 정렬이 필요했습니다. 7일 성장률로 아카이브를 정렬해 지금 무엇이 움직이고 있는지 확인하는 것이었습니다.

Claude Code가 이 프로젝트의 구현 대부분을 담당했는데, 처음 제안한 답변은 커스텀 SQL이었습니다. GeoDirectory의 쿼리에 덧붙인 커스텀 JOIN과 커스텀 order-by 훅이었습니다.

합리적으로 보였습니다. 로컬에서는 잘 작동했습니다.

라이브 사이트에서는 성능이 무너졌습니다. 빠르게 처리되던 검색이 수십 초씩 걸렸습니다.

저희는 즉시 문제를 발견하고 AI에게 전부 버리고 GeoDirectory 방식으로 다시 하도록 했습니다.

올바른 수정 방법은 간단했습니다. 다음을 추가하세요 growth_7d 를 GeoDirectory 커스텀 필드로 추가하면 상세 테이블에 FLOAT 컬럼이 생성됩니다. 백그라운드 작업에서 값을 계산하고, 해당 필드에 기록하면 됩니다.

그런 다음 GeoDirectory 자체 정렬 시스템에 정렬을 등록하고, GeoDirectory가 다른 항목들을 정렬하듯 이 항목도 정렬하도록 맡기면 됩니다. growth_7d_desc. 끝입니다.

다시 빠릅니다. 60,000개의 리스팅에서도요.

여기에 교훈이 있습니다. 그리고 이것은 이 프로젝트를 훨씬 넘어서는 이야기입니다.

AI 코딩 도구는 기본적으로 여러분의 인프라를 새로 구축하려 합니다. 정렬 문제를 던져주면, 훈련 데이터에서 수백만 번 봤기 때문에 SQL부터 꺼내 듭니다.

Stiofan이 대용량 데이터셋을 위해 GeoDirectory의 쿼리 레이어를 수년에 걸쳐 최적화해 왔다는 사실을 모릅니다.

자신이 막 만들려는 모든 것이 이미 구축되어 프로덕션에서 테스트되고 10년에 걸쳐 다듬어졌다는 사실도 모릅니다.

해결된 문제의 더 나쁜 버전을 자신 있게 내놓고는, 스스로 아주 뿌듯해할 것입니다.

따라서 GeoDirectory 사이트에서 Claude나 ChatGPT를 사용하고 있다면, 줄 수 있는 가장 값진 지침은 바로 이것입니다:

GeoDirectory의 네이티브 검색, 정렬, 필터 인프라를 우회하지 마세요. 커스텀 필드로 확장하세요.

커스텀 필드는 바로 그 용도로 존재합니다. 그게 핵심 비결입니다.

GeoDirectory가 끝나는 곳, 그리고 우리 코드가 시작되는 곳

저희는 커스텀 플러그인 2개를 보유하고 있습니다.

첫 번째는 스크레이퍼입니다. Stiofan이 4년 전에 만든 것으로, 단 하나의 역할만 합니다: 매일 WordPress.org 플러그인 API를 가져와 찾은 내용을 리스팅에 기록하는 것입니다. 이 데이터셋이 존재하는 이유가 바로 이것이며, 그 이후로 조용히 계속 실행되고 있습니다.

두 번째는 V2에서 새롭게 추가된 분석 플러그인입니다. 1,620만 행 규모의 스냅샷 테이블을 담당하며, 플러그인당 하루 한 행씩 순위 위치, 설치 구간, 추정 설치 수, 성장률, 모멘텀 상태를 기록합니다.

시계열 분석은 디렉터리가 할 일이 아니며, GeoDirectory에 그 역할을 맡길 생각은 전혀 없습니다. 해당 테이블은 자체 스키마, 인덱스, 백그라운드 작업을 갖추고 있으며 GeoDirectory 외부에 완전히 독립적으로 존재합니다.

하지만 결과는 다시 가져옵니다.

분석 플러그인은 자체 데이터에 대한 무거운 처리를 수행한 후, 그 결과를 GeoDirectory 커스텀 필드에 기록합니다. 7일 성장률은 수백만 행의 과거 데이터에서 계산되어 리스팅에 단일 FLOAT 값으로 표시됩니다.

GeoDirectory의 관점에서는 그냥 또 하나의 필드일 뿐입니다. 다른 필드와 똑같이 정렬하고, 필터링하고, 표시합니다.

연산은 외부에서. 저장은 내부에서. 쿼리는 GeoDirectory가.

이것이 세 줄로 요약한 아키텍처이며, 매우 큰 데이터셋 위에서도 사이트가 빠른 이유입니다. 아카이브 쿼리는 1,600만 행에 절대 손대지 않습니다. 몇 시간 전에 계산된 단 하나의 숫자를 읽을 뿐입니다.

단일 리스팅 페이지

플러그인 페이지는 하나의 대시보드입니다. 지표 카드, 신뢰도 등급이 포함된 추정 활성 설치 수, 30일·90일·1년·전체 기간에 걸친 성장 차트, 모멘텀 분류기, 다음 마일스톤 예측, 리뷰 및 지원 통계, WordPress.org 키워드 순위, 그리고 최대 3개의 경쟁 플러그인과의 비교 카드가 제공됩니다.

내부적으로는 기본 Blockstrap을 사용하는 표준 GeoDirectory 단일 리스팅 페이지입니다. 커스텀 테마는 없습니다.

대시보드 자체는 저희 코드입니다. 커스텀 필드에서 데이터를 받아 Chart.js로 구현했습니다. 일반 Blockstrap 사용자가 직접 손으로 만들기는 어렵고, 그렇지 않은 척할 이유도 없습니다.

그런데 한 가지 솔직하게 말씀드릴 것이 있습니다: 이제 더 이상 직접 손으로 만들 필요가 없습니다.

2년 전만 해도 이런 페이지를 만들려면 개발자를 몇 주 동안 고용해야 했습니다.

이제는 원하는 것을 설명하기만 하면 AI가 만들어 줍니다. 차트, 카드, 비교 테이블, 조건부 배지까지.

지금은 거의 간단한 일이 되었습니다. 어려운 부분은 이미 끝났으니까요. 데이터는 GeoDirectory 커스텀 필드 안에 구조화되고, 타입이 지정되고, 쿼리 가능한 형태로 자리 잡고 있었습니다.

AI는 깔끔한 데이터 레이어 위에서 구축하는 것을 매우 잘합니다. 하지만 데이터 레이어를 처음부터 만드는 것은 매우 서툽니다.

잘 구조화된 커스텀 필드를 주고 성장 차트를 요청하면 점심 전에 완성됩니다. 쿼리 레이어 설계를 맡기면, 저희가 직접 겪어봤듯이, AI는 신나게 사이트를 망가뜨릴 겁니다.

그래서 역할 분담은 간단합니다. 데이터와 쿼리는 GeoDirectory가 담당하고, 그 위에 원하는 것은 무엇이든 AI가 만듭니다.

그 순서대로 진행하면, 이런 종류의 사이트는 한 사람의 손이 닿는 범위 안에 있습니다.

아카이브

여기서 위의 모든 것이 결실을 맺습니다.

트렌딩 페이지는 활성 설치 수가 10,000 이상인 플러그인을 7일간 성장 속도 순으로 표시합니다. 순위, 플러그인, 24시간 변동, 7일 변동, 성장률, 예상 활성 설치 수가 나타납니다.

전체 구성은 GeoDirectory 리스팅 블록입니다.

GeoDirectory 자체 리스팅 블록이 GeoDirectory 정렬 옵션으로 정렬되고, GeoDirectory 커스텀 필드를 읽습니다. 트렌딩 정렬은 다른 모든 정렬과 함께 GeoDirectory의 정렬 시스템 안에 위치하므로, 리스팅이 작동하는 곳이라면 어디서든 동작합니다.

어디에도 커스텀 SQL은 없습니다.

통계 페이지에서 바로 연결됩니다.

는 클릭 한 번이면 됩니다.

커스텀 필드에 데이터를 넣고 정렬을 올바르게 등록하면, GeoDirectory가 이미 제공하는 구성 요소들로 아카이브가 저절로 조립됩니다.

소유권 주장 흐름

플러그인 소유자는 자신의 리스팅을 소유권 주장할 수 있습니다. 이는 GeoDirectory의 기본 소유권 주장 기능에 저희 인증 로직을 추가한 것입니다.

저희는 플러그인의 Plugin URI: 헤더, 즉 메인 PHP 파일에 있는 항목을 확인하고, 소유권 주장자가 해당 도메인을 제어하는지 검증합니다.

이메일 인증 후, 클릭 시 자동 승인됩니다.

첫 주에 약 100개의 플러그인이 소유권 주장되었습니다.

이 사이트 전반에 걸친 동일한 패턴입니다.

GeoDirectory가 기능을 제공합니다. 비즈니스 규칙은 그 위에 얹으시면 됩니다.

트래픽, 속도, 그리고 Elasticsearch 문제

론칭은 거의 전적으로 X에 의해 주도되었습니다.

해당 게시물이 널리 퍼지면서 WordPress 분야의 유명 인사 몇 명이 이를 공유했고, 트래픽이 한꺼번에 몰려들었습니다.

론칭 당일 실제 사용자 3,000명. 24시간에 고르게 분산된 것이 아니라, 특정 몇 시간에 집중되었습니다.

측정에 관해 한 말씀 드립니다. 이 부분에서 많은 분들이 실수를 하시거든요. Cloudflare는 해당 기간 동안 72,000명의 순방문자를 보고했습니다. 서버 로그에는 약 3,000명의 실제 사용자가 기록되어 있었습니다. 나머지는 봇이었습니다.

클라이언트에게 디렉토리 트래픽을 보고하기 전에, 축배를 들기 전에 서버 로그를 먼저 확인하세요.

스택은 버텼습니다. GeoDirectory Cloud, 앞단의 Cloudflare, LiteSpeed 캐싱.

특별할 것 없는 구성입니다.

Google PageSpeed 점수는 92점이며, 최적화는 아직 시작도 하지 않았습니다(베타가 끝나면 진행할 예정입니다).

이제 솔직한 이야기를 해드릴게요.

이 사이트의 검색은 GeoDirectory용으로 자체 개발한 Elasticsearch 익스텐션을 통해 작동합니다.

40개의 커스텀 필드를 가진 60,000개의 리스팅과 계산된 값을 기준으로 정렬하다 보니, 검색과 커스텀 정렬이 원하는 것보다 느려지고 있었습니다.

MySQL이 필요 이상으로 과부하를 처리하고 있었습니다.

대부분의 디렉토리는 그 수준에 근접하지도 않을 것입니다.

GeoDirectory의 기본 검색은 빠르며, 몇 천 개의 리스팅을 운영하고 계신다면 이미 충분한 선택입니다. 저희가 그렇게 말씀드릴 수 있습니다.

wp-rankings는 실제로 곡선의 가장 끝자락에 위치한 사례이며, Elasticsearch 익스텐션은 MySQL의 한계를 넘어선 사이트를 위한 맞춤형 빌드에 설치하고 구성하는 솔루션입니다.

중요한 점은 GeoDirectory의 검색 레이어에 연결된다는 것입니다.

내부 엔진만 교체되며, 그 위의 모든 것은 기본 방식을 유지합니다. 검색, 정렬, 필터는 여전히 GeoDirectory가 담당합니다.

반대 방향에서 바라보는, 앞서 말씀드린 것과 같은 원칙입니다.

GeoDirectory의 인프라와 함께 작업하세요. 절대 우회하지 마세요. 하나는 사이트를 확장시키고, 다른 하나는 망가뜨립니다.

나머지 스택

UsersWP 계정, 로그인, 회원가입, 프로필을 위해.

Blockstrap, 그리고 Blockstrap 페이지 빌더 플러그인, 템플릿과 모든 시각적 요소를 위해.

Turnstile 로그인 및 회원가입에 적용, AyeCode Connect.

GetPaid 및 UsersWP Membership 수요가 실제로 입증될 경우 프리미엄 티어를 위해. 아직 구축하지 않았습니다.

예상치 못했던 수요는 광고입니다.

이미 여섯 명 가까운 사람들이 사이트 스폰서십을 문의해 왔고, 그래서 GeoDirectory Advertising 애드온을 다음에 추가할 예정입니다. 셀프서비스 방식으로, 스폰서가 저희의 개입 없이 직접 광고 지면을 구매할 수 있습니다.

완전한 AyeCode 스택이 설계된 목적 그대로 작동합니다. 여기에 임시방편은 없습니다.

이것이 증명하는 것

"GeoDirectory는 얼마나 확장될 수 있나요?"라는 질문에 예전에는 어깨를 으쓱하며 클라이언트 사이트 목록을 내밀곤 했습니다.

이제 직접 가서 한번 망가뜨려 볼 수 있는 공개 사이트가 있습니다.

60,000개의 리스팅. 각각 40개의 커스텀 필드. 그 뒤에 1,600만 행의 기록.

대부분의 디렉토리 사이트를 무너뜨릴 만한 트래픽 급증도, 흔들림 없이 소화해냈습니다.

단 두 명이 만들었습니다.

구현의 대부분은 AI의 도움을 받았으며, 진짜 문제가 생긴 유일한 순간은 AI가 GeoDirectory의 구조를 활용하는 대신 새로 설계하도록 내버려 뒀을 때였습니다.

직접 확인해 보세요: wp-rankings.com

비슷한 것을 만들고 싶다면, 무엇으로 구동되는지 이미 알고 계실 겁니다.