SvelteKit 페이지 간 파일 전달

시나리오

<!-- routes/img/+page.svelte -->

<script>
  let file;

  function handleFileChange(event) {
    const selectedFile = event.target.files[0];
    if (selectedFile) {
      file = selectedFile;
    }
  }
  
  async function uploadImage() {
    // 1. createURLComponent 사용
    // OR 2. sessionStorage에 저장
    // OR 3. store에 저장

    goto("img/result");
  }
</script>

<input type="file" accept="image/*" onchange={handleFileChange} />
<button onclick={uploadImage}>Upload</button>

/img에서 input 태그를 이용해 이미지 파일을 업로드한다. 이미지가 선택되면 handleFileChange를 통해 file 변수가 업데이트된다.

Upload 버튼을 누르면 /img/result로 이동해 사진을 띄운다.


1. URL로 전달

API로부터 전달받은 이미지를 URL로 변환해 /result?image=...로 전달한다. 그럼 API는 URL의 image를 읽어 처리한다.

async function uploadImage() {
  // 이미지를 URL로 변환
  const url = URL.createObjectURL(file);
  goto(`/img/result?image=${encodeURIComponent(url)}`);
}
  1. createObjectURL을 통해 파일을 브라우저 메모리에 저장하고, 주소 참조값을 받는다.
  2. 문자열(주소)encodeURIComponent를 통해 안전한 URL 형식으로 바뀐다.
  3. goto를 통해 /result?image=로 이동한다.
<!-- routes/img/result/+page.svelte -->
<script>
  import { browser } from "$app/environment";

  let processedImage = "";

  if (browser) {
    // URL 가져오기
    const urlParams = new URLSearchParams(window.location.search);
    // 이미지를 변수에 저장
    let processedImageUrl = urlParams.get("image");
    processedImage = decodeURIComponent(processedImageUrl);
  }
</script>

{#if processedImage}
  <img src={processedImage} alt="" />
{/if}

이 방식은 URL에 불필요한 정보가 노출된다.


2. sessionStorage 사용

sessionStorage를 사용하면 새로고침해도 문제없이 이미지를 보여준다.

// routes/img/+page.svelte

import { goto } from "$app/navigation";

let file;

async function uploadImage() {
  // base64로 변환
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = () => {
    // 이미지 저장
    sessionStorage.setItem("image", file);
    goto("/img/result");
  }
}
  1. 이미지를 Base64로 인코딩해 setItem으로 sessionStorage에 저장한다.
  2. /img/result로 이동해 파일을 읽어온다.
<!-- routes/img/result/+page.svelte -->
<script>
  import { onMount } from "svelte";

  let processedImage = "";
  onMount(() => {
    processedImage = sessionStorage.getItem("image");
  });
</script>
  • 브라우저를 새로고침해도 문제 없이 작동한다.
  • URL에 정보를 노출하지 않는다.
  • Base64 인코딩 과정에서 파일 용량이 커진다.

3. Store 사용

svelte/store는 변경 가능한 state를 선언하는 writable 함수를 제공한다.

// src/lib/stores.js

import { writable } from "svelte/store";
export const imageStore = writable(null);

이미지를 imageStore에 저장한 뒤, 다른 페이지에서 불러올 수 있다.

// routes/img/+page.svelte

async function uploadImage() {
  // base64로 이미지 변환
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = () => {
    // 이미지 저장
    imageStore.set(reader.result);
    goto("/img/result");
  };
}
<!-- routes/img/result/+page.svelte -->
<script>
  import { imageStore } from "$lib/stores.js";

  let processedImage;
  imageStore.subscribe((value) => (processedImage = value));
</script>

set으로 이미지를 저장하고, subscribe로 불러온다.

  • URL에 정보를 노출하지 않는다.
  • 새로고침하면 오류가 발생한다.

새로고침이 가능하도록 하기 위해 2번 방법과 3번 방법을 함께 사용할 수도 있다.


이 외에도 서버에 이미지를 저장해 가져오는 등 방법이 있다.