React

 

1. Supabase 프로젝트 생성

https://supabase.com/

 

  1. Supabase에 로그인 후 New Project를 생성합니다.

 

  1. 프로젝트가 생성되면 Project URLanon public API Key를 확인합니다.
    • Settings > API에서 확인 가능
    • 이 값들은 .env.local 파일에 저장할 것입니다.

 

superbase 에  sql Editor  에서 다음과  같이  users 테이블 등록, postsql 이라 대소문자를 인식하려면   따옴표

CREATE TABLE users (
  "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  "email" TEXT UNIQUE NOT NULL,
  "accountType" TEXT NOT NULL, -- "personal" | "company"
  "dob" TIMESTAMP NOT NULL,
  "password" TEXT NOT NULL,
  "name" TEXT,
  "companyName" TEXT,
  "numberOfEmployees" INT,
  "createdAt" TIMESTAMP DEFAULT now(),
  "updatedAt" TIMESTAMP DEFAULT now()
);

-- updated_at 자동 갱신을 위한 트리거 함수 생성
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 트리거 생성: users 테이블의 데이터가 업데이트될 때 updated_at을 자동 변경
CREATE TRIGGER set_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_timestamp();


alter table users add column auth_id uuid references auth.users(id) on delete cascade;

 

. Supabase Auth의 기본 users 테이블과 연결 (선택 사항)

Supabase에는 이미 auth.users 테이블이 존재합니다. 이를 활용하려면 users 테이블과 관계를 맺을 수 있습니다.

alter table users add column auth_id uuid references auth.users(id) on delete cascade;

 

 

 

 

2. Next.js 15 프로젝트에 Supabase 설치

npm install @supabase/supabase-js

또는

pnpm install @supabase/supabase-js

 

 

3. 환경 변수 설정 (.env)

루트 디렉터리에 .env 파일 또는  .env.local 파일을 만들고 다음 정보를 추가하세요.

NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY

 

  • YOUR_SUPABASE_URL → Supabase 대시보드에서 확인한 Project URL
  • YOUR_SUPABASE_ANON_KEY → API 페이지에서 확인한 anon 키

 

 

4. Supabase 클라이언트 설정 (lib/supabaseClient.ts)

프로젝트 루트에 lib/supabaseClient.ts 파일을 만들고 다음 내용을 추가합니다.

 

import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;

export const supabase = createClient(supabaseUrl, supabaseAnonKey);

 

  • createClient를 사용하여 Supabase 인스턴스를 생성합니다.
  • process.env.NEXT_PUBLIC_... 값을 사용하여 환경 변수에서 URL과 키를 가져옵니다.

 

 

5. 사용 예제 - 사용자 로그인 (app/login/page.tsx)

다음과 같이 Supabase를 이용한 로그인 기능을 구현할 수 있습니다.

'use client';

import { useState } from 'react';
import { supabase } from '@/lib/supabaseClient';
import { useRouter } from 'next/navigation';

export default function LoginPage() {
  const router = useRouter();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState<string | null>(null);

  const handleLogin = async () => {
    const { error } = await supabase.auth.signInWithPassword({
      email,
      password,
    });

    if (error) {
      setError(error.message);
    } else {
      router.push('/dashboard');
    }
  };

  return (
    <div className="flex flex-col gap-4 max-w-md mx-auto mt-20">
      <input
        type="email"
        placeholder="이메일"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        className="p-2 border rounded"
      />
      <input
        type="password"
        placeholder="비밀번호"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        className="p-2 border rounded"
      />
      <button onClick={handleLogin} className="bg-blue-500 text-white p-2 rounded">
        로그인
      </button>
      {error && <p className="text-red-500">{error}</p>}
    </div>
  );
}

 

 

 

6. 사용 예제 - 데이터베이스 조회 (app/posts/page.tsx)

Supabase에서 데이터를 조회하고 렌더링하는 방법입니다.

import { supabase } from '@/lib/supabaseClient';

export default async function PostsPage() {
  const { data: posts, error } = await supabase.from('posts').select('*');

  if (error) return <p className="text-red-500">데이터를 불러오는 중 오류가 발생했습니다.</p>;

  return (
    <div className="max-w-2xl mx-auto mt-10">
      <h1 className="text-2xl font-bold mb-4">게시글 목록</h1>
      <ul className="space-y-4">
        {posts?.map((post) => (
          <li key={post.id} className="border p-4 rounded shadow">
            <h2 className="text-xl font-semibold">{post.title}</h2>
            <p className="text-gray-600">{post.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

 

 

7. Next.js 15의 서버 액션과 Supabase 연동

Next.js 15에서는 서버 액션(Server Actions) 기능을 활용할 수 있습니다.


예를 들어, 새로운 게시글을 추가하는 서버 액션을 만들 수 있습니다.

(1) 서버 액션 생성 (app/actions.ts)

'use server';

import { supabase } from '@/lib/supabaseClient';

export async function addPost(title: string, content: string) {
  const { error } = await supabase.from('posts').insert([{ title, content }]);

  if (error) {
    throw new Error(error.message);
  }

  return { success: true };
}

 

(2) 클라이언트에서 서버 액션 호출 (app/posts/page.tsx)

'use client';

import { useState } from 'react';
import { addPost } from '../actions';

export default function NewPostForm() {
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const [error, setError] = useState<string | null>(null);

  const handleSubmit = async () => {
    try {
      await addPost(title, content);
      alert('게시글이 추가되었습니다.');
    } catch (err) {
      setError(err.message);
    }
  };

  return (
    <div className="max-w-md mx-auto">
      <h2 className="text-xl font-bold mb-4">새 게시글 작성</h2>
      <input
        type="text"
        placeholder="제목"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        className="p-2 border rounded w-full mb-2"
      />
      <textarea
        placeholder="내용"
        value={content}
        onChange={(e) => setContent(e.target.value)}
        className="p-2 border rounded w-full mb-2"
      />
      <button onClick={handleSubmit} className="bg-green-500 text-white p-2 rounded w-full">
        추가하기
      </button>
      {error && <p className="text-red-500 mt-2">{error}</p>}
    </div>
  );
}

 

 

8. Supabase 인증 보호된 페이지 설정

Supabase의 auth.getUser()를 사용해 로그인된 사용자만 특정 페이지를 볼 수 있도록 설정할 수 있습니다.

import { supabase } from '@/lib/supabaseClient';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const { data: user } = await supabase.auth.getUser();

  if (!user) {
    redirect('/login');
  }

  return <p>환영합니다, {user.email}님!</p>;
}

 

 

 

 

 

Prisma와 함께 사용하려면 Prisma Schema 변경

만약 Prisma와 함께 Supabase를 사용하려면 schema.prisma에서 PostgreSQL을 사용하도록 변경하세요.

 

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL") // Supabase의 DATABASE_URL 사용
}

model User {
  id                String  @id @default(uuid())
  email             String  @unique
  accountType       String
  dob               DateTime
  password          String
  name              String?
  companyName       String?
  numberOfEmployees Int?
  createdAt         DateTime @default(now())
  updatedAt         DateTime @updatedAt
}

 

 

Prisma를 다시 적용하려면 다음 명령어를 실행하세요.

npx prisma migrate dev --name init


 

 

 

  • Supabase는 기본적으로 auth.users 테이블을 제공하지만, 추가 필드가 필요하면 users 테이블을 만들어야 함

 

  • SQL을 이용해 users 테이블을 생성하고 필요하면 auth.users와 연결 가능

 

  • Prisma를 사용한다면 PostgreSQL을 지원하도록 설정 변경 필요

 

 

 

 

about author

PHRASE

Level 60  라이트

주역(周易)의 이치를 깨닫고 이것을 본받을 만한 사람이 아니라면 주역의 도(道)는 제 스스로 헛되게 행해지는 것은 아니다. 적당한 사람을 얻지 못하면 어떤 일이라도 그것만이 잘되어 갈 수는 없다는 말. -역경

댓글 ( 0)

댓글 남기기

작성