본문 바로가기
프로그래밍/Web

Laravel Inertia - Pages

by 사악신 2024. 1. 18.

Inertia 를 사용하여 애플리케이션을 구축할 때, 애플리케이션의 각 페이지는 일반적으로 자체 컨트롤러/라우트와 해당하는 JavaScript 컴포넌트를 가집니다. 이를 통해 해당 페이지에 필요한 데이터만 검색할 수 있으며, API는 필요하지 않습니다.

또한, 페이지에 필요한 모든 데이터는 브라우저에서 페이지가 렌더링되기 전에 검색될 수 있어, 사용자가 애플리케이션을 방문할 때 "loading" 상태를 표시할 필요가 없어집니다.

Creating pages 페이지 생성하기

Inertia 페이지는 단순히 JavaScript 컴포넌트입니다. Vue, React, 또는 Svelte 컴포넌트를 작성해본 적이 있다면 금방 익숙해질 것입니다. 아래 예시에서 볼 수 있듯이, 페이지는 애플리케이션의 컨트롤러로부터 props로 데이터를 받습니다.

<script setup>
import Layout from './Layout'
import { Head } from '@inertiajs/vue3'

defineProps({ user: Object })
</script>

<template>
  <Layout>
    <Head title="Welcome" />
    <h1>Welcome</h1>
    <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
  </Layout>
</template>

위에 제시된 페이지는 컨트롤러 또는 라우트에서 인터시아 응답(Inertia response)을 반환하여 렌더링할 수 있습니다. 이 예제에서, 이 페이지가 라라벨(Laravel) 애플리케이션 내의 resources/js/Pages/User/Show.vue에 저장되어 있다고 가정해봅시다.

use Inertia\Inertia;

class UserController extends Controller
{
    public function show(User $user)
    {
        return Inertia::render('User/Show', [
          'user' => $user
        ]);
    }
}

Creating layouts 레이아웃 생성하기

필수는 아니지만, 대부분의 프로젝트에서는 모든 페이지가 확장할 수 있는 사이트 레이아웃을 생성하는 것이 좋습니다. 위의 페이지 예제에서 볼 수 있듯이, 페이지 내용을 <Layout> 컴포넌트로 감싸고 있습니다. 아래는 그러한 컴포넌트의 예시입니다:

<script setup>
import { Link } from '@inertiajs/vue3'
</script>

<template>
  <main>
    <header>
      <Link href="/">Home</Link>
      <Link href="/about">About</Link>
      <Link href="/contact">Contact</Link>
    </header>
    <article>
      <slot />
    </article>
  </main>
</template>

보시다시피, 이 템플릿 내에는 Inertia 특유의 것이 없습니다. 이것은 단지 전형적인 Vue 컴포넌트일 뿐입니다.

Persistent layouts 지속적인 레이아웃

레이아웃을 페이지 컴포넌트의 자식으로 구현하는 것은 간단하지만, 이는 방문 사이에 레이아웃 인스턴스가 파괴되고 다시 생성되어야 함을 의미합니다. 이는 페이지 간 탐색할 때 지속적인 레이아웃 상태를 가질 수 없다는 것을 의미합니다.

예를 들어, 사용자가 사이트를 탐색할 때 계속 재생되기를 원하는 팟캐스트 웹사이트의 오디오 플레이어가 있을 수 있습니다. 또는, 페이지 방문 사이에 사이드바 탐색의 스크롤 위치를 유지하고 싶을 수도 있습니다. 이러한 상황에서는 Inertia 의 지속적인 레이아웃을 활용하는 것이 해결책입니다.

<script>
import Layout from './Layout'

export default {
  // 렌더링 함수를 사용하면...
  layout: (h, page) => h(Layout, [page]),

  // 단축 구문을 사용하면...
  layout: Layout,
}
</script>

<script setup>
defineProps({ user: Object })
</script>

<template>
  <H1>Welcome</H1>
  <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
</template>

중첩된 레이아웃을 사용하여 더 복잡한 레이아웃 구성을 만들 수도 있습니다.

<script>
import SiteLayout from './SiteLayout'
import NestedLayout from './NestedLayout'

export default {
  // 렌더링 함수를 사용하면...
  layout: (h, page) => {
    return h(SiteLayout, () => h(NestedLayout, () => page))
  },

  // 단축 구문을 사용하면...
  layout: [SiteLayout, NestedLayout],
}
</script>

<script setup>
defineProps({ user: Object })
</script>

<template>
  <H1>Welcome</H1>
  <p>Hello {{ user.name }}, welcome to your first Inertia app!</p>
</template>

Vue 2.7이나 Vue 3를 사용하는 경우, <script setup> 내에서 레이아웃을 정의하기 위해 defineOptions plugin 을 대안적으로 사용할 수 있습니다:

<script setup>
import Layout from './Layout'

defineOptions({ layout: Layout })
</script>

Default layouts 기본 레이아웃

라라벨에서 지속적인 레이아웃을 사용하고 있다면, 애플리케이션의 주요 자바스크립트 파일에 있는 resolve() 콜백에서 기본 페이지 레이아웃을 정의하는 것이 편리할 수 있습니다.

import Layout from './Layout'

createInertiaApp({
  resolve: name => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
    let page = pages[`./Pages/${name}.vue`]
    page.default.layout = page.default.layout || Layout
    return page
  },
  // ...
})

이 방법은 이미 해당 페이지에 레이아웃이 설정되어 있지 않은 경우, 자동으로 페이지 레이아웃을 Layout으로 설정합니다.

더 나아가 resolve() 콜백에서 사용 가능한 페이지 name에 기반하여 조건부로 기본 페이지 레이아웃을 설정할 수도 있습니다. 예를 들어, 공개 페이지에 기본 레이아웃을 적용하고 싶지 않을 수 있습니다.

import Layout from './Layout'

createInertiaApp({
  resolve: name => {
    const pages = import.meta.glob('./Pages/**/*.vue', { eager: true })
    let page = pages[`./Pages/${name}.vue`]
    page.default.layout = name.startsWith('Public/') ? undefined : Layout
    return page
  },
  // ...
})
반응형

'프로그래밍 > Web' 카테고리의 다른 글

Laravel Inertia - Redirects  (0) 2024.01.18
Laravel Inertia - Responses  (0) 2024.01.18
Laravel Inertia Client-side 설치  (0) 2024.01.10
Laravel Inertia Server-side 설치  (0) 2024.01.10
Laravel Jetstream Livewire  (1) 2024.01.08

댓글