YouTube Live 클론을 Next.js, Clerk, TailwindCSS로 구축하기 - Part One

발행: (2025년 12월 13일 오전 02:56 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

실시간 스트리밍 플랫폼이 수천 명의 시청자에게 실시간 비디오를 어떻게 전송하는지 궁금하셨나요?
이 두 파트 시리즈에서는 Next.js, TailwindCSS, 그리고 Stream을 사용해 YouTube Live 클론을 만드는 방법을 배웁니다. TailwindCSS로 UI를 만들고, Clerk으로 인증을 설정하며, Prisma를 사용해 앱 데이터를 모델링하고 영구 저장합니다. 이후 Stream Video 및 Audio SDK를 통합해 라이브스트리밍을 구현하고, Stream Chat SDK를 이용해 각 스트림에 실시간 채팅을 추가합니다. 최종적으로 YouTube Live의 핵심 기능을 그대로 구현한 작동하는 앱을 만들 수 있습니다.

첫 번째 파트에서는 프로젝트를 설정하고, 인증을 추가하며, 홈 페이지를 구축합니다. 라이브 데모를 확인하고 전체 소스 코드는 GitHub에서 확인할 수 있습니다.

Prerequisites

  • React에 대한 기본 이해
  • Node.js와 npm이 설치되어 있음
  • TypeScript, Next.js, TailwindCSS에 익숙함

Setting up the Next.js Project

# Clone the repository
git clone https://github.com/TropicolX/youtube-live-clone.git

# Navigate into the project directory
cd youtube-live-clone

# Check out the starter branch
git checkout starter

# Install the dependencies
npm install

Setting Up the Database

개발 환경에서는 Prisma와 SQLite를 사용합니다.

npm install prisma@6.19.0 --save-dev
npm install @prisma/client@6.19.0 sqlite3

Prisma 초기화:

npx prisma init

prisma/schema.prisma 파일을 수정:

datasource db {
  provider = "sqlite"
  url      = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

model Subscription {
  subscriberId String
  channelId    String
  createdAt    DateTime @default(now())
  @@id([subscriberId, channelId])
}

enum ReactionType {
  LIKE
  DISLIKE
}

model Reaction {
  userId        String
  livestreamId  String
  type          ReactionType
  createdAt     DateTime @default(now())
  @@id([userId, livestreamId])            // one reaction per user per livestream
  @@index([livestreamId, type])           // fast counts per type
}

Configuring the Database Connection

.env에 추가:

DATABASE_URL=file:./dev.db

마이그레이션을 실행하고 클라이언트를 생성:

npx prisma migrate dev --name init
npx prisma generate

lib/prisma.ts 파일 생성:

import { PrismaClient } from '@prisma/client';

let prisma: PrismaClient;

if (process.env.NODE_ENV === 'production') {
  prisma = new PrismaClient();
} else {
  // @ts-expect-error global.prisma is used in development
  if (!global.prisma) {
    // @ts-expect-error global.prisma is used in development
    global.prisma = new PrismaClient();
  }
  // @ts-expect-error global.prisma is used in development
  prisma = global.prisma;
}

export default prisma;

User Authentication with Clerk

What is Clerk?

Clerk는 사용자 관리, 인증, 프로필 처리를 바로 제공하는 서비스입니다.

Setting Up a Clerk Account

  1. Clerk 웹사이트에서 회원가입합니다.
  2. 대시보드에서 Create application을 클릭합니다.
  3. 이름을 “Youtube Live Clone”으로 지정합니다.
  4. “Email”, “Username”, “Google” 로그인 옵션을 활성화합니다.
  5. 애플리케이션을 저장하고 Publishable KeySecret Key를 기록해 둡니다.

Configuring Required User Fields

  1. Configure 탭 → User model로 이동합니다.
  2. “Require first and last name”을 활성화합니다.
  3. 변경 사항을 저장합니다.

Installing Clerk in Your Project

npm install @clerk/nextjs

.env.local 파일 생성:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up

위의 자리표시자를 Clerk 앱에서 발급받은 키 값으로 교체합니다.

app/layout.tsx (또는 새로운 App Router를 사용하는 경우 app/layout.tsx)를 업데이트:

import type { Metadata } from 'next';
import { ClerkProvider } from '@clerk/nextjs';
import './globals.css';

export const metadata: Metadata = {
  title: 'YouTube Live clone',
  description: 'A YouTube Live clone built with Next.js and Stream.',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ClerkProvider>
      {children}
    </ClerkProvider>
  );
}

Creating the Sign‑Up and Sign‑In Pages

app/sign-up/[[...sign-up]]/page.tsx에 회원가입 페이지를 생성:

'use client';
import { SignUp } from '@clerk/nextjs';

export default function Page() {
  return (
    <SignUp />
  );
}

app/sign-in/[[...sign-in]]/page.tsx에 로그인 페이지를 생성 (구조는 동일하며 SignIn 사용):

'use client';
import { SignIn } from '@clerk/nextjs';

export default function Page() {
  return (
    <SignIn />
  );
}

이제 Clerk가 앱 전반에 걸쳐 인증 UI와 로직을 처리합니다.

Back to Blog

관련 글

더 보기 »