>웹 프론트엔드 >JS 튜토리얼 >Google Cloud 개발자를 위한 SvelteKit 소개

Google Cloud 개발자를 위한 SvelteKit 소개

PHPz
PHPz원래의
2024-07-17 19:39:17638검색

 A gentle introduction to SvelteKit for Google Cloud developers

소개

이 시리즈의 이전 게시물(React에 대한 매우 부드러운 소개)에서는 독자들에게 웹앱 개발을 위한 뛰어난 React 프레임워크 시스템을 소개했습니다. SvelteKit은 대체 프레임워크입니다. React와 어떻게 다르며 더 나은가요?

기능적으로는 큰 차이가 없는 것 같아요. React에서 할 수 있는 대부분의 작업은 SvelteKit에서 할 수 있습니다. 그 반대도 마찬가지입니다. 그러나 세부 사항을 살펴보면 많은 사람들이 SvelteKit이 "반응형" 목표를 쉽게 달성할 수 있다는 점에서 우위에 있다고 생각합니다. Svelte는 "우아함"을 의미하며, 바로 그 의미입니다. 가늘고 적응력이 뛰어나며 실용적인 도구입니다.

개인적으로 저는 SvelteKit이 서버측 디자인, 즉 사용자의 웹 브라우저가 아닌 웹앱의 클라우드 서버에서 실행되는 코드를 지향하도록 유도하는 경향이 있기 때문에 SvelteKit에 매력을 느꼈습니다. 원래 웹앱 개발에 빠져들게 했던 클라이언트 측 코드를 쉽게 작성하고 디버깅할 수 있었기 때문에 이것은 아이러니합니다. 그러나 나는 인덱싱 스파이더가 클라이언트 측 코드를 "수화"하는 데 얼마나 노력을 투자하는 것을 꺼리는지 발견하고 여기에 더 많은 노력을 기울여야 한다는 것을 깨달았습니다(수반되는 내용을 보려면 아래 SvelteKit의 디버깅 참조). 그러나 서버 측 코드 사용을 고려할 수 있는 다른 이유도 있습니다. 다음은 몇 가지입니다.

  • Postmark(이메일 발송) 또는 Paypal(결제 수금)과 같은 타사 서비스를 사용하기 시작하면 해당 보안 코드를 클라이언트 측 코드에 포함하는 것이 좋지 않다는 것을 알게 될 것입니다. 당신 "검사관"을 사용하여 이를 볼 수 있다면 다른 사람도 볼 수 있습니다. 서버측에서 실행되는 코드는 액세스할 수 없습니다.

  • 서버측 코드는 데이터에 더 가까이 위치하며 클라이언트 노트북보다 더 빠르게 실행됩니다.

SvelteKit을 사용하면 웹앱의 어떤 부분을 로컬로 실행할지, 어떤 부분을 원격으로 실행할지 지정하여 음악을 쉽게 재생할 수 있습니다.

  • 어떤 경우에는 페이지가 완전히 서버측에서 렌더링될 수 있습니다. 페이지에 정적 정보만 포함되어 있는 경우 Sveltekit을 사용하여 해당 페이지를 "사전 렌더링"할 수 있습니다. 사전 렌더링된 페이지는 빌드 시 구성되며 순수 HTML 슬래브로 다운로드됩니다.
  • 또는 완전히 클라이언트 측에서 렌더링될 수도 있습니다.
  • 아니면 두 가지 모두에서 실행될 수도 있습니다. 최적의 응답 시간 제공을 목표로 하는 SvelteKit 웹 앱은 처음에는 서버 소스의 "자리 표시자" 화면만 표시하여 무엇이든 볼 수 있습니다(여기서 Google의 색인 생성 봇에 큰 공을 들인 것으로 보입니다). 그런 다음 이는 사용자 인스턴스 관련 정보를 사용하여 클라이언트측 코드로 "수화"됩니다.

좀 더 구체적으로 살펴보겠습니다.

Svelte의 라우팅

외부적으로 Sveltekit 웹 앱은 mywebapp/dosomethingwithmyfiles와 같은 "페이지" 계층 구조 등 기존 브라우저 애플리케이션과 똑같아 보입니다. 클라이언트 사용자가 이러한 유형의 배열을 기대하고 의존하기 때문에 이와 같습니다. 그러나 표면 아래에서 SvelteKit 웹앱은 React 웹앱과 완전히 다른 방식으로 이러한 배열을 제공합니다. React에서 이러한 페이지는 실제로 하나의 거대한 코드 조각의 모든 부분이며 요청은 웹 인터페이스에서 작동하는 리디렉션에 의해 그곳으로 라우팅됩니다. (해당 문장이 이해가 되지 않는다면 Whats a 'Single- 페이지' 웹앱?). SvelteKit은 프로젝트 구조를 사용하여 페이지 구조를 정의함으로써 이를 달성합니다. 따라서 mywebapp/dosomethingwithmyfiles 페이지를 갖고 싶다면 dosomethingwithmyfiles 폴더 안에 +page.svelte 파일이 있어야 합니다. 이러한 배열이 이루어지면 배포된 앱은 각 URL에 대해 별도의 실제 페이지를 제공합니다.

다음은 SvelteKit 프로젝트의 샘플 소스 폴더 구조입니다.

내 프로젝트
├───src
│ └───경로
│ └───내 파일로 뭔가를 하세요

SvelteKit을 설치하고 나면(신규 개발자를 위한 Svelte 참조) 이 구조는 대량의 복잡한 구성 파일과 빌드 폴더 등으로 보강됩니다. 그러나 현재로서는 경로 폴더에 초점이 맞춰져 있습니다. 여기에 페이지 코드를 저장합니다. SvelteKit이 귀하에게 적합한지 궁금해지기 시작할 수 있는 곳입니다. 이제 상황이 좀 복잡해지기 때문에 꽉 잡으세요.

SvelteKit에서는 페이지 폴더의 콘텐츠에 대해 매우 엄격한 명명 규칙을 따라야 합니다. dosomethingwithmyfiles 폴더에 표시될 수 있는 파일 이름 목록은 다음과 같습니다.

  • dosomethingwithmyfiles/+page.svelte. 이 파일에는 브라우저 화면에 URL myproject/dosomethingwithmyfile에 대한 페이지를 표시하는 코드의 소스가 포함됩니다. 우와 - 잠시 생각해 보세요. 여섯 개의 서로 다른 페이지가 있는 SvelteKit 프로젝트의 VSCode 편집기에서 작업할 때 파일 표시줄에 +page.svelte라는 이름의 여섯 개의 탭이 표시될 수 있습니다. 혼란스럽나요? 네, 동의합니다.

처음에는 이것이 도저히 받아들일 수 없는 일이라고 느낄 수도 있습니다. 그러나 각 +page.svelte 파일은 폴더 소유자, dosomethingwithmyfiles 등의 이름으로 편집기 표시줄에서 한정됩니다. 본격적으로 편집을 시작하기 전에 +page.svelte의 소유자를 확인하도록 스스로를 훈련하는 것은 그리 어렵지 않습니다. 그리고 일단 SvelteKit 프로젝트를 한두 개 개발하고 나면 배열의 목적을 선언하는 컨벤션의 가치를 인식하기 시작할 것입니다. )

이 충격을 흡수하는 동안 제가 조금 격려해드리겠습니다. +page.svelte 파일에서는 동등한 React 파일에서 볼 수 있는 것과 동일한 종류의 코드를 찾을 수 있을 것으로 예상할 수 있습니다. 페이지 상태를 조작하기 위한 이국적인 useState 호출과 '반응'을 위한 JSX 호출이 혼합되어 있습니다. 이에 HTML을 생성합니다. +page.svelte 파일은 확실히 동일한 작업을 수행하지만 "이국적인" 비트를 삭제하고 일반 자바스크립트와 특수 키워드를 뿌려 순수하고 희석되지 않은 HTML을 사용합니다. 상쾌하게 느껴질 수도 있습니다.

다음은 dosomethingwithmyfiles 폴더에서 찾을 수 있는 몇 가지 표준 파일 이름입니다.

  • dosomethingwithmyfiles/+page.js, 여기에는 데이터를 +page.svelte 파일(예: React useEffect와 동일)로 전달하는 파일의 소스가 포함됩니다. 여기의 코드는 페이지가 처음 로드될 때 서버에서 실행됩니다. 이후에 페이지가 다시 참조되면 +page.js 코드가 앞서 나열된 이점을 사용하여 브라우저에서 실행됩니다.

     

    흥미롭게도 과거에 브라우저에서 실행할 웹 API 코드 작성과 Firebase 기능에서 서버 측 실행을 위한 Node.js 스타일 사이를 전환할 때마다 자바스크립트 두뇌를 "다시 프로그래밍"해야 하는 불편을 겪었다면 Sveltekit에서 Web API 버전이 이제 서버 측에서도 완벽하게 실행된다는 소식을 듣게 되어 기쁩니다.

     

    당연히 +page.js 파일에서 읽은 데이터가 연결된 +page.svelte에 도달하도록 구성하는 방법을 알고 싶을 것입니다. 현재로서는 이것이 SvelteKit 마법에 의해 도착한다고 말씀드리겠습니다. 정확한 메커니즘은 "반응형" 변수를 정의하기 위한 SvelteKit의 배열을 설명한 후에야 명확해질 것입니다. 지금은 모자를 꽉 쥐고 계세요.

     

  • dosomethingwithmyfiles/+page.server.js. 여기에는 서버에서만 실행하려는 코드를 배치하는 곳입니다(일반적으로 보안 또는 성능상의 이유로). 앞서 언급했듯이 사전 렌더링되어 빌드 시 구성되도록 요청할 수 있습니다. 이 경우 성능은 정말 놀랍습니다.

     

  • dosomethingwithmyfiles/+layout.svelte. 여기에는 다른 페이지 전체에 공통된 페이지 비트(예: 도구 모음 헤더)를 설정하는 코드를 배치하는 곳입니다. +layout.svelte 파일은 모든 하위 경로와 형제 +page.svelte에 적용됩니다. 레이아웃을 임의의 깊이로 중첩할 수 있습니다. 다시 말하지만, 수신자 페이지에 공통 레이아웃을 삽입하기 위한 정확한 배열은 나중을 위해 남겨두겠습니다. Svelte의 마법이 더욱 강화되었습니다.

     

    +layout.svelte 페이지에 일부 데이터가 필요한 경우 +layout.server.js 파일을 포함할 수 있습니다.

     

  • myfiles/+server.js로 뭔가를 해보세요. 여기에는 myProject/dosomethingwithmyfiles?type="pdf"와 같은 매개변수화된 URL을 통해 "API 엔드포인트"로 사용하려는 코드를 배치하는 곳입니다. 이 구성에 대한 자세한 내용은 나중에 알려드리겠습니다.

SvelteKit의 '반응형 변수' 및 '반응형 HTML'

'반응형 변수'란 브라우저 페이지가 변경될 때 다시 렌더링되도록 하는 데이터 항목을 의미합니다. '반응형 HTML'이란 HTML이 이러한 변경 사항에 응답하도록 구성된 것을 의미합니다.

React에서 반응성 변수는 변수를 상태 객체의 속성으로 정의하는 useState 표현식을 사용하여 선언된다는 것을 기억하실 것입니다. 선언은 또한 초기 속성 값과 이를 변경하는 함수를 지정합니다.

다음은 클릭하면 사라지는 팝업을 표시하는 React 웹앱의 예입니다.

import React, { useState } from "react";

const [screenState, setScreenState] = useState({popupVisible: true,});

return (
    <div>
        <h1 style={{textAlign: "center"}}
            onClick = {() => {setScreenState({popupVisible: !screenState.popupVisible})}}>
        Main Page - Click to toggle popup
        </h1>

    {screenState.popupVisible && 
        <div 
            style={{ textAlign: "center", marginLeft: "auto", marginRight: "auto", height: "2rem", width: "25rem", backgroundColor: "gainsboro" }}
            onClick = {() => {setScreenState({popupVisible: !screenState.popupVisible})}}>
            <h2> Popup Window - Click to Hide popup</h2>
        </div>  
    }
    </div>
)

Svelte에서는(이제 작동하는 프레임워크가 아니라 언어에 대해 이야기하고 있습니다) src/routes/demo/+에서 이 효과를 얻을 수 있습니다. page.svelte 파일에 popupVisible을 자바스크립트 변수로 선언하면 됩니다

<script>
    let popupVisible = false;
</script>

 <div>
    <h1 style="text-align: center" 
        on:click={() => (popupVisible = !popupVisible)}>
        Main Page - Click to toggle popup
    </h1>

    {#if popupVisible}
        <div
            style="text-align: center; margin-left: auto; margin-right: auto; height: 2rem; width: 25rem; background-color: gainsboro"
            on:click={() => (popupVisible = !popupVisible)}
        >
            <h2>Popup Window - Click to Hide popup</h2>
        </div>
    {/if}
</div>

다음은 주요 차이점을 요약한 것입니다.

  • Svelte uses a standard Javascript let declaration to introduce state variables instead of the strange React useState expression

  • Svelte uses a down to earth #if 'logical expression' keyword to replace the awkward JSX {'logical expression' &&syntax. This makes your code much more readable. Svelte also provides associated else and each keywords.

  • Svelte uses plain CSS to define HTML classes rather than the perplexing JSX style objects (eg {{textAlign: "center"}}).

Note also that the demo/+pagesvelte file defined above will run directly in the browser as /demo. To run the React version you would have to put some code into an associated src/main.jsx file to define the new route.

Inputs: Local Functions, Actions and API endpoints

Keyboard input in React generally uses the following pattern:

const [myState, setMyState] = useState({myProperty: "",});

function handleChange({ target }) {
    setMyState({ ...myState, [target.name]: target.value });
};

return (
    <input name="myProperty"
        value={myState.myProperty}
        onChange={handleChange} />
)

Here, an input labelled as "myProperty" fires a general-purpose handleChange function every time you press a key. In handleChange its value is extracted and applied to the page's state to trigger a re-render.

Svelte thinks this is too complicated and introduces a "bind" keyword to its input syntax. This automatically transmits changes to an associated state variable. A Svelte version of the above thus looks like this:

<script>
    let myProperty = "";
</script>
<input bind:value={myProperty} />

The bind keyword is also used to enable you to create two-way communication between parent and child components. This is a powerful feature.

An interesting feature of Svelte is that it encourages you to use forms and server-side processing for input handling. Thus it's perfectly permissible in Svelte to launch a client-side function like this:

<script>
    let myProperty = "";
    function commitChange() {
        // Use the global myProperty variable to update server storage
    }
</script>

<span>myProperty = </span><input bind:value={myProperty}  />
<button on:click={commitChange}>Commit Change</button>
/>

Svelte docs correctly insist that interactions like this are better handled by forms and server-side processing in a +page.server.js file. Here the validation and submission of the user input can be safely protected from the sort of interference possible in client-based code. Here also, any subsequent processing can be performed with maximum efficiency.

To implement this view, Svelte provide a neat automatic link between a form reading data on a +page.svelte and a function handling the processing of that data in the associated +page.server.js file. Here's an example:

src/routes/login/+page.svelte
<form method="POST">
    <span>myProperty = </span><input name="myProperty">
    <button>Commit Change</button>
</form>

src/routes/login/+page.server.js
export const actions = {
    default: async (event) => {
        // TODO handle the processing for the input read by the form on +page.svelte
    }
};

Note that no Javascript has been used in the form - no "on click" or "on submit", for example. The linkage has been established entirely through "Svelte magic".

In practice, of course, a +page.svelte file is likely to want to be the source of multiple "actions". See Svelte Form Actions for details of how Svelte manages this. (Note that Svelte docs are organised under two URLs: kit.svelte.dev for framework topics like routing and svelte.dev for elements of the language itself)

Finally, to conclude this section, suppose you wanted users to be able to call on the service of an action by referencing it directly through a javascript "fetch" (or, at its simplest by launching a parameterised url via the browser - eg https:// mySite/myPage?param1=3 etc). This is where you would use a +server.js file to create an API "endpoint" function. Firebase users might well use such an arrangement where they had previously used a Firebase function. Not the least advantage of this would be that testing and debugging could be done in the Sveltekit server rather than the Firebase emulator.

Components

  • 1-way bindings

Each +page.svelte file defines a component, and you mark variables declared here as "props" - ie make them accessible to "consumers" of the component - by adding the export keyword to their declarations. So, if you're still wondering how a +page.svelte file gets its data from +page.server.js - this is how it's done. A +page.svelte file wanting to receive "load" data from its +page.server.js (or +page.js) file just needs to put something like the following in its