이전 글
이전 글에서 Next 프로젝트와 Supabase 프로젝트를 생성하고, 두 프로젝트를 연결해 보았어요.
그리고 Supabase의 데이터를 Next에서 러프하게 노출시켰습니다.
정말 데이터를 그대로 노출한 것이라서 아직 페이지라는 느낌이 안들죠. 😅
이번 글에서는 할 일 목록 UI 추가해보려고 합니다.
할 일 목록 구현하기
UI 구현
우선은 할 일을 확인할 수 있는 목록 UI를 구현해봅시다!
지난 글에서 생성했던 `src/app/todos/page.tsx` 파일을 아래와 같이 수정했습니다.
스타일링은 초기 설정할 때 함께 설치한 `tailwind`를 사용했어요.
"use client";
export default function Todos() {
// 더미데이터!
const todos = [
"할 일 목록 구현하기",
"할 일 추가 기능 구현하기",
"할 일 완료 기능 구현하기",
];
return (
<div className="w-screen h-screen flex justify-center items-center">
<section className="w-[400px] p-[30px] rounded-lg bg-gray-400 bg-opacity-10">
<h2 className="text-2xl font-bold mb-4">TO DO</h2>
<ul>
{todos.map((todo) => (
<li className="px-[10px] text-lg leading-8" key={todo}>
{todo}
</li>
))}
</ul>
</section>
</div>
);
}
간단하게 todos 배열을 노출시키는 UI를 완성했습니다.
(정말 간단한 UI죠? ㅎ)
타입 정의
이전 글에서 다음과 같이 테이블을 생성했었어요.
이름 | 설명 | 타입 | 기본값 | 빈 값 허용 여부 |
id | 고유 id (primary) | int8 | 자동생성 | X |
createdAt | 생성한 날짜 | timestamptz | now() | X |
contents | 할 일 내용 | text | - | X |
isDone | 완료 여부 | bool | false | X |
이 테이블에 맞게 Next에서도 Todo 객체의 타입을 정의해줍시다!
`src/types/todo.ts` 파일을 생성하고 아래와 같이 타입정의를 해주었습니다.
// src/types/todo.ts
export interface Todo {
id: number;
createdAt: string;
contents: string;
isDone: boolean;
}
다시 `src/app/todos/page.tsx` 파일로 돌아가서 todos 배열의 타입을 정의하고,
타입에 맞게 데이터를 수정해줍시다.
// src/app/todos/pages.tsx
"use client";
import { Todo } from "@/types/todo";
export default function Todos() {
// 더미데이터!
const todos: Todo[] = [
{
id: 1,
createdAt: new Date().toString(),
contents: "할 일 목록 구현하기",
isDone: false,
},
{
id: 2,
createdAt: new Date().toString(),
contents: "할 일 추가 기능 구현하기",
isDone: false,
},
{
id: 3,
createdAt: new Date().toString(),
contents: "할 일 완료 기능 구현하기",
isDone: false,
},
];
return (
<div className="w-screen h-screen flex justify-center items-center">
<section className="w-[400px] p-[30px] rounded-lg bg-gray-400 bg-opacity-10">
<h2 className="text-2xl font-bold mb-4">TO DO</h2>
<ul>
<!-- key값은 고유한 todo.id -->
{todos.map((todo) => (
<li className="px-[10px] text-lg leading-8" key={todo.id}>
<!-- 할 일 콘텐츠 노출 -->
{todo.contents}
</li>
))}
</ul>
</section>
</div>
);
}
API 선언 및 호출
더미데이터를 사용했었으니,
이번에는 supabase에 저장된 실제 데이터를 가져와봅시다!
1. Next API route 선언하기
`src/app/api/todo/route.ts` 파일을 생성하고,
다음과 같이 코드를 작성해줍니다.
// src/app/api/todos/route.ts
import { createClient } from "@/utils/supabase/server";
import { NextResponse } from "next/server";
export async function GET() {
const supabase = createClient();
const { data, error } = await supabase.from("todos").select("*");
return NextResponse.json({ data, error });
}
supabase의 todos 테이블의 데이터를 불러오고,
그 데이터를 Response 해주는 API입니다.
중요한 것은 폴더 구조입니다.
`api/todos/route.ts` 로 선언한 후 함수명을 `GET`으로 했다면,
`GET {도메인}/api/todos` 호출했을 때 위의 응답을 반환해줍니다.
2. API 호출하기
그러면 다시 UI 페이지로 돌아가서 생성한 API를 호출해봅시다!
// src/app/todos/page.tsx
"use client";
import { Todo } from "@/types/todo";
import { useEffect, useState } from "react";
export default function Todos() {
const [todos, setTodos] = useState<Todo[]>([]);
const loadTodos = async () => {
// 위에서 선언한 GET /api/todos 호출!
const response = await fetch("/api/todos", { method: 'GET' });
const { data } = await response.json();
setTodos(data);
};
useEffect(() => {
loadTodos();
}, []);
return (
<div className="w-screen h-screen flex justify-center items-center">
<section className="w-[400px] p-[30px] rounded-lg bg-gray-400 bg-opacity-10">
<h2 className="text-2xl font-bold mb-4">TO DO</h2>
<ul>
{todos.map((todo) => (
<li className="px-[10px] text-lg leading-8" key={todo.id}>
{todo.contents}
</li>
))}
</ul>
</section>
</div>
);
}
supabase에 저장되어있던 데이터를 불러오는데 성공했습니다!
데이터가 너무 없으니 데이터 몇 개만 더 추가해볼게요!
3. 데이터 추가하기
이렇게 데이터를 추가하고 다시 새로고침 해보면
추가된 데이터도 잘 보입니다.
이제 데이터 할 일 목록 구현이 완료되었습니다! 🎉
'개발 > Next' 카테고리의 다른 글
[Next14] 검색 기능 만들기 with Supabase (0) | 2024.11.04 |
---|---|
[Next14] To Do List 만들기 with Supabase (1) 프로젝트 세팅 (0) | 2024.07.07 |
[Next14] 페이지와 레이아웃 : Pages and Layouts (0) | 2024.05.26 |
[Next14] 라우트 정의하기 : Defining Routes (0) | 2024.05.26 |
[Next14] 라우팅 기초 : Routing Fundamentals (0) | 2024.05.26 |