# iOS 푸시 프라이머

푸시 프라이머는 iOS 시스템 푸시 권한 프롬프트 **전에** 표시하는 소프트 옵트인 대화 상자입니다. iOS는 설치당 한 번만 시스템 프롬프트를 표시합니다. 사용자가 **허용 안 함**을 탭하면, 설정에서 다시 활성화할 때까지 푸시를 보낼 수 없게 됩니다. 프라이머를 사용하면 먼저 가치를 설명하고 적절한 순간에 요청할 수 있으므로, 이미 동의한 사용자에게만 한 번뿐인 시스템 프롬프트를 사용할 수 있습니다.

버전 7.1.1부터 사용할 수 있습니다. 프라이머는 `PushwooshFramework`의 일부이며, 추가 모듈이 필요하지 않습니다.

<figure style={{ textAlign: "center" }}>
  <img
    src="/ios-push-primer-1.webp"
    alt="시스템 권한 프롬프트 전에 표시되는 푸시 프라이머 대화 상자"
    style={{ display: "block", margin: "0 auto", maxWidth: "300px", height: "auto" }}
    width="300"
  />
  <figcaption>iOS 시스템 권한 프롬프트 전에 표시되는 푸시 프라이머</figcaption>
</figure>

## 작동 방식

프라이머는 상태를 완전히 인식합니다. 현재 알림 승인 상태를 읽고 무엇을 할지 결정하므로, 매 실행 시 호출해도 안전합니다:

- **결정되지 않음** — 프라이머를 표시합니다. 수락 시 시스템 권한 프롬프트를 트리거합니다.
- **승인됨 또는 임시** — 프라이머를 조용히 억제합니다 (아무것도 표시되지 않음).
- **거부됨** — 프라이머를 표시합니다. 수락 시 사용자를 앱의 알림 설정으로 안내합니다 (`fallbackToSettings`가 활성화된 경우).

프라이머를 **언제** 호출할지는 사용자가 결정합니다 (예: 온보딩 후 또는 주요 작업 후). SDK는 아래에 설명된 선택적 `minInterval` 스로틀을 제외하고는 자체적인 타이밍을 강제하지 않습니다.

## 기본 사용법

플루언트 빌더로 프라이머를 구성하고 `present`를 호출합니다. 최소 설정에는 제목, 메시지, 그리고 두 개의 버튼 제목이 필요합니다.

<Tabs>
<TabItem label="Swift">
```swift
import PushwooshFramework

Pushwoosh.configure.pushPrimer
    .title("최신 소식을 받아보세요")
    .message("할인 및 주문 업데이트 알림을 가장 먼저 받아보세요")
    .acceptButton("알림 활성화")
    .declineButton("나중에")
    .present()
```
</TabItem>
</Tabs>

<Aside type="note">
앱 UI가 화면에 표시된 후 (예: 실행 후 잠시 뒤 또는 플로우의 특정 단계에서) 프라이머를 호출하여 인터페이스 위에 표시되도록 하세요.
</Aside>

## 스타일 및 위치

`style`을 사용하여 시스템 경고와 사용자 정의 시트 중에서 선택하고, `position`을 사용하여 사용자 정의 시트를 배치합니다. 각 위치에는 고유한 기본 디자인이 있습니다.

| 값 | 설명 |
|-------|-------------|
| `.alert` | 시스템 `UIAlertController`. 위치는 무시됩니다. |
| `.sheet` + `.bottom` | 위로 슬라이드되는 하단 시트, 그래버와 전체 너비 버튼 포함 (기본값). |
| `.sheet` + `.top` | 알림처럼 상단에서 내려오는 컴팩트한 배너. |
| `.sheet` + `.center` | 가운데에 위치하며 크기가 조절되고 페이드인되는 대화 상자. |

<Tabs>
<TabItem label="Swift">
```swift
Pushwoosh.configure.pushPrimer
    .style(.sheet)
    .position(.top)
    .title("최신 소식을 받아보세요")
    .message("할인 및 주문 업데이트 알림을 가장 먼저 받아보세요")
    .acceptButton("알림 활성화")
    .declineButton("나중에")
    .present()
```
</TabItem>
</Tabs>

<img src="/ios-push-primer-positions.webp" alt="하단, 상단 및 중앙 위치의 푸시 프라이머"/>

## 사용자 정의

모든 시각적 설정은 선택 사항입니다. 생략하면 라이트 및 다크 모드에 적응하는 네이티브 기본값을 사용합니다.

<Tabs>
<TabItem label="Swift">
```swift
Pushwoosh.configure.pushPrimer
    .style(.sheet)
    .position(.center)
    .title("최신 소식을 받아보세요")
    .message("할인 및 주문 업데이트 알림을 가장 먼저 받아보세요")
    .acceptButton("알림 활성화")
    .declineButton("나중에")
    .image(UIImage(named: "PrimerHero"))          // 로컬 이미지 또는 .imageURL("https://…")
    .backgroundColor(.systemBackground)
    .titleColor(.label)
    .messageColor(.secondaryLabel)
    .acceptButtonColor(.systemBlue)
    .acceptButtonTextColor(.white)
    .declineButtonColor(.clear)
    .declineButtonTextColor(.secondaryLabel)
    .cornerRadius(24)
    .buttonCornerRadius(14)
    .buttonBorderColor(.separator)
    .present()
```
</TabItem>
</Tabs>

사용자 정의 참조:

| 설정자 | 설명 |
|--------|-------------|
| `image` / `imageURL` | 로컬 `UIImage` 또는 원격 URL. 중앙 및 하단 레이아웃에서는 원으로, 상단 배너에서는 아이콘으로 렌더링됩니다. 로컬 이미지가 URL보다 우선합니다. |
| `backgroundColor` | 카드의 단색 배경색입니다. |
| `backgroundGradient` | 부드러운 다중 색상 그라데이션으로 렌더링되는 색상 배열입니다. `backgroundColor`를 재정의합니다. |
| `titleColor` / `messageColor` | 제목 및 메시지 텍스트 색상입니다. |
| `acceptButtonColor` / `acceptButtonTextColor` | 수락 버튼 배경 및 텍스트 색상입니다. 수락 색상은 기본 아이콘에도 적용됩니다. |
| `declineButtonColor` / `declineButtonTextColor` | 거절 버튼 배경 및 텍스트 색상입니다. |
| `cornerRadius` | 카드의 모서리 반경입니다. |
| `buttonCornerRadius` / `buttonBorderColor` | 두 버튼의 모서리 반경 및 테두리 색상입니다. |

<Aside type="note">
프라이머는 전달한 문자열을 정확히 표시합니다. 다국어를 지원하려면 현지화된 문자열을 전달하세요 (예: `NSLocalizedString` 사용).
</Aside>

## 동작 설정

### 설정 폴백

기본적으로 알림이 이미 거부된 경우 프라이머가 표시되고 수락 버튼을 누르면 사용자가 앱의 알림 설정으로 이동합니다. 대신 거부된 상태에서 프라이머를 완전히 억제하려면 `false`를 전달하세요.

```swift
.fallbackToSettings(false)
```

### 표시 빈도

기본적으로 프라이머에는 내장된 스로틀링이 없습니다. `present`를 호출할 때마다 표시됩니다 (알림이 승인되면 자동으로 억제됨). `minInterval`을 사용하여 프라이머가 다시 나타나는 빈도를 제한할 수 있습니다. 마지막으로 표시된 시간은 실행 간에 유지됩니다.

```swift
.minInterval(7 * 24 * 60 * 60)   // 최대 일주일에 한 번 표시
```

## 결과 처리

결과에 반응하려면 `present`에 완료 핸들러를 전달하세요.

<Tabs>
<TabItem label="Swift">
```swift
Pushwoosh.configure.pushPrimer
    .title("최신 소식을 받아보세요")
    .message("할인 및 주문 업데이트 알림을 가장 먼저 받아보세요")
    .acceptButton("알림 활성화")
    .declineButton("나중에")
    .present { outcome in
        switch outcome {
        case .accepted:            break   // 표시됨, 사용자가 수락, 시스템 프롬프트 요청됨
        case .declined:            break   // 표시됨, 사용자가 거절
        case .suppressed:          break   // 표시되지 않음 (이미 승인되었거나 스로틀링됨)
        case .redirectedToSettings: break  // 거부 상태, 사용자가 설정으로 이동됨
        @unknown default:          break
        }
    }
```
</TabItem>
</Tabs>

최종 시스템 프롬프트 결과(허용/거부 상태 및 디바이스 토큰)는 일반 등록 콜백을 통해 도착합니다. 프라이머는 수락 시 `registerForPushNotifications`를 재사용하며 해당 체인을 복제하지 않습니다.

## 참조

<CardGrid>
  <LinkCard
    title="iOS SDK API 참조"
    description="모든 공개 클래스, 메서드 및 속성을 다루는 완전한 기술 문서입니다."
    href="https://pushwoosh.github.io/pushwoosh-ios-sdk/"
  />
  <LinkCard
    title="iOS SDK 사용자 정의"
    description="Pushwoosh iOS SDK를 앱에 맞게 조정하는 다른 방법들입니다."
    href="/developer/pushwoosh-sdk/ios-sdk/customizing-ios-sdk/"
  />
</CardGrid>