모비온 광고가 렌더링되지 않던 스크립트 주입 버그 수정
목차
innerHTML로 심은 <script> 태그가 광고를 전혀 렌더링하지 못하고 있었다.
배경 — innerHTML의 script 미실행 함정
모비온 광고 슬롯을 붙일 때 초기 구현은 단순했다. 서버에서 내려온 광고 스크립트 문자열을 그냥 컨테이너 div의 innerHTML에 박아 넣는 방식. 얼핏 보면 동작할 것 같지만 브라우저 스펙상 innerHTML로 삽입된 <script> 태그는 실행되지 않는다. 이건 XSS 방어 목적으로 오래전부터 정해진 동작이고, React 환경에서는 dangerouslySetInnerHTML을 쓴다 해도 결과는 동일하다.
문제는 QA 환경에서는 광고 슬롯이 "있는 것처럼" 보였다는 거다. 컨테이너 div는 DOM에 붙어 있었고, innerHTML 자체는 삽입됐으니까 엘리먼트 트리상 문제가 없어 보였다. 실제 광고 렌더링 SDK가 초기화되지 않은 것을 한동안 눈치채지 못했다. 클릭 가능한 UI가 없으니 QA 체크리스트를 통과해버린 것.
이 버그가 노출된 건 광고 성과 수치가 의심스럽게 낮다는 제보가 들어오고 나서였다. 로그를 뒤지니 모비온 SDK의 초기화 콜백이 단 한 번도 찍히지 않고 있었다. 곧바로 원인을 AdSlot.tsx의 innerHTML 주입 방식으로 좁혔다.
작업 내용 — client 렌더러로 교체
| 파일 | 변경 전 | 변경 후 |
|---|---|---|
AdSlot.tsx |
innerHTML / dangerouslySetInnerHTML로 스크립트 주입 |
MobonClient 컴포넌트 위임으로 교체 |
MobonClient.tsx |
(신규) | document.createElement('script') + appendChild 방식으로 동적 삽입 |
핵심은 MobonClient.tsx를 별도 컴포넌트로 분리해서 클라이언트 사이드에서 직접 <script> 엘리먼트를 생성·삽입하도록 바꾼 것이다. 브라우저가 script 태그를 실행하려면 innerHTML이 아니라 createElement → src 또는 textContent 할당 → appendChild 경로를 타야 한다.
// MobonClient.tsx — 핵심 패턴
useEffect(() => {
const script = document.createElement('script');
script.src = slotScriptUrl;
script.async = true;
containerRef.current?.appendChild(script);
return () => {
// 언마운트 시 script 제거 — 중복 삽입 방지
containerRef.current?.removeChild(script);
};
}, [slotScriptUrl]);
useEffect 안에서 처리한 이유는 SSR 환경에서 document에 접근하지 않기 위해서다. Next.js 계열 환경이면 이 패턴이 거의 필수고, MobonClient라는 이름 자체가 "이 컴포넌트는 클라이언트 전용"임을 팀 내에서 명시적으로 선언하는 역할도 한다. 파일 이름 자체가 문서화인 셈.
AdSlot.tsx는 슬롯 배치 레이아웃과 래퍼 역할만 남기고, 실제 스크립트 생애주기 관리는 MobonClient에 위임하는 구조로 정리됐다. 책임 분리도 자연스럽게 따라왔다.
회고
이 버그를 보면서 팀원들과 짧게 얘기를 나눴는데, innerHTML로 스크립트를 심으려 했던 최초 코드가 왜 그렇게 짜였는지는 어느 정도 이해가 됐다. 광고 SDK 연동 코드는 대부분 서드파티 문서에서 "이 <script> 태그를 페이지에 넣으세요" 식으로 안내가 오고, 그걸 React 컴포넌트로 옮길 때 별 생각 없이 dangerouslySetInnerHTML로 처리하는 게 가장 직관적으로 느껴지기 때문이다.
하지만 이건 전형적인 "브라우저 보안 스펙을 모르면 빠지는 함정"이고, 코드 리뷰 단계에서 걸렸어야 했다. 이번 건은 기능 자체가 눈에 보이는 오류 없이 조용히 동작하지 않는 케이스라 더 까다로웠다. 앞으로 외부 광고·태그 스크립트를 React에 붙이는 패턴이 또 나올 텐데, MobonClient.tsx 방식이 사내 레퍼런스 구현체가 되길 기대하고 있다. 이런 게 쌓여서 팀의 암묵지가 명시적 패턴으로 굳어지는 거라고 생각한다.
끝.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.