> For the complete documentation index, see [llms.txt](https://docs.dfinery.ai/developer-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dfinery.ai/developer-guide/platform/hybridapp/web-view-interface.md).

# 연동하기

본 가이드에서는 Android, iOS에서 하이브리드 앱을 연동했을 시의 가상의 시나리오를 다룹니다. HTML 뷰와 Native 뷰 간의 차이를 해소하여 HTML 뷰에서 이벤트를 기록하고 앱으로 보낼 수 있는 방법에 대해 설명합니다.

해당 방법을 적용하기 위해선 SDK 설치 및 연동 작업이 선행되어야 합니다.

* [Android 시작하기](https://docs.dfinery.ai/developer-guide/platform/android/integration)
* [iOS 시작하기](https://docs.dfinery.ai/developer-guide/platform/ios/integration)

더 자세히 알아보려면 [리소스 및 샘플](/developer-guide/common/resource-and-sample.md)을 참조하세요.

## 자바스크립트 인터페이스 <a href="#javascript-interface" id="javascript-interface"></a>

Android와 iOS 모두 web view에서 native code를 호출할 수 있는 네이티브 자바스크립트 인터페이스를 갖고 있습니다.

* Android: [JavascriptInterface](https://developer.android.com/guide/webapps/webview)
* iOS: [JavaScriptCore](https://developer.apple.com/documentation/javascriptcore)

구현은 다음 단계들로 구성됩니다.

1. Webview 또는 웹페이지를 위한 HTML 코드
2. Webview를 위한 네이티브 코드 구현

### Android

#### Android 용 HTML 코드

다음 HTML 코드를 Webview 또는 웹 페이지에 추가합니다.

```html
<h1>Logging Event From Web View</h1>
<div id="main">
 <button id="logSignUpEvent" onclick="logSignUPEvent()"> SignUp </button>
</div>
<script type="text/javascript">
 function logLoginEvent(){
 var eventName = "df_sign_up"
 var eventProperty = {'df_sign_channel': 'Facebook'};
 window.customJsBridge.logEvent(eventName, JSON.stringify(eventProperty));
}
</script>
```

#### WebActivity 클래스

다음 코드를 사용하여 웹 액티비티 클래스를 작성합니다.

{% tabs %}
{% tab title="Java" %}

```java
myWebview.getSettings().setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new MainJsInterface(), "customJsBridge");
myWebView.loadUrl("https://yourwebsite.com");
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
webView.settings.apply {
  this.javaScriptEnabled = true
}
myWebView.addJavascriptInterface(MainJsInterface(), "customJsBridge")
myWebView.loadUrl("https://yourwebsite.com")
```

{% endtab %}
{% endtabs %}

#### Javascript 인터페이스 클래스

JavascriptInterface로 invoke()를 구현할 MainJsInterface class를 생성합니다.

{% tabs %}
{% tab title="Java" %}

```java
public class MainJsInterface {
    @JavascriptInterface
    public void logEvent(String eventName, String eventProperty){
        JSONObject eventPropertyJsonObject = null;
        if(eventProperty != null){
            try {
                eventPropertyJsonObject = new JSONObject(eventProperty);
                } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        Dfinery.getInstance().logEvent(eventName, eventPropertyJsonObject);
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class MainJsInterface {
    @JavascriptInterface
    fun logEvent(eventName: String?, eventProperty: String?) {
        var eventPropertyJsonObject: JSONObject? = null
        if (eventProperty != null) {
            try {
                eventPropertyJsonObject = JSONObject(eventProperty)
            } catch (e: JSONException) {
                e.printStackTrace()
            }
        }
        Dfinery.getInstance().logEvent(eventName!!, eventPropertyJsonObject)
    }
}
```

{% endtab %}
{% endtabs %}

### iOS

#### iOS 용 HTML 코드

다음 HTML 코드를 Webview 또는 웹 페이지에 추가합니다.

```html
<h1>Logging Event From Web View</h1>
<div id="main">
 <button id="logSignUpEvent" onclick="logSignUPEvent()"> SignUp </button>
</div>
<script type="text/javascript">
 function logLoginEvent(){
 var eventName = "df_sign_up"
 var eventProperty = {'df_sign_channel': 'Facebook'};
 var message = {
    'eventName' : eventName,
    'eventProperty' : eventProperty
 };
 webkit.messageHandlers.customJsBridge.postMessage(message);
}
</script>
```

#### WKWebView 설정

다음과 같이 WKWebView 객체의 messageHandler를 연결후 웹뷰를 로드해 주세요.

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

```swift
import UIKit
import WebKit
import DfinerySDK

class WebView: UIViewController, WKScriptMessageHandler {

    var webView: WKWebView!
    
    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // messageHandler 연결
        webView.configuration.userContentController.add(self, name: "customJsBridge")

        let myURL = URL(string:"https://www.YOUR_WEBSITE.com")
        let myRequest = URLRequest(url: myURL!)
        webView.load(myRequest)
    }

    // WKScriptMessageHandler 프로토콜 구현
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "customJsBridge", let messageBody = message.body as? [String: Any] {
            if let eventName = messageBody["eventName"] as? String,
               let eventProperty = messageBody["eventProperty"] as? [String: Any] {
                // Dfinery SDK 이벤트 호출
                Dfinery.shared().logEvent(name: eventName, properties: property)
            }
        }
    }
}
```

{% endtab %}

{% tab title="Objective-C" %}

```objective-c
// WebView.h
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
#import <DfinerySDK/DfinerySDK.h>

@interface WebView : UIViewController <WKScriptMessageHandler>

@property (nonatomic, strong) WKWebView *webView;

@end

@implementation WebView

// WebView.m

#import "WebView.h"

@implementation WebView

- (void)loadView {
    WKWebViewConfiguration *webConfiguration = [[WKWebViewConfiguration alloc] init];
    self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfiguration];
    self.view = self.webView;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // messageHandler 연결
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"customJsBridge"];
    
    NSURL *myURL = [NSURL URLWithString:@"https://www.YOUR_WEBSITE.com"];
    if (myURL) {
        NSURLRequest *myRequest = [NSURLRequest requestWithURL:myURL];
        [self.webView loadRequest:myRequest];
    }
}

// WKScriptMessageHandler 프로토콜 구현
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"customJsBridge"]) {
        if ([message.body isKindOfClass:[NSDictionary class]]) {
            NSDictionary *messageBody = (NSDictionary *)message.body;
            
            NSString *eventName = messageBody[@"eventName"];
            NSDictionary *eventProperty = messageBody[@"eventProperty"];
            
            if (eventName && [eventProperty isKindOfClass:[NSDictionary class]]) {
                // Dfinery SDK 이벤트 호출
                [[Dfinery shared] logEvent:eventName withProperties:eventProperty];
            }
        }
    }
}

@end

```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Swift로 작성된 하이브리드 앱에서 logEvent 호출 시\
logEvent(\_ name: String, properties: \[String: Any]) 메서드가 아닌\
logEvent(name: String, properties: \[String: Any]) 메서드를 호출해 주세요
{% endhint %}

## 더 알아보기 <a href="#learn-more" id="learn-more"></a>

### 날짜 및 시간 형식 속성 입력하기 <a href="#datetime-property" id="datetime-property"></a>

날짜 및 시간 형식은 `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` 포맷의 문자열 형태로 입력해야합니다.

{% hint style="info" %}
javascript에서 Date 객체를 활용하는 방법은 이 [문서](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Date)를 참고해주시기 바랍니다.
{% endhint %}

{% tabs %}
{% tab title="For Android" %}

```javascript
let today = new Date().toISOString();
let eventName = "df_sign_up"
let eventProperty = {
    'custom_property': today
};
window.customJsBridge.logEvent(eventName, JSON.stringify(eventProperty));
```

{% endtab %}

{% tab title="For iOS" %}

```javascript
let today = new Date().toISOString();
var eventName = "df_sign_up"
let eventProperty = {
    'custom_property': today
};
var message = {
    'eventName' : eventName,
    'eventProperty' : eventProperty
 };
webkit.messageHandlers.customJsBridge.postMessage(message);
```

{% endtab %}
{% endtabs %}

### 유저 식별 정보 설정 <a href="#set-identity" id="set-identity"></a>

Dfinery Android SDK는 유저 식별 정보를 Enum으로 입력 받고 있습니다. HTML에서 유저 식별 정보를 입력하기 위해서는 [유저 식별 정보 상수](/developer-guide/common/constants.md#undefined-9)의 값을 입력하여 자바스크립트 인터페이스 상에서 문자열을 Enum으로 치환한 뒤 호출하는 것을 권장합니다.

#### Javascript

```javascript
window.customJsBridge.setIdentity('external_id', 'sampleUser');
```

{% tabs %}
{% tab title="Java" %}

```java
public class MainJsInterface {
    @JavascriptInterface
    public void setIdentity(String key, String value){
        DFIdentity identity = DFIdentity.get(key);
        DfineryProperties.setIdentity(identity, value);
    }
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
class MainJsInterface {
    @JavascriptInterface
    fun setIdentity(key: String?, value: String?) {
        val identity: DFIdentity = DFIdentity.get(key)
        DfineryProperties.setIdentity(identity, value)
    }
}
```

{% endtab %}
{% endtabs %}
