광고 게이트와 모비온 경쟁 조건을 잡고 분석 스크립트 전체 적용
목차
세 가지 서로 다른 성격의 작업이 하나의 커밋에 묶인 날이었다. 광고 게이트 모달, race condition 픽스, 그리고 분석 스크립트 강제 로드 — 각각 독립적인 문제처럼 보이지만 결국 "광고/분석 레이어가 올바르게 동작하는가"라는 같은 질문에서 출발한 작업들이었다.
광고 게이트 모달 — psy 패턴으로 구현한 이유
광고를 보여주기 전에 사용자에게 "진입 여부"를 한 번 묻는 게이트 모달은 UI 패턴 자체는 단순해 보이지만, 타이밍과 상태 관리가 생각보다 까다롭다. 여기서 psy 패턴을 선택한 건 모달의 노출 조건과 닫힘 이후 흐름을 선언적으로 다루기 위해서였다.
psy 패턴이라고 부르는 건 기본적으로 "사용자의 심리적 흐름(Psychology)"을 인터페이스 상태와 1:1로 매핑하는 방식인데, 구체적으로는 모달 열림/닫힘/확인/거부 각 상태를 분리된 플래그로 다루지 않고 단일 상태 머신처럼 처리하는 구조다. 이렇게 하면 "모달이 열려있는데 광고가 먼저 로드됐을 때" 같은 엣지 케이스를 조건 분기로 억지로 막을 필요 없이 흐름 자체가 자연스럽게 막힌다.
<!-- MobonSlot.astro 내부 개념 구조 -->
{gateState === 'confirmed' && (
<div class="mobon-slot">
<!-- 광고 슬롯 렌더 -->
</div>
)}
게이트를 통과하지 않으면 슬롯 자체가 DOM에 올라오지 않는 구조. 단순하지만 이게 핵심이었다.
모비온 race condition — 왜 항상 여기서 터지나
모비온 같은 외부 광고 SDK는 대부분 "스크립트가 로드된 이후에 슬롯 초기화를 호출해야 한다"는 전제를 갖는다. 문제는 Astro 같은 정적 생성 환경에서 컴포넌트 마운트 타이밍과 외부 스크립트 로드 타이밍이 충돌하는 경우가 생긴다는 것.
전형적인 race condition 시나리오는 이렇다:
| 순서 | 상황 | 결과 |
|---|---|---|
| 1 | 컴포넌트 마운트 → 슬롯 초기화 시도 | SDK 미로드 상태 → 에러 or 묵묵히 실패 |
| 2 | SDK 로드 완료 | 이미 초기화 타이밍 놓침 |
| 3 | 광고 비노출 | 사용자 경험 깨짐, 수익 손실 |
이걸 고치는 방법은 크게 두 가지다. SDK 로드를 기다린 다음 초기화를 호출하거나, SDK 쪽에서 ready 콜백/이벤트를 제공하면 그걸 활용하거나. 이번 픽스는 MobonSlot.astro 내에서 초기화 호출 타이밍을 명시적으로 SDK 로드 이후로 보장하는 방식으로 처리했다.
// race condition 방지 패턴 (개념 예시)
function initSlot() {
if (typeof MobonSDK === 'undefined') {
window.addEventListener('mobon:ready', initSlot, { once: true });
return;
}
MobonSDK.init(/* slot config */);
}
initSlot();
외부 스크립트에 의존하는 컴포넌트는 항상 이 "SDK가 있다고 가정하지 말 것" 원칙을 지켜야 한다. 이게 팀 코드리뷰에서도 자주 지적하는 포인트인데, 로컬에서는 캐시 덕분에 안 터지다가 프로덕션 첫 로드에서만 터지는 버그가 전형적으로 여기서 나온다.
HawkEyes 무조건 로드 — 조건부 로드의 함정
분석 스크립트를 특정 조건(로그인 여부, 환경, 특정 페이지 등)에 따라 조건부로 로드하는 건 얼핏 최적화처럼 보인다. 근데 실제로는 "어떤 케이스에서 분석이 빠졌는지"를 나중에 추적하기가 매우 어려워진다는 문제가 있다.
HawkEyes를 Base.astro에서 무조건 로드하도록 바꾼 건 그 이유다. 분석 도구는 기본적으로 "모든 케이스를 봐야 의미 있다"는 전제를 가지고 있고, 조건부 로드로 인한 데이터 구멍은 생각보다 오래 뒤에야 발견된다. 발견했을 때는 이미 비교 기준이 없어서 복구도 안 된다.
- 조건부 로드는 성능에는 유리하지만 분석 완결성을 희생함
- 무조건 로드는 데이터 신뢰도를 높이는 대신 번들/네트워크 비용이 약간 올라감
- 분석 스크립트는 대부분 async/defer로 메인 렌더를 블로킹하지 않기 때문에 무조건 로드의 실질적 성능 페널티는 작음
Base.astro에 올려두면 레이아웃을 상속하는 모든 페이지에 자동으로 포함되므로 관리 포인트도 하나로 줄어든다. 이 쪽이 훨씬 깔끔하다.
한 커밋에 세 작업이 묶인 건 사실 이상적이진 않다. 리뷰어 입장에서 변경 의도를 파악하는 범위가 넓어지기 때문이다. 그래도 세 작업이 모두 "광고/분석 레이어 안정화"라는 같은 맥락에 묶여 있었고, 각각을 분리해서 배포하면 오히려 중간 상태가 불완전해지는 리스크가 있어서 묶었다. 이런 판단은 항상 트레이드오프다. 커밋 단위의 명확성 vs 배포 단위의 안전성. 다음 번엔 작업 순서를 미리 정리해서 하나씩 올리는 게 낫긴 했을 것 같다.
끝.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.