백엔드 개발 블로그
React Hook을 이용하여 카카오 애드핏(Adfit) 연동하기 본문
React 17 버전을 기준으로 작성된 글입니다. (2022/04)
TL;DR
// KakaoAdfit.jsx
import {useEffect, useRef} from "react";
function KakaoAdFit({unit, width, height, disabled}: any) {
const scriptElementWrapper = useRef(null);
useEffect(() => {
if (!disabled) {
const script = document.createElement("script");
script.setAttribute("src", "https://t1.daumcdn.net/kas/static/ba.min.js");
scriptElementWrapper.current.appendChild(script);
return () => {
const globalAdfit = window.adfit;
if (globalAdfit) globalAdfit.destroy(unit);
}
}
}, [])
return <div ref={scriptElementWrapper}>
<ins className="kakao_ad_area" style={{display: "none"}}
data-ad-unit={unit}
data-ad-width={width}
data-ad-height={height}></ins>
</div>
}
export default KakaoAdFit;
// 사용 예
<KakaoAdFit unit={"DAN-MyExampleAdUnit"} width={"320"} height={"100"} disabled={false}/>
Try #1 : Naive HTML
카카오 애드핏에서 광고 단위를 발급 받으면, 가이드에서는 다음과 같은 형태의 HTML을 원하는 광고 위치에 삽입하도록 안내하고 있습니다.
<ins class="kakao_ad_area" style="display:none;"
data-ad-unit = "DAN-MyExampleAdUnit"
data-ad-width = "320"
data-ad-height = "100"></ins>
<script type="text/javascript" src="//t1.daumcdn.net/kas/static/ba.min.js" async></script>
적당히 wrapping만 해주면 되지 않을까? 생각해서 아래와 같이 컴포넌트를 만들어 봅니다.
function KakaoAdFit({unit, width, height}: any) {
return <>
<ins className="kakao_ad_area" style={{display: "none"}}
data-ad-unit={unit}
data-ad-width={width}
data-ad-height={height}></ins>
<script type="text/javascript" src="//t1.daumcdn.net/kas/static/ba.min.js" async></script>
</>
}
export default KakaoAdFit;
잘 작동했다면 이 글을 쓸 필요가 없었겠죠???
어느정도 예상했지만 광고가 노출되지 않습니다.
Try #2: createElement
를 사용한 스크립트 동적 생성
JSX 문법에서는 script
태그를 사용할 수 없기 때문에, 위와 같이 script
태그를 추가하여도 HTML에 반영이 되지 않습니다.
HTML로 선언하는 것이 아닌, 동적으로 스크립트를 생성하는 방법으로 우회해봅시다.
Ref를 사용하면 low-level HTML element에 접근할 수 있습니다.
컴포넌트가 mount 된 후 최초 한 번 동적 script
element를 생성하여, 감싸고 있는 div
에 추가해봅시다.
// KakaoAdfit.jsx
import {useEffect, useRef} from "react";
function KakaoAdFit({unit, width, height}: any) {
const scriptElementWrapper = useRef(null);
useEffect(() => {
const script = document.createElement("script");
script.setAttribute("src", "https://t1.daumcdn.net/kas/static/ba.min.js");
scriptElementWrapper.current.appendChild(script);
}, [])
return <div ref={scriptElementWrapper}>
<ins className="kakao_ad_area" style={{display: "none"}}
data-ad-unit={unit}
data-ad-width={width}
data-ad-height={height}></ins>
</div>
}
export default KakaoAdFit;
결과는... 잘 나오는 것 같은데요.
문제는 광고가 없는 다른 페이지로 갔다가 다시 원래의 페이지로 돌아오면 광고가 표시되지 않습니다.
참고: 위와 같이 동적으로 script를 생성할 때, async
attribute는 필요 없는 것으로 보입니다.
Stack Overflow: Add defer or async attribute to dynamically generated script tags via JavaScript
Try #3: destroy 구현
이미 한번 로딩이 된 광고 단위에 대해 스크립트를 다시 로딩한다고 하더라도 광고가 다시 갱신되지 않는 것이 원인으로 보입니다.
리액트에서 페이지가 이동되어도 애드핏에서는 인지할 수 없으니까요.
기존에 노출되었던 광고 단위를 삭제하거나 정리하는 기능이 있으면 좋을텐데요...
애드핏 스크립트를 로딩하면 global에 adfit
이라는 인스턴스가 생성됩니다.
디버거를 확인하면 해당 인스턴스에 destroy
메소드가 존재하는 것을 확인할 수 있습니다.
해당 destroy
함수를 호출해서 컴포넌트가 unmount될 때 기존 광고 단위를 정리해주도록 합시다.
// KakaoAdfit.jsx
import {useEffect, useRef} from "react";
function KakaoAdFit({unit, width, height, disabled}: any) {
const scriptElementWrapper = useRef(null);
useEffect(() => {
if (!disabled) {
const script = document.createElement("script");
script.setAttribute("src", "https://t1.daumcdn.net/kas/static/ba.min.js");
scriptElementWrapper.current.appendChild(script);
return () => {
const globalAdfit = window.adfit;
if (globalAdfit) globalAdfit.destroy(unit);
}
}
}, [])
return <div ref={scriptElementWrapper}>
<ins className="kakao_ad_area" style={{display: "none"}}
data-ad-unit={unit}
data-ad-width={width}
data-ad-height={height}></ins>
</div>
}
export default KakaoAdFit;
그러면 이제 페이지를 이동하여도 광고가 잘 갱신되는 걸 확인할 수 있습니다.
'React' 카테고리의 다른 글
React Hook 정리 및 Tips (0) | 2022.04.17 |
---|