Skip to main content

왜 FastAPI + SvelteKit인가?

FastAPI + SvelteKit 풀스택 개발 A to Z

최근 몇 년간 Python 백엔드 생태계에서 FastAPI가 빠르게 자리를 잡았고, 프론트엔드 쪽에서는 Svelte/SvelteKit이 React·Next.js의 강력한 대안으로 떠오르고 있습니다. 이 두 기술을 함께 사용하면 빠른 개발 속도높은 런타임 성능을 동시에 얻을 수 있습니다. 이 글에서는 FastAPI 백엔드 세팅부터 SvelteKit 프론트엔드 연동, AWS Lightsail + Vercel 배포까지 전체 흐름을 실전 코드와 함께 정리합니다.

1. FastAPI 백엔드 세팅

FastAPI는 Python 3.8+ 비동기 프레임워크로, 자동 OpenAPI 문서 생성과 타입 힌트 기반 유효성 검사가 내장되어 있습니다. 다음은 프로젝트 초기 구조입니다.

1-1. 프로젝트 구조

backend/
  app/
    api/
      v1/
        endpoints/
          users.py
          items.py
    core/
      config.py
      security.py
    db/
      session.py
      models.py
    main.py
  requirements.txt
  Dockerfile

1-2. main.py 기본 구성

아래는 CORS 미들웨어와 라우터를 등록하는 최소 구성 예시입니다. 실제 프로젝트에서는 lifespan 훅으로 DB 연결 풀을 초기화합니다.

from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.v1 import router as api_router
from app.db.session import engine
from app.db import models

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 시작 시 테이블 생성
    async with engine.begin() as conn:
        await conn.run_sync(models.Base.metadata.create_all)
    yield
    await engine.dispose()

app = FastAPI(title="MyService API", version="1.0.0", lifespan=lifespan)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://myservice.vercel.app"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.include_router(api_router, prefix="/api/v1")

1-3. SQLAlchemy 비동기 세션

SQLAlchemy 2.0의 비동기 엔진을 사용하면 async with AsyncSession 패턴으로 DB 쿼리를 깔끔하게 처리할 수 있습니다.

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from app.core.config import settings

engine = create_async_engine(settings.DATABASE_URL, echo=False, pool_size=10)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

async def get_db():
    async with AsyncSessionLocal() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise

2. SvelteKit 프론트엔드 연동

SvelteKit은 서버사이드 렌더링(SSR)과 정적 생성(SSG)을 모두 지원하는 풀스택 프레임워크입니다. API 호출은 +page.server.tsload 함수에서 서버 측에서 처리하거나, 클라이언트 측에서 fetch를 사용합니다.

2-1. 서버 측 데이터 로딩

// src/routes/users/+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ fetch, cookies }) => {
  const token = cookies.get('access_token');
  const res = await fetch(`${process.env.API_BASE}/api/v1/users`, {
    headers: { Authorization: `Bearer ${token}` }
  });

  if (!res.ok) {
    return { users: [] };
  }

  const users = await res.json();
  return { users };
};

2-2. 클라이언트 측 폼 액션

SvelteKit의 Form Actions를 활용하면 JavaScript 없이도 서버 측 폼 처리가 가능합니다. Progressive Enhancement 패턴으로 UX를 향상시킬 수 있습니다.

// src/routes/login/+page.server.ts
import { fail, redirect } from '@sveltejs/kit';
import type { Actions } from './$types';

export const actions: Actions = {
  default: async ({ request, cookies, fetch }) => {
    const data = await request.formData();
    const email = data.get('email') as string;
    const password = data.get('password') as string;

    const res = await fetch(`${process.env.API_BASE}/api/v1/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password })
    });

    if (!res.ok) {
      return fail(401, { message: '이메일 또는 비밀번호가 잘못되었습니다.' });
    }

    const { access_token } = await res.json();
    cookies.set('access_token', access_token, {
      path: '/',
      httpOnly: true,
      secure: true,
      maxAge: 60 * 60 * 24 * 7
    });

    redirect(303, '/dashboard');
  }
};

3. AWS Lightsail 배포

FastAPI 백엔드는 AWS Lightsail 인스턴스에 Docker로 배포합니다. $10/월 플랜(2GB RAM)이면 소규모 서비스에 충분합니다. 다음은 핵심 Dockerfile입니다.

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY ./app ./app

EXPOSE 8000

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]

Nginx를 리버스 프록시로 앞단에 두고, Let’s Encrypt로 HTTPS를 설정합니다. docker-compose.yml에서 network_mode: host를 사용하면 Nginx가 컨테이너 포트에 직접 접근할 수 있어 설정이 단순해집니다.

4. Vercel 프론트엔드 배포

SvelteKit은 @sveltejs/adapter-vercel을 사용하면 Vercel에 원클릭 배포가 가능합니다. svelte.config.js에서 adapter를 변경하고, Vercel 대시보드에서 환경 변수 API_BASE를 Lightsail 서버 URL로 설정하면 됩니다.

// svelte.config.js
import adapter from '@sveltejs/adapter-vercel';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

/** @type {import('@sveltejs/kit').Config} */
const config = {
  preprocess: vitePreprocess(),
  kit: {
    adapter: adapter({
      runtime: 'nodejs20.x',
      regions: ['icn1'], // 서울 리전
      memory: 1024
    })
  }
};

export default config;

5. 환경 변수 관리 팁

로컬 개발 환경과 프로덕션 환경의 환경 변수를 분리 관리하는 것이 중요합니다. FastAPI 쪽에서는 pydantic-settings를 활용하면 타입 안전하게 환경 변수를 로드할 수 있습니다.

from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")

    DATABASE_URL: str
    SECRET_KEY: str
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
    CORS_ORIGINS: list[str] = []

settings = Settings()

SvelteKit은 .env 파일의 PUBLIC_ 접두사 변수는 클라이언트에 노출되고, 접두사 없는 변수는 서버에서만 접근 가능합니다. 민감한 API 키는 반드시 접두사 없이 관리하세요.

마무리

FastAPI + SvelteKit 조합은 타입 안전성, 성능, 개발 속도 세 가지를 동시에 만족하는 강력한 풀스택 선택입니다. FastAPI의 자동 문서화와 SvelteKit의 파일 기반 라우팅이 더해지면, 혼자서도 빠르게 프로덕션 수준의 서비스를 만들 수 있습니다. AWS Lightsail과 Vercel의 조합으로 인프라 비용도 최소화할 수 있어 1인 개발자나 스타트업에게 특히 추천합니다.

코드벤터는 이런 실전 경험을 바탕으로 기술 블로그를 운영하며, 개발자들이 더 빠르고 효율적으로 서비스를 만들 수 있도록 실용적인 가이드를 지속적으로 공유합니다.

댓글 남기기