npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tenqube/visual-reward-react-native

v1.1.6

Published

Tenqube Visual Reward SDK for React Native

Readme

React Native

React Native WebView 기반 리워드 광고 SDK입니다.

요구사항

  • React Native 0.76+
  • iOS 13.0+
  • Android minSdk 24

설치

npm (권장)

  • https://www.npmjs.com/package/@tenqube/visual-reward-react-native

    npm install @tenqube/visual-reward-react-native react-native-webview

수동 설치

  • Visual Reward React Native SDK

    • https://github.com/tenqube/visual-reward-sdk-react-native/releases
  • visual-reward-react-native-{version}.zip을 다운로드한 뒤 압축을 해제합니다 (zip에는 android/, ios/ 네이티브 모듈이 포함되어 있습니다).

  • package.jsonfile: 경로 및 react-native-webview를 추가합니다.

    "dependencies": {
      "@tenqube/visual-reward-react-native": "file:./visual-reward-react-native",
      "react-native-webview": ">=13.0.0"
    }
    npm install

iOS pod install

  • 두 방법 모두 iOS는 추가로 pod install을 실행합니다.

    cd ios && pod install

VisualRewardContainer 루트 추가

  • 앱의 루트 컴포넌트(예: App.tsx)에 <VisualRewardContainer />을 추가합니다.
import { VisualRewardContainer } from '@tenqube/visual-reward-react-native';

export default function App() {
  return (
    <>
      <YourNavigator />
      <VisualRewardContainer />
    </>
  );
}

권한

iOS

  • IDFA 조회(getIDFA)를 사용하려면 Info.plist에 ATT 사용 목적 문자열을 추가해야 합니다.

    <key>NSUserTrackingUsageDescription</key>
    <string>맞춤형 광고 제공을 위해 기기 식별자를 사용합니다.</string>

    ATT 권한 요청은 SDK가 웹뷰 로드 전 네이티브 ATTrackingManager로 자동 처리합니다. 이미 권한이 결정된 경우 팝업 없이 즉시 진행됩니다.

Ad Manager WebView 광고 연동

  • SDK 의존성·App ID·초기화는 모두 호스트 앱에서 설정이 필요합니다.
  • 호스트 앱에 Google Mobile Ads SDK가 링크돼 있으면, SDK가 리워드 웹뷰를 자동으로 registerWebView에 등록해 WebView 내부 광고(AdSense/GPT/IMA HTML5)의 수익화·측정 신호를 개선합니다.
  • 기존에 애드몹 등을 사용 중인 경우 정상 적용 여부만 확인해주시면 됩니다.

의존성

# GMA WebView API for Ads
npm install react-native-google-mobile-ads

App ID

  1. AndroidManifest.xml

    <!-- App ID 누락 시 시작 크래시 -->
    <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
    <!-- WebView 전용일 때만 추가. 자체 광고도 서빙하면 이 메타데이터는 삭제 -->
    <meta-data
        android:name="com.google.android.gms.ads.INTEGRATION_MANAGER"
        android:value="webview" />
  2. Info.plist

    <!-- App ID 누락 시 시작 크래시 -->
    <key>GADApplicationIdentifier</key>
    <string>ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy</string>
    <!-- WebView 전용일 때만 추가. 자체 광고도 서빙하면 이 키는 삭제 -->
    <key>GADIntegrationManager</key>
    <string>webview</string>

초기화

  • 호스트 앱 시작 시 1회 초기화합니다.

    import mobileAds from 'react-native-google-mobile-ads';
    
    useEffect(() => {
      mobileAds().initialize();
    }, []);

시퀀스 다이어그램

sequenceDiagram
    title interaction VisualReward SDK

    participant A as Host App
    participant B as VisualReward SDK
    participant C as VisualReward 서버
    participant D as WebView 화면

    A->>B: initialize(appKey, ...)
    B->>C: config 요청
    C-->>B: config 응답
    B-->>A: onSuccess()

    A->>B: setUserId(userId)

    A->>B: open(serviceName, ...)
    B->>D: 웹뷰 열기

    D->>B: 웹뷰 닫힘
    B-->>A: onClose

사용법

디버그 설정

  • initialize() 전에 호출합니다.

    import { VisualReward } from '@tenqube/visual-reward-react-native';
    
    VisualReward.setDebugEnabled(__DEV__);

초기화

  • App.tsxuseEffect 등 앱 시작 시 한 번만 호출합니다.

    import { VisualReward } from '@tenqube/visual-reward-react-native';
    import AsyncStorage from '@react-native-async-storage/async-storage';
    
    useEffect(() => {
      VisualReward.initialize({
        appKey: 'tq_live_xxx',
        storage: AsyncStorage,  // config 캐싱용 (선택)
        timeoutMs: 5000,        // 기본값 (ms)
        onSuccess: () => { /* SDK 준비 완료 */ },
        onFailure: (e) => { /* 초기화 실패 */ },
      });
    }, []);

    config 캐싱을 사용하려면 storageAsyncStorage를 주입합니다. 미주입 시 매번 네트워크에서 config를 fetch합니다. @react-native-async-storage/async-storage가 설치되어 있지 않다면 npm install @react-native-async-storage/async-storage로 설치합니다.

  • initialize 파라미터

    | 파라미터 | 타입 | 필수 | 설명 | 기본값 | | --- | --- | --- | --- | --- | | appKey | string | ✅ | stage별 app_key 발급 요청이 필요합니다. | | | storage | AsyncStorageLike | | config 캐싱용 AsyncStorage 구현체. 미주입 시 캐싱 없이 매번 fetch | undefined | | timeoutMs | number | | 초기화 완료 대기 시간 (ms). 초과 시 INITIALIZE_TIMEOUT 에러 발생 | 5000 | | onSuccess | () => void | | 초기화 성공 콜백 | undefined | | onFailure | (error: VisualRewardError) => void | | 초기화 실패 콜백 | undefined |

사용자 설정

  • 로그인 후 또는 사용자가 변경될 때 호출합니다. open() 전에 반드시 호출해야 합니다.

    VisualReward.setUserId(user.id);

웹뷰 열기

  • initialize() 후에 호출합니다.

    import { VisualReward } from '@tenqube/visual-reward-react-native';
    
    await VisualReward.open({
      serviceName: 'reward_home',
      locale: 'ko',
      extra: undefined,
      onClose: () => { /* 웹뷰 닫힘 */ },
    });
  • open 파라미터

    | 파라미터 | 타입 | 필수 | 설명 | 기본값 | | --- | --- | --- | --- | --- | | serviceName | string | ✅ | 사용 서비스별 serviceName 전달 예정입니다. | | | locale | string \| undefined | | BCP 47 (RFC 5646) 언어 서브태그(ISO 639-1, 2자리 소문자)를 사용 | "ko" | | extra | string \| undefined | | 포스트백 추가 데이터 (JSON serialize된 문자열) | undefined | | onClose | () => void | | 웹뷰가 닫힐 때 호출되는 콜백 | undefined | | onError | (error: VisualRewardError) => void | | 에러 발생 시 호출되는 콜백 | undefined |

에러 처리

에러 타입

| 타입 | 설명 | | --- | --- | | NETWORK_ERROR | 네트워크 연결 실패 | | INITIALIZE_TIMEOUT | initialize() 호출 후 완료까지 타임아웃 | | INVALID_APP_KEY | 유효하지 않은 앱 키 (404) | | SERVER_ERROR | 서버 오류 (5xx) | | PARSE_ERROR | 응답 파싱 실패 | | NOT_INITIALIZED | initialize() 호출 없이 open() 호출 | | USER_ID_NOT_SET | setUserId() 호출 없이 open() 호출 |

initialize 에러 처리

  • onFailure 콜백에서 에러 타입을 분기합니다.

    import { VisualReward, VisualRewardError } from '@tenqube/visual-reward-react-native';
    
    VisualReward.initialize({
      appKey: 'tq_live_xxx',
      timeoutMs: 5000,
      onSuccess: () => { /* SDK 준비 완료 */ },
      onFailure: (e) => {
        if (e instanceof VisualRewardError) {
          switch (e.code) {
            case 'NETWORK_ERROR':
              break; // 네트워크 연결 실패
            case 'INITIALIZE_TIMEOUT':
              break; // 초기화 타임아웃
            case 'INVALID_APP_KEY':
              break; // 존재하지 않는 앱 키
            case 'SERVER_ERROR':
              break; // 서버 오류
            case 'PARSE_ERROR':
              break; // 응답 파싱 실패
          }
        }
      },
    });

open 에러 처리

  • open()은 예외를 throw하지 않고 onError 콜백으로 에러를 전달합니다. 콜백에서 에러 타입을 분기합니다.

    import { VisualReward, VisualRewardError } from '@tenqube/visual-reward-react-native';
    
    await VisualReward.open({
      serviceName: 'reward_home',
      locale: 'ko',
      extra: undefined,
      onClose: () => { /* 웹뷰 닫힘 */ },
      onError: (e: VisualRewardError) => {
        switch (e.code) {
          case 'NOT_INITIALIZED':
            break; // initialize() 미호출
          case 'USER_ID_NOT_SET':
            break; // setUserId() 미호출
          case 'INITIALIZE_TIMEOUT':
            break; // 초기화 대기 타임아웃
          case 'NETWORK_ERROR':
            break; // 네트워크 연결 실패
          default:
            break; // 기타 오류
        }
      },
    });