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 뷰 구조를 확인하고 코드에서 BuzzFlexAdView를 추가하세요.

뷰 구조
BuzzFlexAdView는 다음과 같은 구성으로 이루어집니다:
| 영역 | 설명 | 크기 |
|---|---|---|
| 광고 콘텐츠 영역 | 로딩 상태, VAST 동영상, 정적 이미지 등이 표시되는 영역 | 16:9 비율 |
| 베네핏허브 CTA | 베네핏허브로 이동하는 하단 버튼 (자동 포함) | 약 40pt |
| 구분선 | 아래 콘텐츠와의 경계선 (자동 포함) | 1pt |
따라서 광고 콘텐츠는 16:9이지만, 전체 BuzzFlexAdView 높이는 16:9 + 약 41pt입니다.
코드로 구성하는 경우
import UIKit
import BuzzvilSDK
class FlexAdViewController: UIViewController {
private let buzzFlexAdView = BuzzFlexAdView()
override func viewDidLoad() {
super.viewDidLoad()
// FlexAd 뷰 설정
view.addSubview(buzzFlexAdView)
// 제약 조건 설정 (wrap_content 형태)
buzzFlexAdView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
buzzFlexAdView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
buzzFlexAdView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
buzzFlexAdView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
// 높이는 자동 계산됨 (16:9 콘텐츠 + 하단 CTA + 구분선)
])
// 그 외 추가 콘텐츠 설정
setupAdditionalContent()
}
}
✏️ 참고
BuzzFlexAdView의 높이는 지정하지 않습니다. 뷰가 필요한 높이만 자동으로 차지합니다.- 광고 콘텐츠가 16:9 비율로 자동 관리되며, 하단 CTA와 구분선이 자동으로 포함됩니다.
BuzzFlexAdView아래에 추가 콘텐츠를 배치할 때는 충분한 여백을 확보하세요.
3 단계. 광고 보여주기
BuzzFlex 객체를 생성하고 Delegate를 설정한 후 광고를 로드하세요. bind()는 Delegate 콜백 내에서 호출합니다.
import UIKit
import BuzzvilSDK
class FlexAdViewController: UIViewController {
private let buzzFlexAdView = BuzzFlexAdView()
private let buzzFlex = BuzzFlex(unitId: YOUR_FLEXAD_UNIT_ID)
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
// 1. Delegate 설정 (반드시 load() 이전에)
buzzFlex.delegate = self
// 2. (Optional) 주요 색상 설정
buzzFlex.setPrimaryColor(.systemBlue)
// 3. load() 호출 (Delegate가 설정된 상태에서)
buzzFlex.load()
}
}
// MARK: - BuzzFlexDelegate
extension FlexAdViewController: BuzzFlexDelegate {
func buzzFlexOnSuccess() {
// load() 완료 후 호출됨
// 여기서 bind() 호출
buzzFlexAdView.bind(buzzFlex)
}
func buzzFlexOnFailure(_ error: Error) {
// 광고 할당에 실패했습니다
if let buzzError = error as? BuzzError {
switch buzzError {
case .agePolicy:
// age policy 위반: UI 숨김
buzzFlexAdView.isHidden = true
case .emptyResponse:
// 할당 가능한 광고 없음: 일시적 상황으로 bind() 호출
buzzFlexAdView.bind(buzzFlex)
default:
// 기타 에러: bind() 호출
buzzFlexAdView.bind(buzzFlex)
}
}
}
func buzzFlexOnClicked() {
// 유저가 광고를 클릭했습니다
}
}
⚠️ 중요
delegate를 반드시load()이전에 설정하세요.bind()는buzzFlexOnSuccess()또는buzzFlexOnFailure()콜백 내에서만 호출하세요.BuzzFlex의 생명주기는BuzzFlexAdView가 자동으로 관리하므로,handleResume(),handlePause()등을 명시적으로 호출할 필요가 없습니다.buzzFlexOnSuccess()는 최초 광고 할당에만 호출되며, 이후 자동 갱신은 UI 업데이트만 수행합니다.
4 단계. 기본 연동 테스트하기
모든 기본 연동 단계를 완료한 후 다음을 확인하세요:
- 광고가 정상적으로 할당되고 표시되는지 확인
- 광고 참여 후 자동으로 다음 광고로 전환되는지 확인
- 베네핏허브 진입점이 정상적으로 동작하는지 확인
추가 구현
주요 색상 커스터마이징
FlexAd UI의 주요 색상(Primary Color)을 설정할 수 있습니다:
let buzzFlex = BuzzFlex(unitId: YOUR_FLEXAD_UNIT_ID)
// 색상 설정
buzzFlex.setPrimaryColor(.systemBlue)
buzzFlex.delegate = ...
buzzFlex.load()
리워드 pill, progress bar 등 UI 요소의 색상이 설정한 primary color로 변경됩니다.
광고 운영 정책 (필수 준수 사항)
광고 요청 정책
- 광고 요청은 앱 화면이 켜지는 시점에 최초 1회만 진행해주세요.
- 이후 광고 재요청(재할당)은 화면 전환 등 명확한 사용자 액션이 있을 때만 허용됩니다.
- 일정 시간 간격으로 자동으로 광고를 리프레시하는 방식은 금지됩니다.
과도한 광고 요청은 사용자 경험을 저해하고, 광고 효율 및 수익에 악영향을 미칠 수 있습니다.
오류 처리
FlexAd 연동 중 발생할 수 있는 오류를 처리하는 방법을 안내합니다.
오류 코드
buzzFlexOnFailure() 콜백에서 반환되는 Error를 BuzzError로 캐스팅하여 오류의 원인을 파악할 수 있습니다.
| 오류 코드 | 설명 | 원인 | 해결 방법 |
|---|---|---|---|
.notInitialized | SDK 미초기화 | 시작하기에서 SDK 초기화를 완료하지 않음 | SDK 초기화 확인 |
.serverError | 서버 오류 (HTTP 500) | 버즈빌 서버 내부 오류 | 네트워크 상태 확인 후 재시도 |
.clientError | 클라이언트 오류 (HTTP 400) | 잘못된 요청 또는 만료된 토큰 | Unit ID 확인, 로그인 상태 재확인 |
.connectionTimeout | 네트워크 타임아웃 | 네트워크 연결 불안정 또는 느린 연결 | 네트워크 상태 확인 |
.emptyResponse | 광고 미할당 | 할당할 수 있는 광고가 없음 | FlexAd 지면 활성화 여부 확인 |
.waitingForResponse | 응답 대기 중 | 이전 요청이 아직 진행 중 | 충분한 시간 경과 후 재시도 |
.agePolicy | Google 정책 미충족 | 14세 이하 사용자로 판별됨 | 나이 정보 재확인 |
.privacyPolicyNotGranted | 개인정보 제공 동의 미흡 | 유저가 개인정보 수집에 동의하지 않음 | 유저에게 개인정보 수집 동의 요청 |
.unknown | 미확인 오류 | 특정할 수 없는 예외 상황 | Troubleshooting 참고, 버즈빌 담당자 문의 |
agePolicy 오류시 지면을 제거하거나, 추가적인 동작을 커스텀해주세요.
오류 처리 예시
extension FlexAdViewController: BuzzFlexDelegate {
func buzzFlexOnFailure(_ error: Error) {
guard let buzzError = error as? BuzzError else { return }
switch buzzError {
case .emptyResponse:
// 광고 미할당: UI 숨김 처리
buzzFlexAdView.isHidden = true
case .connectionTimeout:
// 네트워크 오류: 재시도 버튼 제공
showRetryButton()
case .serverError:
// 서버 오류: 사용자에게 안내
let alert = UIAlertController(
title: "알림",
message: "서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "확인", style: .default))
present(alert, animated: true)
default:
// 기타 오류
print("FlexAd 로드 실패: \(error.localizedDescription)")
}
}
func buzzFlexOnSuccess() {
// 성공 처리
buzzFlexAdView.isHidden = false
}
func buzzFlexOnClicked() {
// 클릭 처리
}
}
✏️ 참고
- 광고 미할당(
.emptyResponse)은 FlexAd 지면이 활성화되지 않았거나, 할당할 수 있는 광고가 일시적으로 없는 정상적인 상황입니다.- 자세한 문제 해결 방법은 Troubleshooting 페이지를 참고하세요.
자주 하는 질문
| 질문 | 답변 |
|---|---|
| 광고가 할당되지 않으면 어떻게 하나요? | buzzFlexOnFailure() 콜백에서 에러 타입을 확인할 수 있습니다. 네트워크 연결 상태를 확인하거나, FlexAd 지면이 활성화되어 있는지 버즈빌 담당자(help@buzzvil.com)에게 문의하세요. |
| 광고 참여 후 자동으로 다음 광고로 전환되나요? | 네, FlexAd는 유저가 광고 참여를 완료하면 자동으로 다음 광고로 전환합니다. 별도의 구현이 필요하지 않습니다. |
| 특정 광고 포맷만 사용할 수 있나요? | FlexAd는 최적화된 광고 경험을 제공하기 위해 모든 광고 포맷을 함께 사용하도록 설계되었습니다. 특정 포맷만 선별하는 방식은 지원하지 않습니다. |
| 광고 클릭 시 커스텀 동작을 추가할 수 있나요? | buzzFlexOnClicked() 콜백에서 로그 기록이나 분석만 수행하는 것을 권장합니다. 광고의 자동 동작과 충돌할 수 있으므로 추가적인 비즈니스 로직 구현은 피해주세요. |
| Benefithub광고만 나와요 | 연동 확인 및 로그 확인을 부탁들립니다. 연동, 셋팅, 서버 오류일 경우 Benefithub inhouse 광고만 노출될 수 있습니다. |