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

# LogBrew로 React Native 로깅하기

> React Native SDK를 설치하고 테스트 로그를 보낸 다음 올바른 LogBrew 프로젝트에서 찾으세요. Expo를 안전하게 설정하고 전송 오류를 처리하세요.

React Native 앱에서 LogBrew로 로그를 보내세요. 먼저 테스트 로그 1개를 보낸 다음 CLI로 올바른 프로젝트에서 찾으세요. 이 가이드는 Expo를 사용합니다. 베어 React Native 앱은 자체 설정으로 키를 불러옵니다.

시작하기 전에 다음이 필요합니다.

* 로컬에서 실행할 수 있는 React Native 앱.
* LogBrew 프로젝트. [프로젝트 및 설정](/ko/concepts/projects)을 참고하세요.
* 로그인된 CLI. [CLI 사용하기](/ko/guides/cli)를 참고하세요.

## SDK 설치하기

앱 디렉터리에 두 패키지를 모두 설치하세요. 앱의 React 및 React Native 의존성은 그대로 두세요.

```bash theme={null}
npm install @logbrew/sdk@0.1.28 @logbrew/react-native@0.1.35
```

## 프로젝트 SDK 키 만들기

앱에는 프로젝트 범위의 쓰기 전용 SDK 키를 주세요. Expo는 모든 `EXPO_PUBLIC_*` 값을 앱 번들에 넣습니다. 이 변수에 계정 자격 증명이나 서버 자격 증명을 넣지 마세요.

CLI v0.1.32 이상은 기존 프로젝트의 키를 만듭니다. 새 프로젝트는 만들지 않습니다. 프로젝트 ID를 찾으세요.

```bash theme={null}
logbrew projects --json
```

키를 만드세요. 소유자만 접근할 수 있는 디렉터리 안의 새 파일 경로를 사용하세요.

```bash theme={null}
install -d -m 700 "$HOME/.logbrew" &&
logbrew projects keys create "<project_id>" \
  --ingest-key-file "$HOME/.logbrew/my-mobile-app.ingest" \
  --label "My mobile app" \
  --kind sdk \
  --json
```

명령어가 성공한 뒤에만 다음 단계로 넘어가세요. 결과가 불분명하면 같은 인수로 같은 명령어를 다시 실행하세요. `--abandon-retry`는 사용하지 마세요.

키 파일은 소스 관리에 넣지 마세요. CLI를 승인한 계정 자격 증명을 사용하지 마세요. 로컬 Expo 개발에서는 앱 루트의 무시된 `.env.local` 파일에 키를 넣으세요.

```dotenv theme={null}
EXPO_PUBLIC_LOGBREW_CLIENT_KEY=<your_project_sdk_key>
```

아래 설정 모듈에서는 `process.env.EXPO_PUBLIC_LOGBREW_CLIENT_KEY`를 직접 참조하는 코드를 그대로 두세요. 값을 바꾼 뒤에는 앱을 완전히 다시 불러오세요. 빌드 시점 설정은 [Expo 환경 변수](https://docs.expo.dev/guides/environment-variables/)를 참고하세요. 베어 React Native 앱은 대신 자체 설정으로 키를 불러옵니다.

## 클라이언트 만들기

이 설정은 앱이 시작할 때 불러오는 모듈 1개에 넣으세요. 렌더링할 때마다 클라이언트를 만들지 마세요. 서비스, 환경, 릴리스는 `context`에 넣으세요.

```js theme={null}
import { AppState } from "react-native";
import {
  createAppStateListener,
  createLogBrewReactNativeClient,
  createReactNativeFetchTransport
} from "@logbrew/react-native";

const clientKey = process.env.EXPO_PUBLIC_LOGBREW_CLIENT_KEY;
if (!clientKey) {
  throw new Error("Set EXPO_PUBLIC_LOGBREW_CLIENT_KEY");
}

const client = createLogBrewReactNativeClient({
  clientKey,
  context: {
    schemaVersion: 1,
    resource: {
      service: { name: "my-mobile-app" },
      deployment: {
        environment: __DEV__ ? "development" : "production",
        release: "mobile@1.0.0"
      }
    }
  },
  transport: createReactNativeFetchTransport()
});

const stopAppStateListener = createAppStateListener(client, AppState, {
  flushOnBackground: true
});

export async function verifyLogBrewSetup() {
  client.log(`evt_react_native_setup_${Date.now()}`, new Date().toISOString(), {
    level: "info",
    message: "React Native setup check"
  });

  const receipt = await client.flush();
  if (receipt.statusCode < 200 || receipt.statusCode >= 300) {
    throw new Error("LogBrew did not accept the setup event");
  }
  return {
    status_code: receipt.statusCode,
    attempts: receipt.attempts,
    batches: receipt.batches
  };
}
```

fetch 전송을 사용하면 재시도 횟수 제한과 큐가 있는 자동 전송이 켜집니다. 두 번째 flush 타이머를 추가하지 마세요. AppState 리스너는 앱이 비활성 상태가 되거나 백그라운드로 갈 때 마지막 flush를 요청합니다. 앱을 정리할 때 `stopAppStateListener()`를 호출하세요.

네이티브 큐를 쓰면 키 1개는 활성 클라이언트 1개만 사용할 수 있습니다. 같은 키로 두 번째 클라이언트를 만들면 `configuration_error`로 실패합니다. 이것도 클라이언트를 한 번만 만들어야 하는 이유입니다.

## 테스트 로그 보내고 찾기

개발 전용 테스트 액션에서 `verifyLogBrewSetup()`을 한 번 호출하세요. 결과를 await하고 거부된 promise를 처리하세요. 키나 이벤트 배치를 출력하지 마세요.

`2xx` 결과의 `batches`가 0보다 크면 LogBrew가 배치를 접수했다는 뜻입니다. 자동 전송이 이벤트를 먼저 보냈을 수 있으므로, 빈 flush는 시도 0회, 배치 0개와 함께 `204`를 반환합니다. 두 경우 모두 CLI로 저장된 로그를 읽으세요.

```bash theme={null}
logbrew read logs --project "<project_id>" \
  --search "React Native setup check" --since 1h --json
```

결과에서 이벤트 시각과 서비스를 확인하세요. 결과가 비어 있어도 원인은 알 수 없습니다. 프로젝트, 키, 기간을 확인하세요.

`RecordingTransport.alwaysAccept()`는 로컬 테스트 전용입니다. 가짜 `202`를 반환하며 요청을 보내지 않습니다.

## 오프라인 및 재시작 후 전송

실행 중인 앱에서 `client.deliveryHealth().storage`를 읽으세요.

* `persistent`: 클라이언트가 네이티브 큐를 사용합니다. 대기 중인 이벤트는 앱을 다시 시작한 뒤 다시 불러옵니다.
* `memory`: JavaScript 런타임이 다시 시작되면 대기 중인 이벤트가 사라집니다.

기본값 `persistentQueue: "auto"`는 앱 바이너리에 LogBrew 네이티브 모듈이 있으면 네이티브 큐를 사용합니다. Expo Go와 이전 바이너리는 메모리를 사용합니다. JavaScript만 업데이트해서는 네이티브 모듈을 추가할 수 없습니다.

프로덕션 앱에서 재시작 후 전송이 필요하면 `persistentQueue: "required"`를 설정하세요. 그러면 네이티브 큐가 없을 때 클라이언트 생성이 `configuration_error`로 실패합니다. 네이티브 모듈을 포함해 앱을 다시 빌드하세요. 메모리 큐를 원할 때만 `persistentQueue: "disabled"`를 사용하세요.

네이티브 큐에는 최대 1,000개의 이벤트와 4 MiB의 이벤트 데이터가 들어갑니다. 클라이언트 한도가 더 작으면 그 한도도 적용됩니다. 네이티브 큐의 이벤트는 재시작 뒤에도 이벤트 ID를 유지합니다.

전송은 최소 한 번 보장 방식이므로, 재시도로 이벤트가 두 번 전송될 수 있습니다. 이벤트 ID와 내용이 LogBrew가 이미 접수한 이벤트와 일치하면 LogBrew는 다시 저장하지 않습니다. 백그라운드 flush는 시도일 뿐 전송의 증명이 아닙니다. 오프라인 수집과 앱 재시작을 테스트하세요. 그런 다음 프로젝트에서 저장된 이벤트를 찾으세요.

### 전송 상태 읽기

`client.deliveryHealth()`는 이벤트 내용 없이 큐 상태와 전송 상태를 반환합니다. 다음 필드를 먼저 읽으세요.

| 필드 | 의미 |
| - | - |
| `storage` | `persistent` 또는 `memory`입니다. |
| `deliveryState` | 자동 전송의 현재 상태입니다. |
| `lastOutcome` | 마지막 전송 시도의 결과입니다. |
| `lastStatusClass` | 마지막 응답 상태의 분류 또는 네트워크 오류입니다. |
| `pausedReason` | `401` 뒤에는 `authentication`, `429` 뒤에는 `rate_limit`입니다. |
| `queueEvents` | 전송을 기다리는 이벤트 수입니다. |
| `acceptedEvents` | LogBrew가 접수한 이벤트 수입니다. |
| `droppedByReason` | 클라이언트가 버린 이벤트 수를 이유별로 나눈 값입니다. |

## 로그 내용 정하기

각 메시지는 짧고 구체적으로 쓰세요. 요청 실패나 예약된 재시도처럼 앱에서 일어난 결과를 설명하세요. 이름, 이메일 주소, 액세스 토큰, 폼 값, 요청 본문을 넣지 마세요.

이벤트에 맞는 심각도를 사용하세요. `info`, `warning`, `error`, `critical` 중 하나입니다. 관련 기록을 찾을 수 있도록 서비스, 환경, 릴리스를 일관되게 유지하세요.

`npx react-native log-ios`와 `npx react-native log-android`는 로컬 기기 로그를 보여 줍니다. LogBrew를 조회하지 않습니다. [React Native 네이티브 디버깅](https://reactnative.dev/docs/debugging-native-code)을 참고하세요.

## 확인에 실패했을 때 복구하기

`flush()`가 실패하면 SDK 오류 코드와 함께 거부됩니다. 오류 보고에 키와 이벤트 본문을 넣지 마세요.

| 결과 | 다음 단계 |
| - | - |
| 클라이언트 키 없음 | 전송 전에 설정이 멈춥니다. 앱 설정으로 프로젝트 SDK 키를 불러오세요. |
| `401`, `unauthenticated` | LogBrew가 키를 거부했습니다. 자동 전송이 `pausedReason: "authentication"`으로 일시 중지됩니다. 새 클라이언트를 만들기 전에 프로젝트 SDK 키를 고치거나 교체하세요. 계정 자격 증명은 절대 사용하지 마세요. |
| `429`, `rate_limited` | SDK가 배치를 보관하고 `pausedReason: "rate_limit"`으로 자동 전송을 일시 중지합니다. 재시도 루프를 추가하지 마세요. |
| `400`, `transport_error` | LogBrew가 요청을 거부했습니다. 이벤트 필드와 패키지 버전을 확인하세요. |
| `network_failure` | SDK에 전송 결과가 없습니다. LogBrew가 이벤트를 접수했을 수도 있습니다. 연결 상태와 `deliveryHealth()`를 확인하세요. |
| `5xx`, `transport_error` | SDK가 이미 재시도했습니다. 직접 다시 시도하기 전에 저장된 로그를 읽으세요. |
| 빈 CLI 결과 | 프로젝트, 키, 이벤트 시각, 필터를 확인하세요. |

더 많은 확인 방법은 [문제 해결](/ko/guides/troubleshooting)을 참고하세요.

## 릴리스 번들에 Expo Debug ID 유지하기

LogBrew로 Expo Metro 설정을 만드세요. 그러면 런타임 번들이 소스맵과 같은 Debug ID를 갖게 됩니다.

```js theme={null}
// metro.config.js
const { getLogBrewExpoConfig } = require("@logbrew/react-native/metro");

module.exports = getLogBrewExpoConfig(__dirname);
```

앱이 React Native Worklets 번들 모드를 사용한다면 LogBrew 헬퍼 다음에 그 변환을 적용하세요.

```js theme={null}
// metro.config.js
const { getLogBrewExpoConfig } = require("@logbrew/react-native/metro");
const { getBundleModeMetroConfig } = require("react-native-worklets/bundleMode");

module.exports = getBundleModeMetroConfig(getLogBrewExpoConfig(__dirname));
```

헬퍼는 기존 Expo 사전 직렬화 플러그인을 유지합니다.

베어 React Native 앱은 대신 완성된 Metro 설정을 `withLogBrewMetroConfig()`로 감쌉니다. Expo에서는 이 래퍼를 사용하지 마세요. 사용하면 프로덕션 빌드가 `getLogBrewExpoConfig()`를 안내하는 메시지와 함께 멈춥니다.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.