본문 바로가기
카테고리 없음

[supabase][vue] 포트폴리오 사이트 데이터 베이스 설계

by Or0i쿠 2025. 8. 8.

테이블명: projects

포함될 컬럼:

  • 프로젝트이름: project_name
  • 개발환경: development_environment
  • 프로젝트 기간: project_duration
  • url: project_url
  • 깃허브 url: github_url
  • 프로젝트 설명: description
  • 코멘트: comments

1. Supabase 대시보드에서 projects 테이블 생성하기

순서:

  1. Supabase 대시보드 접속 후 해당 프로젝트로 이동합니다.
  2. 왼쪽 사이드바에서 Table Editor (테이블 에디터) 아이콘을 클릭합니다.
  3. 화면 중앙 또는 상단의 + New table (새 테이블) 버튼을 클릭합니다.

테이블 설정 (New table 팝업창):

  • Name: projects 입력
  • Description: (선택 사항) 사용자의 포트폴리오 프로젝트 정보를 저장합니다. 입력
  • Schema: public (기본값)
  • Enable Row Level Security (RLS): 체크된 상태 그대로 유지합니다. (매우 중요!)

컬럼(Column) 추가:

이제 아래 명세에 따라 + Add Column 버튼을 눌러 각 컬럼을 추가합니다.

컬럼 이름 (Name)데이터 타입 (Type)기본값 (Default Value)기본 키 (Is Primary Key)NULL 허용 (Is Nullable)고유값 (Is Unique)설명 (비고)

             
id uuid gen_random_uuid() (함수 선택) ✓ (체크) X (체크 해제) X (체크 해제) 테이블의 고유 식별자
project_name text (비워둠) X X X 프로젝트의 이름 (필수)
development_environment text (비워둠) X X X React, Vue, Next.js 등 개발 환경 (필수)
project_duration text (비워둠) X X X 프로젝트 기간 (예: 2023.01 ~ 2023.03)
project_url text (비워둠) X ✓ (체크) X 배포된 프로젝트 URL (선택 사항)
github_url text (비워둠) X ✓ (체크) X GitHub 저장소 URL (필수)
description text (비워둠) X ✓ (체크) X 프로젝트 상세 설명 (필수)
comments text (비워둠) X ✓ (체크) X 기타 코멘트 (선택 사항)
             

 Project 인터페이스 TypeScript 정의

// src/types/supabase.ts 

/**
 * Supabase 'projects' 테이블의 데이터 구조를 정의
 */
export interface Project {
  id: string; 
  project_name: string;
  development_environment: string[];
  project_duration: string;
  project_url: string | null;
  github_url: string;
  description: string;
  comments: string[] | null;

  // --- 새로 추가된 배열 타입 컬럼 ---
  additional_urls: string[] | null; // 기타 URL들 (문자열 배열 혹은 null)
  // --- 새로 추가된 배열 타입 컬럼 ---
}

/**
 * 프로젝트 생성 또는 업데이트 시 필요한 데이터를 정의하는 타입
 */
export type NewProject = Omit<Project, 'id' | 'created_at'>;

/**
 * Supabase에서 데이터를 조회할 때 반환될 수 있는 모든 테이블의 타입을 모아둔 Database
 */
export type Database = {
  public: {
    Tables: {
      projects: {
        Row: Project;
        Insert: Omit<Project, 'id' | 'created_at'>;
        Update: Partial<Omit<Project, 'id' | 'created_at'>>;
      };
    };
  };
};

TypeScript 정의 활용 예시

더보기
import { supabase } from '@/lib/supabaseClient'; // Supabase 클라이언트 초기화 파일
import type { Project, NewProject } from '@/types/supabase';

// 프로젝트 목록 가져오기
async function fetchProjects(): Promise<Project[] | null> {
  const { data, error } = await supabase
    .from('projects')
    .select('*')
    .order('created_at', { ascending: false }); // 최신순 정렬

  if (error) {
    console.error('프로젝트 조회 중 오류 발생:', error.message);
    return null;
  }
  return data as Project[]; // 가져온 데이터를 Project 타입으로 캐스팅
}

// 새 프로젝트 추가하기
async function addProject(newProjectData: NewProject): Promise<Project | null> {
  const { data, error } = await supabase
    .from('projects')
    .insert([newProjectData])
    .select() // 삽입된 데이터 반환받기
    .single(); // 단일 객체로 받기

  if (error) {
    console.error('프로젝트 추가 중 오류 발생:', error.message);
    return null;
  }
  return data as Project;
}

// 사용 예시
async function runExample() {
  // 프로젝트 가져오기
  const myProjects = await fetchProjects();
  if (myProjects) {
    console.log('내 프로젝트 목록:', myProjects);
  }

import { supabase } from '@/lib/supabaseClient';
import type { Project, NewProject } from '@/types/supabase';

// 새 프로젝트 추가 예시
const projectToAdd: NewProject = {
  project_name: '나의 포트폴리오 사이트',
  development_environment: ['Nuxt 4', 'Vue 3', 'TypeScript', 'Tailwind CSS', 'Supabase'],
  project_duration: '2024.07 ~ 2024.08',
  project_url: 'https://my-portfolio.com',
  github_url: 'https://github.com/jey/my-portfolio',
  description: '개인 역량과 프로젝트 경험을 보여주는 포트폴리오 사이트입니다.',
  comments: ['이 프로젝트를 통해 Supabase 연동 경험을 쌓았습니다.', '반응형 디자인에 중점을 두었습니다.'],
  additional_urls: [ // 여기에 기타 URL들을 배열로!
    'https://notion.so/my-portfolio-planning',
    'https://figma.com/my-portfolio-design'
  ],
};

// addProject(projectToAdd); // 이 함수를 호출하여 데이터 삽입

 

<script setup lang="ts">
defineProps<{
  name: string;
  description: string | null;
  project_url: string | null;
  github_url: string | null;
  development_environment: string[] | null;
}>();
</script>

<template>
  <div class="rounded-lg border p-4 hover:shadow">
    <h3 class="text-lg font-semibold">{{ name }}</h3>
    <p class="mt-2 text-sm text-gray-600" v-if="description">{{ description }}</p>
    <div class="mt-3 flex flex-wrap gap-2" v-if="development_environment?.length">
      <span class="rounded bg-gray-100 px-2 py-0.5 text-xs" v-for="tag in development_environment" :key="tag">{{ tag }}</span>
    </div>
    <div class="mt-3 flex gap-3 text-sm">
      <a v-if="project_url" :href="project_url" target="_blank" class="text-blue-600 hover:underline">Demo</a>
      <a v-if="github_url" :href="github_url" target="_blank" class="text-blue-600 hover:underline">GitHub</a>
    </div>
  </div>
</template>