FastAPI와 PostgreSQL로 16,750페이지 프로그램형 SEO 사이트 구축기

발행: (2026년 5월 27일 AM 02:31 GMT+9)
7 분 소요
원문: Dev.to

출처: 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 데이터셋입니다.

  1. 추출 – 공식 BSB CSV(은행 코드, 지점명, 주소, 주, 우편번호, 결제‑방법 플래그)를 파싱합니다.
  2. 보강 – BSB 접두사를 모은행의 SWIFT/BIC 코드와 매핑합니다.
  3. 스냅샷 – 타임스탬프가 붙은 스냅샷을 저장해 과거 변동(지점 폐쇄, 합병, 이전)을 추적합니다.
  4. 로드 – 적절한 인덱스를 적용해 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    (편집 콘텐츠)

한 번에 모두 제출하기보다 며칠에 걸쳐 배치로 제출했습니다 — 이는 크롤러가 과부하되지 않게 하고 스팸 플래그를 피하는 데 도움이 됩니다.


도구

핵심 조회 외에도 실제 가치를 더하는 여러 유틸리티를 만들었습니다:

|

0 조회
Back to Blog

관련 글

더 보기 »