> 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/react-native/screen-navigation/layout.md).

# 레이아웃

레이아웃은 여러 페이지에서 반복되는 UI 요소(헤더, 네비게이션 바, 푸터 등)를 일관성 있게 관리하기 위한 구조예요. 공통 레이아웃을 정의하면 코드 중복을 줄이고, 일관된 사용자 경험을 제공할 수 있어요.

### 레이아웃 파일 만들기

레이아웃은 `_layout.tsx` 파일을 생성해서 정의해요. 파일의 위치에 따라 적용되는 범위가 달라져요.

```tsx
import { PropsWithChildren } from "react";

export default function Layout({ children }: PropsWithChildren) {
  return <>{children}</>;
}
```

### 레이아웃 적용 범위 설정하기

레이아웃은 파일 경로에 따라 자동으로 적용돼요.

* `pages/_layout.tsx`: 모든 페이지에 전역 적용돼요.
* `pages/about/_layout.tsx`: `intoss://{서비스명}/about` 하위의 모든 페이지에만 적용돼요.

레이아웃은 중첩해서 사용할 수 있어요. 여러 레이아웃이 함께 있을 때는 상위 디렉토리의 레이아웃부터 순서대로 적용돼요.

```
pages/
├── _layout.tsx          // 전역 레이아웃
├── about/
│   ├── _layout.tsx     // about 섹션 레이아웃
│   ├── index.tsx       // about 메인 페이지
│   └── team.tsx        // 팀 소개 페이지
└── index.tsx           // 메인 페이지
```

예를 들어, 위와 같은 구조라면 `about/team.tsx` 페이지는 아래 순서로 레이아웃이 적용돼요.

1. `pages/_layout.tsx` (전역 레이아웃)
2. `pages/about/_layout.tsx` (섹션 레이아웃)
3. `pages/about/team.tsx` (실제 페이지 컴포넌트)

이렇게 구성하면 전역적으로 필요한 UI 요소와, 특정 섹션에서만 필요한 UI 요소를 분리해서 관리할 수 있어요.

### 레이아웃 예시

#### 전역 레이아웃

모든 페이지에 공통으로 적용되는 레이아웃을 만들어볼게요.

{% tabs %}
{% tab title="pages/\_layout.tsx" %}

```tsx
import { PropsWithChildren } from "react";
import { View } from "react-native";
import { Header } from "../components/Header";
import { Footer } from "../components/Footer";

export default function Layout({ children }: PropsWithChildren) {
  return (
    <View style={{ flex: 1 }}>
      <Header />
      {children}
      <Footer />
    </View>
  );
}
```

{% endtab %}

{% tab title="components/Header.tsx" %}

```tsx
import { View, Text, StyleSheet } from "react-native";

export function Header() {
  return (
    <View style={styles.header}>
      <Text style={styles.title}>My App</Text>
      <View style={styles.nav}>
        <Text style={styles.navItem}>홈</Text>
        <Text style={styles.navItem}>소개</Text>
        <Text style={styles.navItem}>설정</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  header: {
    padding: 16,
    backgroundColor: "#ffffff",
    borderBottomWidth: 1,
    borderBottomColor: "#e5e5e5",
  },
  title: {
    fontSize: 24,
    fontWeight: "bold",
    marginBottom: 8,
  },
  nav: {
    flexDirection: "row",
    gap: 16,
  },
  navItem: {
    fontSize: 16,
    color: "#666666",
  },
});
```

{% endtab %}

{% tab title="components/Footer.tsx" %}

```tsx
import { View, Text, StyleSheet } from "react-native";

export function Footer() {
  return (
    <View style={styles.footer}>
      <Text style={styles.copyright}>© 2024 My App. All rights reserved.</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  footer: {
    padding: 16,
    backgroundColor: "#f5f5f5",
    alignItems: "center",
  },
  copyright: {
    fontSize: 14,
    color: "#666666",
  },
});
```

{% endtab %}
{% endtabs %}

#### 섹션별 레이아웃

특정 섹션에서만 사용하는 레이아웃을 만들 수 있어요.

{% tabs %}
{% tab title="pages/about/\_layout.tsx" %}

```tsx
import { PropsWithChildren } from "react";
import { View } from "react-native";
import { AboutSidebar } from "../../components/AboutSidebar";

export default function AboutLayout({ children }: PropsWithChildren) {
  return (
    <View style={{ flexDirection: "row" }}>
      <AboutSidebar />
      <View style={{ flex: 1 }}>{children}</View>
    </View>
  );
}
```

{% endtab %}

{% tab title="components/AboutSidebar.tsx" %}

```tsx
import { View, Text, StyleSheet } from "react-native";

export function AboutSidebar() {
  return (
    <View style={styles.sidebar}>
      <Text style={styles.title}>About</Text>
      <View style={styles.menu}>
        <Text style={styles.menuItem}>회사 소개</Text>
        <Text style={styles.menuItem}>팀 소개</Text>
        <Text style={styles.menuItem}>연혁</Text>
        <Text style={styles.menuItem}>오시는 길</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  sidebar: {
    width: 200,
    padding: 16,
    backgroundColor: "#f8f9fa",
    borderRightWidth: 1,
    borderRightColor: "#e5e5e5",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
    marginBottom: 16,
  },
  menu: {
    gap: 12,
  },
  menuItem: {
    fontSize: 16,
    color: "#495057",
  },
});
```

{% endtab %}
{% endtabs %}

### 레이아웃에서 쿼리 파라미터 받아오기

레이아웃에서도 쿼리 파라미터를 사용할 수 있어요. `useParams` 훅을 이용하면 현재 화면의 파라미터를 읽어서 동적으로 활용할 수 있어요.

#### `useParams` 훅 사용 예시

아래 예시는 URL 쿼리 파라미터로 전달된 `title` 값을 가져와서 화면 상단 제목으로 표시해요.

{% tabs %}
{% tab title="pages/\_layout.tsx" %}

```tsx
import { useParams } from "@granite-js/react-native";
import { PropsWithChildren } from "react";
import { View, Text } from "react-native";

export default function Layout({ children }: PropsWithChildren) {
  // 현재 화면의 파라미터를 가져와요.
  const params = useParams({ strict: false });

  // 'title' 파라미터를 가져오고 기본값을 설정해요.
  const title = params?.title ?? "기본 제목";

  return (
    <View style={{ flex: 1 }}>
      {/* 동적으로 생성된 헤더 */}
      <View style={{ padding: 16, backgroundColor: "#f0f0f0" }}>
        <Text style={{ fontSize: 20, fontWeight: "bold" }}>{title}</Text>
      </View>
      {/* 자식 컴포넌트를 렌더링 */}
      <View style={{ flex: 1 }}>{children}</View>
    </View>
  );
}
```

{% endtab %}
{% endtabs %}

### 참고 문서

* [화면 이동하기](/documentation/react-native/screen-navigation/navigation.md)
* 쿼리 파라미터 사용하기


---

# 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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/react-native/screen-navigation/layout.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
