> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/common/navigationbar.md).

# 네비게이션 바 설정

네비게이션 바는 화면 상단에 고정되어 있는 공통 UI 컴포넌트예요. 앱인토스 SDK를 적용하면 네비게이션 바는 별도 구현 없이 자동으로 표시돼요.

{% hint style="info" %}
**참고하세요**

미니앱 로고 설정은 WebView 설정 문서를 참고해 주세요.
{% endhint %}

***

### 1. 네비게이션 바 기본 기능

#### 게임 <a href="#game" id="game"></a>

게임용 네비게이션 바는 **더보기 버튼**과 **닫기(X) 버튼**으로 구성돼요. `granite.config.ts`에서 앱 타입을 `game`으로 설정하면 게임 네비게이션 바를 사용할 수 있어요.

```typescript
import { defineConfig } from '@apps-in-toss/web-framework/config';

export default defineConfig({
  // ...
  webViewProps: {
    type: 'game',
  },
});
```

{% hint style="info" %}
**참고하세요**

* [safeArea](/documentation/common/screen/safe-area.md) 문서를 참고하여 X 버튼이 게임 화면의 다른 버튼과 겹치지 않도록 개발해 주세요.
  {% endhint %}

#### 비게임 <a href="#non-game" id="non-game"></a>

비게임 미니앱에서는 흰색 배경의 네비게이션 바가 기본으로 제공돼요. 좌측에는 **미니앱 로고**와 **이름**이, 우측에는 **더보기 버튼**과 **X 버튼**이 위치해요.

#### 더보기 버튼 기능 <a href="#more-button-features" id="more-button-features"></a>

더보기 버튼을 통해 아래 기능들을 별도 서버 연동이나 추가 구현 없이 바로 사용할 수 있어요.

**문의하기 / 신고하기**

콘솔에 등록한 **고객센터 링크와 홈페이지 주소**가 자동으로 표시돼요. 신고하기 기능을 통해 사용자가 제보를 보낼 수 있고, 파트너사는 콘솔을 통해 제보 내용을 확인할 수 있어요.

**공유하기**

사용자는 미니앱을 다른 사람에게 쉽게 공유할 수 있어요. 공유 시 **미니앱 이름**과 **딥링크 주소**가 함께 전송돼요.

**권한 설정**

사용자는 미니앱이 요청하는 권한을 확인하고, 언제든지 ON/OFF로 제어할 수 있어요.

**홈 화면에 추가하기**

자주 사용하는 미니앱을 휴대폰 홈 화면에 바로 등록할 수 있어요. 토스앱 5.246.0 이상부터 확인할 수 있어요.

**미니앱 용량 삭제**

자주 사용하지 않는 미니앱의 용량을 선택적으로 삭제할 수 있어요. 미니앱 네비게이션 바의 설정 버튼을 통해 서비스별 데이터를 삭제할 수 있어요.

**미니앱 알림 ON/OFF**

미니앱별 알림 수신 여부를 직접 설정할 수 있어요. 미니앱 네비게이션 바의 설정 버튼을 통해 서비스별 알림을 ON/OFF 할 수 있어요.

***

### 2. 네비게이션 바 커스터마이징

<figure><img src="https://3242303459-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbbsGTd7OgbyqnSM8Iwcy%2Fuploads%2F5xDvG4chVknxeZeAs6dB%2F1%E1%84%80%E1%85%A2%20(1).png?alt=media&amp;token=a17947b5-2688-4c79-8d9f-a6e7321d63e8" alt=""><figcaption></figcaption></figure>

`비게임` 미니앱에서는 필요에 따라 다양하게 네비게이션 커스터마이징이 가능해요.

{% hint style="warning" %}
내비게이션바에 기본 로고와 앱 이름은 제거할 수 있지만, 파트너사 자체 로고를 추가하는 건 허용되지 않아요.
{% endhint %}

WebView SDK 3.x는 `apps-in-toss.config.ts`, SDK 2.x는 `granite.config.ts`의 `navigationBar` 옵션으로 표시 방식을 설정해요.

```typescript
interface NavigationBarOptions {
  withBackButton?: boolean;
  withHomeButton?: boolean;
  withTitle?: boolean;
  transparentBackground?: boolean;
  theme?: 'light' | 'dark';
  initialAccessoryButton?: InitialAccessoryButton;
}

// WebView SDK 3.10 이상 기준이에요.
type InitialAccessoryButton = (
  | { accessibilityLabel: string; title?: string }
  | { accessibilityLabel?: string; title: string }
) & {
  id?: string; // 기존 설정과 호환되며, 새 연동에서는 생략해요.
  icon:
    | { name: string; source?: never }
    | { name?: never; source: { uri: string } };
};
```

* **`withBackButton`** — 네비게이션 바 왼쪽에 뒤로가기 버튼을 표시할지 설정해요.
* **`withHomeButton`** — 비게임 미니앱에서 홈으로 이동하는 버튼을 표시할지 설정해요.
* **`withTitle`** — 네비게이션 바 왼쪽에 미니앱 아이콘과 미니앱 이름을 표시할지 설정해요.
* **`transparentBackground`** — 네비게이션 바 배경을 투명하게 설정할지 정해요. 콘텐츠가 네비게이션 바 아래로 이어지는 풀스크린 레이아웃에 적합해요.
* **`theme`** — 네비게이션 바 테마를 `light` 또는 `dark`로 설정해요. 배경색에 맞춰 버튼과 텍스트 색상을 조정할 때 사용해요.
* **`initialAccessoryButton`** — 더보기 버튼 왼쪽 영역에 액세서리 아이콘을 초기 노출해요. 한 번에 1개만 표시할 수 있어요.

예를 들어 미니앱 아이콘과 앱 이름을 숨기고, 어두운 배경 위에 네비게이션 바를 올리고 싶다면 아래처럼 설정할 수 있어요.

```typescript
navigationBar: {
  theme: 'dark',
  transparentBackground: true,
  withTitle: false,
}
```

WebView SDK 3.10 이상에서 홈 버튼과 액세서리 아이콘을 초기 노출하려면 아래처럼 설정해요. 기존 WebView 설정은 아래 [기존 WebView 연동 방식](#기존-webview-연동-방식)을 참고해 주세요.

```typescript
navigationBar: {
  withBackButton: true,
  withHomeButton: true,
  initialAccessoryButton: {
    accessibilityLabel: '찜하기',
    icon: {
      name: 'icon-heart-mono',
    },
  },
}
```

게임앱이라면 `transparentBackground` 를 `true` 로 설정해주세요.

```typescript
import { defineConfig } from '@apps-in-toss/web-framework/config';

export default defineConfig({
  // ...
  navigationBar: {
    transparentBackground: true,
  },
});
```

비게임에서도 게임처럼 화면 몰입도를 높이고 싶다면 투명한 배경에 더보기 버튼과 닫기 버튼만 남긴 네비게이션 바를 구성할 수 있어요.

```typescript
import { defineConfig } from '@apps-in-toss/web-framework/config';

export default defineConfig({
  // ...
  navigationBar: {
    withBackButton: false,
    withHomeButton: false,
    withTitle: false,
    transparentBackground: true,
  },
});
```

***

### 3. 디자인 가이드

상단 네비게이션은 사용자에게 일관된 정보 구조를 전달하기 위해 **모노톤 아이콘**만을 사용해요. 컬러 아이콘은 시각적 주의를 과도하게 분산시키고, 불필요한 강조로 혼란을 줄 수 있기 때문이에요. 특수한 케이스를 제외하고는 모두 **모노톤 아이콘으로 통일**해 사용하고 있어요.

***

### 4. 액세서리 아이콘 추가하기

게임, 비게임 미니앱 모두 우측 상단 **더보기 버튼 왼쪽 영역**에 아이콘을 한 개 추가할 수 있어요.

#### 플랫폼별 설정 방식 <a href="#platform-specific-configuration" id="platform-specific-configuration"></a>

* **WebView (SDK 3.10 이상)**
  * [NavigationBar.addAccessoryButton](/documentation/sdk/domains-api/navigationbar/navigationbar.addaccessorybutton.md)으로 버튼을 추가하고, [NavigationBar.removeAccessoryButton](/documentation/sdk/domains-api/navigationbar/navigationbar.removeaccessorybutton.md)으로 제거해요.
  * 클릭은 [NavigationBar.subscribeAccessoryButton](/documentation/sdk/domains-api/navigationbar/navigationbar.subscribeaccessorybutton.md)으로 구독해요.
  * 처음부터 버튼을 표시하려면 `apps-in-toss.config.ts`의 `navigationBar.initialAccessoryButton`을 설정해요.

{% hint style="info" %}
기존 `partner` API와 `tdsEvent`를 사용한 연동은 수정 없이 계속 사용할 수 있어요. 초기 버튼 설정의 `title`과 `id`도 계속 지원해요. WebView에서 새로 연동할 때는 `NavigationBar` API와 `accessibilityLabel`을 사용해 주세요.

이번 변경으로 추가되는 토스앱 최소 버전 조건은 없어요.
{% endhint %}

#### 초기 설정 <a href="#initial-configuration" id="initial-configuration"></a>

```ts
import { defineConfig } from '@apps-in-toss/web-framework/config';

export default defineConfig({
  appName: 'my-app',
  permissions: [],
  navigationBar: {
    initialAccessoryButton: {
      accessibilityLabel: '찜하기',
      icon: { name: 'icon-heart-mono' },
    },
  },
});
```

WebView의 `initialAccessoryButton`은 다음 설정을 받아요.

| 속성                   | 설명                                                                                                                |
| -------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `accessibilityLabel` | 스크린리더가 읽는 버튼의 동작 설명이에요. 화면에는 표시되지 않아요. `찜하기`처럼 동작을 적어 주세요.                                                        |
| `title`              | 기존 접근성 이름이에요. deprecated지만 계속 지원해요. `accessibilityLabel`과 함께 지정하면 `accessibilityLabel`이 우선해요. 두 값 중 하나는 반드시 지정해요. |
| `id`                 | 기존 버튼 식별자예요. deprecated지만 계속 지원해요. 생략하면 `navigation-bar-accessory-button`을 사용해요.                                  |
| `icon`               | `{ name: string }` 또는 `{ source: { uri: string } }` 중 하나를 지정해요. `name`과 `source`를 함께 지정할 수 없어요.                   |

이미지 URI는 초기 설정에서만 사용할 수 있어요. 런타임의 `NavigationBar.addAccessoryButton`은 `icon.name`만 받아요. 두 방식 모두 모노톤 아이콘 사용 기준을 지켜 주세요.

#### 동적 추가 <a href="#dynamic-addition" id="dynamic-addition"></a>

{% tabs %}
{% tab title="WebView (JS)" %}

```js
import { NavigationBar } from '@apps-in-toss/web-framework';

const unsubscribe = NavigationBar.subscribeAccessoryButton({
  onEvent: () => {
    console.log('찜하기 버튼을 클릭했어요.');
  },
  onError: (error) => {
    console.error(error);
  },
});

await NavigationBar.addAccessoryButton({
  accessibilityLabel: '찜하기',
  icon: { name: 'icon-heart-mono' },
});

// SPA에서는 화면을 벗어나는 시점에도 이 함수를 호출해 주세요.
function cleanup() {
  unsubscribe();
  void NavigationBar.removeAccessoryButton().catch(console.error);
}

window.addEventListener('pagehide', cleanup, { once: true });
```

{% endtab %}

{% tab title="WebView (React)" %}

```tsx
import { useEffect } from 'react';
import { NavigationBar } from '@apps-in-toss/web-framework';

useEffect(() => {
  const unsubscribe = NavigationBar.subscribeAccessoryButton({
    onEvent: () => {
      console.log('찜하기 버튼을 클릭했어요.');
    },
    onError: (error) => {
      console.error(error);
    },
  });

  void NavigationBar.addAccessoryButton({
    accessibilityLabel: '찜하기',
    icon: { name: 'icon-heart-mono' },
  }).catch(console.error);

  return () => {
    unsubscribe();
    void NavigationBar.removeAccessoryButton().catch(console.error);
  };
}, []);
```

{% endtab %}
{% endtabs %}

**버튼과 구독은 각각 정리해 주세요.**

* 초기 버튼과 동적으로 추가한 버튼은 같은 슬롯을 사용해요. 버튼을 다시 추가하면 기존 버튼을 교체해요.
* 구독은 버튼을 추가하기 전이나 후에 시작할 수 있어요. 초기 설정이나 기존 API로 만든 버튼의 클릭도 받아요.
* `onEvent`는 버튼 식별자 구분 없이 인자 없이 실행돼요. `onError`를 생략하면 구독 오류를 전달하지 않아요.
* 구독 해제는 버튼을 제거하지 않고, 버튼 제거도 구독을 해제하지 않아요. 화면을 벗어날 때 둘 다 호출해 주세요.

#### 기존 WebView 연동 방식

기존 번들과 아래 방식으로 연동한 코드는 계속 동작해요. 이번 변경 때문에 기존 미니앱을 재배포할 필요는 없어요.

| 기존 방식                                                        | 새 연동에 권장하는 방식                                                    | 호환성                                                              |
| ------------------------------------------------------------ | ---------------------------------------------------------------- | ---------------------------------------------------------------- |
| `partner.addAccessoryButton({ id, title, icon })`            | `NavigationBar.addAccessoryButton({ accessibilityLabel, icon })` | 기존 메서드는 deprecated지만 계속 동작해요. `title`은 접근성 이름으로 사용하고 `id`는 유지해요. |
| `partner.removeAccessoryButton()`                            | `NavigationBar.removeAccessoryButton()`                          | 기존 메서드는 deprecated지만 계속 동작해요.                                    |
| `tdsEvent.addEventListener('navigationAccessoryEvent', ...)` | `NavigationBar.subscribeAccessoryButton(...)`                    | 기존 이벤트 구독은 deprecated 대상이 아니며 계속 지원해요. 클릭 시 `{ id }`를 전달해요.      |

기존 이벤트 구독에서 `partner.addAccessoryButton`으로 만든 버튼은 지정한 `id`를 받아요. `NavigationBar.addAccessoryButton`으로 만든 버튼은 `navigation-bar-accessory-button`을 받아요. 새 구독 API의 `onEvent()`는 인자를 받지 않으므로 이전 예제의 `id` 분기를 그대로 옮기지 마세요.

{% tabs %}
{% tab title="기존 초기 설정" %}

```tsx
import { defineConfig } from '@apps-in-toss/web-framework/config';

export default defineConfig({
  // ...
  navigationBar: {
    withBackButton: true,
    withHomeButton: true,
    initialAccessoryButton: {
      id: 'heart',
      title: 'Heart',
      icon: {
        name: 'icon-heart-mono',
      },
    },
  },
});
```

{% endtab %}

{% tab title="기존 Web (JS)" %}

```js
import { partner, tdsEvent } from '@apps-in-toss/web-framework';

partner.addAccessoryButton({
  id: 'heart',
  title: '하트',
  icon: {
    name: 'icon-heart-mono',
  },
});

const cleanup = tdsEvent.addEventListener('navigationAccessoryEvent', {
  onEvent: ({ id }) => {
    if (id === 'heart') {
      console.log('버튼 클릭');
    }
  },
});

window.addEventListener('pagehide', () => {
  cleanup();
});
```

{% endtab %}

{% tab title="기존 Web (React)" %}

```tsx
import { partner, tdsEvent } from '@apps-in-toss/web-framework';

useEffect(() => {
  partner.addAccessoryButton({
    id: 'heart',
    title: '하트',
    icon: {
      name: 'icon-heart-mono',
    },
  });

  const cleanup = tdsEvent.addEventListener('navigationAccessoryEvent', {
    onEvent: ({ id }) => {
      if (id === 'heart') {
        console.log('버튼 클릭');
      }
    },
  });

  return cleanup;
}, []);
```

{% endtab %}
{% endtabs %}

***

### 5. 홈 버튼 추가하기

비게임 미니앱에서는 왼쪽 상단에 **홈으로 이동하는 버튼**을 표시할 수 있어요. 홈 버튼은 서비스 이름 오른쪽에 위치하며, 사용자가 언제든 첫 화면으로 돌아올 수 있도록 도와줘요. 홈 버튼 관련 동작 제어는 [이벤트 제어하기](/documentation/common/screen/event.md) 문서를 참고해 주세요.

{% hint style="info" %}
**주의해주세요**

* 오른쪽 액세서리 버튼 영역에는 홈 버튼을 중복 추가하지 말아주세요.
* 홈 버튼은 "서비스 진입점" 역할만 수행하며, 커스텀 기능이나 문구 추가는 불가능해요.
  {% endhint %}

```typescript
interface NavigationBarOptions {
  withHomeButton?: boolean; // 홈 버튼 표시 여부
}
```

```tsx
navigationBar: {
  withBackButton: true,
  withHomeButton: true,
}
```

***

### 참고사항 <a href="#notes" id="notes"></a>

* 액세서리 버튼은 **모노톤 아이콘**만 지원돼요.
* 한 번에 표시할 수 있는 액세서리 버튼은 1개뿐이에요.
* 컬러 아이콘이나 커스텀 UI 추가는 지원하지 않아요.
* 홈 버튼은 비게임 미니앱에서만 사용 가능해요.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://developers-apps-in-toss.toss.im/documentation/common/navigationbar.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
