# SvelteKit으로 만든 초고속 만화 뷰어: 웹 스크래핑부터 배포까지 완전 가이드

---

# # 서론 – “만화 읽을 때마다 느끼는 불편함”

온라인에서 만화를 감상할 때, 페이지 전환이 느리거나 광고가 끊임없이 나타나는 경험, 한 번쯤은 해보셨을 겁니다. 특히 모바일 환경에서는 로딩 시간 하나가 독서 흐름을 깨뜨리는 큰 요인이 되죠. 이런 일상적인 불편을 해결하고 싶어 “코드로 내 손에 맞는 만화 뷰어를 만들 수 있지 않을까?” 하는 생각이 떠오릅니다.

이번 포스트에서는 **SvelteKit**을 활용해 **초고속 만화 뷰어**를 직접 구현하는 과정을 단계별로 풀어보겠습니다. 웹 스크래핑, 이미지 최적화, 배포까지 초보자도 따라 할 수 있도록 상세히 설명합니다.

> **핵심 SEO 키워드**: `SvelteKit`, `만화 뷰어`, `웹 스크래핑`

---

# # 1️⃣ 프로젝트 개요와 목표

| 목표 | 내용 |

|------|------|

| **빠른 로딩** | 이미지 프리로드와 CDN 캐시 활용 |

| **광고 차단** | 불필요한 스크립트와 요소를 제거 |

| **반응형 UI** | 모바일·데스크톱 모두 최적화 |

| **쉽게 확장** | 새로운 만화 사이트 추가 시 최소 수정 |

프로젝트는 크게 **세 부분**으로 나뉩니다.

1. **프론트엔드** – SvelteKit으로 UI와 라우팅 구현

2. **백엔드(Edge Function)** – 웹 스크래핑을 통해 원본 이미지 URL을 추출

3. **배포** – Vercel·Netlify 등 서버리스 플랫폼에 배포

---

# # 2️⃣ SvelteKit 기본 설정 (초보자도 OK)

1. **프로젝트 생성**

```
bash

npm init svelte@next manga-reader

cd manga-reader

npm install

```

2. **파일 구조**

```

src/

 ├─ routes/

 │   └─ +page.svelte   # 메인 뷰 페이지

 └─ lib/

     └─ api/

         └─ fetchManga.ts   # Edge Function 호출 함수

```

3. **라우팅** – `src/routes/+page.svelte`에 간단한 입력 폼을 만든 뒤, 사용자가 입력한 만화 URL을 `fetchManga` 함수에 전달합니다.

```
svelte

<script lang='ts'>

  import { fetchManga } from '$lib/api/fetchManga';

  let mangaUrl = '';

  let images: string[] = [];

  async function loadManga() {

    images = await fetchManga(mangaUrl);

  }

</script>

<input bind:value={mangaUrl} placeholder='만화 페이지 URL 입력' />

<button on:click={loadManga}>읽기</button>

{#if images.length}

  <div class='gallery'>

    {#each images as src}

      <img src={src} loading='lazy' />

    {/each}

  </div>

{/if}

```

SvelteKit은 **SSR**(Server‑Side Rendering)과 **CSR**(Client‑Side Rendering)를 자동으로 최적화해 주기 때문에 별도 설정 없이도 빠른 초기 로딩을 경험할 수 있습니다.

---

# # 3️⃣ 웹 스크래핑 구현 – Edge Function에서 이미지 URL 추출

## # 3.1 왜 Edge Function인가?

- **지연 시간 최소화**: 사용자와 가장 가까운 엣지 서버에서 실행 → API 호출 횟수 감소

- **서버 비용 절감**: 사용량 기반 과금, 무한히 확장 가능

## # 3.2 구현 코드 (Node.js + Cheerio)

`src/lib/api/fetchManga.ts`

```
ts

import { json } from '@sveltejs/kit';

import cheerio from 'cheerio';

export async function GET({ url }) {

  const target = url.searchParams.get('url');

  const res = await fetch(target);

  const html = await res.text();

  const $ = cheerio.load(html);

  // 사이트마다 다르지만 보통 이미지가 <img class='page'> 형태

  const imgUrls = $('img.page')

    .map((_, el) => $(el).attr('src'))

    .get()

    .filter(Boolean);

  return json({ images: imgUrls });

}

```

위 코드는 **Vercel Edge Functions** 혹은 **Netlify Functions**에 그대로 배포할 수 있습니다.

## # 3.3 CORS와 보안

- `fetch` 시 `mode: 'no-cors'` 대신 서버 측에서 직접 요청 → 브라우저 CORS 문제 회피

- 외부 도메인에 대한 무분별한 요청을 방지하기 위해 허용 도메인 화이트리스트를 설정합니다.

---

# # 4️⃣ 이미지 최적화와 캐시 전략

1. **이미지 포맷 변환** – `sharp` 라이브러리로 WebP 변환 후 반환 (Edge Function 안에서 처리 가능)

2. **CDN 캐시** – Vercel/Netlify가 제공하는 자동 캐시 헤더(`Cache-Control: public, max-age=31536000`) 활용

3. **Lazy Loading** – `<img loading='lazy'>` 속성으로 화면에 보일 때만 로드

> **팁**: 이미지가 많을 경우 `IntersectionObserver`를 직접 구현하면 더욱 세밀한 로딩 제어가 가능합니다.

---

# # 5️⃣ 배포와 성능 테스트

| 단계 | 작업 내용 |

|------|-----------|

| **빌드** | `npm run build` (SvelteKit이 정적 파일과 서버less 함수 생성) |

| **배포** | Vercel CLI `vercel --prod` 혹은 Netlify UI에 연결 |

| **테스트** | Lighthouse(Chrome DevTools)로 **Performance** 점수 90점 이상 목표 |

| **모니터링** | Vercel Analytics → 페이지 뷰, 응답 시간 확인 |

배포 후 실제 모바일 기기에서 **네트워크·CPU throttling**을 적용해 테스트하면, 페이지 최초 로딩이 1~2초 내에 완료되는 것을 확인할 수 있습니다.

---

# # 결론 – 직접 만들고 공유해 보세요!

SvelteKit과 Edge Function을 조합하면, 복잡한 서버 구축 없이도 **초고속 만화 뷰어**를 손쉽게 구현할 수 있습니다. 웹 스크래핑을 통해 원하는 콘텐츠를 직접 가져오고, 이미지 최적화와 CDN 캐시로 사용자 경험을 크게 향상시킬 수 있죠.

지금 바로 위 과정을 따라해 보시고, 자신만의 커스텀 만화 뷰어를 만들면서 **프론트엔드·백엔드 통합 개발** 역량을 한 단계 끌어올려 보세요.

> **행동 유도**: 프로젝트를 직접 깃허브에 올리고, 블로그에 사용 후기와 개선 아이디어를 공유해 주세요! 여러분의 피드백이 다음 업데이트를 만드는 원동력이 됩니다. 🚀
