Firebase Auth Context 설계: 로그인 권한과 라우팅 관리하기

2026.01.14·수정 2026.09.13·약 7분·작성: 해비·블로그 소개

학습 목표와 사전 지식

목표: Auth Context의 로딩·계정 변경·권한 표시 상태를 설계하고 라우팅과 권한 집행을 구분합니다.
사전 지식: React Context/useEffect, Next.js App Router, Firebase 초기화

AuthProvider는 인증을 구독해 화면에 공유합니다. 서버 접근 권한까지 보장하는 장치는 아닙니다. 인증과 claim 읽기가 끝나기 전에 보호 화면을 렌더링하지 않고, 이전 계정의 비동기 응답이 새 계정 상태를 덮어쓰지 않게 해야 합니다.

전체 Context 모듈

Next.js 기존 프로젝트의 src/context/AuthProvider.tsx에 둡니다. src/shared/libs/firebase/firebase.ts는 초기화 글의 모듈을 사용합니다. 로그인·가입·로그아웃 동작은 Authentication 글의 유틸을 호출하고, Context는 현재 인증 상태와 권한 표시만 맡깁니다. 별도 프로필 쿼리 라이브러리는 이 최소 예제에 필요하지 않습니다.

src/context/AuthProvider.tsx · 전체 모듈; 기존 React/Next.js 프로젝트에 적용

"use client";
import { createContext, useContext, useEffect, useState, type ReactNode } from 'react';
import { onIdTokenChanged, type User } from 'firebase/auth';
import { auth } from '../shared/libs/firebase/firebase';

type State = { user: User | null; loading: boolean; isAdmin: boolean; error: string | null };
const AuthContext = createContext<State | undefined>(undefined);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [state, setState] = useState<State>({ user: null, loading: true, isAdmin: false, error: null });
  useEffect(() => {
    let generation = 0;
    const unsubscribe = onIdTokenChanged(auth, async (user) => {
      const current = ++generation;
      setState({ user, loading: !!user, isAdmin: false, error: null });
      if (!user) return;
      try {
        const token = await user.getIdTokenResult();
        if (current !== generation) return;
        setState({ user, loading: false, isAdmin: token.claims.admin === true, error: null });
      } catch {
        if (current !== generation) return;
        setState({ user, loading: false, isAdmin: false, error: '권한 정보를 확인하지 못했습니다.' });
      }
    });
    return () => { generation += 1; unsubscribe(); };
  }, []);
  return <AuthContext.Provider value={state}>{children}</AuthContext.Provider>;
}

export function useAuth() {
  const value = useContext(AuthContext);
  if (!value) throw new Error('AuthProvider 내부에서 사용하세요.');
  return value;
}
Firebase Auth 상태와 React Context 연결 흐름

왜 요청 세대 번호를 비교하는가

A 계정의 claim 조회가 느린 동안 로그아웃하거나 B로 로그인할 수 있습니다. generation을 바꾸고 완료 시 동일한 번호일 때만 상태를 반영하면 이전 요청 결과를 버립니다. 로그아웃 시 isAdmin을 즉시 false로 만들고 구독 해제 때도 진행 중 요청을 무효화합니다. 이 처리는 네트워크 요청을 취소하는 것과 다릅니다.

라우팅은 보호 화면 안에서

루트 layout의 children을 AuthProvider로 감싸고 보호 화면에서 loading이면 로딩 UI를, !user면 로그인 안내 또는 router.replace(“/auth/login”)를 실행합니다. 리다이렉트는 effect에서 처리하고 결과가 정해지기 전에는 보호 데이터를 표시하지 않습니다. pathname.includes(“/mypage”)처럼 우연히 포함된 문자열까지 보호하지 말고 경로 세그먼트를 명시합니다. Context 전체에 라우팅 부작용을 넣으면 공개 페이지까지 얽히기 쉽습니다.

로그인 유지와 보호 라우팅 점검 기준

role 필드와 claim을 혼동하지 않기

사용자가 바꿀 수 있는 프로필 role을 근거로 서버 권한을 허용하면 안 됩니다. isAdmin은 claim 기반 UI 안내일 뿐이며 관리자 API는 ID token 검증 뒤 claim을 다시 검사하고 Firestore·Storage는 Rules를 적용합니다. banned 상태를 화면에서만 체크하는 것도 실제 차단이 아닙니다. 서버·Rules의 정책과 연결해야 합니다.

확인 순서

새로고침 시 첫 인증 결과 전 loading이 유지되는지 확인합니다. A→로그아웃→B 전환 중 네트워크를 느리게 만들어 A의 권한이 되살아나지 않는지 봅니다. claim 조회 실패 시 관리자 화면을 숨기고 에러를 표시해야 합니다. UI isAdmin을 임의 변경해도 실제 관리자 요청이 거부되는지 개발 서버에서 따로 검사합니다.

직접 확인할 결과

타입/비동기 세대 처리 정적 검토
Next.js 빌드·브라우저 계정 전환 미실행

검증 범위와 기준일

공식 문서 확인일: 2026-09-13. 웹 SDK 예제는 모듈형 API 기준입니다. 이 글의 코드·구조 정적 검토와 실제 클라우드 인증·저장·배포 검증을 구분합니다. 본인 개발 Firebase 프로젝트의 실제 인증·권한·배포 요청은 이 편집 환경에서 실행하지 않았습니다.

이어서 학습하기

공식 문서

이 글이 도움이 되었나요?

조회 중

Firebase 학습 순서

필수 13개 · 전체 19개

읽음 기록 관리

전체 과정 목차 (19개)
  1. 필수 길잡이 · Firebase 실무 로드맵: Auth, Firestore, Storage, Functions
  2. 필수 학습 · Firebase 초기화 구조: Next.js firebase.ts 설계 기준
  3. 필수 학습 · Firebase Authentication 사용 기준: 로그인 유지와 비밀번호 재설정
  4. 필수 학습 · Firebase 보안 규칙 설계: Firestore와 Storage 권한 관리하기
  5. 필수 학습 · Firestore CRUD 사용법: 컬렉션 구조와 읽기 쓰기 흐름
  6. 필수 학습 · Firebase Auth Context 설계: 로그인 권한과 라우팅 관리하기 현재 글
  7. 필수 학습 · Firebase Storage 이미지 업로드 사용법: 상품 이미지 관리 흐름 만들기
  8. 필수 학습 · Firebase Custom Claims 사용법: 관리자 권한 구분하기
  9. 필수 학습 · Firebase Functions v2 사용법: 트리거 배포 Secret 처리
  10. 필수 학습 · Firestore seed data 설계: 리뷰 더미 데이터 구조 잡기
  11. 선택 참고 · Firebase 배포 제외 파일 설정: firebase.json의 ignore 사용법
  12. 선택 참고 · Firebase Firestore 인덱스 삭제 질문 해결: 배포 중 안전하게 판단하기
  13. 선택 참고 · Firebase Auth unauthorized-domain 오류 해결: 로그인 도메인 설정 확인
  14. 선택 참고 · Firebase permission-denied 오류 해결: Firestore Rules 체크리스트
  15. 선택 참고 · Firebase Storage 이미지 오류 해결: 403·404·token·Rules 확인법
  16. 선택 참고 · Firebase CORS 오류 해결: Storage 이미지 업로드가 막힐 때 확인할 설정
  17. 필수 선수 · Firebase 실무 오류 해결 모음: Storage, Firestore, Auth 체크리스트
  18. 필수 학습 · Firestore undefined 오류 해결: 선택 필드가 저장을 막을 때
  19. 필수 학습 · Firestore arrayUnion 중첩 배열 오류: 배열을 그대로 넘기면 실패하는 이유

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기