Firebase Admin Custom Claims로 관리자 권한 설정하는 방법

주요 포인트 한눈에 보기

이 문서는 Firebase 관리자 권한(Custom Claims)을 설정할 수 있도록,
실제 프로젝트에서 필요한 정보만 남기고 보안상 민감한 값은 모두 예시 값으로 대체하여 정리한 가이드입니다.
로컬에서 단 한 번 실행하는 설정 스크립트 기준으로 설명하며,
운영 코드나 배포 환경에는 어떠한 영향도 주지 않습니다.

이 방식이 필요한 이유

Firebase Authentication 자체에는 “관리자 계정”이라는 개념이 존재하지 않습니다.
모든 사용자는 기본적으로 동일한 로그인 사용자일 뿐이며,
관리자 여부는 서버에서 별도로 권한을 부여해야만 구분할 수 있습니다.

Firestore 문서에 role: 'admin'과 같은 값을 저장하는 방식도 가능하지만,
이 정보는 클라이언트에서 조회가 가능하기 때문에
보안 규칙이나 서버 기준 권한 판단으로 사용하기에는 취약합니다.
이 문제를 해결하기 위한 공식적인 방법이 바로 Custom Claims입니다.

Custom Claims 개념

이 방식은 다음과 같은 상황에서 특히 필요합니다.

  • 관리자 전용 페이지 접근 제어
  • 상품 등록·수정·삭제와 같은 민감한 관리 기능
  • 주문 상태 변경, 강제 환불 처리 등 운영자 권한이 필요한 작업
  • 관리자 API 엔드포인트 보호

Custom Claims는 Firebase 로그인 토큰(ID Token)에 포함되는
서버 전용 권한 정보입니다.
이 값은 클라이언트 코드로는 절대 수정할 수 없으며,
Firebase Admin SDK를 통해서만 설정할 수 있습니다.

예를 들어 사용자 토큰에 { admin: true }가 포함되어 있으면,
해당 사용자는 관리자 전용 페이지 접근,
관리자 API 호출,
관리자 Firestore 규칙 통과 여부 판단의 기준으로 사용할 수 있습니다.

관리자 설정 스크립트 작성

관리자 권한은 웹 서비스 코드 내부에서 설정하지 않습니다.
대신 Node.js 환경에서 단독으로 실행하는 스크립트를 하나 만들어
필요한 사용자에게만 한 번 권한을 부여합니다.

/**
 * AI가 작성해준 코드
 * Firebase Admin Custom Claims 설정 스크립트
 * 
 * 사용법:
 * 1. Firebase CLI 로그인: firebase login
 * 2. 실행: node scripts/set-admin.js
 */

const admin = require('firebase-admin');
const path = require('path');

// 서비스 계정 키 파일 경로
// Firebase Console > 프로젝트 설정 > 서비스 계정 > 새 비공개 키 생성
const serviceAccountPath = path.join(__dirname, 'serviceAccountKey.json');

// Firebase Admin SDK 초기화
if (!admin.apps.length) {
  try {
    const serviceAccount = require(serviceAccountPath);
    admin.initializeApp({
      credential: admin.credential.cert(serviceAccount),
      projectId: 'PROJECT_ID_EXAMPLE'
    });
    console.log('서비스 계정 키로 초기화 완료');
  } catch (error) {
    console.error('서비스 계정 키 파일을 찾을 수 없습니다.');
    console.error(`경로: ${serviceAccountPath}`);
    process.exit(1);
  }
}

// 관리자로 설정할 UID (예시)
const ADMIN_UID = 'EXAMPLE_USER_UID';

async function setAdminClaim() {
  try {
    const user = await admin.auth().getUser(ADMIN_UID);

    await admin.auth().setCustomUserClaims(ADMIN_UID, { admin: true });

    const updatedUser = await admin.auth().getUser(ADMIN_UID);
    console.log('Admin Custom Claims 설정 완료');
    console.log(updatedUser.customClaims);

    process.exit(0);
  } catch (error) {
    console.error('Admin 설정 실패:', error.message);
    process.exit(1);
  }
}

setAdminClaim();

위 코드에서 serviceAccountKey.json
EXAMPLE_USER_UID는 모두 설명용 대체 값입니다.
이렇게 작성한 이유는, 이 문서가 블로그·포트폴리오 등
외부에 공개되는 문서이기 때문입니다.
실제 서비스 계정 키나 실제 UID는 Firebase 프로젝트 전체 권한과
사용자 계정 식별 정보에 직접 연결되므로,
문서에 그대로 포함될 경우 심각한 보안 사고로 이어질 수 있습니다.

따라서 문서에서는 항상 대체 값을 사용해 구조와 흐름만 설명하고,
실제 작업 시에만 로컬 환경에서 본인의 값으로 교체하는 방식을 취합니다.
이는 실무에서도 내부 위키나 기술 문서를 작성할 때
일반적으로 사용하는 안전한 문서화 패턴입니다.

실제로 이 스크립트를 실행하려면 다음과 같이 값을 준비해야 합니다.

  • Firebase Console > 프로젝트 설정 > 서비스 계정에서 비공개 키(JSON) 다운로드
  • 다운로드한 파일을 scripts/serviceAccountKey.json 경로에 저장
  • 관리자로 지정할 사용자의 UID를 Firebase Authentication 화면에서 확인
  • EXAMPLE_USER_UID를 실제 UID 값으로 교체

이 과정을 거친 뒤 node scripts/set-admin.js를 실행하면,
해당 UID 사용자에게만 관리자 권한(Custom Claims)이 부여됩니다.
문서와 실제 실행 환경을 명확히 분리함으로써
설명의 명확성과 보안 안정성을 동시에 확보할 수 있습니다.

이제 코드가 어떤 의도로 구성되어 있는지,
실무 기준에서 중요한 부분 위주로 하나씩 설명합니다.

먼저 serviceAccountPath는 서비스 계정 키 JSON 파일의 절대 경로를 생성합니다.
path.join(__dirname, ...) 방식을 사용함으로써
운영체제 차이(Windows, macOS)나 실행 위치 변경에도
경로 오류가 발생하지 않도록 설계되어 있습니다.

if (!admin.apps.length) 조건은
Firebase Admin SDK가 중복 초기화되는 상황을 방지하기 위한 안전장치입니다.
테스트 환경이나 스크립트 재실행 시에도
초기화 충돌 없이 안정적으로 동작하게 됩니다.

getUser(ADMIN_UID) 호출은 단순 조회 목적이 아니라,
실제 존재하지 않는 UID를 대상으로 권한을 설정하는 실수를
사전에 차단하기 위한 검증 단계입니다.
실무에서는 이 단계 없이 바로 Custom Claims를 설정하는 경우는 드뭅니다.

setCustomUserClaims는 Firestore 데이터를 수정하는 것이 아니라,
인증 토큰에 포함되는 권한 정보를 서버에서 서명하여 부여하는 작업입니다.
따라서 설정 직후에는 기존 로그인 상태에 즉시 반영되지 않으며,
반드시 로그아웃 후 재로그인을 통해 새로운 토큰을 발급받아야 합니다.

마지막으로 다시 getUser를 호출해
updatedUser.customClaims를 출력하는 부분은
권한 설정이 실제로 반영되었는지 확인하는 검증 단계입니다.
이 패턴은 운영 환경에서 로그 추적과 장애 대응에 매우 중요합니다.

실행 절차 정리

전체 과정은 아래 순서대로 진행됩니다.
이 문서만 보고 그대로 따라 하면 설정이 가능하도록 구성되어 있습니다.

# firebase-admin 패키지 설치
npm install firebase-admin --save-dev

# 관리자 권한 설정 스크립트 실행
node scripts/set-admin.js

스크립트가 정상적으로 실행되면
지정한 사용자 계정의 로그인 토큰에 관리자 권한이 저장됩니다.
이 작업 이후에는 반드시 로그아웃 후 다시 로그인해야
새로운 토큰이 발급되며 권한이 적용됩니다.

보안상 주의사항

이 문서에서 다룬 내용은 “관리자 권한을 설정하는 단계”까지를 다룹니다.
실제 서비스에서는 이후 단계에서 이 권한을 어떻게 활용하는지가 중요합니다.

다음 학습 단계로는 아래 주제를 이어서 살펴보는 것이 좋습니다.

  • 프론트엔드(AuthContext 등)에서 Custom Claims를 읽는 방법
  • Next.js / API Route / 서버 미들웨어에서 관리자 토큰 검증
  • Firestore 보안 규칙에서 request.auth.token.admin 활용

서비스 계정 키(JSON)는 Firebase 프로젝트의 최상위 권한을 가집니다.
따라서 GitHub 저장소에 업로드하거나,
블로그·문서·스크린샷에 그대로 노출하면 안 됩니다.

FAQ

Q. 이 스크립트는 서비스 코드에 포함되나요?
아닙니다. 로컬에서 한 번 실행하는 설정용 스크립트이며,
배포 서버나 클라이언트 코드와는 완전히 분리됩니다.

Q. 관리자 여부를 프론트엔드에서 어떻게 확인하나요?
로그인 후 발급된 ID Token을 통해 Custom Claims를 확인하거나,
서버 API에서 토큰 검증 시 관리자 여부를 판단합니다.

Q. 관리자 권한을 여러 명에게 주려면 어떻게 하나요?
동일한 스크립트를 사용하되,
UID만 바꿔서 여러 번 실행하면 됩니다.

이 글이 마음에 드세요?

RSS 피드를 구독하세요!

댓글 남기기