Choorai
Lv.2 React

Clerk 인증 가이드

Clerk은 React 앱에 가장 쉽게 인증을 추가할 수 있는 서비스입니다. 10분 만에 로그인/회원가입 기능을 완성할 수 있습니다.

왜 Clerk인가요?

  • React에 최적화된 컴포넌트와 훅 제공
  • 소셜 로그인 (Google, GitHub 등) 기본 지원
  • 무료 티어: 월 10,000 MAU
  • UI 컴포넌트 커스터마이징 가능

1Clerk 프로젝트 설정

  1. clerk.com 에서 무료 계정 생성
  2. Create application 클릭
  3. 앱 이름 입력 (예: My React App)
  4. 로그인 방식 선택 (Email, Google, GitHub 등)
  5. API Keys에서 Publishable key 복사

2React 앱 연동

패키지 설치

터미널
npm install @clerk/clerk-react

환경 변수 설정

.env.local
# .env.local
VITE_CLERK_PUBLISHABLE_KEY=pk_test_xxx...

ClerkProvider 설정

main.tsx
// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ClerkProvider } from '@clerk/clerk-react';
import App from './App';
import './index.css';

const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY;

if (!PUBLISHABLE_KEY) {
  throw new Error('Missing Publishable Key');
}

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <ClerkProvider publishableKey={PUBLISHABLE_KEY}>
      <App />
    </ClerkProvider>
  </React.StrictMode>
);

환경 변수 주의

Vite를 사용하는 경우 환경 변수 이름이 VITE_로 시작해야 합니다. Next.js는 NEXT_PUBLIC_을 사용합니다.

3인증 UI 컴포넌트

Clerk은 바로 사용할 수 있는 UI 컴포넌트를 제공합니다.

components/AuthButtons.tsx
// components/AuthButtons.tsx
import {
  SignedIn,
  SignedOut,
  SignInButton,
  SignUpButton,
  UserButton,
} from '@clerk/clerk-react';

export function AuthButtons() {
  return (
    <div className="flex items-center gap-4">
      <SignedOut>
        <SignInButton mode="modal">
          <button className="px-4 py-2 bg-blue-600 text-white rounded-lg">
            로그인
          </button>
        </SignInButton>
        <SignUpButton mode="modal">
          <button className="px-4 py-2 border border-gray-300 rounded-lg">
            회원가입
          </button>
        </SignUpButton>
      </SignedOut>
      <SignedIn>
        <UserButton afterSignOutUrl="/" />
      </SignedIn>
    </div>
  );
}

주요 컴포넌트

  • SignedIn - 로그인된 상태에서만 표시
  • SignedOut - 로그아웃된 상태에서만 표시
  • UserButton - 프로필 드롭다운 메뉴
  • SignInButton - 로그인 버튼/모달
  • SignUpButton - 회원가입 버튼/모달

4보호된 라우트 구현

로그인이 필요한 페이지를 보호하려면 ProtectedRoute 컴포넌트를 만듭니다.

components/ProtectedRoute.tsx
// components/ProtectedRoute.tsx
import { SignedIn, SignedOut, RedirectToSignIn } from '@clerk/clerk-react';

interface ProtectedRouteProps {
  children: React.ReactNode;
}

export function ProtectedRoute({ children }: ProtectedRouteProps) {
  return (
    <>
      <SignedIn>{children}</SignedIn>
      <SignedOut>
        <RedirectToSignIn />
      </SignedOut>
    </>
  );
}

5사용자 정보 접근

useUser 훅으로 현재 로그인한 사용자 정보에 접근할 수 있습니다.

components/UserProfile.tsx
// components/UserProfile.tsx
import { useUser } from '@clerk/clerk-react';

export function UserProfile() {
  const { isLoaded, isSignedIn, user } = useUser();

  if (!isLoaded) {
    return <div>로딩 중...</div>;
  }

  if (!isSignedIn) {
    return <div>로그인이 필요합니다</div>;
  }

  return (
    <div className="p-4 bg-white rounded-lg shadow">
      <img
        src={user.imageUrl}
        alt={user.fullName || '프로필'}
        className="w-16 h-16 rounded-full"
      />
      <h2 className="mt-2 text-lg font-bold">{user.fullName}</h2>
      <p className="text-gray-600">{user.primaryEmailAddress?.emailAddress}</p>
    </div>
  );
}

6백엔드 API 연동 (선택)

백엔드 API를 호출할 때 인증 토큰을 포함하려면 useAuth 훅을 사용합니다.

hooks/useAuthenticatedFetch.ts
// hooks/useAuthenticatedFetch.ts
import { useAuth } from '@clerk/clerk-react';

export function useAuthenticatedFetch() {
  const { getToken } = useAuth();

  return async (url: string, options: RequestInit = {}) => {
    const token = await getToken();

    return fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
    });
  };
}

// 사용 예시
// const authFetch = useAuthenticatedFetch();
// const data = await authFetch('/api/projects');

백엔드에서 토큰 검증

server.js
// 백엔드 (Node.js/Express 예시)
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node';

// 미들웨어로 토큰 검증
app.get('/api/protected',
  ClerkExpressRequireAuth(),
  (req, res) => {
    // req.auth.userId로 사용자 ID 접근 가능
    res.json({ userId: req.auth.userId });
  }
);

언제 Clerk을 선택할까요?

Clerk 추천

  • React/Next.js 프로젝트
  • 빠른 인증 구현이 필요할 때
  • 소셜 로그인이 필요할 때
  • UI 커스터마이징이 중요할 때

다른 선택지 고려

  • Next.js만 사용 → NextAuth
  • Supabase 사용 중 → Supabase Auth
  • 엔터프라이즈 요구사항 → Auth0

다음 단계

마지막 업데이트: 2026년 2월 22일 · 버전: v0.0.1

피드백 보내기

입력한 내용으로 새 이슈 페이지를 엽니다.

GitHub 이슈로 보내기