Laravel 프로젝트에서 Inertia.js를 사용하는 방법

게시 됨: 2022-12-08

다중 페이지 애플리케이션(MPA)은 날이 갈수록 인기가 떨어지고 있습니다. Facebook, Twitter, YouTube, Github 등과 같은 유명한 플랫폼은 이미 SPA(Single-Page Application) 기술을 대신 사용하고 있습니다.

모든 것이 클라이언트측에서 렌더링되기 때문에 이 트렌디한 기술을 통해 사용자는 웹 애플리케이션에 빠르고 반응적으로 참여할 수 있습니다. 그러나 Laravel 또는 Django와 같은 프레임워크를 사용하여 서버 측 렌더링 애플리케이션을 구축하는 개발자에게는 골칫거리가 될 수 있습니다.

다행히 Inertia.js가 개입하여 구조에 나섰습니다.
Laravel 프로젝트에 필요한 누락된 요소가 있습니까? Inertia.js. 이 철저한 가이드에서 자세히 알아보기 Click to Tweet
이 기사에서는 Inertia.js를 사용하여 시작하는 방법과 이를 Laravel, Vue.js 및 Tailwind CSS와 함께 사용하여 최신 블로그 웹 앱을 만드는 방법을 보여줍니다. 또한 SPA를 보다 SEO 친화적으로 만드는 방법과 몇 가지 다른 요령도 공유합니다.

Laravel을 이제 막 시작했다면 이 글을 먼저 읽고 시작할 준비가 되었는지 확인하는 것이 좋습니다.

왜 스파?

Inertia를 사용해야 하는 이유를 묻기 전에 먼저 "왜 SPA인가?"라고 물어야 합니다.

누가 전통적인 서버측 애플리케이션보다 클라이언트측 렌더링된 애플리케이션을 선호하는 이유는 무엇입니까? 풀스택 Laravel 개발자가 블레이드 구성 요소에 작별을 고하게 만드는 것은 무엇입니까?

짧은 대답: 성공적인 사용자 참여를 위해서는 속도와 응답성이 필수적이기 때문입니다.

MPA의 경우 브라우저는 지속적으로 백엔드로 요청을 보낸 다음 수많은 데이터베이스 쿼리를 실행합니다. 데이터베이스와 서버가 쿼리를 처리하고 브라우저에 전달하면 페이지가 렌더링됩니다.

하지만 SPA는 다릅니다. 이 애플리케이션은 사용자가 필요로 하는 모든 것을 페이지로 바로 가져오므로 브라우저가 쿼리를 보내거나 새 HTML 요소를 렌더링하기 위해 페이지를 다시 로드할 필요가 없습니다.

이러한 독특한 사용자 경험 때문에 많은 유명 회사에서 웹사이트가 단일 페이지 애플리케이션이 되기를 요구하고 있습니다.

말하자면 단일 페이지 애플리케이션을 만드는 것은 Laravel 개발자가 블레이드 템플릿 대신 Vue.js 또는 React를 사용해야 하므로 시간과 노력을 절약하는 많은 Laravel gem이 손실되기 때문에 어려울 수 있습니다.

이제 Inertia.js가 있으므로 모든 것이 변경되었습니다.

왜 관성인가?

Laravel 개발자가 Inertia 이전에 Vue로 웹 SPA를 구축했다면 API를 설정하고 Laravel로 JSON 데이터를 반환한 다음 AXIOS와 같은 것을 사용하여 Vue 구성 요소에서 데이터를 검색해야 합니다. 또한 경로를 관리하기 위해 Vue Router와 같은 것이 필요합니다. 이는 미들웨어 및 컨트롤러뿐만 아니라 Laravel 라우팅이 손실됨을 의미합니다.

반면에 Inertia.js를 사용하면 개발자가 클래식 서버 측 라우팅 및 컨트롤러를 사용하여 최신 단일 페이지 Vue, React 및 Svelte 앱을 빌드할 수 있습니다. Inertia는 Laravel, Ruby on Rails 및 Django 개발자가 컨트롤러 생성, 데이터베이스에서 데이터 가져오기 및 뷰 렌더링과 같은 코딩 기술을 변경하지 않고도 앱을 빌드할 수 있도록 설계되었습니다.

Inertia.js 덕분에 Laravel 개발자는 편안함을 느낄 것입니다.

관성이 작동하는 방식

Laravel 및 Vue만으로 SPA를 구축하면 프런트엔드에 대한 전체 JavaScript 페이지가 제공되지만 단일 페이지 앱 경험은 제공되지 않습니다. 링크를 클릭할 때마다 다음 페이지 로드 시 클라이언트 측 프레임워크가 재부팅됩니다.

이것은 관성이 그림에 들어가는 곳입니다.

Inertia는 기본적으로 클라이언트 측 라우팅 라이브러리입니다. 전체 페이지를 다시 로드하지 않고도 페이지 사이를 탐색할 수 있습니다. 이는 표준 앵커 태그를 감싸는 경량 래퍼인 <Link> 구성 요소를 통해 수행됩니다.

Inertia 링크를 클릭하면 Inertia가 클릭을 차단하고 대신 XHR로 리디렉션합니다. 브라우저는 이런 방식으로 페이지를 다시 로드하지 않으므로 사용자에게 전체 단일 페이지 환경을 제공합니다.

관성 시작하기

상단의 파란색 배너에 "Kinsta Blog"가 있는 간단한 페이지와 한 줄의 샘플 기사 카드.
Inertia.js로 만든 샘플 페이지

Inertia를 이해하고 이를 Laravel과 통합하는 방법을 이해하기 위해 가장 강력한 콤보, 백엔드용 Laravel, JavaScript 프런트엔드용 Vue.js, 스타일링용 Tailwind CSS를 사용하여 Kinsta Blog 라는 블로그 웹 앱을 빌드할 것입니다.

로컬 환경에서 이 자습서를 따르려는 경우 개발자, 디자이너 및 에이전시를 위한 강력한 도구인 DevKinsta를 사용하여 단일 및 다중 페이지 WordPress 웹 앱을 구성할 수 있습니다. 다행히 WordPress는 Corcel 패키지를 사용하여 Laravel과 쉽게 통합할 수 있습니다.

전제 조건

이 자습서를 최대한 활용하려면 다음 사항을 숙지해야 합니다.

  • Laravel 기본 사항(설치, 데이터베이스, 데이터베이스 마이그레이션, Eloquent 모델, 컨트롤러 및 라우팅)
  • Vue.js 기본 사항(설치, 구조 및 양식)

확신이 서지 않는다면 환상적인 Laravel 무료 및 유료 튜토리얼을 확인하십시오. 그렇지 않으면 뛰어들자.

1단계: 핵심 요소 설치

Inertia.js에 집중하고 재미있는 부분을 바로 시작하려면 다음 설정을 준비해야 합니다.

  1. kinsta-blog 라는 새로 설치된 Laravel 9 프로젝트
  2. Laravel 프로젝트에 설치된 Tailwind CSS CLI
  3. 블로그 홈페이지를 보기 위한 kinsta-blog/resources/views의 두 블레이드 구성요소와 아래와 같이 블로그의 단일 기사:

    "/resources/views/ index.blade.php ":

     <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Kinsta Blog</title> </head> <body> <header> <h1>Kinsta Blog</h1> </header> <main> <h2>Read our latest articles</h2> <section> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>Title for the blog</h3> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem itaque error vel perferendis aliquam numquam dignissimos, expedita perspiciatis consectetur! </p> <a href="#">Read more</a> </article> </section> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </body> </html>

    "/resources/views/ show.blade.php ":

     <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Kinsta Blog</title> </head> <body> <main> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h1>Title for the blog</h1> <p>Article content goes here</p> </article> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </body> </html>
  4. 프로젝트에 연결된 kinsta_blog 라는 MySQL 로컬 데이터베이스:

    " .env ":

     DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=kinsta_blog DB_USERNAME=root DB_PASSWORD=
  5. 문서 모델, 마이그레이션 및 팩토리:

    "앱/모델 /Article.php ":

     <?php namespace AppModels; use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel; class Article extends Model { use HasFactory; protected $fillable = ['title', 'excerpt', 'body']; }

    "데이터베이스/마이그레이션/ create_articles_table.php ":

     <?php use IlluminateDatabaseMigrationsMigration; use IlluminateDatabaseSchemaBlueprint; use IlluminateSupportFacadesSchema; return new class extends Migration { public function up() { Schema::create('articles', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('excerpt'); $table->text('body'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('articles'); } };

    "데이터베이스/팩토리/ ArticleFactory.php ":

     <?php namespace DatabaseFactories; use IlluminateDatabaseEloquentFactoriesFactory; class ArticleFactory extends Factory { public function definition() { return [ 'title' => $this->faker->sentence(6), 'excerpt' => $this->faker->paragraph(4), 'body' => $this->faker->paragraph(15), ]; } }

시작하는 데 필요한 전부입니다! 이제 본론으로 들어가 우리 프로젝트에 Inertia.js를 소개하겠습니다.

2단계: Inertia 설치

Inertia 설치 프로세스는 서버 측(Laravel)과 클라이언트 측(VueJs)의 두 가지 주요 단계로 나뉩니다.

Inertia 문서의 공식 설치 가이드는 Laravel 9가 이제 기본적으로 Vite를 사용하기 때문에 약간 구식이지만 이에 대해서도 살펴보겠습니다.

1. 서버측

먼저 Composer를 통해 아래 터미널 명령으로 Inertia 서버 측 어댑터를 설치해야 합니다.

 composer require inertiajs/inertia-laravel

이제 CSS 및 JS 파일을 로드하는 데 사용할 단일 블레이드 파일과 JavaScript 애플리케이션을 시작하는 데 사용할 Inertia 루트인 루트 템플릿을 설정합니다.

가장 최신 버전인 Laravel 9 v9.3.1을 사용하고 있기 때문에 Vite를 /resources/views/ app.blade.php 의 태그에 포함시켜 마법을 작동하도록 해야 합니다.

 <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <!-- Fetch project name dynamically --> <title inertia>{{ config('app.name', 'Laravel') }}</title> <!-- Scripts --> @vite('resources/js/app.js') @inertiaHead </head> <body class="font-sans antialiased"> @inertia </body> </html>

Inertia 속성을 <title> 태그에 추가하여 동적으로 프로젝트 제목을 가져올 수 있는 방법에 주목하십시오.

또한 Vite가 앱을 만들고 CSS를 가져온 JavaScript 기본 파일의 경로를 알 수 있도록 @vite 지시문을 헤드에 추가했습니다. Vite는 개발자가 로컬 개발 중에 페이지를 새로 고치지 않고도 프런트엔드 변경 사항을 볼 수 있도록 하여 JavaScript 및 CSS 개발에 도움이 되는 도구입니다.

우리의 다음 단계는 HandleInertiaRequests 미들웨어를 생성하고 프로젝트에 게시하는 것입니다. 프로젝트의 루트 디렉토리 내에서 아래 터미널 명령을 실행하여 이를 수행할 수 있습니다.

 php artisan inertia:middleware

이 작업이 완료되면 "App/Http/ Kernel "로 이동하여 웹 미들웨어의 마지막 항목으로 HandleInertiaRequests 를 등록합니다.

 'web' => [ // ... AppHttpMiddlewareHandleInertiaRequests::class, ],

2. 클라이언트 측

다음으로 서버 측과 동일한 방식으로 프런트엔드 Vue.js 3 종속성을 설치해야 합니다.

 npm install @inertiajs/inertia @inertiajs/inertia-vue3 // or yarn add @inertiajs/inertia @inertiajs/inertia-vue3

다음으로 Vue.js 3을 가져와야 합니다.

 npm install [email protected]

그런 다음 기본 JavaScript 파일을 업데이트하여 Vue.js 3, Vite 및 Laravel로 Inertia.js를 초기화합니다.

"자원/js/ app.js ":

 import "./bootstrap"; import "../css/app.css"; import { createApp, h } from "vue"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .mount(el); }, });

위의 코드 스니펫에서 Laravel의 플러그인 resolvePageComponent 를 사용하고 ./Pages/$name.vue 디렉토리에서 컴포넌트를 해결하도록 지시합니다. 프로젝트 후반부에 Inertia 구성 요소를 이 디렉토리에 저장하고 이 플러그인이 올바른 디렉토리에서 해당 구성 요소를 자동으로 로드하는 데 도움이 되기 때문입니다.

남은 것은 vitejs/plugin-vue 를 설치하는 것입니다.

 npm i @vitejs/plugin-vue

그리고 vite.config.js 파일을 업데이트합니다.

 import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [ laravel({ input: ["resources/css/app.css", "resources/js/app.js"], refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });

마지막 단계는 종속성을 설치하고 파일을 컴파일하는 것입니다.

 npm install npm run dev

짜잔! Vue.js 3 및 Vite와 함께 작동하는 Laravel 9 애플리케이션이 있습니다. 이제 우리는 실제로 일어나는 일을 볼 필요가 있습니다!

관성 페이지 만들기

우리 홈페이지와 단일 기사를 보기 위한 두 개의 블레이드 파일( indexshow )을 기억하십니까?

Inertia를 사용하는 동안 필요한 유일한 블레이드 파일은 App.blade.php 이며 Inertia를 설치할 때 이미 사용한 적이 있습니다. 이제 그 파일들은 어떻게 될까요?

블레이드 구성 요소에서 Inertia.js 구성 요소로 해당 파일을 변환합니다.

애플리케이션의 각 페이지에는 자체 컨트롤러와 Inertia가 포함된 JavaScript 구성 요소가 있습니다. 이렇게 하면 API를 사용하지 않고 해당 페이지에 필요한 데이터만 얻을 수 있습니다. Inertia 페이지는 JavaScript 구성 요소에 지나지 않습니다. 우리의 경우에는 Vue.js 구성 요소입니다. 그들은 그들에 대해 특별히 주목할만한 것이 없습니다. 따라서 우리가 할 일은 <template> 태그 사이에 모든 HTML 콘텐츠를 래핑하는 것이며 JavaScript와 관련된 모든 내용은 <script> 태그로 래핑됩니다.

"Pages"라는 폴더를 만들고 거기에 파일을 옮깁니다. 따라서 " ./resources/js/Pages "에 " index.blade.php " 및 " show.blade.php "가 있습니다. 그런 다음 파일 형식을 ".blade.php" 대신 ".vue"로 변경하고 이름의 첫 글자를 대문자로 만들고 내용을 표준 Vue.js 구성 요소로 바꿉니다. <html> , <head><body> 태그는 기본 루트 블레이드 구성 요소에 이미 포함되어 있으므로 제외합니다.

"자원/js/페이지 /Index.vue ":

 <script setup> // </script> <template> <header> <h1>Kinsta Blog</h1> </header> <main> <h2>Read our latest articles</h2> <section> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>Title for the blog</h3> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem itaque error vel perferendis aliquam numquam dignissimos, expedita perspiciatis consectetur! </p> <a href="#">Read more</a> </article> </section> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </template>

"리소스/js/페이지/ Show.vue ":

 <script setup> // </script> <template> <header> <h1>Welcome to Kinsta Blog</h1> </header> <main> <article> <h1>Title for the blog</h1> <p>Article content goes here</p> </article> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </template>

정말 마음에 걸리는 일이 있습니다! 각 구성 요소에 머리글과 바닥글을 계속 복사하여 붙여넣는 것은 좋은 방법이 아닙니다. 영구 구성 요소를 저장하기 위해 Inertia 기본 레이아웃을 생성해 보겠습니다.

" /resources/js "에 "Layouts"라는 폴더를 만들고 해당 폴더 내에 "KinstaLayout.vue"라는 파일을 만듭니다. 이 파일에는 이 레이아웃으로 래핑된 모든 구성 요소가 그 안에 포함되도록 헤더 및 바닥글과 <slot /> 이 있는 main 이 있습니다. 이 파일은 다음과 같아야 합니다.

"resources/js/Layouts/ KinstaLayout.vue ":

 <script setup></script> <template> <header> <h1>Kinsta Blog</h1> </header> <main> <slot /> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </template>

그런 다음 페이지에서 이 새 레이아웃을 가져오고 모든 HTML 콘텐츠를 래핑합니다. 구성 요소는 다음과 같아야 합니다.

Index.vue :

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; </script> <template> <KinstaLayout> <section> <h2>Read our latest articles</h2> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>Title for the blog</h3> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem itaque error vel perferendis aliquam numquam dignissimos, expedita perspiciatis consectetur! </p> <a href="#">Read more</a> </article> </section> </KinstaLayout> </template>

.뷰 :

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; </script> <template> <KinstaLayout> <article> <h1>Title for the blog</h1> <p>Article content goes here</p> </article> </KinstaLayout> </template>

Laravel 경로 및 관성 렌더링

먼저 자습서 시작 지점에서 가져온 " ArticleFactory " 파일을 사용하고 일부 기사를 데이터베이스에 시드합니다.

" 데이터베이스 /시드/databaseSeeder.php":

 <?php namespace DatabaseSeeders; use AppModelsArticle; use IlluminateDatabaseSeeder; class DatabaseSeeder extends Seeder { public function run() { Article::factory(10)->create(); } }

그런 다음 아래 터미널 명령을 눌러 테이블을 마이그레이션하고 공장에서 가짜 데이터를 시드하십시오.

 php artisan migrate:fresh --seed

이렇게 하면 데이터베이스에 10개의 가짜 기사가 생성되며 Laravel 라우팅을 사용하여 뷰에 전달해야 합니다. 뷰를 렌더링하기 위해 Inertia를 사용하고 있으므로 경로를 작성하는 데 사용한 방식이 약간 변경됩니다. "routes/ web.php "에 첫 번째 Laravel Inertia 경로를 생성하고 "/resources/js/Pages/ Index.vue "에서 홈페이지 보기를 반환해 보겠습니다.

"경로/ web.php ":

 <?php use AppModelsArticle; use IlluminateSupportFacadesRoute; use InertiaInertia; Route::get('/', function () { return Inertia::render('Index', [ 'articles' => Article::latest()->get() ]); })->name('home');

우리는 Inertia 를 임포트했고 뷰를 반환하기 위해 view() Laravel 헬퍼를 사용하지 않고 대신 Inertia::render 를 사용했습니다. Inertia는 또한 기본적으로 "resources/js"의 Pages 폴더에 있는 경로에서 언급한 파일 이름을 찾습니다.

인덱스 파일로 이동하여 검색된 데이터를 소품으로 설정하고 v-for 로 반복하여 결과를 표시합니다. 스크립트 태그 사이에 전달된 데이터를 소품으로 정의합니다. Inertia가 알아야 할 모든 것은 예상하는 데이터 유형이며, 우리의 경우 기사 배열을 포함하는 '기사' 개체입니다.

"자원/js/페이지 /Index.vue ":

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ Articles: Object, }); </script>

Vue.js 3 컴포지션 API의 setup 형식을 사용하고 있기 때문에 반환하지 않고 소품으로 정의하는 것으로 충분합니다. 옵션 API를 사용하는 경우 이를 반환해야 합니다.

루프를 만들어 봅시다:

 <template> <KinstaLayout> <h2>Read our latest articles</h2> <section> // Looping over articles <article v-for="article in articles":key="article.id"> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>{{article.title}}</h3> <p>{{article.excerpt}}</p> <a href="#">Read more</a> </article> </section> </KinstaLayout> </template>

npm run dev (우리는 Vite를 사용하고 있으므로 실행 상태로 두십시오) 및 php artisan serve 은 laravel 개발 서버를 시작하고 웹 사이트에 액세스하는 역할을 합니다. 데이터베이스에 있는 10개의 기사를 모두 표시하는 예상 페이지를 볼 수 있습니다.

이제 Google Chrome의 Vue DevTools 확장 프로그램을 사용하여 애플리케이션을 디버깅할 수 있습니다. 데이터가 구성 요소에 어떻게 전달되는지 보여드리겠습니다.

열린 페이지의 Inertia 속성 목록을 보여주는 Chrome의 Vue DevTools 확장 프로그램.
관성 속성 검사.

"기사"는 기사 배열을 포함하는 소품 개체로 구성 요소에 전달됩니다. 배열의 각 기사는 데이터베이스에서 얻은 데이터에 해당하는 속성을 가진 개체이기도 합니다. 이는 Laravel에서 Inertia로 전송하는 모든 데이터가 소품으로 취급됨을 의미합니다.

Inertia.js와 함께 Tailwind CSS 사용

Tailwind는 프로젝트 시작 지점에 이미 설치되어 있으므로 Inertia 구성 요소를 읽도록 지시하기만 하면 됩니다. 이는 다음과 같이 " tailwind.config.js "를 편집하여 수행할 수 있습니다.

 /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./storage/framework/views/*.php", "./resources/views/**/*.blade.php", "./resources/js/**/*.vue", ], theme: { extend: {}, }, plugins: [], };

그런 다음 "resources/js/ app.js "에 CSS 파일을 가져왔는지 확인합니다.

 import "../css/app.css";

이제 구성 요소의 스타일을 지정할 준비가 되었습니다.

"자원/js/페이지 /Index.vue ":

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ articles: Object, }); </script> <template> <KinstaLayout> <h2 class="text-2xl font-bold py-10">Read our latest articles</h2> <section class="space-y-5 border-b-2 pb-10"> <article v-for="article in articles" :key="article.id" class="flex justify-center items-center shadow-md bg-white rounded-xl p-4 mx-auto max-w-3xl" > <img src="/images/kinsta-logo.png" class="w-32 h-32 rounded-xl object-cover" alt="" /> <div class="flex flex-col text-left justify-between pl-3 space-y-5"> <h3 class="text-xl font-semibold text-indigo-600 hover:text-indigo-800" > <a href="#">{{ article.title }}</a> </h3> <p> {{ article.excerpt }} </p> <a href="#" class="text-indigo-600 hover:text-indigo-800 w-fit self-end font-semibold" >Read more</a > </div> </article> </section> </KinstaLayout> </template>

"resources/js/Layouts/ KinstaLayout.vue ":

 <script setup></script> <template> <Header class="bg-gradient-to-r from-blue-700 via-indigo-700 to-blue-700 w-full text-center py-4" > <h1 class="text-white font-bold text-4xl">Kinsta Blog</h1> </Header> <main class="container mx-auto text-center"> <slot /> </main> <footer class="bg-gradient-to-b from-transparent to-gray-300 w-full text-center mt-5 py-10 mx-auto" > <h2 class="font-bold text-xl pb-5">Join our Newsletter</h2> <input class="rounded-xl w-80 h-12 px-3 py-2 shadow-md" type="email" placeholder="Write your email.." /> </footer> </template>

브라우저를 보면 Vite가 이미 Tailwind 마법으로 페이지를 업데이트했음을 알 수 있습니다.

이전의 "Kinsta Blog" 예제의 작동 버전을 보여주는 스크롤 이미지.
렌더링 관성 속성.

관성 링크

이제 데이터베이스의 모든 기사를 표시할 수 있는 작동하는 홈페이지가 있으므로 개별 기사를 표시하는 또 다른 경로를 만들어야 합니다. 새 경로를 만들고 URL을 "id" 와일드카드로 설정해 보겠습니다.

"경로 /web.php "

 <?php use AppModelsArticle; use IlluminateSupportFacadesRoute; use InertiaInertia; Route::get('/', function () { return Inertia::render('Index', [ 'articles' => Article::latest()->get() ]); })->name('home'); Route::get('/posts/{article:id}', function (Article $article) { return Inertia::render('Show', [ 'article' => $article ]); })->name('article.show');

"Article" 모델을 가져 오고 Show.vue Inertia 구성 요소를 반환하는 새 경로를 추가했습니다. 우리는 또한 Laravel의 경로 모델 바인딩을 활용하여 Laravel이 우리가 참조하는 기사를 자동으로 가져올 수 있도록 했습니다.

지금 필요한 것은 전체 페이지를 다시 로드하지 않고 홈페이지에서 링크를 클릭하여 이 경로를 방문하는 방법입니다. 이것은 Inertia의 마법 도구 <Link> 로 가능합니다. 도입부에서 Inertia가 표준 앵커 태그 <a> 의 래퍼로 <Link> 를 사용하고 이 래퍼가 페이지 방문을 최대한 원활하게 만들기 위한 것이라고 언급했습니다. Inertia에서 <Link> 태그는 <GET> 요청을 수행하는 앵커 태그로 동작할 수 있지만 동시에 <button><form> 으로 동작할 수도 있습니다. 프로젝트에 어떻게 적용할 수 있는지 봅시다.

Index.vue에서 Inertia에서 <Link> 를 가져오고 앵커 태그 <a> 를 제거하고 Inertia <Link> 태그로 대체합니다. href 속성은 기사를 보기 위해 이전에 만든 경로 URL로 설정됩니다.

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; import { Link } from "@inertiajs/inertia-vue3"; defineProps({ articles: Object, }); </script> <template> <KinstaLayout> <section class="space-y-5 border-b-2 pb-10"> <h2 class="text-2xl font-bold pt-10 mx-auto text-center"> Read our latest articles </h2> <article v-for="article in articles" :key="article.id" class="flex justify-center items-center shadow-md bg-white rounded-xl p-4 mx-auto max-w-3xl" > <img src="/images/kinsta-logo.png" class="w-32 h-32 rounded-xl object-cover" alt="" /> <div class="flex flex-col text-left justify-between pl-3 space-y-5" > <h3 class="text-xl font-semibold text-indigo-600 hover:text-indigo-800" > <Link :href="'/posts/' + article.id">{{ article.title }}</Link> </h3> <p> {{ article.excerpt }} </p> <Link :href="'/posts/' + article.id" class="text-indigo-600 hover:text-indigo-800 w-fit self-end font-semibold" >Read more </Link> </div> </article> </section> </KinstaLayout> </template>

Tailwind를 사용하여 Show.vue 의 스타일을 지정하여 좀 더 차려입고 방문할 준비가 된 것처럼 보이도록 합시다. 또한 "Article" 객체를 예상하고 소품으로 설정해야 함을 알려야 합니다.

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ article: Object, }); </script> <template> <KinstaLayout> <article class="mx-auto mt-10 flex justify-center max-w-5xl border-b-2"> <img src="/images/kinsta-logo.png" class="w-80 h-80 rounded-xl mx-auto py-5" alt="" /> <div class="text-left flex flex-col pt-5 pb-10 px-10"> <h1 class="text-xl font-semibold mb-10">{{ article.title }}</h1> <p>{{ article.body }}</p> </div> </article> </KinstaLayout> </template>

이제 기사 제목이나 "더 읽기"를 클릭하면 페이지를 새로고침하지 않고도 마법처럼 Show.vue 로 이동합니다.

가동 중지 시간 및 WordPress 문제로 어려움을 겪고 있습니까? Kinsta는 시간을 절약하도록 설계된 호스팅 솔루션입니다! 우리의 기능을 확인하십시오
작동하는 링크가 있는 기사 카드를 보여주는 "Kinsta 블로그" 페이지의 예.
관성 링크가 제자리에 있습니다.

우리의 경우 <Link> 를 경로에 GET 요청을 보내고 새 데이터를 반환하는 앵커 태그로 사용하고 있지만 POST , PUT , PATCHDELETE 에도 <Link> 를 사용할 수 있습니다.

"경로/ web.php ":

 <Link href="/logout" method="post" as="button" type="button">Logout</Link>

당신이 알아야 할 라라벨 관성 팁과 요령

이제 Laravel, Inertia 및 Tailwind CSS로 구축된 작동하는 SPA가 있습니다. 그러나 관성은 우리가 훨씬 더 많은 것을 성취하도록 도울 수 있습니다. 개발자와 애플리케이션 방문자 모두에게 도움이 될 몇 가지 Inertia 기술을 습득할 때입니다.

URL 생성

Laravel 경로를 사용하지 않고 이름을 추가하고 있음을 눈치채셨을 것입니다. Inertia를 사용하면 전체 경로를 수동으로 기록하는 대신 구성 요소 내에서 명명된 경로를 사용할 수 있습니다.

프로젝트에 Ziggy 패키지를 설치하여 이를 달성할 수 있습니다.

 composer require tightenco/ziggy

그런 다음 "resources/js/app.js"로 이동하여 다음과 같이 업데이트합니다.

 import "./bootstrap"; import "../css/app.css"; import { createApp, h } from "vue"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m"; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .use(ZiggyVue, Ziggy) .mount(el); }, });

"/resources/views/ app.blade.php "로 이동하고 @route 지시문으로 헤드를 업데이트합니다.

 <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Fetch project name dynamically --> <title inertia>{{ config('app.name', 'Laravel') }}</title> <!-- Scripts --> @routes @vite('resources/js/app.js') @inertiaHead </head> <body class="font-sans antialiased"> @inertia </body> </html>

… 그리고 아래 두 개의 터미널 명령을 눌러 NPM 패키지를 새로 고칩니다.

 npm install && npm run dev

이 패키지를 사용하면 Inertia 구성 요소 내에서 명명된 경로를 사용할 수 있으므로 Index.vue 로 이동하여 이전 수동 경로를 제거하고 컨트롤러에 있는 것처럼 데이터를 정상적으로 전달하면서 경로 이름으로 대체합니다.

우리는 이것을 대체할 것입니다:

 <Link :href="'/posts/' + article.id"> {{ article.title }} </Link>

...이와 함께:

 <Link :href="route('article.show', article.id)"> {{ article.title }} </Link>

이렇게 하면 우리가 했던 것과 똑같은 동작을 할 수 있지만 더 개발자 친화적이고 경로에서 많은 매개변수를 예상할 때 매우 유용합니다.

진행률 표시기

이것은 Inertia.js의 가장 멋진 기능 중 하나입니다. SPA는 대화형 사용자 경험을 제공하기 때문에 요청이 로드되고 있는지 여부에 대한 지속적인 피드백을 갖는 것은 애플리케이션에 환상적인 추가 기능이 될 것입니다. 이것은 Inertia가 제공하는 별도의 라이브러리에 의해 달성될 수 있습니다.

"@inertiajs/progress" 라이브러리는 관성 이벤트에 따라 로드 표시기를 조건부로 표시하는 NProgress 주변의 래퍼입니다. 이 작업이 배후에서 어떻게 작동하는지 실제로 알 필요는 없으므로 작동하도록 합시다.

아래 터미널 명령으로 이 라이브러리를 설치할 수 있습니다.

 npm install @inertiajs/progress

설치가 완료되면 " resources/js/app.js "로 가져와야 합니다.

 import "./bootstrap"; import "../css/app.css"; import { createApp, h } from "vue"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m"; import { InertiaProgress } from "@inertiajs/progress"; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .use(ZiggyVue, Ziggy) .mount(el); }, }); InertiaProgress.init({ color: "#000000", showSpinner: true });

이렇게 하면 로딩 막대와 로딩 스피너가 검은색으로 표시되지만 Inertia.js 진행 표시기 문서에서 찾을 수 있는 다른 유용한 옵션과 함께 색상을 변경할 수 있습니다.

오른쪽 상단에 회전 표시기가 있는 파란색 "Kinsta Blog" 헤더.
관성 진행률 표시기(오른쪽 상단).

스크롤 관리

경우에 따라 동일한 스크롤 위치를 유지하면서 새 페이지로 이동해야 할 수 있습니다. 사용자가 댓글을 남길 수 있도록 허용하는 경우 필요할 수 있습니다. 이렇게 하면 양식이 제출되고 데이터베이스의 새 주석이 구성 요소로 로드됩니다. 사용자가 스크롤 위치를 잃지 않고 이런 일이 일어나기를 원할 것입니다. 관성은 우리를 위해 이것을 처리합니다.

우리의 경우 이것을 Index.vue<Link> 태그에 적용해 보겠습니다. Inertia의 <Link> 를 사용하여 다른 페이지로 리디렉션하는 동안 스크롤 위치를 유지하려면 <Link <Link>preserve-scroll 속성을 추가하기만 하면 됩니다.

 <Link :href="route('article.show', article.id)" preserve-scroll> {{ article.title }} </Link>

SEO 팁

SPA가 탄생한 이후 사람들은 검색엔진최적화(SEO)에 대해 고민했습니다. SPA 접근 방식을 사용하는 경우 모든 것이 클라이언트 측에서 렌더링되어 검색 결과 상단에 웹 사이트가 표시되지 않기 때문에 검색 엔진이 웹 애플리케이션을 크롤링하는 데 어려움을 겪는다는 것은 일반적으로 알려져 있습니다. 그럼에도 불구하고 Facebook 및 Github와 같은 인기 있는 플랫폼이 이제 SPA이고 여전히 SEO에서 잘 수행되는 이유는 무엇입니까?

음, 이것은 임무가 아닙니다. 더 이상 불가능합니다. Inertia는 SPA가 SEO 친화적이 되도록 돕는 몇 가지 솔루션을 제공합니다.

Laravel 및 Vite를 사용한 Inertia Vue SSR

검색 엔진은 콘텐츠를 식별하기 위해 항상 웹사이트에서 HTML을 찾고 있습니다. 그러나 URL에 HTML이 없으면 이 작업이 더 어려워집니다. SPA를 개발할 때 페이지에 있는 모든 것은 JavaScript와 JSON입니다. Inertia는 애플리케이션에 추가할 수 있는 SSR(Server-Side Rendering) 기능을 도입했습니다. 이렇게 하면 앱이 서버에서 초기 페이지 방문을 미리 렌더링한 다음 렌더링된 HTML을 브라우저로 보낼 수 있습니다. 이를 통해 사용자는 페이지가 완전히 로드되기 전에 페이지를 보고 상호 작용할 수 있으며 검색 엔진이 사이트를 색인화하는 데 걸리는 시간을 단축하는 것과 같은 다른 이점도 있습니다.

작동 방식을 요약하면 Inertia는 Node.js 서버에서 실행 중인지 식별하고 구성 요소 이름, 속성, URL 및 자산 버전을 HTML로 렌더링합니다. 이렇게 하면 사용자와 검색 엔진에 페이지가 제공하는 거의 모든 것이 제공됩니다.

그러나 우리는 Laravel을 다루고 있기 때문에 Laravel이 PHP 프레임워크이고 Node.js 서버에서 실행되지 않기 때문에 이것은 거의 의미가 없습니다. 따라서 페이지를 렌더링하고 HTML을 반환하는 Node.js 서비스로 요청을 전달합니다. 이렇게 하면 기본적으로 Laravel Vue 애플리케이션 SEO가 친숙해집니다.

먼저 Vue.js SSR npm 패키지를 설치해야 합니다.

 npm install @vue/server-renderer

또 다른 유용한 Inertia "NPM" 패키지는 간단한 "HTTP" 서버를 제공합니다. 다음과 같이 설치하는 것이 좋습니다.

 npm install @inertiajs/server

그런 다음 "resources/js/"에서 ssr.js 라는 새 파일을 추가합니다. 이 파일은 Inertia를 설치할 때 만든 app.js 파일과 매우 유사하지만 브라우저가 아닌 Node.js에서만 실행됩니다.

 import { createSSRApp, h } from "vue"; import { renderToString } from "@vue/server-renderer"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import createServer from "@inertiajs/server"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m"; const appName = "Laravel"; createServer((page) => createInertiaApp({ page, render: renderToString, title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ app, props, plugin }) { return createSSRApp({ render: () => h(app, props) }) .use(plugin) .use(ZiggyVue, { ...page.props.ziggy, location: new URL(page.props.ziggy.location), }); }, }) );

Make sure not to include everything in the ssr.js file since it will not be visible to visitors; this file is only for search engines and browsers to show the data within your page, so include only what is important to your data or only what will make your data available.

“By default, Inertia's SSR server will operate on port 13714. However, you can change this by providing a second argument to the createServer method.” Inertia DOCss.

The Inertia.js DOCs aren't explaining how to integrate Inertia SSR with Vite, but we will go through this now. Head to vite.config.js and paste the below:

 import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [ laravel({ input: "resources/js/app.js", ssr: "resources/js/ssr.js", }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });

Next, head to package.json and change the build script:

 "build": "vite build && vite build --ssr"

Now if we run npm run build , Vite will build our SSR bundle for production. For more information about this you may visit Inertia SSR DOCs and Vite SSR DOCs.

Title and Meta

Because JavaScript applications are rendered within the document's <body> , they cannot render markup to the document's <head> because it is outside of their scope. Inertia has a <Head> component that may be used to set the page <title> , <meta> tags, and other <head> components.

To add <head> element to your Page, we must import <head> from Inertia same as we did with <Link> component:

import { Head } from '@inertiajs/inertia-vue3' <Head> <title>Kinsta Blog</title> <meta name="description" content="Kinsta blog for developers"> </Head>

또한 모든 페이지에 대한 전체 제목을 추가할 수 있습니다. 이렇게 하면 모든 페이지의 제목 옆에 애플리케이션 이름이 추가됩니다. app.js 파일에서 이미 수행했습니다.

 createInertiaApp({ title: (title) => `${title} - ${appName}`, // });

즉, 제목이 있는 애플리케이션의 홈페이지에 <head title="Homepage"> 를 추가하면 <title>Home - My App</title> 과 같이 렌더링됩니다.

앱 모니터링

속도는 웹사이트에서 SEO 성능을 최적화하는 데 가장 중요한 요소 중 하나입니다. 이러한 이유로 웹 사이트에 WordPress를 사용하는 경우 Kinsta APM은 작동 중인 애플리케이션을 모니터링하고 면밀히 주시하는 데 도움을 줄 것입니다. WordPress 성능 문제를 식별하는 데 도움이 되며 모든 Kinsta 호스팅 사이트에서 무료로 사용할 수 있습니다.

요약

Inertia.js는 사용 가능한 가장 중요한 기술 중 하나입니다. 이를 Laravel과 혼합하면 PHP 및 JavaScript로 구축된 최신 단일 페이지 애플리케이션을 갖게 됩니다. Laravel의 창시자인 Taylor Otwell은 Inertia에 큰 관심을 보였고 Laravel은 Inertia 및 SSR을 지원하는 가장 인기 있는 스타터 키트인 Laravel Breeze 및 Jetstream을 출시했습니다.
이 가이드에서 Inertia.js 사용을 시작하는 방법과 이를 Laravel, Vue.js 및 Tailwind CSS와 함께 사용하여 현대적인 블로그 웹 앱을 만드는 방법을 알아보세요. Click to Tweet
Laravel 팬이거나 전문 개발자라면 Inertia.js가 의심할 여지 없이 눈길을 끌 것입니다. 이 자습서에서는 단 몇 분 만에 매우 기본적이고 직관적인 블로그를 만들었습니다. 관성에 대해 배울 것이 여전히 많으며, 이것은 많은 기사와 튜토리얼 중 첫 번째에 불과할 수 있습니다.

라라벨에 대해 우리가 탐구했으면 하는 다른 어떤 것이 있습니까? 아래 의견란에 알려주십시오.