🐨CoalaCoding
DocsExamplesTry itBoardB반B반
🐨CoalaCoding

개발자를 위한 한국어 웹 기술 문서

문서

  • JavaScript
  • Web Publishing
  • React
  • Python

커뮤니티

  • 게시판
  • 예제 모음
  • Try it 에디터

기타

  • GitHub
  • 관리자
© 2026 CoalaCoding. All rights reserved.
  • 1-supabase기초
  • 2-oauthnext설치
  • 3-oauthsupabase설정
  • 4-프로필테이블생성인증연동
  • 5-reactquery설정
  • 6-logout
  1. 홈
  2. 문서
  3. JavaScript
  4. Supabase & Next.js
  5. 5-reactquery설정

5-reactquery설정

코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.

구문

1-TanStackQuery설치

1-1-패키지설치

  1. https://tanstack.com/query/latest/docs/framework/react/installation 이동
  2. 설치 npm i @tanstack/react-query

1-2-파일생성

  1. next-with-supabase\components\query-provider.tsx 파일생성

  1. QueryPrivider 컴포넌트 작성
'use client';
import {QueryClient,QueryClientProvider} from '@tanstack/react-query';
import React, {ReactNode, useState} from 'react';

const QueryProvider = ({children}: {children: ReactNode}) => {
  const [queryClient] = useState(
    () =>
      new QueryClient({
        defaultOptions: {queries: {staleTime: Infinity}},
      })
  );
  return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
};
export default QueryProvider;

1-3-devtool 설치

  1. https://tanstack.com/query/latest/docs/framework/react/devtools#devtools
  2. npm i @tanstack/react-query-devtools
  3. 문서대로 따라한다. https://tanstack.com/query/latest/docs/framework/react/devtools#floating-mode
import { ReactQueryDevtools } from '@tanstack/react-query-devtools’
    <QueryClientProvider client={queryClient}>
      {children}
**      <ReactQueryDevtools initialIsOpen={false} />**
    </QueryClientProvider>

1-4-Provider컴포넌트 적용

1-4-1-Layout.tsx

  1. next-with-supabase\app\layout.tsx
  2. ThemeProvider를 QueryPrivider 컴포넌트로 래핑한다

  1. 개발서버실행

2-사용자정보

2-1-Layout.tsx

  1. next-with-supabase\app\layout.tsx
  2. children을 main으로 래핑한다

2-2-Navbar.tsx

  1. next-with-supabase\components\Navbar.tsx 생성
import React from 'react';

const Navbar = () => {
  return (
    <>
      <div>Navbar</div>
    </>
  );
};
export default Navbar;

  1. next-with-supabase\app\layout.tsx

children 전에 적용한다

  1. 확인

  1. Navbar 이어서 코딩
const Navbar = () => {
//.flex.justify-between.items-center>h1.text-xl.font-bold
  return (
	  <div className="flex justify-between items-center">
      <h1 className="text-xl font-bold">Logo</h1>
      
    </div>
  )
};
export default Navbar;

  1. Profile 컴포넌트 추가후 생성

파일생성후 import 의 확장자 삭제

2-3-Profile.tsx

  1. next-with-supabase\components\Profile.tsx
import React from 'react';
import {Button} from './ui/button';
import Link from 'next/link';

const Profile = () => {
  return (
    <div>
      <Link href="/auth">
        <Button variant="outline">SignIn</Button>
      </Link>
    </div>
  );
};
export default Profile;

2-4-Navbar.tsx

  1. next-with-supabase\components\Navbar.tsx
**import Link from 'next/link';**
import Profile from './Profile';

const Navbar = () => {
  return (
    <div className="flex justify-between items-center">
**      <Link href="/">**
        <h1 className="text-xl font-bold">Logo</h1>
**      </Link>**
      <Profile />
    </div>
  );
};
export default Navbar;

  1. 확인

2-5-사용자프로필

2-5-1-useUser.tsx

Info: 💡 리액트 쿼리를 사용하여 사용자 정보를 가져온다

  1. next-with-supabase\app\hook\useUser.tsx
  2. 표시된 파일을 생성한다

  1. 코드작성
'use client';
import {useQuery} from '@tanstack/react-query';
import {createClient} from '@/lib/supabase/client';

export default function useUser() {
  return useQuery({
    queryKey: ['user'],
    queryFn: async () => {
      const supabase = createClient();
      const {data} = await supabase.auth.getSession();
      if (data.session?.user) {
        const {data: user} = await supabase.from('profiles').select('*').eq('id', data.session.user.id);
        return user;
      }
    },
  });
}

2-5-2-수파베이스 타입 설치

수파베이스의 데이터베이스에서 사용중인 데이터들의 타입을 일일히 작성하기란 너무나도 까마득한 일이다. 수파베이스의 타입 생성기를 사용하면 자동으로 생성 된다.

  1. https://supabase.com/docs/guides/api/rest/generating-types 참조문서를 보면서 진행한다

  1. 웹브라우저를 열고 수파베이스에 로그인한다.
  2. npx supabase login 실행
  3. Ok to proceed 가 나오면 y 입력후 엔터

  1. 자동 로그인하려면 엔터 친다
  2. 웹브라우저가 열리고 인증키가 보이면 복사한다

  1. 터미널에 붙여넣고 엔터키 입력

  1. 성공

  1. 아래명령실행
npx supabase init

  1. $PROJECT_REF 에 본인의 ProjectID를 확인하여 변경한다
npx supabase gen types typescript --project-id "$PROJECT_REF" --schema public > database.types.ts

루트에 이미지와 같은 파일이 생성되었다.

Info: 💡 만약 수파베이스 데이터베이스의 스키마나 테이블 등의 변경이 있을 경우 기존의 파일을 삭제한 후 8번을 다시 한다.

  1. 타입지정
  2. lib\supabase\server.ts
  3. lib\supabase\client.ts 두 파일에 타입을 연결해보자. 아래 영상을 참조.

루트 경로에 저장된 database.type 의 타입을 참조하고 있다. 11. 조회 결과 필터링

  1. app\hook\useUser.tsx 데이터베이스를 조회하는 메서드 위에 마우스를 호버하면 타입추론이 되는것을 볼수있다.

  1. 아래의 코드는 supabase의 특정 id 를 가진 데이터를 profiles 테이블에서 모두 조회하는 sql 쿼리이다.
supabase.from('profiles').select('*').eq('id', data.session.user.id)     
  1. 동일한 아이디를 가진 사용자는 유일하므로 하나만 조회 하도록 한다.
...
if (data.session?.user) {
	const {data: user} = await supabase.from('profiles').select('*').eq('id', data.session.user.id)**.single();**
	return user;
}
...

2-5-3-조회결과가 없을경우

조회결과가 없을 경우에 대해 작성한다.

  1. app\hook\useUser.tsx
'use client';
import {useQuery} from '@tanstack/react-query';
import {createClient} from '@/lib/supabase/client';

**const initUser = {
  created_at: '',
  display_name: '',
  email: '',
  id: '',
  image_url: '',
};

**...**
**        return user;
      } //end of if**
    return initUser; 
**    },
  });
}**
**

2-5-4-Profile.tsx

  1. useUser 훅 임포트
**'use client';**
import React from 'react';
import {Button} from './ui/button';
import Link from 'next/link';
**import useUser from '@/app/hook/useUser';**

const Profile = () => {
**  const {isFetching, data} = useUser();**
  return (
    <div>
      <Link href="/auth">
        <Button variant="outline">SignIn</Button>
      </Link>
    </div>
  );
};
export default Profile;

3-테이블권한설정

인증된 사용자는 데이터베이스의 읽기권한을 할당하고 개발화면에서 확인해보자

  1. 수파베이스 대시보드

  1. 데이터 연동 확인

4-Profile.tsx

4-1-유저이름표시하기

'use client';
import React from 'react';
import {Button} from './ui/button';
import Link from 'next/link';
import useUser from '@/app/hook/useUser';

const Profile = () => {
  const {isFetching, data} = useUser();
**  if (isFetching) {
    return <></>;
  }**
  return (
    <div>
**      {!data?.id ? (**
        <Link href="/auth">
          <Button variant="outline">SignIn</Button>
        </Link>
    **  ) : (
        <h1>{data.display_name}</h1>
      )}**
    </div>
  );
};
export default Profile;

4-2-아바타표시하기

  1. h1을 삭제하고 NextJS의 Image 컴포넌트를 추가한다 components\Profile.tsx
...
import Image from 'next/image';
...
{!data?.id ? (
        <Link href="/auth">
          <Button variant="outline">SignIn</Button>
        </Link>
      ) : (
**        <Image src={data.image_url || ''} alt={data.display_name || ''} width={50} height={50} className="rounded-full" />**
      )}
    </div>
  1. 이미지 패스 추가 테이블의 image_url의 도메인 부분을 next설정 파일에 작성한다 next.config.ts
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'avatars.githubusercontent.com',
      },
      {
        protocol: 'https',
        hostname: 'lh3.googleusercontent.com',
      },
    ],
  },
};

export default nextConfig;

  1. 확인

5-완료코드

목차

  • 구문