FastAPI와 PostgreSQL로 16,750페이지 프로그램형 SEO 사이트 구축기
출처: Dev.to
모든 호주 은행 이체에는 BSB 번호가 필요합니다 — 은행과 지점을 식별하는 6자리 코드입니다. 16,750개가 넘는 활성 BSB 코드가 존재함에도 기존 조회 도구들은 사용성이 떨어지거나 광고가 많거나 은행 웹사이트 안에 파묻혀 있었습니다.
그래서 저는 **BSBFinder.com**을 만들었습니다 — 빠르고 무료인 도구로, 어떤 BSB 코드를 검색하더라도 은행명, 지점 주소, SWIFT 코드, 결제 가능 여부를 즉시 확인할 수 있습니다.
스택
| 구성 요소 | 기술 |
|---|---|
| 백엔드 | FastAPI (Python) |
| 데이터베이스 | PostgreSQL |
| 템플릿 엔진 | Jinja2 (서버‑사이드 렌더링) |
| 리버스 프록시 | Caddy |
| 인프라 | Docker on AWS Lightsail |
| 데이터 소스 | AusPayNet (공식 BSB 레지스트리) |
저는 SPA 대신 서버‑사이드 렌더링을 선택했습니다. 16,750개 이상의 개별 페이지를 가진 프로그램적 SEO 사이트에서는 SSR이 크롤링 가능한 HTML을 즉시 제공해 검색 엔진이 바로 색인할 수 있게 해 줍니다 — JavaScript 렌더링이 필요 없습니다.
데이터 파이프라인
프로젝트의 기반은 호주 BSB 할당을 관리하는 공식 기관인 AusPayNet의 BSB 데이터셋입니다.
- 추출 – 공식 BSB CSV(은행 코드, 지점명, 주소, 주, 우편번호, 결제‑방법 플래그)를 파싱합니다.
- 보강 – BSB 접두사를 모은행의 SWIFT/BIC 코드와 매핑합니다.
- 스냅샷 – 타임스탬프가 붙은 스냅샷을 저장해 과거 변동(지점 폐쇄, 합병, 이전)을 추적합니다.
- 로드 – 적절한 인덱스를 적용해 PostgreSQL에 Upsert합니다.
스냅샷 시스템은 제가 가장 자부심을 갖는 기능 중 하나입니다. 주기적인 스냅샷을 저장함으로써 BSBFinder는 사용자가 마지막으로 BSB가 변경된 시점과 어떤 내용이 바뀌었는지를 보여줄 수 있어, 더 이상 유효하지 않은 오래된 BSB를 다룰 때 유용합니다.
# Simplified snapshot comparison logic
def detect_changes(current_snapshot, previous_snapshot):
changes = []
for bsb, data in current_snapshot.items():
if bsb not in previous_snapshot:
changes.append({"bsb": bsb, "type": "added"})
elif data != previous_snapshot[bsb]:
changes.append({
"bsb": bsb,
"type": "modified",
"old": previous_snapshot[bsb],
"new": data
})
for bsb in previous_snapshot:
if bsb not in current_snapshot:
changes.append({"bsb": bsb, "type": "discontinued"})
return changes
프로그램적 SEO: 템플릿으로 만든 16,750 페이지
핵심 SEO 전략은 프로그램적이며 — 각 BSB 코드는 템플릿을 통해 개별 페이지가 생성됩니다. “프로그램적”이 얇은 페이지를 의미하는 것은 아닙니다. 각 BSB 페이지에는 다음과 같은 내용이 포함됩니다.
- BSB 번호, 은행명, 전체 지점 주소
- 모은행의 SWIFT/BIC 코드
- 결제 방식 지원 (BECS, NPP, Direct Entry)
- 동일 은행의 인근 지점
- 해당 BSB에 대한 가장 흔한 질문을 모은 FAQ 섹션
- 리치 검색 결과를 위한 Schema.org 구조화 데이터
핵심 교훈: 구글은 16,750개의 거의 동일한 페이지와 16,750개의 각각 고유하고 유용한 콘텐츠가 있는 페이지를 매우 다르게 취급합니다. 인근 지점 섹션, 동적 FAQ, 결제 가능 상세 정보가 각 페이지를 진정으로 차별화합니다.
URL 구조
평평하고 읽기 쉬운 구조는 URL을 짧고 크롤링에 친화적으로 유지합니다:
/bsb/062-000 → 개별 BSB 페이지
/bank/cba → Commonwealth Bank의 모든 BSB
/state/nsw → 뉴 사우스 웨일즈 주의 모든 BSB
/suburb/vic/melbourne → 빅토리아 주 멜버른의 BSB
/postcode/2000 → 우편번호 2000의 BSB
각 BSB 페이지는 해당 은행, 주, 교외, 우편번호 페이지로 연결되어 내부 링크망을 형성합니다. 이는 검색 엔진이 좋아하는 깊은 웹 구조를 만듭니다.
대규모 사이트맵
BSB 페이지 16,750개에 은행, 주, 교외, 우편번호, 가이드 URL을 더하면 총 20,000개가 넘습니다. 구글의 사이트맵 제한은 파일당 50,000 URL이지만, 저는 크롤링 관리 효율을 위해 5,000개씩 나눠서 제공했습니다.
/sitemap-index.xml
├── /sitemap-bsb-1.xml (5,000 BSB 페이지)
├── /sitemap-bsb-2.xml (5,000 BSB 페이지)
├── /sitemap-bsb-3.xml (5,000 BSB 페이지)
├── /sitemap-bsb-4.xml (남은 BSB 페이지)
├── /sitemap-banks.xml (은행 페이지)
├── /sitemap-locations.xml (주, 교외, 우편번호 페이지)
└── /sitemap-guides.xml (편집 콘텐츠)
한 번에 모두 제출하기보다 며칠에 걸쳐 배치로 제출했습니다 — 이는 크롤러가 과부하되지 않게 하고 스팸 플래그를 피하는 데 도움이 됩니다.
도구
핵심 조회 외에도 실제 가치를 더하는 여러 유틸리티를 만들었습니다:
|