ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

2025.02.28 (๊ธˆ) Works

 

1. DB ์—ฐ๊ฒฐํ•˜๊ธฐ

- Tanstack Query

- custom hook

 

 

DB ์—ฐ๊ฒฐํ•˜๊ธฐ

 

๐Ÿ“Tanstack Query

๊ณผ์ œ ํ•„์ˆ˜ ๊ตฌํ˜„ ์‚ฌํ•ญ ์ค‘ ํƒ ์Šคํƒ ์ฟผ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ํ•ญ๋ชฉ์ด ์žˆ๋‹ค.

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—๋Š” supabase, ์นด์นด์˜ค ์ง€๋„ API, ์œ ํŠœ๋ธŒ API ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

์‚ฌ์‹ค ์ „์ฒด์ ์œผ๋กœ CRUD ์ค‘ R ์™ธ์—๋Š” ํฌ๊ฒŒ ๊ธฐ๋Šฅ์ด ์—†๊ธฐ๋„ ํ•˜๊ณ 

supabase์— ๊ฐ’์„ ์ˆ˜์ž‘์—…์œผ๋กœ ๋„ฃ์–ด ์ค€ ๊ณ ์ • ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ํƒ ์Šคํƒ์„ ์–ด๋””์— ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋‚˜ ๊ณ ๋ฏผ์ด ๋˜์—ˆ๋‹ค.

 

์กฐ์›๋ผ๋ฆฌ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆ ๋ณด๋ฉฐ '๊ตณ์ด ์บ์‹ฑ์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์ด ์—†์ง€ ์•Š๋ƒ' ๋Š” ์ด์•ผ๊ธฐ๊ฐ€ ๋‚˜์™”๊ณ  ํŠœํ„ฐ๋‹˜๊ป˜ ์งˆ๋ฌธ์„ ๋“œ๋ ธ๋‹ค.

ํŠœํ„ฐ๋‹˜์˜ ๋ง์”€์— ๋”ฐ๋ฅด๋ฉด

ํƒ ์Šคํƒ์€ ํŠน์ • key(queryKey)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
์ด๋Š” ์บ์‹ฑ๋งŒ์ด ๋ชฉ์ ์ด ์•„๋‹ˆ๋ฉฐ pending๊ณผ error๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๋‹ค : ๋ฐ์ดํ„ฐ ํŒจ์นญ์„ ๊ด€๋ฆฌํ•˜๋Š” ํ›…์— '์บ์‹ฑ'์ด๋ผ๋Š” ๊ธฐ๋Šฅ์ด ๋ถ™์€ ๋А๋‚Œ
์บ์‹ฑ์ด ํ•„์š”์—†๋‹ค๋ฉด staleTime ์ด๋‚˜ gcTime์„ 0์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ์ƒˆ๋กœ๊ณ ์นจ์ด๋‚˜ ํŽ˜์ด์ง€๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กญ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
(ํ™”๋ฉด ๋‚ด๋ถ€์—์„œ์˜ ๋ฆฌ๋ Œ๋”๋ง์ด๋ž‘์€ ๋ฌด๊ด€)

๋‹ค๋งŒ ์นด์นด์˜ค์ง€๋„, ์œ ํŠœ๋ธŒ ํŠนํžˆ ์œ ํŠœ๋ธŒ API๋Š” ํ•˜๋ฃจ์— ์‚ฌ์šฉ ํšŸ์ˆ˜๊ฐ€ ์ œํ•œ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์บ์‹ฑ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋‚˜๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ‘‡๐Ÿป๊ธฐ์–ตํ•ด๋‘๋ฉด ์ข‹์„๋งŒํ•œ ์ž๋ฃŒ

ํŠœํ„ฐ๋‹˜์˜ ๋ง์”€์„ ๋“ฃ๊ณ  supabase, ์นด์นด์˜ค์ง€๋„, ์œ ํŠœ๋ธŒ ์„ธ ๊ณณ ๋ชจ๋‘ ํƒ ์Šคํƒ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

์ตœ์ƒ๋‹จ ํŒŒ์ผ(main.jsx)์—์„œ new QueeryClient ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€

'์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ Tanstack Query ๋กœ ํ•˜๊ฒ ๋‹ค' ๊ณ  ์„ ์–ธ(?) ํ•˜๋Š” ๊ฒƒ์ด๋‚˜ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค ใ…Žใ…Ž

 

๊ทธ๋ ‡๋‹ค๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์„ธ ๊ฐœ์˜ ์„œ๋ฒ„ ์ƒํƒœ๋Š” ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ•ด์„œ ์“ฐ๋‚˜?

๋ฐ”๋กœ queryKey๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์ฃผ์–ด ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด ์ฟผ๋ฆฌํ‚ค์— ๋”ฐ๋ผ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ์บ์‹ฑ, ๋ฆฌํŒจ์นญ, ๋ฌดํšจํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

 

๋‚˜๋Š” ํ•ซํ”Œ ๋ฆฌ์ŠคํŠธ์™€ ๋ถ๋งˆํฌ ํŽ˜์ด์ง€๋ฅผ ๋งก์•˜์œผ๋‹ˆ supabase์˜ 'hotplaces' ํ…Œ์ด๋ธ”์˜ ๊ฐ’๋งŒ ์บ์‹ฑํ•ด์˜ค๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 // HotPlaceList.jsx
 
 // supabase์—์„œ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ
 const HotPlaceList = () => {
    const getHotplaces = async () => {
      const { data, error } = await supabase.from('hotplaces').select('*');
      if (error) {
        throw new Error(error.message);
      }
      return data;
    };
  
  
  // useQuery ์‚ฌ์šฉํ•˜๊ธฐ
    const {
      data: hotplaces = [],
      isPending,
      isError,
    } = useQuery({
      queryKey: ['hotplaces'],
      queryFn: getHotplaces,
    });

    if (isPending) {
      return <div>๋กœ๋”ฉ ์ค‘...</div>;
    }
  
    if (isError) {
      <div>์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.</div>;
    }
  
  };
export default HotPlaceList;

 

 

 

๐Ÿ“custom hook

ํŒ€์›๋“ค๊ณผ ํŒŒ์ผ ๊ตฌ์กฐ๋ฅผ ์ •ํ•  ๋•Œ query๋Š” ํŽ˜์ด์ง€ ์•ˆ์— ๋‘๊ธฐ๋ณด๋‹ค๋Š” ๋ถ„๋ฆฌํ•ด์„œ ๊ด€๋ฆฌํ•˜์ž๋Š” ์ด์•ผ๊ธฐ๊ฐ€ ๋‚˜์™”๋‹ค.

lib ํด๋” > quries ํด๋” ๋‚ด์—์„œ ํŒŒ์ผ๋กœ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

 

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„์— ์ž‘์„ฑํ•œ ๋กœ์ง์„ ์ ์ ˆํžˆ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

๋ฐ”๋กœ ์ปค์Šคํ…€ ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค!

queries ํด๋” ์•ˆ์— ์žˆ๋Š” js ํŒŒ์ผ์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์•„๋‹Œ ์ปค์Šคํ…€ ํ›…์ด๋‹ค.

 

์ด์ „์— ์ปค์Šคํ…€ ํ›…์˜ ๊ธฐ๋ณธ ์›๋ฆฌ์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด ๋‘” ๊ธ€์ด ์žˆ๋‹ค.

custom hook ์ •๋ฆฌ๊ธ€(ํด๋ฆญ)

 

 

์ด๋ฒˆ์— ๋งŒ๋“  ์ปค์Šคํ…€ ํ›…๋„ ๋กœ์ง์„ ๋ณด๋ฉฐ ์ •๋ฆฌํ•ด๋ณด๊ฒ ๋‹ค.

// GetHotplaces.js

import supabase from '@/lib/api/supabaseAPI';
import { useQuery } from '@tanstack/react-query';

export const useGetHotplaces = () => {
  const getHotplaces = async () => {
    const { data, error } = await supabase.from('hotplaces').select('*');
    if (error) {
      throw new Error(error.message);
    }
    return data;
  };

  return useQuery({
    queryKey: ['hotplaces'],
    queryFn: getHotplaces,
  });
};
์šฐ์„  ์ด ํ›…์€ useQuery๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
useQuery๋Š” Key์— ํ•ด๋‹นํ•˜๋Š” ์ด๋ฆ„์œผ๋กœ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ ๊ฐ’์„ ์บ์‹ฑํ•œ๋‹ค.
๋น„๋™๊ธฐ ํ•จ์ˆ˜ getHotplaces๋Š” supabase์—์„œ 'hotplaces' ๋ผ๋Š” ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค.

 

์ฆ‰, ์ด ํ›…์€ supabase์—์„œ ๊ฐ€์ ธ ์˜จ ํ•ซํ”Œ๋ ˆ์ด์Šค์˜ ์ •๋ณด๋ฅผ ์บ์‹ฑํ•œ๋‹ค.

 

 

// HotplaceList.jsx
const HotplaceList = () => {
  const { data: hotplaces = [], isPending, isError } = useGetHotplaces();

  if (isPending) {
    return <div>๋กœ๋”ฉ ์ค‘...</div>;
  }

  if (isError) {
    return <div>์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.</div>;
  }
  
  return(
  ...

์œ„์—์„œ ๋งŒ๋“  ์ปค์Šคํ…€ ํ›…์„ ์ ์šฉ์‹œํ‚ค๋Š” ์ปดํฌ๋„ŒํŠธ์ด๋‹ค.

์ปค์Šคํ…€ ํ›…์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ์บ์‹ฑ๋œ ์ •๋ณด ์ค‘, ์šฐ๋ฆฌ์—๊ฒŒ ํ•„์š”ํ•œ ์„ธ ๊ฐ€์ง€๋ฅผ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์œผ๋กœ ๋ฝ‘์•„๋‚ธ๋‹ค.(data, isPending, isError)

 

data๋Š” hotplaces๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ดˆ๊ธฐ๊ฐ’์„ ๋นˆ ๋ฐฐ์—ด๋กœ ์ง€์ •ํ•œ๋‹ค. ์ด ๋ฐฐ์—ด๋กœ ๋ฆฌ์ŠคํŠธ๋ฅผ mapping ํ•œ๋‹ค.

isPending์€ state๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ผ ๋•Œ return์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

isError๋„ state๋กœ ์—๋Ÿฌ ์ƒํ™ฉ์ผ ๋•Œ return์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

 

+ ๋ฆฌ์ŠคํŠธ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ถ๋งˆํฌ ํŽ˜์ด์ง€๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ปค์Šคํ…€ ํ›…์„ ์ด์šฉํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค.

 

[์ปค์Šคํ…€ ํ›…]

// GetBookmarks.js

import supabase from '../api/supabaseAPI';
import { useQuery } from '@tanstack/react-query';

export const useGetBookmarks = () => {
  const getBookmarks = async () => {
    const { data, error } = await supabase.from('bookmarks').select('*, hotplaces(name, img_url)');
    if (error) {
      throw new Error(error.message);
    }
    return data;
  };

  return useQuery({
    queryKey: ['bookmarks'],
    queryFn: getBookmarks,
  });
};

 

 

[๋ถ๋งˆํฌ ํŽ˜์ด์ง€]

// BookMark.jsx

const BookMark = () => {
  const { data: bookmarkList = [], isPending, isError } = useGetBookmarks();

  if (isPending) {
    return <div>๋กœ๋”ฉ ์ค‘...</div>;
  }

  if (isError) {
    <div>์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.</div>;
    
    return(
    ...

'Project' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[LoL info App_Final] LoL ์ •๋ณด ํŽ˜์ด์ง€  (0) 2025.03.19
[Outsourcing_Final] HotPlace In Seoul ๐Ÿ”ฅ  (1) 2025.03.05
[Outsourcing_Day 2] HotPlace In Seoul ๐Ÿ”ฅ  (0) 2025.03.01
[Outsourcing_Day 1] HotPlace In Seoul ๐Ÿ”ฅ  (0) 2025.02.27
[MBTI-Test PJ_Final] MBTI Test  (0) 2025.02.25
๊ณต์ง€์‚ฌํ•ญ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€
Total
Today
Yesterday
๋งํฌ
TAG
more
ยซ   2026/03   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
๊ธ€ ๋ณด๊ด€ํ•จ