광고 슬롯을 DB 기반으로 설계해 배포 없이 설정 변경 가능하게 개선
목차
광고 슬롯 컴포넌트를 처음부터 새로 설계하면서 DB 패턴을 함께 도입한 작업이었다.
배경: 왜 admin_db 패턴이 필요했나
기존에는 광고 관련 설정값을 환경변수나 하드코딩으로 박아두는 방식이 많았다. 작은 프로젝트에서는 그게 제일 빠르기도 하고. 그런데 SITE_SLUG라는 개념이 생기면서 상황이 달라졌다. 같은 코드베이스 위에 여러 사이트 슬러그가 올라타는 구조가 되면, 각 슬롯의 광고 ID나 노출 위치가 사이트마다 달라져야 한다. 그걸 전부 env로 관리하면 변수명이 폭발하고, 코드 분기는 더 심해진다.
admin_db 패턴은 그 문제에 대한 대답이다. 광고 설정을 DB 레이어에서 슬러그 기반으로 조회해서 컴포넌트에 넘기는 방식. 운영자가 어드민에서 슬롯 ID나 활성화 여부를 바꿔도 배포 없이 반영된다는 점이 핵심이다. 이번엔 SITE_SLUG=psy로 특정 사이트를 먼저 타깃으로 잡았고, 그 위에서 index 페이지와 result 페이지 두 군데에 광고 호출을 붙이는 게 목표였다.
작업 내용
변경된 파일들을 보면 레이어가 꽤 고르게 퍼져 있다.
| 파일 | 역할 | 이번 변경 의미 |
|---|---|---|
src/lib/db.ts |
DB 접근 유틸 | admin_db 패턴 쿼리 로직 추가 |
src/components/MobonSlot.astro |
광고 슬롯 컴포넌트 | 신규 생성 — DB에서 받은 설정으로 렌더링 |
src/pages/index.astro |
메인 페이지 | MobonSlot 호출 추가 |
src/pages/t/[slug]/r/[result].astro |
결과 페이지 | MobonSlot 호출 추가 |
package.json / package-lock.json |
의존성 | Mobon 관련 패키지 혹은 DB 클라이언트 추가 |
db.ts에서의 변경이 제일 핵심이다. 슬러그를 받아서 해당 사이트의 광고 슬롯 설정을 가져오는 함수 하나가 생겼을 텐데, 이걸 어떻게 설계하느냐가 이후 확장성을 결정한다. 대략 이런 패턴으로 잡았다.
// src/lib/db.ts (패턴 예시)
export async function getAdSlotConfig(siteSlug: string, slotKey: string) {
const row = await db
.selectFrom('ad_slots')
.where('site_slug', '=', siteSlug)
.where('slot_key', '=', slotKey)
.where('is_active', '=', true)
.selectAll()
.executeTakeFirst();
return row ?? null;
}
MobonSlot.astro 컴포넌트는 이 함수를 Astro의 서버 렌더링 시점에 호출해서 슬롯 ID를 받아 스크립트를 주입하는 구조다. 컴포넌트 안에 직접 DB 콜이 들어가는 게 불편하면 페이지에서 미리 조회해서 props로 내려주는 방식도 있는데, 이번엔 슬롯 컴포넌트가 자기 데이터를 직접 책임지는 쪽으로 갔다.
---
// src/components/MobonSlot.astro
import { getAdSlotConfig } from '../lib/db';
const { siteSlug, slotKey } = Astro.props;
const config = await getAdSlotConfig(siteSlug, slotKey);
---
{config && (
<div id={`mobon-${slotKey}`}>
<script async src={`https://ad.mobon.net/...${config.slot_id}...`} />
</div>
)}
null 체크로 슬롯이 없거나 비활성이면 아무것도 안 그리도록 한 게 포인트. 광고 컴포넌트가 조용히 사라지는 게 에러 내뱉는 것보다 훨씬 낫다.
회고
index 페이지와 result 페이지에 동시에 붙인 건 의도적인 판단이었다. 메인과 결과 페이지는 트래픽 성격이 다르고 광고 노출 목적도 다를 수 있는데, 같은 컴포넌트를 slotKey만 다르게 넘겨서 재사용하는 구조가 제대로 동작하는지 초반에 두 곳에서 동시에 검증하고 싶었다.
한 가지 신경 쓰인 건 DB 호출 타이밍이다. Astro SSR에서 컴포넌트마다 DB를 찌르면 페이지 하나에 슬롯이 여러 개 들어갈 경우 N번 쿼리가 나간다. 당장은 슬롯이 많지 않으니 괜찮지만, 나중에 슬롯이 늘어나면 페이지 레벨에서 한 번에 조회해서 컨텍스트로 내려주는 방식을 고려해야 할 것 같다.
- 슬롯 수가 적을 때: 컴포넌트 자체 조회 → 캡슐화 좋음
- 슬롯 수가 많아질 때: 페이지에서 배치 조회 → 쿼리 수 절감
- 설정 변경 빈도가 높을 때: 짧은 TTL 캐싱 레이어 추가 검토
SITE_SLUG=psy를 먼저 잡은 건 이 사이트가 가장 빠르게 광고 붙여야 하는 우선순위였기 때문이다. 패턴이 검증되면 다른 슬러그로 확장하는 건 DB에 row 하나 추가하는 수준이 된다. 그게 이 설계의 목적이었고, 일단 그 방향으로 잘 잡힌 것 같다.
끝.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.