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

# Android SDK 설정

> OneSignal Android SDK를 사용하여 Android 앱에 푸시 알림과 인앱 메시지를 추가하세요.

export const SdkReleasesIframe = ({sdkFilter = undefined, viewMode = undefined, height, ...frameProps}) => {
  const baseUrl = 'https://onesignal.github.io/sdk-releases';
  const buildUrl = (theme, sdkFilter, viewMode) => {
    const url = new URL(baseUrl);
    const params = new URLSearchParams();
    if (theme) {
      params.set('theme', theme);
    }
    if (sdkFilter) {
      params.set('sdk', sdkFilter);
    }
    if (viewMode) {
      params.set('viewMode', viewMode);
    }
    if (params.toString()) {
      url.search = params.toString();
    }
    return url.toString();
  };
  const detectTheme = () => {
    if (document.documentElement.classList.contains('dark')) {
      return 'dark';
    }
    return 'light';
  };
  const [theme, setTheme] = useState('light');
  const [iframeSrc, setIframeSrc] = useState(() => {
    const initialTheme = detectTheme();
    return buildUrl(initialTheme, sdkFilter, viewMode);
  });
  useEffect(() => {
    const currentTheme = detectTheme();
    setTheme(currentTheme);
    setIframeSrc(buildUrl(currentTheme, sdkFilter, viewMode));
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    const handleThemeChange = () => {
      const newTheme = detectTheme();
      setTheme(newTheme);
      setIframeSrc(buildUrl(newTheme, sdkFilter, viewMode));
    };
    if (mediaQuery.addEventListener) {
      mediaQuery.addEventListener('change', handleThemeChange);
    } else {
      mediaQuery.addListener(handleThemeChange);
    }
    window.addEventListener('storage', handleThemeChange);
    const observer = new MutationObserver(handleThemeChange);
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class', 'data-theme']
    });
    return () => {
      if (mediaQuery.removeEventListener) {
        mediaQuery.removeEventListener('change', handleThemeChange);
      } else {
        mediaQuery.removeListener(handleThemeChange);
      }
      window.removeEventListener('storage', handleThemeChange);
      observer.disconnect();
    };
  }, [sdkFilter, viewMode]);
  const getIframeHeight = () => {
    if (viewMode === 'table') {
      return '450';
    }
    if (viewMode === 'mini') {
      return '170';
    }
    return '800';
  };
  const iframeHeight = height || getIframeHeight();
  return <Frame {...frameProps}>
      <iframe src={iframeSrc} width="100%" height={iframeHeight} frameBorder="0" style={{
    border: "none"
  }} title="SDK Releases" key={iframeSrc} />
    </Frame>;
};

<SdkReleasesIframe sdkFilter="android" viewMode="mini" />

이 가이드는 Android Studio를 사용하여 Android 앱에 OneSignal을 추가하는 과정을 안내합니다. SDK를 설치하고, 푸시 및 인앱 메시지를 설정하며, 테스트 메시지를 보내 모든 것이 올바르게 작동하는지 확인합니다.

OneSignal을 처음 사용하시는 경우 순서대로 단계를 따르세요. 이미 경험이 있으시다면 필요한 섹션으로 바로 이동하셔도 됩니다.

<Info>
  **AI 코딩 어시스턴트를 사용하시나요?**
  AI 기반 설치를 위해 다음 프롬프트를 사용하세요:

  ```
  Integrate the OneSignal Android SDK into this codebase.

  Follow the instructions at:
  https://raw.githubusercontent.com/OneSignal/sdk-ai-prompts/main/docs/android/ai-prompt.md
  ```
</Info>

## 0단계. OneSignal에서 FCM 구성 (푸시 전송에 필수)

이 단계를 완료하지 않아도 OneSignal Android SDK를 설치하고 초기화할 수 있습니다. 하지만 Firebase Cloud Messaging(FCM) 자격 증명이 OneSignal 앱에 구성될 때까지 **푸시 알림은 전송되지 않습니다**.

<Note>
  회사에 이미 OneSignal 계정이 있는 경우, 앱을 구성하려면 [관리자 역할로 초대를 요청](./manage-team-members)하세요. 아직 계정이 없다면 [무료 계정에 가입](https://onesignal.com)하여 시작하세요.
</Note>

<Accordion title="OneSignal 앱을 구성하는 단계.">
  이 단계는 OneSignal 앱을 Firebase Cloud Messaging(FCM)에 연결합니다. 앱당 한 번만 수행하면 됩니다.

  1. [https://onesignal.com](https://onesignal.com)에 로그인하고 앱을 생성하거나 선택하세요.
  2. **Settings > Push & In-App**으로 이동하세요.
  3. \*\*Google Android (FCM)\*\*을 선택하고 설정 마법사를 따라 **Continue**를 클릭하세요.
  4. [Firebase 서버 키 또는 서비스 계정](./android-firebase-credentials) 정보를 입력하세요.
  5. 설정 마법사를 계속 진행하여 App ID를 받으세요. 이 ID는 SDK를 초기화하는 데 사용됩니다.

  <Info>전체 설정 안내는 [모바일 푸시 설정](./mobile-push-setup) 가이드를 참조하세요.</Info>
</Accordion>

***

## 설정 계약 및 요구 사항

이 섹션은 가이드 전체에서 사용되는 도구, 버전 및 전제 조건을 요약합니다.

* **SDK 버전:** `5.6.1+` (최신 버전: [릴리스](https://github.com/OneSignal/OneSignal-Android-SDK/releases) 확인)
* **AI 설정 안내:** `https://raw.githubusercontent.com/OneSignal/sdk-ai-prompts/main/docs/android/ai-prompt.md`
* **SDK 저장소:** `https://github.com/OneSignal/OneSignal-Android-SDK`
* **Android Studio:** Meerkat+ (2024.2.1+)
* **Android API:** 최소 23+ (Android 6.0+), 권장 31+ (Android 12+)
* **기기/에뮬레이터:** Google Play Services가 설치된 Android 7.0+
* **필수 의존성:** `com.onesignal:OneSignal:[5.6.1, 5.9.99]`
* **Application 클래스:** 올바른 SDK 초기화에 필수
* **App ID 형식:** 36자 UUID (예: `12345678-1234-1234-1234-123456789012`) — OneSignal Dashboard > Settings > Keys & IDs에서 확인
* **초기화:** `OneSignal.initWithContext(this, "YOUR_APP_ID")`
* **배터리 최적화:** 백그라운드 알림에 영향을 줄 수 있음
* **권장:** `OneSignal.login("user_id")`를 통해 External ID를 할당하여 기기 간 사용자 통합

***

## Android 설정 단계

아래 단계를 완료하면 다음을 달성하게 됩니다:

* OneSignal SDK가 Android 앱에 설치되고 초기화됨
* 실제 기기에서 푸시 알림 권한 요청이 올바르게 표시됨
* 테스트 푸시 및 인앱 메시지가 성공적으로 전송됨

<Info>
  \*\*0단계(OneSignal에서 FCM 구성)\*\*를 건너뛰었더라도 아래 Android Studio 설정을 완료할 수 있습니다. 푸시 알림을 테스트하거나 보내기 전에 0단계를 완료하세요.
</Info>

### 1단계. OneSignal SDK 추가

1. Android Studio에서 `build.gradle.kts (Module: app)` 또는 `build.gradle (Module: app)` 파일을 여세요
2. `dependencies` 섹션에 OneSignal을 추가하세요:

<CodeGroup>
  ```kotlin app/build.gradle.kts theme={null}
  implementation("com.onesignal:OneSignal:[5.6.1, 5.9.99]")
  ```

  ```groovy app/build.gradle theme={null}
  implementation 'com.onesignal:OneSignal:[5.6.1, 5.9.99]'
  ```
</CodeGroup>

<Frame caption="앱의 build.gradle.kts 파일에 OneSignal을 추가하는 예시.">
  <img src="https://mintcdn.com/onesignal/dlRpLVMLP5Sd65F4/images/sdk/android-add-onesignal-to-build-gradle.png?fit=max&auto=format&n=dlRpLVMLP5Sd65F4&q=85&s=a1e031945c35197d41335c7c2956739e" width="3052" height="2030" data-path="images/sdk/android-add-onesignal-to-build-gradle.png" />
</Frame>

3. **Gradle 동기화:** 표시되는 배너에서 **Sync Now**를 클릭하거나 **File > Sync Project with Gradle Files**로 이동하세요

<Check>
  Gradle 동기화가 의존성 충돌 없이 성공적으로 완료되었는지 확인하세요.
</Check>

### 2단계. Application 클래스 생성 및 구성

모든 진입점에서 올바른 SDK 설정을 보장하려면 `Application` 클래스의 `onCreate` 메서드에서 OneSignal을 초기화하는 것이 모범 사례입니다.

**Application 클래스가 아직 없다면 생성하세요:**

1. **File > New > Kotlin Class/File** (또는 Java Class)
2. 이름: `ApplicationClass` (또는 원하는 이름)

<Frame caption="ApplicationClass라는 이름의 새 Kotlin 클래스를 생성하는 예시.">
  <img src="https://mintcdn.com/onesignal/dlRpLVMLP5Sd65F4/images/sdk/android-create-application-class-kotlin.png?fit=max&auto=format&n=dlRpLVMLP5Sd65F4&q=85&s=7ce9f314acb72ff74311c2695368f5cf" width="2810" height="1798" data-path="images/sdk/android-create-application-class-kotlin.png" />
</Frame>

**Application 클래스에 다음 OneSignal 코드를 추가하세요.**

`YOUR_APP_ID`를 Dashboard > Settings > [Keys & IDs](./keys-and-ids)에서 확인한 실제 OneSignal App ID로 교체하세요.

<CodeGroup>
  ```kotlin ApplicationClass.kt theme={null}
  // FILE: ApplicationClass.kt
  // PURPOSE: Initialize OneSignal when your app launches
  // REQUIREMENT: Must be registered in AndroidManifest.xml

  package com.your.package.name // Replace with your actual package name

  import android.app.Application
  import kotlinx.coroutines.CoroutineScope
  import kotlinx.coroutines.Dispatchers
  import kotlinx.coroutines.launch

  import com.onesignal.OneSignal
  import com.onesignal.debug.LogLevel

  class ApplicationClass : Application() {
      override fun onCreate() {
          super.onCreate()

          // Enable verbose logging to debug issues (remove in production)
          OneSignal.Debug.logLevel = LogLevel.VERBOSE

          // Replace with your 36-character App ID from Dashboard > Settings > Keys & IDs
          OneSignal.initWithContext(this, "YOUR_APP_ID")

          // Prompt user for push notification permission
          // In production, consider using an in-app message instead for better opt-in rates
          CoroutineScope(Dispatchers.IO).launch {
              OneSignal.Notifications.requestPermission(false)
          }
      }
  }
  ```

  ```java ApplicationClass.java theme={null}
  // FILE: ApplicationClass.java
  // PURPOSE: Initialize OneSignal when your app launches
  // REQUIREMENT: Must be registered in AndroidManifest.xml

  package com.your.package.name; // Replace with your actual package name

  import android.app.Application;

  import com.onesignal.Continue;
  import com.onesignal.OneSignal;
  import com.onesignal.debug.LogLevel;

  public class ApplicationClass extends Application {
      @Override
      public void onCreate() {
          super.onCreate();

          // Enable verbose logging to debug issues (remove in production)
          OneSignal.getDebug().setLogLevel(LogLevel.VERBOSE);

          // Replace with your 36-character App ID from Dashboard > Settings > Keys & IDs
          OneSignal.initWithContext(this, "YOUR_APP_ID");

          // Prompt user for push notification permission
          // In production, consider using an in-app message instead for better opt-in rates
          OneSignal.getNotifications().requestPermission(false, Continue.none());
      }
  }
  ```
</CodeGroup>

<Frame caption="ApplicationClass.kt 파일 예시.">
  <img src="https://mintcdn.com/onesignal/dlRpLVMLP5Sd65F4/images/sdk/android-application-class-kotlin.png?fit=max&auto=format&n=dlRpLVMLP5Sd65F4&q=85&s=e035c8995472b308f10e42ed82478a0a" width="3052" height="2030" data-path="images/sdk/android-application-class-kotlin.png" />
</Frame>

<Warning>
  `Activity`(예: `MainActivity`)에서 초기화하는 것은 딥 링크나 알림으로부터의 앱 콜드 스타트 시 호출되지 않을 수 있으므로 권장하지 않습니다. 안정성을 위해 항상 `Application` 클래스에서 OneSignal을 초기화하세요.
</Warning>

**Application 클래스 등록:**

1. 앱의 `AndroidManifest.xml`을 여세요
2. `<application>` 태그에 `android:name=".ApplicationClass"`를 추가하세요 (클래스 이름을 다르게 설정한 경우 `.ApplicationClass`를 실제 클래스 이름으로 교체하세요).

```xml AndroidManifest.xml theme={null}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:name=".ApplicationClass"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        ...
      </application>

  </manifest>
```

<Frame caption=".ApplicationClass 이름이 포함된 AndroidManifest.xml.">
  <img src="https://mintcdn.com/onesignal/dlRpLVMLP5Sd65F4/images/sdk/android-androidmanifest-application-class.png?fit=max&auto=format&n=dlRpLVMLP5Sd65F4&q=85&s=289b016975723e22e23d1871457ae21f" width="3052" height="2030" data-path="images/sdk/android-androidmanifest-application-class.png" />
</Frame>

<Check>
  앱이 오류 없이 빌드되고 실행되는지 확인하세요.
</Check>

### 3단계. 기본 알림 아이콘 구성 (권장)

앱의 브랜딩에 맞게 [알림 아이콘](./notification-icons)을 커스터마이즈하세요. 이 단계는 선택 사항이지만 전문적인 외관을 위해 권장됩니다.

### 4단계. 통합 테스트

**구독 생성 확인:**

1. Google Play Services가 있는 기기 또는 에뮬레이터에서 앱을 실행하세요
2. Dashboard > **Audience > Subscriptions**를 확인하세요 — 상태가 "Never Subscribed"로 표시됩니다
3. 권한 요청 프롬프트가 나타나면 수락하세요
4. 대시보드를 새로고침하세요 — 상태가 "Subscribed"로 변경됩니다

<Frame caption="iOS 및 Android 푸시 권한 요청 프롬프트 예시">
  <img src="https://mintcdn.com/onesignal/RWtLFPeffHrC81wI/images/docs/a90c2cc443f5fe9e7c80368c680a16cf1ca6203f7b28a0a6eec212add8510f80-Untitled_design_11.png?fit=max&auto=format&n=RWtLFPeffHrC81wI&q=85&s=96dbf224b3ae93b3d814712cdc5416ba" alt="iOS 및 Android 푸시 권한 요청 프롬프트 예시." width="1920" height="1080" data-path="images/docs/a90c2cc443f5fe9e7c80368c680a16cf1ca6203f7b28a0a6eec212add8510f80-Untitled_design_11.png" />
</Frame>

<Frame caption="'Never Subscribed' 상태의 구독을 보여주는 대시보드">
  <img src="https://mintcdn.com/onesignal/mJXnj6xKtiaVBd7y/images/dashboard/subscription-never-subscribed.png?fit=max&auto=format&n=mJXnj6xKtiaVBd7y&q=85&s=f6412faa44ca1c0dfbd07dc39e82fc08" alt="'Never Subscribed' 상태의 구독을 보여주는 대시보드." width="2472" height="1066" data-path="images/dashboard/subscription-never-subscribed.png" />
</Frame>

<Frame caption="푸시 권한을 허용한 후 대시보드를 새로고침하면 구독 상태가 'Subscribed'로 업데이트됩니다">
  <img src="https://mintcdn.com/onesignal/mJXnj6xKtiaVBd7y/images/dashboard/subscription-subscribed.png?fit=max&auto=format&n=mJXnj6xKtiaVBd7y&q=85&s=cef79235b64703bc1a1bbffab775366e" alt="푸시 권한을 허용한 후 대시보드를 새로고침하면 구독 상태가 'Subscribed'로 업데이트됩니다." width="2472" height="1066" data-path="images/dashboard/subscription-subscribed.png" />
</Frame>

<Check>
  [모바일 구독](./subscriptions)을 성공적으로 생성했습니다.
  모바일 구독은 사용자가 기기에서 앱을 처음 열거나 같은 기기에서 앱을 삭제하고 다시 설치할 때 생성됩니다.
</Check>

#### 테스트 구독 및 세그먼트 생성

1. 구독 옆의 \*\*⋮\*\*을 클릭 > **Add to Test Users** > 이름을 지정하세요
2. **Audience > Segments > New Segment**로 이동하세요
3. 이름: `Test Users`, 필터 **Test Users** 추가 > **Create Segment**

<Frame caption="테스트 구독 추가">
  <img src="https://mintcdn.com/onesignal/NCUI56Tiw7V-s0dT/images/dashboard/add-to-test-subscriptions.png?fit=max&auto=format&n=NCUI56Tiw7V-s0dT&q=85&s=2455d4cd74ea4ad686f76730cd95bbaa" alt="테스트 구독 추가." width="1188" height="742" data-path="images/dashboard/add-to-test-subscriptions.png" />
</Frame>

<Frame caption="Test Users 필터로 'Test Users' 세그먼트 생성">
  <img src="https://mintcdn.com/onesignal/NCUI56Tiw7V-s0dT/images/dashboard/create-test-users-segment.png?fit=max&auto=format&n=NCUI56Tiw7V-s0dT&q=85&s=91b8a021be6e83662854e68ec3e1da04" alt="Test Users 필터로 'Test Users' 세그먼트 생성." width="1188" height="742" data-path="images/dashboard/create-test-users-segment.png" />
</Frame>

<Check>
  테스트 사용자 세그먼트를 성공적으로 생성했습니다.

  이제 이 개별 기기와 테스트 사용자 그룹에 메시지 전송을 테스트할 수 있습니다.
</Check>

#### API를 통한 테스트 푸시 전송

1. \*\*Settings > [Keys & IDs](./keys-and-ids)\*\*로 이동하세요.
2. 아래 코드에서 `YOUR_APP_API_KEY`와 `YOUR_APP_ID`를 실제 키로 교체하세요. 이 코드는 앞서 생성한 `Test Users` 세그먼트를 사용합니다.

```bash theme={null}
curl -X POST 'https://api.onesignal.com/notifications' \
  -H 'Content-Type: application/json; charset=utf-8' \
  -H 'Authorization: Key YOUR_APP_API_KEY' \
  -d '{
    "app_id": "YOUR_APP_ID",
    "target_channel": "push",
    "name": "Testing basic setup",
    "headings": { "en": "👋" },
    "contents": {"en": "Hello world!"},
    "included_segments": ["Test Users"],
    "big_picture": "https://avatars.githubusercontent.com/u/11823027?s=200&v=4"
  }'
```

<Frame caption="이미지는 축소된 알림 보기에서 작게 표시됩니다. 알림을 펼치면 전체 이미지를 볼 수 있습니다.">
  <img src="https://mintcdn.com/onesignal/Z6xkXGfmy814If53/images/docs/e4e3e812eb6841ff11795a6ee0ea36eff483920ea9266733d6948ed34df3def3-Untitled_design_9.png?fit=max&auto=format&n=Z6xkXGfmy814If53&q=85&s=9bf6f4a73e38ec424b8cfec75a474a26" alt="푸시 알림의 이미지는 축소된 알림 보기에서 작게 표시됩니다. 알림을 펼치면 전체 이미지를 볼 수 있습니다." width="1200" height="800" data-path="images/docs/e4e3e812eb6841ff11795a6ee0ea36eff483920ea9266733d6948ed34df3def3-Untitled_design_9.png" />
</Frame>

<Frame caption="확인된 전송을 보여주는 전송 통계 (무료 플랜에서는 사용 불가)">
  <img src="https://mintcdn.com/onesignal/r7d-mmGxYBGknd0e/images/dashboard/delivery-stats-confirmed-delivery.png?fit=max&auto=format&n=r7d-mmGxYBGknd0e&q=85&s=9949b389aec0cc2e08fc338eaad941de" alt="확인된 전송을 보여주는 전송 통계 (무료 플랜에서는 사용 불가)." width="2444" height="1462" data-path="images/dashboard/delivery-stats-confirmed-delivery.png" />
</Frame>

<Check>
  테스트 기기가 다음 항목이 포함된 알림을 수신했는지 확인하세요:

  * 커스텀 아이콘 (구성한 경우)
  * 펼쳤을 때의 큰 이미지
  * Dashboard > **Delivery > Sent Messages**에 "Confirmed" 상태 표시 (무료 플랜에서는 사용 불가).
</Check>

<Warning>
  * 알림이 수신되지 않나요? [모바일 푸시가 표시되지 않음](./notifications-show-successful-but-are-not-being-shown)을 참조하세요.
  * 커스텀 아이콘이 표시되지 않나요? 아이콘 이름이 `onesignal_small_icon_default`이고 올바른 drawable 폴더에 있는지 확인하세요.
  * 문제가 있나요? API 요청과 앱 실행 처음부터 끝까지의 로그를 `.txt` 파일에 복사하세요. 두 파일을 `support@onesignal.com`으로 공유하세요.
</Warning>

#### 인앱 메시지 테스트

1. 30초 이상 앱을 종료하세요
2. Dashboard > **Messages > In-App > New In-App** > **Welcome** 템플릿을 선택하세요
3. 대상: **Test Users** 세그먼트
4. 트리거: **On app open**
5. 스케줄: **Every time trigger conditions are satisfied**
6. **Make Message Live**를 클릭하세요
7. 앱을 여세요

<Frame caption="인앱 메시지로 'Test Users' 세그먼트 타겟팅">
  <img src="https://mintcdn.com/onesignal/mJXnj6xKtiaVBd7y/images/dashboard/targeting-test-users-segment-with-in-app-message.png?fit=max&auto=format&n=mJXnj6xKtiaVBd7y&q=85&s=4f2e70263b932745cf929bad9030c819" alt="인앱 메시지로 'Test Users' 세그먼트 타겟팅." width="2444" height="712" data-path="images/dashboard/targeting-test-users-segment-with-in-app-message.png" />
</Frame>

<Frame caption="인앱 Welcome 메시지 커스터마이즈 예시">
  <img src="https://mintcdn.com/onesignal/r7d-mmGxYBGknd0e/images/dashboard/example-customization-of-in-app-welcome-message.png?fit=max&auto=format&n=r7d-mmGxYBGknd0e&q=85&s=3decc127e575020980828a95eb7f96ce" alt="인앱 Welcome 메시지 커스터마이즈 예시." width="2440" height="1488" data-path="images/dashboard/example-customization-of-in-app-welcome-message.png" />
</Frame>

<Frame caption="인앱 메시지 스케줄링 옵션">
  <img src="https://mintcdn.com/onesignal/r7d-mmGxYBGknd0e/images/dashboard/in-app-message-scheduling-options.png?fit=max&auto=format&n=r7d-mmGxYBGknd0e&q=85&s=d7a46112e5ac3e12bc83b4f8e408159e" alt="인앱 메시지 스케줄링 옵션." width="2440" height="1074" data-path="images/dashboard/in-app-message-scheduling-options.png" />
</Frame>

<Frame caption="기기에 표시된 Welcome 인앱 메시지">
  <img src="https://mintcdn.com/onesignal/RWtLFPeffHrC81wI/images/docs/a7ed4bb02be56900a65d2519e3d69f9c9b2c2a1c65fe740f07789e4ffe79cd67-Untitled_design_10.png?fit=max&auto=format&n=RWtLFPeffHrC81wI&q=85&s=6f692b569706ca39df0b4cc2b70f3de2" alt="기기에 표시된 Welcome 인앱 메시지." width="1920" height="1080" data-path="images/docs/a7ed4bb02be56900a65d2519e3d69f9c9b2c2a1c65fe740f07789e4ffe79cd67-Untitled_design_10.png" />
</Frame>

<Check>
  테스트 기기가 인앱 메시지를 수신했는지 확인하세요. 자세한 내용은 [인앱 메시지 설정](./in-app-messages-setup) 가이드를 참조하세요.
</Check>

<Warning>
  메시지가 보이지 않나요?

  * 새 세션 시작
    * 앱을 최소 30초 이상 종료하거나 백그라운드로 전환한 후 다시 여세요. 이렇게 하면 새 세션이 시작됩니다.
    * 자세한 내용은 [인앱 메시지가 표시되는 방식](./in-app-messages-setup#how-are-iams-displayed%3F)을 참조하세요.
  * `Test Users` 세그먼트에 여전히 포함되어 있나요?
    * 앱을 재설치하거나 기기를 변경한 경우, [테스트 구독](./test-users)에 기기를 다시 추가하고 Test Users 세그먼트에 포함되어 있는지 확인하세요.
  * 문제가 있나요?
    * 위의 단계를 재현하면서 [디버그 로그 가져오기](./capturing-a-debug-log)를 따르세요. 이렇게 하면 `support@onesignal.com`으로 공유할 수 있는 추가 로그가 생성되며, 저희가 문제를 조사하는 데 도움을 드리겠습니다.
</Warning>

<Check>
  OneSignal SDK를 성공적으로 설정하고 다음과 같은 중요한 개념을 배웠습니다:

  * [구독](./subscriptions) 수집, [테스트 구독](./test-users) 설정, [세그먼트](./segmentation) 생성.
  * 세그먼트와 [메시지 생성](/reference/create-message) API를 사용하여 이미지가 포함된 [푸시](./push) 전송.
  * [인앱 메시지](./in-app-messages-setup) 전송.

  이 가이드를 계속 진행하여 앱에서 사용자를 식별하고 추가 기능을 설정하세요.
</Check>

### 일반적인 오류 및 해결 방법

| 오류 / 증상                              | 원인                                  | 해결 방법                                                         |
| ------------------------------------ | ----------------------------------- | ------------------------------------------------------------- |
| `Cannot resolve symbol 'OneSignal'`  | SDK 의존성이 추가되지 않았거나 Gradle이 동기화되지 않음 | build.gradle에 의존성을 추가하고 프로젝트를 동기화하세요                          |
| `Application class not found`        | Application 클래스가 매니페스트에 등록되지 않음     | `<application>` 태그에 `android:name=".ApplicationClass"`를 추가하세요 |
| `Google Play Services not available` | 에뮬레이터/기기에 Play Services가 없음         | Play Store가 있는 기기 또는 Google APIs가 포함된 에뮬레이터를 사용하세요            |
| 푸시가 수신되지만 기본 Android 아이콘이 표시됨        | 커스텀 아이콘이 구성되지 않았거나 이름이 잘못됨          | `onesignal_small_icon_default`라는 이름의 알림 아이콘 에셋을 생성하세요         |
| 푸시 알림이 수신되지 않음                       | OneSignal에서 FCM이 구성되지 않음            | 0단계를 완료하세요: OneSignal 대시보드에서 FCM 자격 증명을 구성하세요                 |
| 인앱 메시지가 표시되지 않음                      | 세션이 시작되지 않았거나 네트워크 문제               | 앱을 30초 이상 종료하고 다시 열고, 인터넷 연결을 확인하세요                           |
| `Manifest merger failed`             | 매니페스트 속성 충돌                         | 중복된 애플리케이션 이름이나 권한 충돌을 확인하세요                                  |
| 배터리 최적화로 알림이 차단됨                     | 기기 전원 관리                            | 사용자에게 앱의 배터리 최적화를 비활성화하도록 안내하세요                               |
| 문제를 진단할 수 없음                         | 로그 정보가 부족함                          | 상세 로깅을 추가하고 logcat 출력에서 오류를 확인하세요                             |

***

## 사용자 관리

이전에 모바일 [구독](./subscriptions)을 생성하는 방법을 설명했습니다. 이제 OneSignal SDK를 사용하여 모든 구독(푸시, 이메일, SMS 포함)에서 [사용자](./users)를 식별하는 방법으로 확장합니다.

### External ID 할당 (권장)

External ID를 사용하여 백엔드의 사용자 식별자를 통해 기기, 이메일 주소 및 전화번호에서 사용자를 일관되게 식별하세요. 이를 통해 채널 및 서드파티 시스템 간에 메시징이 통합된 상태로 유지됩니다. 자세한 내용과 Java 코드 예시는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)를 참조하세요.

```kotlin Kotlin theme={null}
// Call when user logs in or is identified, safe to call multiple times
// Typically used in a login completion handler, or on app launch if already authenticated
fun onUserAuthenticated(userId: String) {
    OneSignal.login(userId)
}

// If you want to remove the External ID from the Subscription, setting it to an anonymous user
fun onUserLoggedOut() {
    OneSignal.logout()
}
```

<Note>
  OneSignal은 구독(Subscription ID)과 사용자(OneSignal ID)에 대해 고유한 읽기 전용 ID를 생성합니다.

  SDK를 통해 External ID를 설정하는 것은 생성 방식에 관계없이 모든 구독에서 사용자를 식별하기 위해 강력히 권장됩니다.

  SDK 레퍼런스 가이드에서 [`login` 메서드](./mobile-sdk-reference#login-external-id)에 대해 자세히 알아보세요.
</Note>

### 태그 및 커스텀 이벤트 추가

태그와 커스텀 이벤트는 사용자에게 데이터를 추가하는 두 가지 방법입니다. 태그는 `key-value` 문자열이며 일반적으로 사용자 속성(예: `username`, `role`, `status`)과 연결되고, 커스텀 이벤트는 JSON 형식이며 일반적으로 동작(예: `new_purchase`, `abandoned_cart` 및 관련 속성)과 연결됩니다. 두 가지 모두 고급 [메시지 개인화](./message-personalization) 및 Journeys를 구동하는 데 사용할 수 있습니다. 자세한 내용과 Java 코드 예시는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)를 참조하세요.

```kotlin Kotlin theme={null}
// Add a tag when the user's name is set
OneSignal.User.addTag("username", "john_doe")

// Create a custom event when user abandoned a cart
val properties = mapOf(
    "product_id" to "123456",
    "product_name" to "Product Name",
    "product_price" to 100,
    "product_quantity" to 1
)
OneSignal.User.trackEvent("abandoned_cart", properties)
```

<Note>
  태그와 커스텀 이벤트를 사용하는 방법에 대한 자세한 내용은 [태그](./add-user-data-tags) 및 [커스텀 이벤트](./custom-events) 가이드를 참조하세요.
</Note>

### 이메일 및/또는 SMS 구독 추가

푸시 알림 외에도 이메일과 SMS 채널을 통해 사용자에게 도달할 수 있습니다. 이메일 주소 및/또는 전화번호가 이미 OneSignal 앱에 존재하는 경우, SDK는 이를 기존 사용자에게 추가하며 중복을 생성하지 않습니다. 자세한 내용과 Java 코드 예시는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)를 참조하세요.

```kotlin Kotlin theme={null}
// Add email subscription
// Call when user provides their email (e.g., account creation, settings update) after calling OneSignal.login("user_id")
OneSignal.User.addEmail("user@example.com")

// Add SMS subscription
// Use E.164 format: + country code + number
// Call when user provides their phone number (e.g., account creation, settings update) after calling OneSignal.login("user_id")
OneSignal.User.addSms("+15551234567")
```

<Frame caption="External ID로 통합된 푸시, 이메일, SMS 구독이 있는 사용자 프로필">
  <img src="https://mintcdn.com/onesignal/mJXnj6xKtiaVBd7y/images/dashboard/user-profile-with-push-email-and-sms-subscriptions-unified-by-external-id.png?fit=max&auto=format&n=mJXnj6xKtiaVBd7y&q=85&s=3e7d5ed8763acb24e0afa5c4ff8f0d81" alt="External ID로 통합된 푸시, 이메일, SMS 구독이 있는 사용자 프로필." width="2440" height="1392" data-path="images/dashboard/user-profile-with-push-email-and-sms-subscriptions-unified-by-external-id.png" />
</Frame>

<Note>
  멀티채널 커뮤니케이션 모범 사례

  * 이메일 또는 SMS 구독을 추가하기 전에 명시적 동의를 받으세요.
  * 각 커뮤니케이션 채널의 이점을 사용자에게 설명하세요.
  * 사용자가 선호하는 채널을 선택할 수 있도록 채널 환경 설정을 제공하세요.
</Note>

***

### 개인정보 보호 및 사용자 동의

OneSignal이 사용자 데이터를 수집하는 시점을 제어하려면 SDK의 동의 제어 메서드를 사용하세요. 자세한 내용과 Java 코드 예시는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)를 참조하세요.

```kotlin Kotlin theme={null}
// In ApplicationClass onCreate(), BEFORE OneSignal.initWithContext()
// Use this if your app requires GDPR or other privacy consent before data collection
OneSignal.consentRequired = true

// Later, after user grants consent (e.g., taps "I Agree" on your consent screen)
OneSignal.consentGiven = true
```

<Note>
  개인정보 보호 및 보안 문서에서 자세히 알아보세요:

  * [SDK에서 수집하는 데이터](./data-collected-by-the-onesignal-sdk)
  * [개인 데이터 처리](./handling-personal-data)
</Note>

***

## 푸시 권한 요청

앱이 열릴 때 즉시 `requestPermission()`을 호출하는 대신, 더 전략적인 접근 방식을 취하세요. 권한을 요청하기 전에 인앱 메시지를 사용하여 푸시 알림의 가치를 설명하세요.

모범 사례와 구현 세부 사항은 [푸시 권한 요청](./prompt-for-push-permissions) 가이드를 참조하세요.

***

## 푸시, 사용자 및 인앱 이벤트 수신

SDK 리스너를 사용하여 사용자 동작 및 상태 변경에 반응하세요. `OneSignal.initWithContext()` 이후 Application 클래스에서 이를 추가하세요.

### 푸시 알림 이벤트

```kotlin Kotlin theme={null}
// Add click listener to handle when users tap notifications
val clickListener = object : INotificationClickListener {
  override fun onClick(event: INotificationClickEvent) {
    Log.d("OneSignal", "Notification clicked: ${event.notification.title}")
  }
}
OneSignal.Notifications.addClickListener(clickListener)
```

### 사용자 상태 변경

아래 예시는 푸시 구독 옵저버를 사용하는 방법을 보여줍니다. 사용자 상태 옵저버 및 알림 권한 옵저버와 같은 다른 사용자 상태 이벤트는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)에서 확인할 수 있습니다.

```kotlin Kotlin theme={null}
// Add subscription observer to track push subscription changes
class MyObserver : IPushSubscriptionObserver {
  init {
    OneSignal.User.pushSubscription.addObserver(this)
  }

  override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) {
    if (state.current.optedIn) {
      println("User is now opted-in with push token: ${state.current.token}")
    }
  }
}
```

### 인앱 메시지 이벤트

추가 인앱 메시지 메서드는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)에서 확인할 수 있습니다.

```kotlin Kotlin theme={null}
// Add click listener for in-app message interactions
val clickListener = object : IInAppMessageClickListener {
  override fun onClick(event: IInAppMessageClickEvent) {
    print(event.result.actionId)
  }
}
OneSignal.InAppMessages.addClickListener(clickListener)
```

***

## 고급 설정 및 기능

### Android 전용 기능

* **[알림 채널](./mobile-sdk-reference#notification-channels)** — 알림을 카테고리별로 분류 (Android 8.0+)
* **[서비스 확장](./service-extensions)** — 고급 알림 커스터마이즈
* **[Huawei/HMS 지원](./huawei-sdk-setup)** — Google Play Services 대안

### 공통 기능

* [딥 링킹](./deep-linking) — 알림에서 특정 화면으로 사용자 이동
* [액션 버튼](./action-buttons) — 알림에 인터랙티브 버튼 추가
* [신원 확인](./identity-verification) — 안전한 사용자 식별
* [위치 추적](./mobile-sdk-reference#location) — 위치 기반 타겟팅
* [연동](./integrations) — 분석 및 데이터 플랫폼과 연결
* [다국어 메시징](./multi-language-messaging) — 현지화된 알림

전체 SDK 메서드 문서는 [모바일 SDK 레퍼런스](./mobile-sdk-reference)를 참조하세요.

***

<Info>
  도움이 필요하신가요?

  지원 팀과 채팅하거나 `support@onesignal.com`으로 이메일을 보내주세요.

  다음을 포함해 주세요:

  * 발생한 문제의 세부 정보 및 재현 단계(가능한 경우)
  * OneSignal 앱 ID
  * External ID 또는 Subscription ID(해당하는 경우)
  * OneSignal 대시보드에서 테스트한 메시지의 URL(해당하는 경우)
  * 관련 [로그 또는 오류 메시지](/docs/ko/capturing-a-debug-log)

  기꺼이 도와드리겠습니다!
</Info>

***
