loading
미야옹

[Auth/Next.js] 인증, 인가 구현하기 A to Z (with Supabase, Tanstack Query, Zustand)

·
FE/Auth
1. 들어가며이 글은 Next.js, Tanstack Query, Supabase를 사용하여 로그인과 회원가입을 구현할 때참고할 수 있는 기존 포스팅을 정리한 글이다. 사전 지식이 없다면 먼저 아래 글을 확인하는 것을 추천한다.[Auth] 소셜 로그인 OAuth 동작 원리 이해하기[WEB] 인증과 인가: 쿠키, 세션, 토큰(JWT) 정리[TanStack Query] TanStack Query를 활용해 서버 상태 관리하기[React Hook Form] useState 없는 폼 관리: React Hook Form으로 리렌더링 최적화하기[Zod/React Hook Form] React Hook Form에 Zod를 결합해 유효성 검사 분리하기[Zustand] 복잡한 상태관리는 그만, Zustand와 미들웨어 핵..

[Auth/Next.js] Supabase Auth로 사용자 권한(role)에 따른 접근 제어 및 필터링

·
FE/Auth
1. 들어가며이전 글에서는 보호된 라우트를 통해 인증 여부에 따라 접근 가능한 페이지를 제한하였다. 이번 글에서는 이를 확장하여 관리자 전용 페이지(Admin Page) 를 구현하고,`role` 기반으로 페이지 접근, UI 노출, 데이터 조작 권한을 제어해보자.2. profiles 테이블에 role 필드 추가2.1 Enum 타입 생성 및 컬럼 추가관리자 권한을 구분하려면 사용자 프로필에 역할 정보가 필요하다.이를 위해 `profiles` 테이블에 `role` 컬럼을 추가하였다.Supabase SQL Editor 또는 Table Editor에서 아래 SQL을 실행한다.-- 1. Enum 타입 생성CREATE TYPE user_role AS ENUM ('user', 'admin');-- 2. profiles..

[Auth/Next.js] Zustand와 Supabase로 Header 사용자 정보 렌더링하기

·
FE/Auth
1. 들어가며저번 글에서 인증/인가를 구현하고, Supabase 세션을 Zustand로 전역 상태로 관리하였다.이번 글에서는 앞서 만든 Zustand `useSession` 훅을 활용해,현재 로그인한 사용자의 이메일과 프로필 이미지를 Header에 렌더링하고로그아웃 시 Supabase와 Zustand 스토어를 동시에 업데이트하는 방법을 다룬다.2. Next.js 설정: 외부 이미지 도메인 등록Next.js `next/image`는 외부 이미지 사용 시 도메인을 명시해야 한다.// next.config.tsimport type { NextConfig } from "next";const nextConfig: NextConfig = { images: { remotePatterns: [ { ho..

[Auth/Next.js] 보호된 라우트(Protected Route)를 구현하는 두 가지 방식 (미들웨어 vs ProtectedRoute 컴포넌트)

·
FE/Auth
1. 들어가며웹 애플리케이션에서 인증 여부에 따라 접근 가능한 페이지를 제한하고자 한다. 이때 로그인하지 않은 사용자가 마이페이지, 결제 페이지, 관리자 화면에 접근하지 못하도록 막는 구조를일반적으로 보호된 라우트(Protected Route) 라고 부른다.Next.js 환경에서는 보호된 라우트를 구현하는 방식이 크게 두 가지로 나뉜다.미들웨어(Middleware) 방식ProtectedRoute 컴포넌트 방식이번 글에서는 각각의 구조와 동작 원리를 정리하고, 어떤 상황에서 어떤 방식을 선택해야 하는지 살펴본다.2. 미들웨어(Middleware) 방식 (서버가드)2.1 미들웨어란?미들웨어는 요청(Request)과 페이지(Page) 사이에서 실행되는 서버 코드다.사용자가 어떤 URL에 접근하면 Next.js..

[Auth] 회원가입 시 프로필 정보 자동 생성 (feat. Supabase Auth)

·
FE/Auth
1. 들어가며회원가입만 완료하면 별도의 추가 입력 없이 바로 서비스를 이용할 수 있도록 하기 위해,프로필을 자동으로 생성하는 기능을 구현해 보자.2. DB 트리거 방식 vs 애플리케이션 핸들링DB 트리거란, `users` 테이블에 데이터가 추가되면(Insert),DB가 알아서 `profile` 테이블에도 데이터를 추가하는 방식을 말한다.이런 기능은 DB의 트리거를 이용해 만드는 게 일반적이지만, 이 방식에는 치명적인 단점이 존재한다. 트리거 함수 내부에서 예외가 발생했을 때, 애플리케이션 단에서 이를 감지하고 처리하기가 매우 까다롭다는 점이다.따라서 안전한 방식이라고 확신하긴 어렵다.이러한 이유로, DB 트리거 대신 애플리케이션(클라이언트) 단에서 제어하는 방식을 선택한다.애플리케이션 레벨 프로필 생성 ..

[Auth] 비밀번호 재설정하기 (feat. Supabase Auth)

·
FE/Auth
1. 비밀번호 재설정 과정1.1 재설정 전체 흐름단계구분주체 설명1재설정 요청사용자로그인 화면에서 비밀번호 재설정 요청을 수행한다2인증 링크 발송인증 서버요청을 받아 일회성 토큰이 포함된 인증 링크를 이메일로 발송한다3링크 접근 및 검증인증 서버사용자가 링크를 클릭하면, 포함된 토큰을 기반으로 요청의 유효성을 검증한다4리디렉션인증 서버 → 브라우저검증이 완료되면, 미리 지정된 비밀번호 재설정 페이지로 이동시킨다5비밀번호 변경사용자 → 인증 서버사용자가 새 비밀번호를 입력하면, 검증된 요청에 한해 DB에 반영한다1.2 비밀번호 재설정이 가능한 이유비밀번호 재설정이 가능한 핵심 원리는 인증 링크에 숨어 있다.사용자가 이메일로 받는 비밀번호 재설정 링크는 단순한 페이지 이동용 URL이 아니라,재설정 요청을 검..

[Auth] React / Next.js로 Route Guard 구현하기

·
FE/Auth
1. Route Guard란?특정 페이지(e.g., 마이페이지, 피드 작성)는 로그인이 완료된 사용자만 접근이 가능해야 하고,반대로 로그인 페이지나 회원가입 페이지는 이미 로그인한 사용자가 접근할 필요가 없다.이를 제어하는 기능을 라우트 가드(Route Guard)라고 한다.React(SPA) 환경과 Next.js 환경 각각에서 라우트 가드를 구현하는 방법을 알아보자.2. React 라우트 가드 구현하기2.1 글로벌 레이아웃 (GlobalLayout)라우트 가드를 구현하기 전, 전체적인 레이아웃과 라우터 설정을 먼저 잡자 `Outlet`은 자식 라우트의 페이지 컴포넌트가 실제로 렌더링 되는 위치를 지정한다.// src/layouts/GlobalLayout.tsxconst GlobalLayout = () ..

[Auth/Next.js] Supabase 세션을 Zustand로 전역 상태로 관리하기

·
FE/Auth
1. 기존 세션 관리 방식의 문제점기존에는 로그인된 사용자의 세션 데이터를 단순히 쿠키나 로컬 스토리에 보관했다.이 방식에는 다음과 같은 한계가 존재한다.쿠키에서 세션 데이터를 매번 직접 꺼내와야 한다. (`getCookie`로 읽고, `setCookie`로 갱신의 반복..)세션 데이터 변경을 감지하기 어렵다.컴포넌트 간 세션 상태 공유가 불편하다.이러한 문제를 해결하기 위해, 세션 데이터를 Zustand와 같은 전역 상태 관리 도구에 보관하여모든 컴포넌트에서 손쉽게 접근할 수 있도록 하자. Zustnad 사용 방법은 여기서 확인할 수 있다.2. Session Store 구현가장 먼저 세션 데이터를 담을 스토어를 생성하자.Supabase의 `Session` 타입을 활용하며, Zustand의 `combin..

[Auth] 인증 에러 처리 #2: 에러 메시지 한글화로 UX 개선하기

·
FE/Auth
1. 문제: 인증 에러 메시지가 영어로 출력이전 글에서 에러 발생 시 toast 메시지를 띄우는 기능 구현을 마쳤다. 현재 인증 실패 시 에러 처리는 다음과 같은 형태다.onError: (error) => { toast.error(error.message, { position: "top-center", }); setPassword("");},이 방식은 동작에는 문제가 없지만,`error.message`는 Supabase 서버에서 내려준 영문 메시지이기 때문에 UX면에서 아쉽다.따라서 에러 메시지를 직접 번역해서 출력할 필요가 있다 이번 글에서는 Supabase가 내려주는 인증 에러의 구조를 분석하고,에러 코드를 기반으로 한국어 메시지로 매핑하여 변환하는 방식을 정리한다.2. Supabase 에..

[Auth] 인증 에러 처리#1: 인증 실패 시 비밀번호 초기화 및 Mutation 콜백으로 관심사 분리

·
FE/Auth
1. 들어가며기능을 정상적으로 동작하게 만드는 것만큼이나,실패했을 때 어떻게 처리할지(Error Handling)를 설계하는 것은 중요하다.로그인 기능을 예로 들어보자.사용자가 비밀번호를 틀렸을 때, 아무 일도 일어나지 않는다면 사용자는 당황할 것이다. 이번 글에서는 Tanstack Query의 Mutation을 사용할 때, 이러한 에러 처리를 어디서,어떻게 하는 것이 구조적으로 좋은지 알아보자.2. 기본적인 에러 흐름`mutationFn` 내부에서 에러 발생 (`throw error`)mutation의 `onError` 이벤트 핸들러 호출`onError`의 매개변수로 에러 객체 전달해당 시점에서 에러 로깅, 메시지 출력 등의 처리가 가능이 구조를 기반으로 에러 메시지를 출력하면 된다.3. 문제: mut..

[Auth] 이메일 & 소셜 로그인 구현하기 (feat. Supabase, Tanstack query, React Hook Form)

·
FE/Auth
1. 들어가며지난 글에서살펴봤듯 인증은 크게 세션 방식과 토큰 방식으로 나뉜다. Supabase는 두 방식을 모두 지원하지만,세션 방식은 사용자 수가 증가할수록 DB 및 서버 부하가 누적될 수 있어 무료 요금제에서는 기능이 제한다. 이번 프로젝트에서는 접속자 수 카운트, 동시 접속 제한 등 세션 기반 상태 관리 기능이 필요하지 않았기 때문에,서버 부하를 줄이고 확장성에 유리한 토큰 기반 인증 방식을 채택하여 구현을 진행하였다.Supabase Auth⚡ 사용 배경Supabase 클라이언트의 강점 중 하나는 인증 토큰(Access Token, Refresh Token)을 자동으로 관리해 준다는 점이다. 기본 클라이언트를 사용할 경우 토큰은 브라우저의 localStorage에 저장되며,`@supabase/ss..

[Auth] 소셜 로그인 OAuth 동작 원리 이해하기

·
FE/Auth
1. 소셜 로그인이란?소셜 로그인 이미 가입된 외부 플랫폼(Google, GitHub, Kakao 등)의 계정을 연동하여서비스에 로그인하는 기능을 의미한다.사용자는 새로운 계정을 만들 필요 없이 이미 사용 중인 외부 서비스 계정을 이용해 로그인할 수 있어,오늘날 대부분의 서비스가 기본 기능으로 제공한다.2. OAuth는 인가 프로토콜이다.소셜 로그인은 OAuth(Open Authorization) 프로토콜을 기반으로 동작한다.인증(로그인) 기능을 구현하는데 왜 인가 프로토콜을 사용할까? OAuth는 원래 로그인을 위한 인증(Authentication) 목적이 아니라,권한을 위임받는 인가(Authorization)를 위해 만들어진 프로토콜이기 때문이다.예시노션 캘린더가 구글 캘린더 데이터를 읽어오려면,사용..