# 엔트리포인트(EntryPoint)

Source: https://docs.buzzvil.com/docs/buzzbenefit-ios/v6/entrypoint
Platform: iOS
SDK major version: v6
Language: Korean (ko)

엔트리포인트를 추가하고 SDK 인터페이스를 사용해 부가 기능을 구현하는 방법을 알아보세요.

## 주요 특징

엔트리포인트는 앱 내 다양한 위치에 자연스럽게 배치할 수 있는 진입 컴포넌트로, 유저가 콘텐츠에 쉽게 접근할 수 있도록 도와줍니다. 플로팅 버튼(FAB), 배너(Banner), 바텀 시트(BottomSheet), 팝업(Popup), 커스텀(Custom) 등 다양한 UI 유형을 지원하며, 기획 목적에 따라 자유롭게 선택하고 배치할 수 있습니다. 버즈빌 대시 어드민을 통해 설정할 수 있으며, 클릭 시 [베네핏허브](https://docs.buzzvil.com/docs/buzzbenefit-ios/v6/benefithub), [럭키박스](https://docs.buzzvil.com/docs/buzzbenefit-ios/v6/benefithub#%EB%9F%AD%ED%82%A4%EB%B0%95%EC%8A%A4), [미션팩](https://docs.buzzvil.com/docs/buzzbenefit-ios/v6/benefithub#%EB%AF%B8%EC%85%98%ED%8C%A9) 등으로 이동하거나 앱 내 특정 화면으로 연결되는 딥링크를 설정할 수 있습니다.

![](https://docs.buzzvil.com/api/content-image/buzzbenefit-ios/v6/image/09-entrypoint/00-entrypoint-intro.png)

## 연동

엔트리포인트를 연동하는 방법을 확인해 보세요.

### 1 단계. 준비하기

- [시작하기](https://docs.buzzvil.com/docs/buzzbenefit-ios/v6/getting-started) 적용 완료

### 2 단계. 설정하기

> ✏️  **참고**\
> 네이티브 오버레이의 경우 [네이티브 오버레이 사용하기](https://docs.buzzvil.com/docs/buzzbenefit-ios/v6/native#%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EC%98%A4%EB%B2%84%EB%A0%88%EC%9D%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0)를 참고하세요.\
> 엔트리포인트를 설정하려면 버즈빌 담당자(<help@buzzvil.com>)에게 연락하세요.

#### 엔트리 포인트 유형

| 유형            | 설명                                                                      |
| ------------- | ----------------------------------------------------------------------- |
| `FAB`         | 플로팅 액션 버튼으로, 화면의 오른쪽 하단에 위치합니다.                                         |
| `Banner`      | 화면 내 원하는 위치에 고정된 배너 형태로, 여러 개의 배너 엔트리 목록을 슬라이드 형식으로 표시하며 3초마다 자동 전환됩니다. |
| `Popup`       | 팝업 형태로, 화면 중앙에 표시됩니다.                                                   |
| `BottomSheet` | 바텀 시트 형태로, 화면 하단에서 위로 슬라이드 하여 표시됩니다.                                    |
| `Custom`      | 커스텀 UI를 사용하여 엔트리포인트를 구현할 수 있습니다.                                        |

#### 엔트리 포인트 이미지

| 유형            | 이미지                                                                                                                  |
| ------------- | -------------------------------------------------------------------------------------------------------------------- |
| `FAB`         | ![](https://docs.buzzvil.com/api/content-image/buzzbenefit-ios/v6/image/09-entrypoint/01-entrypoint-fab.png)         |
| `Banner`      | ![](https://docs.buzzvil.com/api/content-image/buzzbenefit-ios/v6/image/09-entrypoint/02-entrypoint-banner.png)      |
| `Popup`       | ![](https://docs.buzzvil.com/api/content-image/buzzbenefit-ios/v6/image/09-entrypoint/03-entrypoint-popup.png)       |
| `BottomSheet` | ![](https://docs.buzzvil.com/api/content-image/buzzbenefit-ios/v6/image/09-entrypoint/04-entrypoint-bottomsheet.png) |

#### 엔트리 포인트 UI 지원 규격

| 유형            | 규격                                                                                                                            |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `FAB`         | 이미지 포맷: PNG, JPG, JSON(Lottie), 파일 크기: 최대 2 MB, 이미지 비율: 60 x 60 (가로 x 세로), 툴팁 글자 수: 최대 6 자 (공백 포함), 메시지 글자 수: 최대 20 자 (공백 포함) |
| `Banner`      | 이미지 포맷: PNG, JPG, JSON(Lottie), 파일 크기: 최대 2 MB, 이미지 비율: 351 x 112 (가로 x 세로)                                                   |
| `Popup`       | 이미지 포맷: PNG, JPG, JSON(Lottie), 파일 크기: 최대 2 MB, 이미지 비율: 335 x 380 (가로 x 세로)                                                   |
| `BottomSheet` | 이미지 포맷: PNG, JPG, JSON(Lottie), 파일 크기: 최대 2 MB, 이미지 비율: 335 x 256 (가로 x 세로)                                                   |

### 3 단계. 요청하기

아래 코드를 참고하여 엔트리포인트를 요청하세요.

> ✏️  **참고**\
> `load`를 호출하면 대시 어드민에 활성화된 모든 엔트리포인트 정보를 한 번에 가져옵니다.

**Swift**

```swift
BuzzEntryPoint.shared.load(
  onSuccess: { [weak self] availableTypes in
    // 요청에 성공하면 표시 가능한 엔트리포인트 타입 배열과 함께 호출됩니다.
  },
  onFailure: { [weak self] error in
    // 요청에 실패하면 에러와 함께 호출됩니다.
  }
)
```

**Objective-C**

```objectivec
[BuzzEntryPoint.shared loadOnSuccess:^(NSArray<NSNumber *> * _Nonnull types) {
  // 요청에 성공하면 표시 가능한 엔트리포인트 타입 배열과 함께 호출됩니다.
  for (NSNumber *typeNumber in types) {
    BuzzEntryPointType type = (BuzzEntryPointType)[typeNumber integerValue];
  }
} onFailure:^(NSError * _Nonnull error) {
  // 요청에 실패하면 에러와 함께 호출됩니다.
}];
```

#### 엔트리 포인트 타입 `BuzzEntryPointType` 종류

| 유형            | Swift          | Objective-C                     |
| ------------- | -------------- | ------------------------------- |
| `FAB`         | `.fab`         | `BuzzEntryPointTypeFab`         |
| `Banner`      | `.banner`      | `BuzzEntryPointTypeBanner`      |
| `Popup`       | `.popup`       | `BuzzEntryPointTypePopup`       |
| `BottomSheet` | `.bottomSheet` | `BuzzEntryPointTypeBottomSheet` |
| `Custom`      | `.custom`      | `BuzzEntryPointTypeCustom`      |

### 4 단계. 표시하기 (FAB)

아래 코드를 참고하여 엔트리포인트 FAB를 표시하세요.

> ✏️  **참고**\
> showFab 메소드는 `BuzzEntryPoint.shared.load` 메소드를 호출하여 성공적으로 onSuccess 응답을 받은 후에 호출할 수 있습니다.\
> canShow 메소드를 사용하여 FAB를 표시할 수 있는지 확인한 후에 호출할 수 있습니다.

**SwiftUI**

```swift
import SwiftUI
import BuzzvilSDK

struct YourView: View {
  @State private var isFabPresented = false
  
  var body: some View {
    Color.clear
      .buzzEntryPointFab(isPresented: $isFabPresented)
  }
}
```

**UIKit(Swift)**

```swift
import UIKit
import BuzzvilSDK

final class YourViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    
    if BuzzEntryPoint.shared.canShow(type: .fab) {
      BuzzEntryPoint.shared.showFab(on: self)
    }
  }
}
```

**UIKit(Objective-C)**

```objectivec
@import UIKit;
@import BuzzvilSDK;

@interface YourViewController ()

@end

@implementation YourViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  if ([BuzzEntryPoint.shared canShowWithType:BuzzEntryPointTypeFab]) {
    [BuzzEntryPoint.shared showFabOn:self];
  }
}

@end
```

### 4 단계. 표시하기 (Banner)

아래 코드를 참고하여 엔트리포인트 Banner를 표시하세요.

> ✏️  **참고**\
> showBanner 메소드는 `BuzzEntryPoint.shared.load` 메소드를 호출하여 성공적으로 onSuccess 응답을 받은 후에 호출할 수 있습니다.\
> canShow 메소드를 사용하여 Banner를 표시할 수 있는지 확인한 후에 호출할 수 있습니다.

**SwiftUI**

```swift
import SwiftUI
import BuzzvilSDK

struct YourView: View {
  @State private var isBannerPresented = false

  var body: some View {
    VStack {
      if isBannerPresented {
        // aspectRatio 는 연동 가이드 비율(351 x 112)에 맞추는 것을 권장합니다. 비율이 맞지 않을 경우 이미지가 잘리거나, 여백이 생길 수 있습니다.
        BuzzEntryPointBannerView.Representable(isVisible: $isBannerPresented)
            .aspectRatio(351.0 / 112.0, contentMode: .fit)
            .frame(maxWidth: .infinity)
            .listRowInsets(EdgeInsets())
            .listRowBackground(Color.clear)
      }
    }
  }
}
```

**UIKit(Swift)**

```swift
import UIKit
import BuzzvilSDK

final class YourViewController: UIViewController {
  private let entryBannerView = BuzzEntryPointBannerView(frame: .zero)

  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(entryBannerView)
    // aspectRatio 는 연동 가이드 비율(351 x 112)에 맞추는 것을 권장합니다. 비율이 맞지 않을 경우 이미지가 잘리거나, 여백이 생길 수 있습니다.
    entryBannerView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      entryBannerView.heightAnchor.constraint(equalTo: entryBannerView.widthAnchor, multiplier: 112.0/351.0),
      // ...
    ])

    BuzzEntryPoint.shared.showBanner(on: entryBannerView)
  }
}
```

**UIKit(Objective-C)**

```objectivec
@import UIKit;
@import BuzzvilSDK;

@interface YourViewController ()

@property (nonatomic, strong, readonly) BuzzEntryPointBannerView *entryBannerView;

@end

@implementation YourViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  self.entryBannerView = [[BuzzEntryPointBannerView alloc] initWithFrame:CGRectZero];
  [self.view addSubview:self.entryBannerView];
  // aspectRatio 는 연동 가이드 비율(351 x 112)에 맞추는 것을 권장합니다. 비율이 맞지 않을 경우 이미지가 잘리거나, 여백이 생길 수 있습니다.
  self.entryBannerView.translatesAutoresizingMaskIntoConstraints = NO;
  [NSLayoutConstraint activateConstraints:@[
    [self.entryBannerView.heightAnchor constraintEqualToAnchor:self.entryBannerView.widthAnchor multiplier:(112.0/351.0)],
    // ...
  ]];

  [BuzzEntryPoint.shared showBannerOn:entryBannerView];
}

@end
```

### 4 단계. 표시하기 (Popup)

아래 코드를 참고하여 엔트리포인트 Popup을 표시하세요.

> ✏️  **참고**\
> showPopup 메소드는 `BuzzEntryPoint.shared.load` 메소드를 호출하여 성공적으로 onSuccess 응답을 받은 후에 호출할 수 있습니다.\
> canShow 메소드를 사용하여 Popup을 표시할 수 있는지 확인한 후에 호출할 수 있습니다.

**SwiftUI**

```swift
import SwiftUI
import BuzzvilSDK

struct YourView: View {
  @State private var isPopupPresented = false
  
  var body: some View {
    Color.clear
      .buzzEntryPointPopup(isPresented: $isPopupPresented)
  }
}
```

**UIKit(Swift)**

```swift
import UIKit
import BuzzvilSDK

final class YourViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    if BuzzEntryPoint.shared.canShow(type: .popup) {
      BuzzEntryPoint.shared.showPopup(on: self)
    } 
  }
}
```

**UIKit(Objective-C)**

```objectivec
@import UIKit;
@import BuzzvilSDK;

@interface YourViewController ()

@end

@implementation YourViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  if ([BuzzEntryPoint.shared canShowWithType:BuzzEntryPointTypePopup]) {
    [BuzzEntryPoint.shared showPopupOn:self];
  }
}

@end
```

### 4 단계. 표시하기 (BottomSheet)

아래 코드를 참고하여 엔트리포인트 BottomSheet을 표시하세요.

> ✏️  **참고**\
> showBottomSheet 메소드는 `BuzzEntryPoint.shared.load` 메소드를 호출하여 성공적으로 onSuccess 응답을 받은 후에 호출할 수 있습니다.\
> canShow 메소드를 사용하여 BottomSheet을 표시할 수 있는지 확인한 후에 호출할 수 있습니다.

**SwiftUI**

```swift
import SwiftUI
import BuzzvilSDK

struct YourView: View {
  @State private var isBottomSheetPresented = false
  
  var body: some View {
    Color.clear
      .buzzEntryPointBottomSheet(isPresented: $isBottomSheetPresented)
  }
}
```

**UIKit(Swift)**

```swift
import UIKit
import BuzzvilSDK

final class YourViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    if BuzzEntryPoint.shared.canShow(type: .bottomSheet) {
      BuzzEntryPoint.shared.showBottomSheet(on: self)
    } 
  }
}
```

**UIKit(Objective-C)**

```objectivec
@import UIKit;
@import BuzzvilSDK;

@interface YourViewController ()

@end

@implementation YourViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  if ([BuzzEntryPoint.shared canShowWithType:BuzzEntryPointTypeBottomSheet]) {
    [BuzzEntryPoint.shared showBottomSheetOn:self];
  }
}

@end
```

### 4 단계. 표시하기 (Custom)

아래 예시 코드를 참고하여 엔트리포인트 Custom을 표시하세요. UI를 자유롭게 구성하고, `customEntryPointClicked` 메소드를 호출하여 클릭 이벤트를 처리할 수 있습니다.

> ✏️  **참고**
>
> - `identifier` 값은 매체사에서 자체적으로 사용하는 구분값을 사용하면 됩니다.
> - 해당 `identifier` 값을 버즈빌 담당자에게 전달해야 합니다.
> - `customEntryPointClicked` 메소드는 식별된 `identifier`에 따라 원하는 페이지로 랜딩할 수 있으며, 식별되지 않는 `identifier`를 인자로 받게 되면 기본 동작인 베네핏허브 열기로 동작합니다.

**SwiftUI**

```swift
import SwiftUI
import BuzzvilSDK

struct YourView: View {
  var body: some View {
    CustomEntryViewControllerRepresentable()
      .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

fileprivate struct CustomEntryViewControllerRepresentable: UIViewControllerRepresentable {
  func makeUIViewController(context: Context) -> CustomEntryViewController {
    CustomEntryViewController()
  }
  
  func updateUIViewController(_ uiViewController: CustomEntryViewController, context: Context) {}
}

fileprivate final class CustomEntryViewController: UIViewController {
  private lazy var customEntryButton: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("Custom Entry", for: .normal)
    button.addTarget(self, action: #selector(customEntryButtonTapped), for: .touchUpInside)
    return button
  }()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    view.addSubview(customEntryButton)
    
    customEntryButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      customEntryButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      customEntryButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
  }
  
  @objc
  private func customEntryButtonTapped() {
    BuzzEntryPoint.shared.customEntryPointClicked(identifier: "YOUR_IDENTIFIER", on: self)
  }
}
```

**UIKit(Swift)**

```swift
import UIKit
import BuzzvilSDK

final class YourViewController: UIViewController {
  private lazy var customEntryButton: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("Custom Entry", for: .normal)
    button.addTarget(self, action: #selector(customEntryButtonTapped), for: .touchUpInside)
    return button
  }()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    view.addSubview(customEntryButton)
    
    customEntryButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      customEntryButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      customEntryButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
    ])
  }
  
  @objc
  private func customEntryButtonTapped() {
    BuzzEntryPoint.shared.customEntryPointClicked(identifier: "YOUR_IDENTIFIER", on: self)
  }
}
```

**UIKit(Objective-C)**

```objectivec
@import UIKit;
@import BuzzvilSDK;

@interface YourViewController ()

@property (nonatomic, strong) UIButton *customEntryButton;

@end

@implementation YourViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  self.customEntryButton = [UIButton buttonWithType:UIButtonTypeSystem];
  [self.customEntryButton setTitle:@"Custom Entry" forState:UIControlStateNormal];
  [self.customEntryButton addTarget:self action:@selector(customEntryButtonTapped) forControlEvents:UIControlEventTouchUpInside];

  [self.view addSubview:self.customEntryButton];
  self.customEntryButton.translatesAutoresizingMaskIntoConstraints = NO;
  [NSLayoutConstraint activateConstraints:@[
    [self.customEntryButton.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
    [self.customEntryButton.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor]
  ]];
}

- (void)customEntryButtonTapped {
  [BuzzEntryPoint.shared customEntryPointClickedWithIdentifier:@"YOUR_IDENTIFIER" on:self];
}

@end
```

## 추가 구현

엔트리포인트에 추가 기능을 구현하는 방법을 안내합니다.

### 딥링크 동작 커스터마이징

엔트리포인트 클릭 시 딥링크 동작을 커스터마이징할 수 있습니다. 아래 예시 코드를 참고하세요.

> ✏️  **참고**\
> 기본으로 설정된 딥링크 클릭 동작은 외부 브라우저로 열기입니다.

**Swift**

```swift
BuzzEntryPoint.shared.setDeepLinkHandler { deepLinkURL in
  // 대시 어드민을 통해 설정한 deepLink url string이 전달됩니다.
  YourRouter.route(deepLinkURL)
}
```

**Objective-C**

```objectivec
[BuzzEntryPoint.shared setDeepLinkHandler:^(NSString * _Nonnull deepLinkURL) {
  // 대시 어드민을 통해 설정한 deepLink url string이 전달됩니다.
  [YourRouter route:deepLinkURL];
}];
```
