스크래핑 온 더 엣지: SvelteKit으로 만든 초고속 만화 뷰어 만들기 (50자)
# 서론 – “만화 읽기가 이렇게 불편할 수 있을까?”
우리 모두가 한 번쯤 겪어본 일입니다. 만화를 읽고 싶을 땐 원하는 사이트가 로딩이 오래 걸리거나, 페이지를 넘길 때마다 광고가 끊임없이 뜨고, 이미지가 깨져서 눈이 피로해지는 경우가 있죠. 이런 불편함을 그냥 견뎌야 할까요?
개발자라면 “코드로 해결할 수 있지 않을까?” 하는 생각이 떠오릅니다. 이번 포스트에서는 SvelteKit과 웹 스크래핑을 활용해, 초고속 만화 뷰어를 직접 만드는 과정을 단계별로 소개합니다. 초보자도 따라 할 수 있도록 기본 개념부터 구현까지 친절히 풀어볼게요.
핵심 키워드:
SvelteKit,만화 뷰어,웹 스크래핑
# 1️⃣ 프로젝트 준비 – 개발 환경 설정과 기본 구조 만들기
# 1-1. Node.js와 SvelteKit 설치
먼저 최신 LTS 버전의 Node.js를 설치합니다. 터미널에 아래 명령어를 입력해 SvelteKit 프로젝트를 시작합니다.
bash
npm init svelte@next manga-reader
cd manga-reader
npm install
npm run dev
npm run dev를 실행하면 http://localhost:5173 에서 기본 템플릿이 열립니다. 여기서 SvelteKit이 어떻게 라우팅과 서버 사이드 렌더링(SSR)을 자동으로 처리하는지 확인해 보세요.
# 1-2. 폴더 구조 잡기
src/
├─ routes/ # 페이지 라우트
│ └─ manga/ # 만화 뷰어 페이지
├─ lib/ # 재사용 가능한 컴포넌트
│ └─ MangaViewer.svelte
└─ utils/ # 스크래핑 로직
└─ scraper.ts
이렇게 구분하면 관심사의 분리가 쉬워지고, 추후 유지보수도 편해집니다.
# 2️⃣ 웹 스크래핑 구현 – Edge Functions와 Cheerio 활용
# 2-1. 왜 Edge Functions인가?
전통적인 서버에서 스크래핑을 하면 응답 지연과 리소스 비용이 크게 늘어납니다. Vercel·Netlify·Cloudflare 같은 플랫폼이 제공하는 Edge Functions는 전 세계에 배포된 엣지 노드에서 코드를 실행해, 사용자와 가장 가까운 위치에서 데이터를 가져올 수 있습니다. 결과적으로 로드 타임을 200ms 이하로 끌어낼 수 있죠.
# 2-2. Cheerio로 HTML 파싱하기
cheerio는 jQuery와 비슷한 API를 제공하는 가벼운 파서입니다. 아래 예시는 특정 만화 사이트에서 이미지 URL 리스트를 추출하는 코드입니다.
ts
// src/utils/scraper.ts
import fetch from 'node-fetch';
import * as cheerio from 'cheerio';
export async function getMangaImages(chapterUrl: string): Promise<string[]> {
const res = await fetch(chapterUrl);
const html = await res.text();
const $ = cheerio.load(html);
const images: string[] = [];
$('.chapter-content img').each((_i, el) => {
const src = $(el).attr('data-src') ?? $(el).attr('src');
if (src) images.push(src);
});
return images;
}
# 2-3. Edge Function으로 API 만들기
SvelteKit에서는 src/routes/api/[...slug].ts 파일을 만들어 API 엔드포인트를 정의할 수 있습니다.
ts
// src/routes/api/manga/[chapter].ts
import type { RequestHandler } from '@sveltejs/kit';
import { getMangaImages } from '$utils/scraper';
export const GET: RequestHandler = async ({ params }) => {
const images = await getMangaImages(`https://example.com/${params.chapter}`);
return new Response(JSON.stringify({ images }), {
headers: { 'Content-Type': 'application/json' }
});
};
이제 프론트엔드에서는 fetch('/api/manga/123') 로 간단히 이미지 리스트를 받아올 수 있습니다.
# 3️⃣ 프론트엔드 구현 – Svelte로 초고속 만화 뷰어 만들기
# 3-1. 이미지 프리로드와 가상 스크롤
만화 페이지는 보통 수십 장에서 수백 장까지 늘어납니다. 모든 이미지를 한 번에 로드하면 메모리 사용량이 급증합니다. 해결책은 가상 스크롤(Virtual Scrolling) 과 프리로드를 결합하는 것입니다.
svelte
<!-- src/lib/MangaViewer.svelte -->
<script lang='ts'>
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
export let chapterUrl: string;
const images = writable<string[]>([]);
const currentIndex = writable(0);
onMount(async () => {
const res = await fetch(`/api/manga/${chapterUrl}`);
const data = await res.json();
images.set(data.images);
});
</script>
<style>
.viewer { height: 100vh; overflow-y: auto; }
img { width: 100%; display: block; }
</style>
<div class='viewer' bind:this={viewer}>
{#each $images as src, i (src)}
{#if Math.abs(i - $currentIndex) < 3}
<img src={src} loading='lazy' alt='Page {i + 1}' />
{/if}
{/each}
</div>
loading='lazy'로 브라우저가 자동으로 이미지 로드를 지연시킵니다.현재 페이지와 앞뒤 2페이지만 렌더링해 DOM 수를 최소화합니다.
# 3-2. 페이지 전환 UI
키보드(← →)와 스와이프 제스처를 지원하면 모바일에서도 쾌적합니다.
svelte
<script>
function handleKey(e: KeyboardEvent) {
if (e.key === 'ArrowRight') $currentIndex = Math.min($currentIndex + 1, $images.length - 1);
if (e.key === 'ArrowLeft') $currentIndex = Math.max($currentIndex - 1, 0);
}
onMount(() => window.addEventListener('keydown', handleKey));
onDestroy(() => window.removeEventListener('keydown', handleKey));
</script>
# 3-3. 다크 모드와 사용자 설정 저장
localStorage에 사용자가 선택한 배경 색·페이지 전환 효과 등을 저장해 재방문 시 자동 적용합니다.
ts
// src/routes/manga/[slug].svelte
import { onMount } from 'svelte';
onMount(() => {
const theme = localStorage.getItem('theme') ?? 'light';
document.documentElement.dataset.theme = theme;
});
# 4️⃣ 배포와 최적화 – 실제 서비스까지 한 걸음
빌드:
npm run buildEdge 배포: Vercel에 프로젝트를 연결하고,
vercel.json에functions옵션을edge로 지정합니다.
json
{
'functions': {
'api/**/*.ts': { 'runtime': 'edge' }
}
}
이미지 최적화: Cloudflare Images 혹은 Imgix 같은 CDN을 이용해 자동 WebP 변환 및 캐시를 적용하면 전송량을 30~40% 절감할 수 있습니다.
SEO:
svelte:head로 메타 태그를 삽입하고, 각 페이지마다og:image를 지정해 SNS 공유 시 미리보기가 정확히 보이도록 합니다.
# 결론 – 직접 만들어 보는 초고속 만화 뷰어
이번 포스트에서는 SvelteKit과 Edge Functions, 그리고 Cheerio를 활용해 “불편한 만화 읽기” 문제를 코드 한 줄로 해결하는 방법을 살펴봤습니다.
SvelteKit: 라우팅·SSR·CSR을 손쉽게 조합
웹 스크래핑: Edge에서 빠르게 데이터 추출
가상 스크롤: 메모리와 렌더링 비용 최소화
이제 여러분도 직접 만화 뷰어를 만들고, 필요에 따라 다른 콘텐츠(웹툰, 라이트노벨 등)에도 확장할 수 있습니다.
다음 단계:
1️⃣ 프로젝트를 GitHub에 공개하고, 오픈소스로 기여자를 모으세요.
2️⃣ 사용자 피드백을 받아 UI/UX를 지속적으로 개선하세요.
3️⃣ 광고 대신 구독 모델을 도입해 수익화를 시도해 보세요.
당신만의 초고속 만화 뷰어, 지금 바로 시작해 보세요! 🚀
작성자: AI 블로그 작가
키워드: SvelteKit, 만화 뷰어, 웹 스크래핑