FlexAd
FlexAd 지면 추가하고 설정하고 SDK 인터페이스를 사용해 부가 기능을 구현하는 방법을 알아보세요.
주요 특징
FlexAd는 기존 네이티브 지면을 업그레이드한 새로운 광고 지면입니다. VAST 동영상, 정적 이미지, 네트워크 광고 등 다양한 광고 포맷을 하나의 지면에서 우선순위 기반으로 통합 지원하여 광고를 송출하여 앱 수익화를 가속할 수 있도록 하는 지면입니다. 유저가 더 많은 광고에 참여할 수 있도록 유도하는 다이나믹한 기능들도 제공합니다.
FlexAd는 다양한 광고 포맷을 단일 지면에서 자동으로 스위칭하며 다음과 같은 기능을 제공합니다:

- 다양한 광고 포맷: VAST 동영상, 정적 이미지, 네트워크 광고를 하나의 지면에서 통합 지원
- 자동 광고 갱신: 유저가 광고 참여를 완료하면 자동으로 다음 광고로 전환
- 시청 추적: Viewability 기반 자동 일시정지/재개 (50% 이상 노출 기준)
연동
FlexAd를 앱에 연동하는 방법을 확인해 보세요.
1 단계. 준비하기
- Buzzvil SDK v6.7.0 이상 필요
- 시작하기 적용 완료
- FlexAd 지면에 사용할 Unit ID (이하
YOUR_FLEXAD_UNIT_ID)
2 단계. 광고 레이아웃 구성하기
FlexAd 레이아웃 구조를 확인하고 XML에서 BuzzFlexAdView를 추가하세요.

레이아웃 구조
BuzzFlexAdView는 다음과 같은 구성으로 이루어집니다:
| 영역 | 설명 | 크기 |
|---|---|---|
| 광고 콘텐츠 영역 | 로딩 상태, VAST 동영상, 정적 이미지 등이 표시되는 영역 | 16:9 비율 |
| 베네핏허브 CTA | 베네핏허브로 이동하는 하단 버튼 (자동 포함) | 약 40dp |
| 구분선 | 아래 콘텐츠와의 경계선 (자동 포함) | 1dp |
따라서 광고 콘텐츠는 16:9이지만, 전체 BuzzFlexAdView 높이는 16:9 + 약 41dp입니다.
XML 레이아웃 예시
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- FlexAd 광고 뷰 (광고 콘텐츠 16:9 + 하단 CTA 자동 포함) -->
<com.buzzvil.buzzbenefit.flexad.BuzzFlexAdView
android:id="@+id/buzzFlexAdView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- 그 외 추가 콘텐츠 (선택사항) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="추가 콘텐츠"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
✏️ 참고
BuzzFlexAdView는wrap_content로 설정합니다. 광고 콘텐츠가 16:9로 자동 관리되고, 하단 CTA와 구분선이 자동으로 포함됩니다.- 특정 높이를 강제할 필요가 없습니다. 뷰가 필요한 높이만 차지합니다.
BuzzFlexAdView아래에 추가 콘텐츠를 배치할 때는 충분한 여백을 확보하세요.
3 단계. 광고 보여주기
BuzzFlex 객체를 생성하고 Listener를 등록한 후 광고를 로드하세요. bind()는 Listener 콜백 내에서 호출합니다.
import com.buzzvil.buzzbenefit.flexad.BuzzFlex
import com.buzzvil.buzzbenefit.flexad.BuzzFlexAdView
import com.buzzvil.buzzbenefit.BuzzAdError
import com.buzzvil.buzzbenefit.benefithub.BuzzBenefitHub
val buzzFlexAdView = findViewById<BuzzFlexAdView>(R.id.buzzFlexAdView)
// 1. BuzzFlex 객체 생성
val buzzFlex = BuzzFlex(YOUR_FLEXAD_UNIT_ID)
// 2. Listener 등록 (반드시 load() 이전에)
buzzFlex.setListener(object : BuzzFlex.Listener {
override fun onSuccess() {
// load() 완료 후 호출됨
// 여기서 bind() 호출
buzzFlexAdView.bind(buzzFlex)
}
override fun onFailure(error: BuzzAdError) {
// 광고 할당에 실패했습니다
when (error.type) {
BuzzAdError.Type.GOOGLE_AGE_POLICY -> {
// age policy 위반: UI 숨김
buzzFlexAdView.visibility = View.GONE
}
BuzzAdError.Type.EMPTY_RESPONSE -> {
// 할당 가능한 광고 없음: 일시적 상황으로 bind() 호출
buzzFlexAdView.bind(buzzFlex)
}
else -> {
// 기타 에러: bind() 호출
buzzFlexAdView.bind(buzzFlex)
}
}
}
override fun onClicked() {
// 유저가 광고를 클릭했습니다
}
})
// 3. load() 호출 (Listener가 등록된 상태에서)
buzzFlex.load()
⚠️ 중요
setListener()를 반드시load()이전에 호출하세요.bind()는onSuccess()또는onFailure()콜백 내에서만 호출하세요.BuzzFlex의 생명주기는BuzzFlexAdView가 자동으로 관리하므로,handleResume(),handlePause()등을 명시적으로 호출할 필요가 없습니다.onSuccess()는 최초 광고 할당에만 호출되며, 이후 자동 갱신은 UI 업데이트만 수행합니다.
4 단계. 기본 연동 테스트하기
모든 기본 연동 단계를 완료한 후 다음을 확인하세요:
- 광고가 정상적으로 할당되고 표시되는지 확인
- 광고 참여 후 자동으로 다음 광고로 전환되는지 확인
- 베네핏허브 진입점이 정상적으로 동작하는지 확인
추가 구현
주요 색상 커스터마이징
FlexAd UI의 주요 색상(Primary Color)을 설정할 수 있습니다:
val buzzFlex = BuzzFlex(YOUR_FLEXAD_UNIT_ID)
// 색상 설정
buzzFlex.setPrimaryColor(ContextCompat.getColor(this, R.color.your_primary_color))
buzzFlex.setListener(...)
buzzFlex.load()
리워드 pill, progress bar 등 UI 요소의 색상이 설정한 primary color로 변경됩니다.
광고 운영 정책 (필수 준수 사항)
광고 요청 정책
- 광고 요청은 앱 화면이 켜지는 시점에 최초 1회만 진행해주세요.
- 이후 광고 재요청(재할당)은 화면 전환 등 명확한 사용자 액션이 있을 때만 허용됩니다.
- 일정 시간 간격으로 자동으로 광고를 리프레시하는 방식은 금지됩니다.
과도한 광고 요청은 사용자 경험을 저해하고, 광고 효율 및 수익에 악영향을 미칠 수 있습니다.
오류 처리
FlexAd 연동 중 발생할 수 있는 오류를 처리하는 방법을 안내합니다.
오류 코드
onFailure() 콜백에서 반환되는 BuzzAdError의 type을 통해 오류의 원인을 파악할 수 있습니다.
| 오류 코드 | 설명 | 원인 | 해결 방법 |
|---|---|---|---|
NOT_INITIALIZED | SDK 미초기화 | 시작하기에서 SDK 초기화를 완료하지 않음 | SDK 초기화 확인 |
SERVER_ERROR | 서버 오류 (HTTP 500) | 버즈빌 서버 내부 오류 | 네트워크 상태 확인 후 재시도 |
CLIENT_ERROR | 클라이언트 오류 (HTTP 400) | 잘못된 요청 또는 만료된 토큰 | Unit ID 확인, 로그인 상태 재확인 |
CONNECTION_TIMEOUT | 네트워크 타임아웃 | 네트워크 연결 불안정 또는 느린 연결 | 네트워크 상태 확인 |
EMPTY_RESPONSE | 광고 미할당 | 할당할 수 있는 광고가 없음 | FlexAd 지면 활성화 여부 확인 |
WAITING_FOR_RESPONSE | 응답 대기 중 | 이전 요청이 아직 진행 중 | 충분한 시간 경과 후 재시도 |
GOOGLE_AGE_POLICY | Google 정책 미충족 | 14세 이하 사용자로 판별됨 | 나이 정보 재확인 |
PRIVACY_POLICY_NOT_GRANTED | 개인정보 제공 동의 미흡 | 유저가 개인정보 수집에 동의하지 않음 | 유저에게 개인정보 수집 동의 요청 |
UNKNOWN | 미확인 오류 | 특정할 수 없는 예외 상황 | Troubleshooting 참고, 버즈빌 담당자 문의 |
GOOGLE_AGE_POLICY 오류시 지면을 제거하거나, 추가적인 동작을 커스텀해주세요.
오류 처리 예시
buzzFlex.setListener(object : BuzzFlex.Listener {
override fun onFailure(error: BuzzAdError) {
when (error.type) {
BuzzAdError.Type.EMPTY_RESPONSE -> {
// 광고 미할당: UI 숨김 처리
buzzFlexAdView.visibility = View.GONE
}
BuzzAdError.Type.CONNECTION_TIMEOUT -> {
// 네트워크 오류: 재시도 버튼 제공
showRetryButton()
}
BuzzAdError.Type.SERVER_ERROR -> {
// 서버 오류: 사용자에게 안내
Toast.makeText(context, "서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.", Toast.LENGTH_LONG).show()
}
else -> {
// 기타 오류
Toast.makeText(context, "광고 로드 실패: ${error.type.name}", Toast.LENGTH_SHORT).show()
}
}
}
override fun onSuccess() {
// 성공 처리
}
override fun onClicked() {
// 클릭 처리
}
})
✏️ 참고
- 광고 미할당(
EMPTY_RESPONSE)은 FlexAd 지면이 활성화되지 않았거나, 할당할 수 있는 광고가 일시적으로 없는 정상적인 상황입니다.- 자세한 문제 해결 방법은 Troubleshooting 페이지를 참고하세요.
자주 하는 질문
| 질문 | 답변 |
|---|---|
| 광고가 할당되지 않으면 어떻게 하나요? | onFailure() 콜백에서 에러 타입을 확인할 수 있습니다. 네트워크 연결 상태를 확인하거나, FlexAd 지면이 활성화되어 있는지 버즈빌 담당자(help@buzzvil.com)에게 문의하세요. |
| 광고 참여 후 자동으로 다음 광고로 전환되나요? | 네, FlexAd는 유저가 광고 참여를 완료하면 자동으로 다음 광고로 전환합니다. 별도의 구현이 필요하지 않습니다. |
| 특정 광고 포맷만 사용할 수 있나요? | FlexAd는 최적화된 광고 경험을 제공하기 위해 모든 광고 포맷을 함께 사용하도록 설계되었습니다. 특정 포맷만 선별하는 방식은 지원하지 않습니다. |
| 광고 클릭 시 커스텀 동작을 추가할 수 있나요? | onClicked() 콜백에서 로그 기록이나 분석만 수행하는 것을 권장합니다. 광고의 자동 동작과 충돌할 수 있으므로 추가적인 비즈니스 로직 구현은 피해주세요. |
| Benefithub광고만 나와요 | 연동 확인 및 로그 확인을 부탁들립니다. 연동, 셋팅, 서버 오류일 경우 Benefithub inhouse 광고만 노출될 수 있습니다. |