Better Auth로 웹 앱에 인증 기능을 추가하는 방법

인증은 거의 모든 웹 애플리케이션의 핵심 기능입니다. SaaS 제품, 개인 프로젝트, 내부 도구 중 무엇을 만들든 사용자 로그인 기능은 대부분 필요합니다.
하지만 인증을 처음부터 직접 구현하는 것은 쉽지 않습니다. 비밀번호 해싱, 세션 관리, OAuth 흐름, 토큰 갱신 등 문제가 발생하기 쉬운 부분이 많습니다. 인증은 중요하지만, 앱을 차별화하는 기능은 아닙니다. 다른 곳에 시간을 투자하고 싶을 것입니다.
이럴 때 Better Auth가 도움이 됩니다.
Better Auth는 웹 애플리케이션의 인증을 간소화하기 위해 설계된 TypeScript 기반의 인증 라이브러리입니다.
유연성, 이식성, 개발자 친화적인 API에 중점을 둡니다:
- 프레임워크 독립적: SvelteKit, Next.js, Nuxt, Express 등 다양한 프레임워크와 통합 가능
- 소셜 로그인 제공자 내장: Google, GitHub, Discord, Twitter 등 주요 OAuth 제공자 지원
- 간단한 API: 일반적인 인증 시나리오에 대해 최소한의 설정으로 사용 가능
- 플랫폼 종속 없음: 데이터베이스에 구애받지 않으며 다양한 플랫폼에 배포 가능
이 가이드에서는 Better Auth를 SvelteKit에 통합하는 방법을 설명합니다. 완료하면 소셜 로그인을 지원하는 인증 시스템을 갖추게 됩니다.
SvelteKit과 통합하기
1. 설치 및 설정
먼저 새로운 SvelteKit 프로젝트를 생성합니다(기존 프로젝트를 사용해도 됩니다):
npx sv create my-app
cd my-appBetter Auth를 설치합니다:
npm install better-auth다음으로 환경 변수를 설정합니다. 프로젝트 루트 디렉토리에 .env 파일을 생성합니다:
# Better Auth Secret Key
BETTER_AUTH_SECRET=your-better-auth-secret
# GitHub OAuth
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secretBETTER_AUTH_SECRET 을 생성하려면 터미널에서 다음 명령을 실행합니다:
openssl rand -base64 32OAuth 자격 증명 얻는 방법:
- GitHub: GitHub Developer Settings에서 새로운 OAuth App 생성
- Google: Google Cloud Console에서 프로젝트를 생성하고 OAuth 2.0 자격 증명 설정
콜백 URL을 http://localhost:5173/api/auth/callback/github (Google의 경우 /google )로 설정합니다.
2. 서버 설정
서버에서 auth 인스턴스를 생성합니다. 여기서 제공자와 설정을 정의합니다.
src/lib/server/auth.ts 를 생성합니다:
import { betterAuth } from 'better-auth';
import { env } from '$env/dynamic/private';
export const auth = betterAuth({
secret: env.BETTER_AUTH_SECRET,
socialProviders: {
github: {
clientId: env.GITHUB_CLIENT_ID as string,
clientSecret: env.GITHUB_CLIENT_SECRET as string
},
google: {
clientId: env.GOOGLE_CLIENT_ID as string,
clientSecret: env.GOOGLE_CLIENT_SECRET as string
}
}
});다음으로 API 라우트 핸들러를 생성합니다. Better Auth는 캐치올 라우트를 사용하여 모든 인증 관련 요청을 처리합니다.
src/routes/api/auth/[...all]/+server.ts 를 생성합니다:
import { auth } from '$lib/server/auth';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ request }) => {
return auth.handler(request);
};
export const POST: RequestHandler = async ({ request }) => {
return auth.handler(request);
};서버 측 설정은 여기까지입니다. Better Auth가 이제 /api/auth/* 라우트를 자동으로 처리합니다.
3. 클라이언트 설정
Svelte 컴포넌트에서 사용할 auth 클라이언트를 생성합니다.
src/lib/auth-client.ts 를 생성합니다:
import { createAuthClient } from 'better-auth/svelte';
export const authClient = createAuthClient();클라이언트는 인증 엔드포인트를 자동으로 감지합니다. 이제 앱 어디서든 authClient 를 사용하여 로그인과 로그아웃을 실행할 수 있습니다.
4. 소셜 로그인 구현
먼저 src/hooks.server.ts 를 생성하여 모든 요청에서 사용자 세션을 가져옵니다:
import { auth } from '$lib/server/auth';
import type { Handle } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve }) => {
const session = await auth.api.getSession({
headers: event.request.headers
});
event.locals.session = session;
return resolve(event);
};locals 에 대한 타입 정의를 추가합니다. src/app.d.ts 를 업데이트합니다:
import type { auth } from '$lib/server/auth';
declare global {
namespace App {
interface Locals {
session: typeof auth.$Infer.Session | null;
}
}
}
export {};이제 세션 데이터를 모든 페이지에 전달하는 layout server load 함수를 생성합니다.
src/routes/+layout.server.ts 를 생성합니다:
import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = async ({ locals }) => {
return {
session: locals.session
};
};로그인 페이지를 만듭니다. src/routes/login/+page.svelte 를 생성합니다:
<script lang="ts">
import { authClient } from '$lib/auth-client';
const signInWithGitHub = async () => {
await authClient.signIn.social({
provider: 'github',
callbackURL: '/'
});
};
const signInWithGoogle = async () => {
await authClient.signIn.social({
provider: 'google',
callbackURL: '/'
});
};
</script>
<div class="login-container">
<h1>Sign In</h1>
<button onclick={signInWithGitHub}>Continue with GitHub</button>
<button onclick={signInWithGoogle}>Continue with Google</button>
</div>사용자 정보 표시와 로그아웃 처리를 위해 layout 컴포넌트를 업데이트합니다. src/routes/+layout.svelte 를 편집합니다:
<script lang="ts">
import { authClient } from '$lib/auth-client';
let { data, children } = $props();
const signOut = async () => {
await authClient.signOut();
};
</script>
<header>
{#if data.session}
<p>Welcome, {data.session.user.name}!</p>
<button onclick={signOut}>Sign Out</button>
{:else}
<a href="/login">Sign In</a>
{/if}
</header>
<main>
{@render children()}
</main>이 방식은 SSR 친화적입니다. 세션 데이터는 페이지 로드 시 즉시 사용할 수 있으며, 인증되지 않은 콘텐츠의 깜빡임이 발생하지 않습니다.
5. 라우트 보호
특정 라우트를 보호하려면 src/hooks.server.ts 를 업데이트하여 페이지 렌더링 전에 인증을 확인합니다:
import { auth } from '$lib/server/auth';
import { redirect, type Handle } from '@sveltejs/kit';
const protectedRoutes = ['/dashboard', '/settings', '/profile'];
export const handle: Handle = async ({ event, resolve }) => {
const session = await auth.api.getSession({
headers: event.request.headers
});
event.locals.session = session;
const isProtected = protectedRoutes.some((route) => event.route.id?.startsWith(route));
if (isProtected && !session) {
throw redirect(303, '/login');
}
return resolve(event);
};이제 /dashboard , /settings , /profile 로 시작하는 모든 라우트는 인증되지 않은 사용자를 로그인 페이지로 리다이렉트합니다.
6. 데이터베이스 (선택 사항)
기본적으로 Better Auth는 세션을 메모리에 저장합니다. 개발 환경에서는 문제없지만, 프로덕션 환경에서는 서버 재시작 후에도 사용자 데이터를 유지하기 위해 데이터베이스가 필요합니다.
Better Auth는 Prisma, Drizzle, MongoDB 등 여러 데이터베이스 어댑터를 지원합니다.
Prisma를 사용한 예시입니다:
import { betterAuth } from 'better-auth';
import { prismaAdapter } from 'better-auth/adapters/prisma';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: 'sqlite', // or mysql, postgresql
}),
socialProviders: {
// ... your providers
}
});전체 데이터베이스 설정 방법은 Better Auth 데이터베이스 문서를 참조하세요.
빠른 시작 템플릿
빠르게 시작하고 싶다면, 모든 설정이 완료된 SvelteKit + Better Auth 템플릿을 준비했습니다:
- GitHub, Google, Discord, Slack, Vercel OAuth 설정 완료
- SSR 지원 세션 관리
- 라우트 보호 예제
- 환경 변수 템플릿
결론
인증 추가가 복잡할 필요는 없습니다. Better Auth와 SvelteKit을 사용하면 1시간 이내에 완전한 소셜 로그인 시스템을 구축할 수 있습니다.
이 가이드에서 다룬 내용:
- SvelteKit 프로젝트에서 Better Auth 설정
- Google 및 GitHub OAuth 제공자 설정
- 로그인/로그아웃 기능 구현
- server hooks를 사용한 라우트 보호
- 프로덕션을 위한 데이터베이스 설정 (선택 사항)
더 빠르게 시작하고 싶다면 템플릿을 사용하여 원클릭으로 배포하세요.