# React Native 연동

## 사전 작업 <a href="#pre-work" id="pre-work"></a>

Push Notification을 설정하려면 Flutter SDK 연동이 필요합니다. 다음 가이드를 완료 후 진행해주세요.

{% content-ref url="../../sdk-integrating/initialize/react-native-sdk" %}
[react-native-sdk](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/sdk-integrating/initialize/react-native-sdk)
{% endcontent-ref %}

## 1. 푸시 권한 요청 (선택)

SDK가 제공하는 함수로 플랫폼 공통 푸시 권한 요청 및 등록을 진행할 수 있습니다. 푸시 권한 설정에 다른 솔루션을 사용하거나 직접 관리중일 경우 생략해주세요.

<pre class="language-typescript"><code class="lang-typescript">import React, {useEffect} from 'react';
import Marketap from 'react-native-marketap-sdk';

const PROJECT_KEY = 'YOUR_PROJECT_KEY';

export default function App() {
  useEffect(() => {
    const initialize = async () => {
        try {
          await Marketap.initialize(PROJECT_KEY);
<strong>          await Marketap.requestAuthorizationForPushNotifications();
</strong>        } catch (error) {
          console.error('Marketap setup failed:', error);
        }
      };

      initialize();
  }, []);

  return null;
}
</code></pre>

## 2. iOS

### 사전 작업

[#id-1.-xcode](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/push-notification/ios#id-1.-xcode "mention") 가이드에 따라 Runner.xcworkspace의 Runner 프로젝트에 Push Capabilities, Notification Service Extension을 추가합니다.

### 2.1 AppDelegate 연동 코드 추가

앱 푸시 설정을 위해 `UNUserNotificationCenterDelegate` 를 추가하고 SDK 와 연동해줍니다. 이미 사용중인 `UNUserNotificationCenterDelegate` 가 있다면 동일하게 사용 가능합니다.

예시에서는 `AppDelegate`에 `UNUserNotificationCenterDelegate`를 채택하고 사용하겠습니다.

{% tabs %}
{% tab title="Swift" %}

<pre class="language-swift"><code class="lang-swift">import UIKit
import UserNotifications
import React
<strong>import MarketapSDK
</strong>
@main
class AppDelegate: RCTAppDelegate, UNUserNotificationCenterDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        // delegate 추가
<strong>        UNUserNotificationCenter.current().delegate = self
</strong>        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    override func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
    ) {
        // ...
        // 푸시 토큰 등록
<strong>        Marketap.setPushToken(token: deviceToken)
</strong>    }
    
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        // ...
        // active 상태 노티피케이션 수신 핸들링 추가
<strong>        if Marketap.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler) {
</strong><strong>            return
</strong><strong>        }
</strong><strong>        // ...
</strong>    }
    
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        // ...
        // 푸시 클릭 핸들링 추가
<strong>        if Marketap.userNotificationCenter(center, didReceive: response, withCompletionHandler: completionHandler) {
</strong><strong>            return
</strong><strong>        }
</strong>        // ...
    }
}
</code></pre>

{% endtab %}

{% tab title="Objective-C (AppDelegate.h)" %}

<pre class="language-objectivec"><code class="lang-objectivec">#import &#x3C;RCTAppDelegate.h>
<strong>#import &#x3C;UserNotifications/UserNotifications.h>
</strong>#import &#x3C;UIKit/UIKit.h>

<strong>@interface AppDelegate : RCTAppDelegate &#x3C;UNUserNotificationCenterDelegate>
</strong>
@end
</code></pre>

{% endtab %}

{% tab title="Objective-C (AppDelegate.mm)" %}

```objective-c
#import "AppDelegate.h"
#import <UserNotifications/UserNotifications.h>
@import MarketapSDK;

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // delegate 추가
  [UNUserNotificationCenter currentNotificationCenter].delegate = self;
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  // ...
  // 푸시 토큰 등록
  [Marketap setPushTokenWithToken:deviceToken];
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
      willPresentNotification:(UNNotification *)notification
        withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
  // ...
  // active 상태 노티피케이션 수신 핸들링 추가
  if ([Marketap userNotificationCenter:center willPresent:notification withCompletionHandler:completionHandler]) {
    return;
  }
  // ...
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
      didReceiveNotificationResponse:(UNNotificationResponse *)response
        withCompletionHandler:(void (^)(void))completionHandler
{
  // ...
  // 푸시 클릭 핸들링 추가
  if ([Marketap userNotificationCenter:center didReceive:response withCompletionHandler:completionHandler]) {
    return;
  }
  // ...
}

@end
```

Objective-C로 연동할 경우, `@import MarketapSDK;` 문법을 지원하기 위해 Xcode에서 모듈 옵션을 활성화해야 합니다.

**\[설정 방법]**

1. Xcode에서 iOS 프로젝트를 엽니다. (`.xcworkspace`)
2. 앱 타겟 선택
3. **Build Settings**에서 아래 항목을 설정합니다.
   * `Enable Modules (C and Objective-C)` = `Yes`
   * `Enable C++ Modules` = `Yes`

`Enable C++ Modules`가 보이지 않으면 아래 키를 직접 추가해주세요.

* `Other C++ Flags`에 `-fcxx-modules` 추가\
  (Debug, Release에 모두 추가해주세요)
  {% endtab %}
  {% endtabs %}

### 2.2 NotificationServiceExtension 설정

[#id-1.2-notification-service-extension](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/push-notification/ios#id-1.2-notification-service-extension "mention") 에서 설정한 NotificationServiceExtension용 sdk를 설치해야합니다. `ios/Podfile` 에 다음과 같이 추가합니다.

```ruby
target 'Runner' do
  ...
  # 추가한 NotificationServiceExtension 타겟 이름을 넣어주세요.
  target 'DummyNotificationServiceExtension' do
    inherit! :search_paths
    pod 'MarketapSDKNotificationServiceExtension', '1.0.9'
  end
end
```

`pod install` 이후, [#id-3.3-notification-service-extension](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/push-notification/ios#id-3.3-notification-service-extension "mention") 문서를 참고하여 설정을 완료합니다.

## 3. Android

### 사전 작업

Marketap Android SDK는 [Jitpack](https://jitpack.io/)을 통해 배포되고 있습니다.  React Native 프로젝트의 android 디렉토리 최상단 build.gradle 파일에 아래 repository를 추가해주세요.

<pre class="language-kts"><code class="lang-kts">buildscript {
      repositories {
          google()
          mavenCentral()
<strong>          maven { url = uri("https://jitpack.io") }
</strong>      }
  }
</code></pre>

이어서, AndroidManifest.xml 파일에 아래 권한들을 추가합니다. 각각 푸시 발송, 이벤트 및 유저정보 수집을 목적으로 합니다.

```xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.INTERNET" />
```

### 3.1 푸시 연동

{% hint style="success" %}
Marketap은 안드로이드 푸시를 지원하기 위해서 Firebase Cloud Messaging을 사용하고 있습니다. 따라서 Flutter 프로젝트의 안드로이드 의존성에 Firebase가 추가되어야 합니다. 자세한 내용은 구글의 [가이드 문서](https://firebase.google.com/docs/android/setup?hl=ko)를 참고해주세요.
{% endhint %}

푸시를 수신하기 위해서는 FirebaseMessagingService 설정이 필요합니다.

{% tabs %}
{% tab title="신규 연동" %}
Marketap은 FCM 기반 푸시 메시지를 수신하고 클릭을 처리하기 위한 전용 서비스를 제공합니다. `MarketapFirebaseMessagingService` 클래스를 AndroidManifest.xml 파일에 등록해 주세요.

```xml
<service
    android:name="com.marketap.sdk.client.push.MarketapFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
```

{% endtab %}

{% tab title="기존 서비스와 함께 사용" %}
이미 앱에서 FirebaseMessagingService를 사용 중이라면, Marketap에서 제공하는 `MarketapFirebaseMessagingService.handleMarketapRemoteMessage()` 메서드를 통해 Marketap 푸시만 안전하게 처리할 수 있습니다.

```kotlin
// Kotlin 예시
class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)

        if (MarketapFirebaseMessagingService.handleMarketapRemoteMessage(this, remoteMessage)) {
            // Marketap 메시지를 처리했습니다.
            // 추가 처리는 필요하지 않습니다.
        } else {
            // Marketap 메시지가 아닙니다.
            // 다른 푸시 핸들러가 있다면 이 메시지를 전달하세요.
        }
    }
}
```

```java
// Java 예시
public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        if (MarketapFirebaseMessagingService.handleMarketapRemoteMessage(this, remoteMessage)) {
            // Marketap 메시지를 처리했습니다.
            // 추가 처리는 필요하지 않습니다.
        } else {
            // Marketap 메시지가 아닙니다.
            // 다른 푸시 핸들러가 있다면 이 메시지를 전달하세요.
        }
    }
}
```

{% endtab %}
{% endtabs %}

## 4. 클릭 액션 커스텀하기 (선택)

푸시 캠페인에 클릭 액션 URL이 설정되어 있는 경우, 마켓탭 SDK는 OS별 기본 동작으로 URL을 처리합니다.

OS별 동작은 아래 링크를 참고해주세요.

* ios: [#id-4](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/push-notification/ios#id-4 "mention")
* android: [#id-5](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/push-notification/android#id-5 "mention")

이 기본 동작을 비활성화하고 클릭 시 액션을 직접 제어하려면, 아래 페이지 안내에 따라 clickHandler 기반 커스텀 연동을 진행해주세요.

{% content-ref url="../../advanced-usage/custom-click-handler" %}
[custom-click-handler](https://docs.marketap.io/t3ZS4WXNMj0HK27EtIMV/developer/advanced-usage/custom-click-handler)
{% endcontent-ref %}

## 5. 이어서 진행하기

이제 Push Notification 연동이 완료되었습니다. 아래 문서에서 이어서 진행해주세요.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Push Notification 테스트</td><td><a href="../test">test</a></td></tr><tr><td>In-App Campaign 테스트</td><td><a href="../../in-app-message/in-app-campaign">in-app-campaign</a></td></tr><tr><td>심화 연동</td><td><a href="../../advanced-usage/overview">overview</a></td></tr></tbody></table>
