인앱 광고 2.0 ver2 (배너 광고 - WebView)
Webview에서 배너 광고를 표시할 수 있는 광고 라이브러리예요.
지원 버전
배너 광고 API는 토스 앱 버전에 따라 다르게 동작해요 :
| 토스 앱 버전 | 지원 여부 | 설명 |
|---|---|---|
| 5.241.0 이상 | 지원 | 배너 광고 사용 가능 |
| 5.241.0 미만 | 미지원 | 배너 광고 API 사용 불가 |
isSupported()메서드를 사용하여 현재 환경에서 배너 광고를 사용할 수 있는지 확인할 수 있어요.
5.241.0 미만 버전 예외 처리
토스앱 5.241.0 미만에서는 빈 화면이 노출될 수 있으니 반드시 예외 처리를 해주세요.
토스앱 버전 가져오기 기능을 사용해 예외 처리를 해주세요.
UI 가이드
피드형 배너 UI 가이드는 조금만 기다려주세요
리스트형 배너 사용 방식

리스트형 배너 광고는 두 가지 방식으로 사용할 수 있어요.
| 방식 | 설명 | 컨테이너 높이 |
|---|---|---|
| 고정형 | 컨테이너 높이를 고정하여 사용 | |
| (ex: 화면 하단 고정 배너 광고) | 96px 권장 | |
| 인라인 | 광고 콘텐츠에 따라 높이가 자동 조절됨 | |
| (ex: 게시판의 게시물 목록 사이의 배너 광고) | 지정하지 않음 |
스타일 옵션
attachBanner의 옵션을 통해 배너의 스타일을 커스터마이즈할 수 있어요.
theme (테마)

| 값 | 설명 |
|---|---|
auto (기본값) | 시스템 다크모드 설정에 따라 자동 전환 |
light | 밝은 테마 고정 |
dark | 어두운 테마 고정 |
tone (배경 색상)

| 값 | 설명 |
|---|---|
blackAndWhite (기본값) | • 흰색(light) 또는 검정색(dark) 광고 배경 • SDK가 서빙되는 화면의 색이 있을 때 추천 |
grey | • 회색 계열 광고 배경 • SDK가 서빙되는 화면의 색이 없을 때 추천 |
variant (배너 형태)

| 값 | 설명 |
|---|---|
expanded (기본값) | 전체 너비로 확장된 형태 |
card | 둥근 모서리의 카드 형태 |
광고 영역 크기 가이드
width는 항상 화면 너비와 동일해야 해요 (100%또는 뷰포트 전체 너비)- 고정형으로 사용할 경우
height: 96px를 권장해요 - 인라인으로 사용할 경우
height를 고정하지 않아야 콘텐츠에 맞게 자동 조절돼요
광고 적용 화면 & 삽입 위치
- 메인 화면, 상세 화면 등 원하는 화면 어디든 붙일 수 있어요
- 튜토리얼/로딩/컷신/시스템팝업/권한요청 모달 같이 일시적으로 뜨는 화면에는 지양해주세요
광고 삽입 위치
게임형 서비스
- 상단 / 하단 중 골라서 붙일 수 있어요
- 화면 중앙에는 붙일 수 없어요
- 상호작용이 가능한 UI 컴포넌트가 없는 빈 영역만 가능해요.(게임의 주요 UI와 겹치는 영역은 광고를 붙일 수 없어요)
이 외
- 상단 / 중앙 / 하단 중 골라서 붙일 수 있어요
- 상호작용이 가능한 UI 컴포넌트가 없는 빈 영역만 가능해요(서비스의 주요 UI와 겹치는 영역은 광고를 붙일 수 없어요)
- 위 아래의 ui 영역을 충분히 확보해주세요
광고 주변 최소 여백
게임형 서비스
- 상단 : 네비게이션(status) bar 아래, 패딩 4px
- 하단 : 인디게이터(네비게이션) bar 바로 위, 패딩 4px
이 외
- 없음
API 개요
TossAds.initialize— 배너 광고 SDK를 초기화해요. 광고를 표시하기 전에 반드시 한 번 호출해야 해요.TossAds.attachBanner— 특정 DOM 요소에 배너 광고를 부착해요. 스타일 프리셋(theme, tone, variant)이 적용되며, 반환된 객체의destroy()메서드로 배너를 제거할 수 있어요.TossAds.destroyAll— 초기화된 모든 배너 슬롯을 제거해요.
각 API는 isSupported() 프로퍼티를 통해 현재 환경에서 해당 기능 사용 가능 여부를 확인할 수 있어요.
배너 광고 SDK 초기화
TossAds.initialize
TossAds.initialize(options: TossAdsInitializeOptions): void;배너 광고 SDK를 초기화해요. 초기화 과정은 비동기로 진행되며, 완료 여부는 콜백으로 전달돼요.
광고를 사용하기 전에 반드시 한 번 초기화해야 하고, 앱의 최상위 컴포넌트에서 한 번만 호출하는 것을 권장해요.
파라미터
프로퍼티
isSupported
TossAds.initialize.isSupported(): boolean현재 환경에서 배너 광고를 사용할 수 있는지 확인해요.
예제
import { TossAds } from '@apps-in-toss/web-framework';
import { useEffect, useState } from 'react';
function App() {
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
// 지원 여부 확인
if (!TossAds.initialize.isSupported()) {
console.warn('배너 광고 기능을 사용할 수 없습니다.');
return;
}
// SDK 초기화
TossAds.initialize({
callbacks: {
onInitialized: () => {
console.log('SDK 초기화 완료');
setIsInitialized(true);
},
onInitializationFailed: (error) => {
console.error('SDK 초기화 실패:', error);
},
},
});
}, []);
return <div>{isInitialized ? '광고 준비 완료' : '광고 준비 중...'}</div>;
}import React, { useEffect, useState } from 'react';
import { View, Text, Alert } from 'react-native';
import { TossAds } from '@apps-in-toss/framework';
export default function App() {
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
// 지원 여부 확인
if (!TossAds.initialize.isSupported()) {
console.warn('배너 광고 기능을 사용할 수 없습니다.');
return;
}
// SDK 초기화
TossAds.initialize({
callbacks: {
onInitialized: () => {
console.log('SDK 초기화 완료');
setIsInitialized(true);
},
onInitializationFailed: (error) => {
console.error('SDK 초기화 실패:', error);
// 네이티브 환경에서는 Alert를 띄워 사용자/개발자에게 알릴 수 있어요
Alert.alert('배너 광고 초기화 실패', String(error?.message ?? error));
},
},
});
}, []);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>{isInitialized ? '광고 준비 완료' : '광고 준비 중...'}</Text>
</View>
);
}TossAdsInitializeOptions
interface TossAdsInitializeOptions {
callbacks?: {
onInitialized?: () => void; // SDK 초기화 성공 시 호출
onInitializationFailed?: (error: Error) => void; // SDK 초기화 실패 시 호출
};
}TossAds.initialize 함수의 옵션 타입이에요.
배너 광고 부착
TossAds.attachBanner
TossAds.attachBanner(
adGroupId: string,
target: string | HTMLElement,
options?: TossAdsAttachBannerOptions
): TossAdsAttachBannerResult;특정 DOM 요소에 배너 광고를 부착해요. 스타일 프리셋(theme, tone, variant)이 적용되며, 반환된 객체의 destroy() 메서드로 배너를 제거할 수 있어요.
TossAds.initialize를 먼저 호출하여 SDK를 초기화한 후에 사용해야해요.
광고 부착 가이드
- 광고를 부착하는 엘리먼트 내부는 비워둬야 해요.
- 컨테이너의
width는 항상 화면 너비와 동일해야 해요 (100%). - 고정형으로 사용할 경우
height: 96px권장해요
파라미터
| 파라미터 | 타입 | 설명 |
|---|---|---|
adGroupId | string | 광고 그룹 ID |
target | string | HTMLElement | 광고를 부착할 DOM 요소 또는 CSS 선택자 |
options | TossAdsAttachBannerOptions | 스타일 및 콜백 옵션 (선택) |
반환값
TossAdsAttachBannerResult 객체를 반환해요. 이 객체의 destroy() 메서드를 호출하여 배너를 제거할 수 있어요.
프로퍼티
isSupported
TossAds.attachBanner.isSupported(): boolean현재 환경에서 배너 광고를 사용할 수 있는지 확인해요.
예제
import { TossAds, TossAdsAttachBannerOptions } from '@apps-in-toss/web-framework';
import { useCallback, useEffect, useRef, useState } from 'react';
function BannerAdComponent({ adGroupId }: { adGroupId: string }) {
const containerRef = useRef<HTMLDivElement>(null);
const { isInitialized, attachBanner } = useTossBanner();
useEffect(() => {
if (!isInitialized || !containerRef.current) return;
// 배너 부착
const attached = attachBanner(adGroupId, containerRef.current, {
theme: 'auto', // 시스템 설정에 따라 자동 전환
tone: 'blackAndWhite', // 흰색/검정색 배경
variant: 'expanded', // 전체 너비 확장 형태
callbacks: {
onAdRendered: (payload) => {
console.log('광고 렌더링 완료:', payload.slotId);
},
onAdViewable: (payload) => {
console.log('광고 노출됨:', payload.slotId);
},
onAdImpression: (payload) => {
console.log('광고 노출 기록됨 (수익 발생):', payload.slotId);
},
onAdClicked: (payload) => {
console.log('광고 클릭됨:', payload.slotId);
},
onNoFill: (payload) => {
console.warn('표시할 광고가 없습니다:', payload.slotId);
},
onAdFailedToRender: (payload) => {
console.error('광고 렌더링 실패:', payload.error.message);
},
},
});
// 클린업: destroy 호출
return () => {
attached?.destroy();
};
}, [isInitialized, adGroupId, attachBanner]);
// 고정형 배너: width 100% + height 96px
return <div ref={containerRef} style={{ width: '100%', height: '96px' }} />;
}
// 초기화 및 배너 부착을 위한 커스텀 훅
function useTossBanner() {
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
if (isInitialized) return;
TossAds.initialize({
callbacks: {
onInitialized: () => setIsInitialized(true),
onInitializationFailed: (error) => {
console.error('Toss Ads SDK initialization failed:', error);
},
},
});
}, [isInitialized]);
const attachBanner = useCallback(
(adGroupId: string, element: HTMLElement, options?: TossAdsAttachBannerOptions) => {
if (!isInitialized) return;
return TossAds.attachBanner(adGroupId, element, options);
},
[isInitialized],
);
return { isInitialized, attachBanner };
}TossAdsAttachBannerOptions
interface TossAdsAttachBannerOptions {
theme?: 'auto' | 'light' | 'dark'; // 테마 (기본값: 'auto')
tone?: 'blackAndWhite' | 'grey'; // 배경 색상 톤 (기본값: 'blackAndWhite')
variant?: 'card' | 'expanded'; // 배너 형태 (기본값: 'expanded')
callbacks?: TossAdsBannerSlotCallbacks;
}TossAds.attachBanner 함수의 옵션 타입이에요.
| 옵션 | 타입 | 기본값 | 설명 |
|---|---|---|---|
theme | 'auto' | 'light' | 'dark' | 'auto' | 테마 설정. auto는 시스템 다크모드에 따라 자동 전환 |
tone | 'blackAndWhite' | 'grey' | 'blackAndWhite' | 배경 색상 톤 |
variant | 'card' | 'expanded' | 'expanded' | 배너 형태. card는 좌우 패딩 + border-radius 적용 |
callbacks | TossAdsBannerSlotCallbacks | - | 광고 이벤트 콜백 |
TossAdsAttachBannerResult
interface TossAdsAttachBannerResult {
destroy: () => void;
}TossAds.attachBanner 함수의 반환 타입이에요.
destroy(): 부착된 배너를 제거해요. 컴포넌트 언마운트 시 메모리 누수를 방지하기 위해 호출해야 호출을 권장해요.
TossAdsBannerSlotCallbacks
interface TossAdsBannerSlotCallbacks {
onAdRendered?: (payload: TossAdsBannerSlotEventPayload) => void;
onAdViewable?: (payload: TossAdsBannerSlotEventPayload) => void;
onAdClicked?: (payload: TossAdsBannerSlotEventPayload) => void;
onAdImpression?: (payload: TossAdsBannerSlotEventPayload) => void;
onAdFailedToRender?: (payload: TossAdsBannerSlotErrorPayload) => void;
onNoFill?: (payload: { slotId: string; adGroupId: string; adMetadata: {} }) => void;
}배너 광고 이벤트 콜백이에요.
onAdRendered: 광고가 렌더링되었어요.onAdViewable: 광고가 화면에 노출되었어요.onAdImpression: 광고 노출이 기록되었어요. (수익 발생 시점)onAdClicked: 사용자가 광고를 클릭했어요.onAdFailedToRender: 광고 렌더링에 실패했어요.onNoFill: 표시할 광고가 없어요.
TossAdsBannerSlotEventPayload
interface TossAdsBannerSlotEventPayload {
slotId: string;
adGroupId: string;
adMetadata: {
creativeId: string;
requestId: string;
};
}배너 광고 이벤트 페이로드예요.
slotId: 생성된 슬롯 IDadGroupId: 광고 그룹 IDadMetadata: 광고 메타데이터 (creativeId, requestId)
TossAdsBannerSlotErrorPayload
interface TossAdsBannerSlotErrorPayload {
slotId: string;
adGroupId: string;
adMetadata: {};
error: {
code: number;
message: string;
domain?: string;
};
}배너 광고 에러 페이로드예요.
모든 배너 슬롯 제거
TossAds.destroyAll
TossAds.destroyAll(): void;초기화된 모든 배너 슬롯을 제거해요.
프로퍼티
isSupported
TossAds.destroyAll.isSupported(): boolean현재 환경에서 배너 광고를 사용할 수 있는지 확인해요.
예제
// 페이지 이동 시 모든 배너 제거
useEffect(() => {
return () => {
TossAds.destroyAll();
};
}, []);사용 가이드
초기화 타이밍
SDK는 앱 시작 시점에 한 번만 초기화하는 것이 좋아요. 다음과 같은 시점에 초기화를 권장해요 :
- 앱 최상위 컴포넌트(App.tsx) 마운트 시
- 광고를 표시할 첫 화면 진입 전
// ✅ 좋은 예: 앱 시작 시 초기화
function App() {
useEffect(() => {
if (TossAds.initialize.isSupported()) {
TossAds.initialize({
callbacks: {
onInitialized: () => console.log('SDK 준비 완료'),
},
});
}
}, []);
return <Router />;
}
// ❌ 나쁜 예: 매번 컴포넌트마다 초기화
function BannerComponent() {
useEffect(() => {
TossAds.initialize({
/* ... */
}); // 중복 초기화 시도
}, []);
}컨테이너 사이즈 설정
광고 컨테이너는 반드시 올바른 사이즈로 설정해야 해요.
// ✅ 고정형: width 100% + height 96px 권장
<div ref={containerRef} style={{ width: '100%', height: '96px' }} />
// ✅ 인라인: width 100% + height 미지정
<div ref={containerRef} style={{ width: '100%' }} />
// ❌ 잘못된 예: width가 고정값
<div ref={containerRef} style={{ width: '320px', height: '96px' }} />메모리 관리
컴포넌트 언마운트 시 배너를 제거해야 메모리 누수를 방지할 수 있어요.
TossAds.attachBanner는 destroy() 메서드를 포함한 객체를 반환하므로, 클린업 시 이를 호출하면 돼요.
useEffect(() => {
if (!isInitialized || !containerRef.current) return;
// 배너 부착
const attached = TossAds.attachBanner(adGroupId, containerRef.current, {
callbacks: { ... },
});
// 클린업: destroy 호출
return () => {
attached?.destroy();
};
}, [isInitialized, adGroupId]);에러 처리
항상 onInitializationFailed와 onAdFailedToRender 콜백을 제공하여 에러에 대비하세요.
TossAds.initialize({
callbacks: {
onInitialized: () => {
console.log('초기화 성공');
},
onInitializationFailed: (error) => {
console.error('초기화 실패:', error);
// 사용자에게 적절한 피드백 제공
},
},
});
TossAds.attachBanner(adGroupId, element, {
callbacks: {
onAdFailedToRender: (payload) => {
console.error('광고 렌더링 실패:', payload.error.message);
// 대체 컨텐츠 표시 또는 재시도
},
},
});이벤트 플로우
TossAds.initialize 호출
↓
onInitialized 콜백 (초기화 완료)
↓
TossAds.attachBanner 호출
↓
onAdRendered 이벤트 (광고 렌더링 완료)
↓
onAdViewable 이벤트 (광고가 화면에 노출됨)
↓
onAdImpression 이벤트 (광고 노출 기록됨)
↓
onAdClicked 이벤트 (선택적 - 사용자 클릭 시)언제 배너가 갱신(refresh) 되나요?
배너 광고는 다음 두 가지 조건 중 하나가 발생하면 SDK가 자동으로 갱신(refresh)돼요.
- 광고가 렌더링된 후 10초 이상 경과한 경우
- 화면의 visibility 가 false → true 로 변경된 경우 (예: 광고 클릭 후 돌아오거나 앱이 백그라운드에서 포어그라운드로 복귀될 때)
재사용 가능한 커스텀 훅
여러 화면에서 배너 광고를 사용할 때 커스텀 훅으로 분리하면 편리해요.
useTossBanner
SDK 초기화와 배너 부착을 함께 처리하는 훅이에요.
import { useCallback, useEffect, useRef, useState } from 'react';
import { TossAds, type TossAdsAttachBannerOptions } from '@apps-in-toss/web-framework';
export function useTossBanner() {
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
if (isInitialized) return;
TossAds.initialize({
callbacks: {
onInitialized: () => setIsInitialized(true),
onInitializationFailed: (error) => {
console.error('Toss Ads SDK initialization failed:', error);
},
},
});
}, [isInitialized]);
const attachBanner = useCallback(
(adGroupId: string, element: HTMLElement, options?: TossAdsAttachBannerOptions) => {
if (!isInitialized) return;
return TossAds.attachBanner(adGroupId, element, options);
},
[isInitialized],
);
return { isInitialized, attachBanner };
}사용 예시
import { useRef, useEffect } from 'react';
function MyPage() {
const bannerRef = useRef<HTMLDivElement>(null);
const { isInitialized, attachBanner } = useTossBanner();
useEffect(() => {
if (!isInitialized || !bannerRef.current) return;
const attached = attachBanner('your-ad-group-id', bannerRef.current, {
theme: 'auto',
tone: 'blackAndWhite',
variant: 'expanded',
callbacks: {
onAdRendered: (payload) => console.log('광고 렌더링:', payload.slotId),
onAdImpression: () => console.log('광고 노출'),
},
});
return () => {
attached?.destroy();
};
}, [isInitialized, attachBanner]);
return (
<div>
<h1>내 페이지</h1>
{/* 고정형 배너: width 100% + height 96px */}
<div ref={bannerRef} style={{ width: '100%', height: '96px' }} />
</div>
);
}참고:
useTossBanner는 여러 컴포넌트에서 호출해도 안전합니다. 이미 초기화된 경우 중복 초기화를 시도하지 않습니다.
자주 묻는 질문
1. 토스 앱 환경에서 실행 중인지 확인해주세요.
2. 앱 버전이 요구사항을 충족하는지 확인해주세요.
3. isSupported() 메서드로 지원 여부를 먼저 확인해주세요.
1. onInitializationFailed 콜백에서 구체적인 에러 메시지 확인해주세요.
2. 네트워크 연결 상태를 확인해주세요.
3. 이미 초기화된 경우 [toss-ad] Already initialized. 에러가 발생해요.
초기화는 앱에서 한번만 해야하며, 상태를 전역으로 관리하여 중복 호출을 방지해주세요.
1. TossAds.initialize를 먼저 호출하고 onInitialized 콜백을 받았는지 확인해주세요.
2. DOM 요소가 실제로 존재하는지 확인해주세요. React의 경우, useEffect에서 ref.current가 null이 아닌지 확인해주세요.
3. onAdFailedToRender 또는 onNoFill 콜백에서 에러를 확인해주세요.
4. adGroupId가 올바른지 확인해주세요. (앱인토스 콘솔에서 발급받은 ID)
1.DOM 요소가 실제로 존재하는지 확인해주세요.
2. 셀렉터 문자열이 올바른지 확인해주세요 (예: "#banner", ".ad-container")
3. React의 경우 ref.current가 null이 아닌지 확인해주세요.
1. callbacks옵션을 TossAds.attach에 전달했는지 확인해주세요.
2. 콜백 함수가 올바르게 정의되었는지 확인해주세요.
3. 콘솔에 에러가 출력되는지 확인해주세요.
TossAds.destroy 또는 TossAds.destroyAll을 사용하세요.
