홈페이지를 대부분 개설한것 같아서 수익화를 넣어주기 위해서 광고를 넣게 되었다.
선택한것은 kakao AdFit이다.
광고에 대해서 기록들과,적립금, 상태에 대해서 알수 있다.
가입및 광고 신청은 흐름에 따라 잘 설명이 되어있으니 절차는 설명하지 않겠다.
내가 작성한 코드를 올려 보도록 하겠다.
광고를 선택하고 완료까지 하면 코드에 넣을 태그가 나온다.
태그 형식은
<ins class="kakao_ad_area" style="display:none;"
data-ad-unit = "DAN-ixFe0ZVFNHsEfSdC"
data-ad-width = "320"
data-ad-height = "50"></ins>
<script type="text/javascript" src="//t1.daumcdn.net/kas/static/ba.min.js" async></script>
이런 식이다. ins 태그와 script태그가 있다.
그대로 코드를 복붙 해서 넣었는데 react 는 리턴에 script 태그를 넣을수 없다. 그래서 검색해보니
ins와 script 태그를 document.createElement 로 만들어주고
각각 태그 속성을 넣어주고 useEffect로 페이지에 들어갈때 만들어 줘야 했다.
일단 나는 랜딩 페이지와 메인 페이지 두곳에 넣기 위해서 컴포넌트로 제작해서 재활용성을 높일수 있었다.
Props로 unit코드와 , width, height, disabled를 받아서 유동적으로 제작하게 되었다.
unit 코드는 각 광고마다 코드가 다른데 광고를 신청할때 받은 코드를 넣어주면 된다.
function KaKaoAd({ unit, width, height, disabled }: Props) {
const scriptElementWrapper = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (!disabled) {
const script = document.createElement("script");
script.setAttribute(
"src",
"https://t1.daumcdn.net/kas/static/ba.min.js"
);
script.setAttribute("async", "true");
scriptElementWrapper.current?.appendChild(script);
return () => {
const globalAdfit = "adfit" in window ? window.adfit : null;
if (globalAdfit) globalAdfit.destroy(unit);
};
}
}, []);
return (
<div
ref={scriptElementWrapper}
style={{ width: "100%", height: "100%" }}>
<ins
className="kakao_ad_area"
style={{ display: "none" }}
data-ad-unit={unit}
data-ad-width={width}
data-ad-height={height}
/>
</div>
);
}
기본 코드는 위와 같다. useEffect 로 받아서 스크립트 태그를 만들어 주고 각각 옵션을 세팅해준다.
useEffect에서 destory부분도 구현하게 되었다.
출처 : https://honeybomb.tistory.com/3
쭉 광고 적용에 대해 찾아보다가 방문하였는데 잘 정리해주신 블로그이다.
한번 로딩이된 광고에 리액트가 페이지가 이동되어도 애드핏에서 인지를 못해서
광고가 다시 갱신되지 않는 것이 문제라서 destory를 사용하게 되었다고 한다.
생각해보니 리액트도 한 html파일에서 route로 이동하니 이동하는것을 눈치 못챌것 같다 라는 생각이 들었다.
그래서 useEffect가 return하면 unmounted일 경우 여서 adfit.destroy함수를 호출하여 기존 광고를 정리해주고 다시 호출하는 것으로 제작할수 있었다.
문제는 타입스크립트를 사용해서 였다. 그냥 기존 코드를 넣어주면 되는데
'window.adfit 값이 없다' 라고 타입스크립트에서 에러로 정해버렸다.
return () => {
const globalAdfit = "adfit" in window ? window.adfit : null;
if (globalAdfit) globalAdfit.destroy(unit);
};
그래서 adfit 이 window객체이 있을때 값을 가지고 없을때 null로 방어를 해주었는데 그러니 아래 if문에서 '{}' 형식에 'destroy' 속성이 없습니다 라는 에러에 또 걸리고 말았다.
타입이 정말 발목을 잡았다. 이걸로 좀 찾아보기도 하고 chatGPT에게 도움도 받기도 하고 했었다. chatGPT에게 도움을 요청하니 코드를 수정해줬는데 에러는 똑같이 떠서 많이 헤메었다.
결국 타입스크립트에게 window adfit에 대해 정의를 해주는 것으로 에러를 해결해줄수 있었다.
interface Adfit {
display: (unit: string) => void;
destroy: (unit: string) => void;
refresh: (unit: string) => void;
}
declare global {
interface Window {
adfit?: Adfit;
}
}
이렇게 타입에게 window에 adfit정의를 해주니 문제를 해결할수 있었다.
타입스크립트 interface ,type 으로 타입을 지정해서 자주 썼는데
declare는 생소해서 찾아보고 공부하게 되었다.
정의는 이렇다.
TypeScript에서 declare 키워드는 외부 모듈, 변수, 함수, 클래스, 인터페이스 등의 타입 정보를 컴파일러에게 제공하는 역할을 합니다. 즉, TypeScript에서는 자바스크립트와 달리 정적 타입 검사를 수행하기 때문에, 컴파일러가 알지 못하는 외부의 타입 정보를 직접 제공해야 하는 경우 declare 키워드를 사용해서 타입 정보를 정의할 수 있습니다.
예를 들어, 외부 라이브러리로부터 가져온 함수나 변수에 대한 타입 정보를 선언할 때 declare 키워드를 사용할 수 있습니다. 이를 통해 컴파일러가 해당 함수나 변수의 타입 정보를 이해하고, 타입 검사를 수행할 수 있습니다.
즉 "내가 잘 모르는 타입이야, 안돼 돌아가"라며 모른다고 찡얼대는 타입스크립트에게 이것의 타입은 이거야 라고 정의를 해줄수 있는 것이다.
이제 광고 심사를 기다리며 완료되면 광고를 통해서 수익을 낼수 있을 것이다.
저도 window.adfit 부분이 에러라 고민이었는데 잘 읽었습니다 :)