> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 스플래시 광고

> React Native 앱에서 스플래시 광고를 구현하는 방법을 알아봅니다.

## 개요

스플래시 광고는 앱이 시작될 때 스플래시 화면에 표시되는 광고입니다. 앱 로고와 함께 광고가 표시되어 자연스러운 사용자 경험을 제공합니다.

### 특징

* 앱 시작 시 자연스러운 광고 노출
* 앱 로고와 함께 브랜드 이미지 유지
* 고정 광고 크기: 360dp × 270dp (Android), 360px × 270px (iOS)
* 이미지 광고 지원

<Note>
  개발 중에는 테스트 유닛 ID를 사용하세요: `PUBLIC_TEST_UNIT_ID_SPLASH`
</Note>

***

## 캐싱 동작

스플래시 광고는 앱 실행과 동시에 즉시 노출되어야 하므로, SDK가 광고를 디바이스에 미리 캐싱하는 구조로 동작합니다. 다음 실행 시점에는 캐싱된 소재가 먼저 노출되고, 동시에 새 광고를 백그라운드로 요청하여 다음 실행에 사용할 캐시를 갱신합니다.

<Warning>
  이 캐싱 구조 때문에, 애드컨트롤 콘솔에서 소재를 **일시정지**하더라도 각 사용자 디바이스의 캐시가 갱신되기 전까지는 이미 캐싱된 소재가 노출될 수 있습니다. 소재 일시정지나 교체가 사용자에게 반영되기까지 시간이 소요될 수 있다는 점을 운영 계획에 반영하세요.
</Warning>

***

## 구현 방법

React Native 앱의 스플래시 광고는 네이티브 플랫폼 설정을 통해 구현됩니다. 스플래시 광고는 React Native 브릿지가 완전히 초기화되기 전에 표시되므로, Android와 iOS 네이티브 레벨에서 설정해야 합니다.

<Info>
  React Native 앱은 JavaScript 번들이 로드되기 전에 표시되는 네이티브 스플래시 화면을 사용합니다. Adrop 스플래시 광고는 이 네이티브 스플래시 흐름과 통합됩니다.
</Info>

***

## Android 설정

### 1단계: strings.xml 설정

`android/app/src/main/res/values/strings.xml`에 다음 설정을 추가합니다.

```xml title="android/app/src/main/res/values/strings.xml" theme={null}
<resources>
    <!-- 앱 이름 -->
    <string name="app_name">My App</string>

    <!-- 스플래시 광고 유닛 ID -->
    <string name="adrop_splash_ad_unit_id" translatable="false">YOUR_SPLASH_UNIT_ID</string>

    <!-- 스플래시 종료 후 이동할 Activity -->
    <string name="adrop_splash_ad_next_activity" translatable="false">com.yourcompany.yourapp.MainActivity</string>
</resources>
```

<Note>
  테스트 시에는 `YOUR_SPLASH_UNIT_ID` 대신 `PUBLIC_TEST_UNIT_ID_SPLASH`를 사용하세요.
</Note>

### 2단계: 스플래시 로고 이미지 추가

앱 로고를 `android/app/src/main/res/drawable/` 폴더에 추가합니다.

```
android/app/src/main/res/drawable/splash_logo.png
```

권장 크기: 288dp × 288dp (@2x: 576px, @3x: 864px)

### 3단계: AndroidManifest.xml 설정

`AdropSplashAdActivity`를 런처 액티비티로 설정합니다.

```xml title="android/app/src/main/AndroidManifest.xml" theme={null}
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:name=".MainApplication"
        android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher"
        android:allowBackup="false"
        android:theme="@style/AppTheme">

        <!-- 스플래시 광고 Activity -->
        <activity
            android:name="io.adrop.ads.splash.AdropSplashAdActivity"
            android:theme="@style/SplashTheme"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- 메인 Activity (React Native) -->
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
            android:launchMode="singleTask"
            android:windowSoftInputMode="adjustResize"
            android:exported="false">
        </activity>

    </application>
</manifest>
```

<Warning>
  `AdropSplashAdActivity`에는 `android:exported="true"`가 필수입니다. `MainActivity`에서 런처 intent-filter를 제거하세요.
</Warning>

### 4단계: 스플래시 테마 설정

`android/app/src/main/res/values/styles.xml`에 스플래시 테마를 추가하거나 업데이트합니다.

```xml title="android/app/src/main/res/values/styles.xml" theme={null}
<resources>
    <!-- 앱 테마 -->
    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
        <item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
    </style>

    <!-- 스플래시 테마 (Android 12+) -->
    <style name="SplashTheme" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@android:color/white</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/splash_logo</item>
        <item name="postSplashScreenTheme">@style/AppTheme</item>
    </style>
</resources>
```

<Note>
  `androidx.core:core-splashscreen` 의존성은 Adrop SDK에 포함되어 있습니다. 별도로 추가하지 않아도 됩니다.
</Note>

### 5단계: 레이아웃 커스터마이징 (선택사항)

커스텀 레이아웃을 사용하려면 `android/app/src/main/res/layout/`에 `activity_adrop_splash_ad.xml`을 생성합니다.

```xml title="android/app/src/main/res/layout/activity_adrop_splash_ad.xml" theme={null}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:paddingHorizontal="24dp"
    android:fitsSystemWindows="true">

    <!-- 앱 로고 (중앙) -->
    <ImageView
        android:src="@drawable/splash_logo"
        android:layout_width="288dp"
        android:layout_height="288dp"
        android:scaleType="fitXY"
        android:layout_centerInParent="true"/>

    <!-- 광고 영역 (하단) - 필수 -->
    <ImageView
        android:id="@+id/adrop_splash_ad_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"/>
</RelativeLayout>
```

<Warning>
  `android:id="@+id/adrop_splash_ad_image"`가 있는 `ImageView`는 필수입니다. 이 뷰에 광고가 표시됩니다.
</Warning>

### 6단계: 표시 시간 설정 (선택사항)

기본 표시 시간을 변경하려면 `android/app/src/main/res/values/integers.xml`을 생성합니다.

```xml title="android/app/src/main/res/values/integers.xml" theme={null}
<resources>
    <!-- 광고 요청 타임아웃 (밀리초, 500~3000) -->
    <integer name="adrop_splash_ad_request_timeout">1000</integer>

    <!-- 광고 표시 시간 (밀리초, 500~3000) -->
    <integer name="adrop_splash_ad_max_timeout">2000</integer>
</resources>
```

### 7단계: AdropSplashAd 리스너 구현 (선택사항)

스플래시 광고 이벤트를 수신하려면 `Application` 클래스에서 리스너를 설정합니다.

<CodeGroup>
  ```kotlin Kotlin theme={null}
  import android.app.Application
  import io.adrop.ads.Adrop
  import io.adrop.ads.splash.AdropSplashAd
  import io.adrop.ads.splash.AdropSplashAdListener
  import io.adrop.ads.model.AdropErrorCode

  class MainApplication : Application() {
      private lateinit var splashAd: AdropSplashAd

      override fun onCreate() {
          super.onCreate()

          // SDK 초기화
          Adrop.initialize(this, production = false)

          // 스플래시 광고 설정
          splashAd = AdropSplashAd(this) { splashAd ->
              // shouldSkip: 스플래시 광고를 건너뛸지 결정
              // true를 반환하면 광고를 건너뛰고 바로 메인 화면으로 이동
              checkShouldSkipSplash()
          }

          splashAd.splashAdListener = object : AdropSplashAdListener {
              override fun onAdReceived(ad: AdropSplashAd) {
                  println("스플래시 광고 수신 성공")
              }

              override fun onAdFailedToReceive(ad: AdropSplashAd, errorCode: AdropErrorCode) {
                  println("스플래시 광고 수신 실패: $errorCode")
              }

              override fun onAdImpression(ad: AdropSplashAd) {
                  println("스플래시 광고 노출")
              }

              override fun onAdClose(ad: AdropSplashAd, impressed: Boolean) {
                  println("스플래시 광고 닫힘 - impressed: $impressed")
              }
          }
      }

      private fun checkShouldSkipSplash(): Boolean {
          // 예: 딥링크로 진입하거나 특정 조건에서 스플래시 건너뛰기
          return false
      }
  }
  ```

  ```java Java theme={null}
  import android.app.Application;
  import io.adrop.ads.Adrop;
  import io.adrop.ads.splash.AdropSplashAd;
  import io.adrop.ads.splash.AdropSplashAdListener;
  import io.adrop.ads.model.AdropErrorCode;

  public class MainApplication extends Application {
      private AdropSplashAd splashAd;

      @Override
      public void onCreate() {
          super.onCreate();

          // SDK 초기화
          Adrop.INSTANCE.initialize(this, false, new String[]{});

          // 스플래시 광고 설정
          splashAd = new AdropSplashAd(this, ad -> checkShouldSkipSplash());

          splashAd.setSplashAdListener(new AdropSplashAdListener() {
              @Override
              public void onAdReceived(AdropSplashAd ad) {
                  System.out.println("스플래시 광고 수신 성공");
              }

              @Override
              public void onAdFailedToReceive(AdropSplashAd ad, AdropErrorCode errorCode) {
                  System.out.println("스플래시 광고 수신 실패: " + errorCode);
              }

              @Override
              public void onAdImpression(AdropSplashAd ad) {
                  System.out.println("스플래시 광고 노출");
              }

              @Override
              public void onAdClose(AdropSplashAd ad, boolean impressed) {
                  System.out.println("스플래시 광고 닫힘 - impressed: " + impressed);
              }
          });
      }

      private boolean checkShouldSkipSplash() {
          // 스플래시 광고를 건너뛸지 결정
          return false;
      }
  }
  ```
</CodeGroup>

<Note>
  `shouldSkip`이 `true`를 반환하면 광고가 로드되지 않고 바로 메인 화면으로 이동합니다.
</Note>

### 8단계: 앱 실행

React Native CLI로 Android 앱을 실행할 때 main activity를 지정해야 합니다:

```bash theme={null}
npx react-native run-android --main-activity io.adrop.ads.splash.AdropSplashAdActivity
```

<Note>
  `MainActivity` 대신 `AdropSplashAdActivity`가 런처 액티비티로 설정되어 있기 때문에 이 옵션이 필요합니다.
</Note>

***

## iOS 설정

### 1단계: AppDelegate 설정

`ios/YourApp/AppDelegate.mm` (또는 `AppDelegate.swift`)를 업데이트하여 스플래시 광고를 표시합니다.

<CodeGroup>
  ```swift Swift theme={null}
  import UIKit
  import React
  import AdropAds

  @main
  class AppDelegate: UIResponder, UIApplicationDelegate {
      var window: UIWindow?

      func application(
          _ application: UIApplication,
          didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
          // Adrop SDK 초기화
          Adrop.initialize(production: false)

          return true
      }
  }
  ```

  ```objc Objective-C theme={null}
  #import "AppDelegate.h"
  #import <React/RCTBundleURLProvider.h>
  @import AdropAds;

  @implementation AppDelegate

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
      // Adrop SDK 초기화
      [Adrop initializeWithProduction:NO useInAppBrowser:NO targetCountries:@[]];

      self.moduleName = @"YourApp";
      self.initialProps = @{};

      return [super application:application didFinishLaunchingWithOptions:launchOptions];
  }

  @end
  ```
</CodeGroup>

### 2단계: SceneDelegate 설정 (iOS 13+)

SceneDelegate를 사용하는 앱의 경우 `ios/YourApp/SceneDelegate.swift`를 생성하거나 업데이트합니다.

```swift title="ios/YourApp/SceneDelegate.swift" theme={null}
import UIKit
import React
import AdropAds

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        guard let windowScene = (scene as? UIWindowScene) else { return }

        window = UIWindow(windowScene: windowScene)

        // React Native 루트 뷰 생성
        let bridge = RCTBridge(delegate: self, launchOptions: nil)!
        let rootView = RCTRootView(bridge: bridge, moduleName: "YourApp", initialProperties: nil)
        let rootViewController = UIViewController()
        rootViewController.view = rootView

        #if DEBUG
        let splashUnitId = "PUBLIC_TEST_UNIT_ID_SPLASH"
        #else
        let splashUnitId = "YOUR_PRODUCTION_SPLASH_UNIT_ID"
        #endif

        // 스플래시 광고 뷰 컨트롤러 생성
        let splashViewController = AdropSplashAdViewController(
            unitId: splashUnitId
        )
        splashViewController.delegate = self
        splashViewController.logoImage = UIImage(named: "splash_logo")
        splashViewController.backgroundColor = .white
        splashViewController.mainViewController = rootViewController

        window?.rootViewController = splashViewController
        window?.makeKeyAndVisible()
    }
}

// MARK: - AdropSplashAdDelegate
extension SceneDelegate: AdropSplashAdDelegate {
    func onAdClose(_ ad: AdropSplashAd, impressed: Bool) {
        print("스플래시 광고 닫힘 - impressed: \(impressed)")
    }

    func onAdReceived(_ ad: AdropSplashAd) {
        print("스플래시 광고 수신 완료")
    }

    func onAdFailedToReceive(_ ad: AdropSplashAd, _ errorCode: AdropErrorCode) {
        print("스플래시 광고 수신 실패: \(errorCode)")
    }

    func onAdImpression(_ ad: AdropSplashAd) {
        print("스플래시 광고 노출")
    }
}
```

<Warning>
  `mainViewController`를 반드시 설정해야 합니다. 스플래시 광고가 닫힌 후 SDK가 이 뷰 컨트롤러로 전환하여 React Native 앱을 표시합니다.
</Warning>

### 3단계: 로고 이미지 추가

iOS 에셋에 앱 로고를 추가합니다:

1. Xcode를 열고 `YourApp/Images.xcassets`로 이동
2. `splash_logo`라는 이름의 새 Image Set 추가
3. 로고 이미지 추가 (@1x, @2x, @3x)

권장 크기: 200×200 \~ 300×300 포인트

### 4단계: Info.plist 설정

SceneDelegate를 사용하는 경우 `Info.plist`에 scene 설정이 있는지 확인합니다:

```xml title="ios/YourApp/Info.plist" theme={null}
<key>UIApplicationSceneManifest</key>
<dict>
    <key>UIApplicationSupportsMultipleScenes</key>
    <false/>
    <key>UISceneConfigurations</key>
    <dict>
        <key>UIWindowSceneSessionRoleApplication</key>
        <array>
            <dict>
                <key>UISceneConfigurationName</key>
                <string>Default Configuration</string>
                <key>UISceneDelegateClassName</key>
                <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
            </dict>
        </array>
    </dict>
</dict>
```

***

## AdropSplashAdDelegate

| 메서드                         | 필수 | 설명                                           |
| --------------------------- | -- | -------------------------------------------- |
| `onAdClose(_:impressed:)`   | 선택 | 스플래시 광고가 닫힐 때 호출. `impressed`는 광고가 표시되었는지 여부 |
| `onAdReceived(_:)`          | 선택 | 광고 수신 성공 시 호출                                |
| `onAdFailedToReceive(_:_:)` | 선택 | 광고 수신 실패 시 호출                                |
| `onAdImpression(_:)`        | 선택 | 광고 노출 기록 시 호출                                |

***

## 모범 사례

### 1. 적절한 타이머 설정

더 나은 사용자 경험을 위해 합리적인 타임아웃 값을 설정합니다.

```xml theme={null}
<!-- Android: integers.xml -->
<integer name="adrop_splash_ad_request_timeout">1000</integer>
<integer name="adrop_splash_ad_max_timeout">2000</integer>
```

<Note>
  iOS에서는 스플래시 광고 표시 시간이 Adrop 콘솔의 광고 유닛 설정에서 구성됩니다.
</Note>

### 2. 로고 이미지 최적화

로딩 시간을 최소화하기 위해 적절한 크기로 앱 로고를 준비합니다.

**Android:**

```
drawable-mdpi/splash_logo.png    (192px × 192px)
drawable-hdpi/splash_logo.png    (288px × 288px)
drawable-xhdpi/splash_logo.png   (384px × 384px)
drawable-xxhdpi/splash_logo.png  (576px × 576px)
drawable-xxxhdpi/splash_logo.png (768px × 768px)
```

**iOS:**

```
splash_logo@1x.png  (200px × 200px)
splash_logo@2x.png  (400px × 400px)
splash_logo@3x.png  (600px × 600px)
```

### 3. 실패 처리

광고 로딩이 실패해도 앱이 정상적으로 시작되도록 합니다.

```swift theme={null}
func onAdFailedToReceive(_ ad: AdropSplashAd, _ errorCode: AdropErrorCode) {
    print("광고 로드 실패: \(errorCode)")
    // AdropSplashAdViewController가 자동으로 onAdClose 호출
}
```

### 4. 테스트/프로덕션 환경 구분

```swift theme={null}
#if DEBUG
let isProduction = false
let splashUnitId = "PUBLIC_TEST_UNIT_ID_SPLASH"
#else
let isProduction = true
let splashUnitId = "YOUR_PRODUCTION_SPLASH_UNIT_ID"
#endif

Adrop.initialize(production: isProduction)
let splashViewController = AdropSplashAdViewController(unitId: splashUnitId)
```

***

## 테스트

### 테스트 유닛 ID

개발 중에는 테스트 유닛 ID를 사용합니다.

```
PUBLIC_TEST_UNIT_ID_SPLASH
```

<Warning>
  프로덕션 릴리스에는 반드시 Adrop 콘솔에서 생성한 실제 유닛 ID를 사용하세요. 테스트 유닛 ID로는 광고 수익이 발생하지 않습니다.
</Warning>

***

## 문제 해결

<AccordionGroup>
  <Accordion title="스플래시 화면이 표시되지 않음 (Android)">
    * AndroidManifest.xml에서 `AdropSplashAdActivity`가 LAUNCHER로 설정되어 있는지 확인
    * `android:exported="true"` 설정 확인
    * SDK 초기화가 완료되었는지 확인
    * `adrop_service.json`이 `android/app/src/main/assets` 폴더에 있는지 확인
  </Accordion>

  <Accordion title="스플래시 화면이 표시되지 않음 (iOS)">
    * `window.rootViewController`가 올바르게 설정되어 있는지 확인
    * Info.plist에 SceneDelegate가 설정되어 있는지 확인
    * SDK 초기화가 완료되었는지 확인
    * `adrop_service.json`이 Xcode 프로젝트에 추가되어 있는지 확인
  </Accordion>

  <Accordion title="광고가 로딩되지 않음">
    * 네트워크 연결 상태 확인
    * 유닛 ID가 올바른지 확인
    * 테스트 환경에서 `production: false` 설정 확인
    * `onAdFailedToReceive`의 에러 코드 확인
  </Accordion>

  <Accordion title="React Native 앱으로 전환되지 않음">
    * `adrop_splash_ad_next_activity`가 올바르게 설정되어 있는지 확인 (Android)
    * `onAdClose` Delegate 구현 확인 (iOS)
    * RCTBridge와 RCTRootView가 제대로 생성되었는지 확인
  </Accordion>

  <Accordion title="커스텀 레이아웃이 적용되지 않음 (Android)">
    * 파일 이름이 정확히 `activity_adrop_splash_ad.xml`인지 확인
    * `@+id/adrop_splash_ad_image` ID가 있는 ImageView가 있는지 확인
    * 클린 빌드 후 다시 실행
  </Accordion>
</AccordionGroup>

***

## 다음 단계

<CardGroup cols={2}>
  <Card title="전면 광고" href="/ko/sdk/react-native/interstitial">
    화면 전환 시 전체 화면 광고 표시
  </Card>

  <Card title="배너 광고" href="/ko/sdk/react-native/banner">
    배너 광고 구현
  </Card>

  <Card title="네이티브 광고" href="/ko/sdk/react-native/native">
    커스텀 디자인 네이티브 광고
  </Card>

  <Card title="보상형 광고" href="/ko/sdk/react-native/rewarded">
    사용자 보상 제공
  </Card>
</CardGroup>
