개발 slecs

광고 슬롯 조회를 빌드 타임 정적 데이터로 전환해 런타임 DB 부하 제거

목차

광고 슬롯 데이터를 런타임에 DB에서 끌어오던 걸, 빌드 타임에 JSON으로 미리 구워두는 방식으로 전환했다.

왜 이 변경이 필요했나

MobonSlot 컴포넌트는 광고 단위(ad unit) 정보를 렌더링 시점에 동적으로 조회하고 있었다. 페이지가 뜰 때마다 DB 쿼리가 발생하는 구조였는데, 사실 광고 슬롯 메타데이터는 자주 바뀌는 데이터가 아니다. 슬롯 ID, 위치 코드, 사이즈 정보 같은 것들은 운영자가 설정하면 길게는 몇 달씩 그대로 유지된다.

그럼에도 매 요청마다 DB를 찌르고 있었다는 건, 초기 구현 당시 "일단 동작하게" 만든 흔적이다. 팀에서 이 부분을 리뷰할 때 "이게 정말 런타임이어야 하는 이유가 있냐"는 질문이 나왔고, 딱히 없었다. 그 시점에 리팩터링 카드를 따로 파두었다가 이번에 처리했다.

Astro 기반 프로젝트에서 이런 판단은 더 명확하게 나온다. Astro는 기본적으로 빌드 타임 정적 생성을 전제로 설계된 프레임워크라서, 런타임 DB 호출이 섞이면 그 컴포넌트만 SSR 경계를 타거나 별도 API route를 물게 된다. 아키텍처가 불필요하게 복잡해지는 것.

작업 내용

변경은 크게 세 단계로 나뉜다.

단계 파일 역할
데이터 추출 scripts/sync-ad-units.js DB에서 광고 단위 목록을 조회해 JSON으로 덤프
데이터 저장 src/data/ad-units.json 빌드 타임에 읽힐 정적 데이터 파일
컴포넌트 수정 src/components/MobonSlot.astro DB 호출 제거, JSON import로 교체
빌드 파이프라인 publish.sh, package.json sync 스크립트를 빌드 전 단계로 등록

sync-ad-units.js는 배포 직전에 한 번 실행되어 최신 광고 단위 데이터를 ad-units.json으로 떨군다. 이후 Astro 빌드가 돌면서 MobonSlot.astro는 이 JSON을 정적으로 import해서 슬롯 정보를 채운다.

// scripts/sync-ad-units.js (패턴 예시)
import { writeFileSync } from 'fs';
import { fetchAdUnits } from '../src/lib/db.js';

const units = await fetchAdUnits();
writeFileSync(
  'src/data/ad-units.json',
  JSON.stringify(units, null, 2)
);
---
// MobonSlot.astro  변경 
import adUnits from '../data/ad-units.json';

const { slotKey } = Astro.props;
const slot = adUnits[slotKey];
---
<div data-slot-id={slot.id} ...>
  <!-- 광고 렌더링 -->
</div>

publish.shnode scripts/sync-ad-units.js 한 줄을 빌드 커맨드 앞에 넣었고, package.json에도 prebuild 훅으로 동일하게 걸어뒀다. 로컬에서 npm run build 해도, CI에서 publish.sh를 실행해도 순서가 보장된다.

회고

이 패턴의 핵심 트레이드오프는 데이터 신선도 vs. 성능/복잡도다.

  • 런타임 조회: 항상 최신 데이터, 하지만 매 요청마다 DB 레이턴시
  • 빌드 타임 sync: 배포 시점 기준 데이터, DB 조회 비용 0

광고 슬롯 메타데이터는 변경 빈도가 낮고, 변경 시에는 어차피 QA를 거쳐 배포가 나간다. 즉 "배포 없이 슬롯 설정이 실시간 반영되어야 한다"는 요구사항이 없다면 빌드 타임 sync가 훨씬 깔끔한 선택이다.

팀원들에게 리뷰 시 이 판단 기준을 같이 공유했다. 데이터의 변경 주기와 그 변경을 누가, 어떤 프로세스로 하는지를 먼저 확인하면, 런타임이 정말 필요한지 아닌지가 금방 보인다. 많은 경우 "혹시 실시간으로 바꿔야 할 수도 있으니까"라는 막연한 가정이 불필요한 동적 처리를 만든다.

ad-units.json이 git에 커밋되는 파일인지도 논의가 있었다. 결론은 .gitignore에 넣고 빌드 산출물로 취급하기로 했다. 소스 코드와 데이터 스냅샷을 혼용하면 PR 노이즈가 생기고, sync 스크립트 자체가 소스 오브 트루스라는 점에서 JSON을 굳이 버전 관리할 이유가 없다.

작은 리팩터링이지만 이런 결정들이 쌓이면 프로젝트의 복잡도 곡선이 확실히 달라진다. 끝.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.