학습 목표와 사전 지식
목표: Next.js에서 Firebase 웹 SDK 초기화 위치와 재사용·서버 경계를 설계합니다.
사전 지식: Next.js App Router, Client Component, TypeScript import, 환경변수
웹 SDK 인스턴스를 한 모듈에서 만들고 공유하면 설정과 리전이 흩어지는 것을 줄입니다. 중복 초기화 방지는 현재 JavaScript 실행 환경의 앱 레지스트리 재사용이지 사용자 인증을 서버에 전달하는 기능이 아닙니다.
프로젝트 준비
기존 Next.js App Router 프로젝트에서 npm install firebase client-only를 실행합니다. Firebase Console에서 웹 앱을 등록하고 공개 웹 설정을 .env.local의 NEXT_PUBLIC_FIREBASE_API_KEY, AUTH_DOMAIN, PROJECT_ID, STORAGE_BUCKET, APP_ID에 각각 대응시킵니다. 모든 변수에는 NEXT_PUBLIC_FIREBASE_ 접두사를 붙입니다. 서비스 계정 private key는 이 파일의 공개 변수로 넣지 않습니다.
src/shared/libs/firebase/firebase.ts · 전체 모듈; 기존 Next.js 프로젝트에 적용
import 'client-only';
import { getApp, getApps, initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { getStorage } from 'firebase/storage';
import { getFunctions } from 'firebase/functions';
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID
};
for (const [name, value] of Object.entries(firebaseConfig)) {
if (!value) throw new Error(`Firebase 설정 누락: ${name}`);
}
const app = getApps().some((item) => item.name === '[DEFAULT]')
? getApp()
: initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const db = getFirestore(app);
export const storage = getStorage(app);
export const functions = getFunctions(app, 'us-central1');
export default app;

client-only와 use client의 역할
client-only는 서버 코드에서 잘못 가져오는 것을 막는 표시입니다. 화면 컴포넌트에는 use client를 쓰고 그 컴포넌트가 이 모듈을 가져오도록 합니다. Admin SDK와 서버 세션 검증은 별도 server-only 모듈에서 다룹니다. 브라우저 currentUser를 서버가 자동으로 공유한다고 생각하면 보호 API가 비게 됩니다.
환경변수 오류를 빨리 드러내기
모듈은 누락된 키 이름만 오류에 포함하고 값 전체는 출력하지 않습니다. 공개 환경변수는 Next.js 빌드 시 브라우저 코드에 포함되므로 배포 설정 변경 후 다시 빌드합니다. dev 서버에서도 .env.local 변경 후 재시작하세요. bucket은 Console의 실제 이름을 그대로 사용하고 Functions 리전은 배포 함수와 일치시킵니다.

Emulator는 별도 연결 선택입니다
이 기본 모듈은 실제 설정의 Firebase 서비스에 연결합니다. Emulator를 사용하려면 최초 서비스 호출 전에 connectAuthEmulator/connectFirestoreEmulator/connectStorageEmulator/connectFunctionsEmulator를 명시적으로 연결해야 합니다. Functions만 로컬로 바꾸어도 Auth·Firestore·Storage가 자동으로 로컬이 되지 않습니다. 예외를 모두 잡아 이미 연결된 것이라고 무시하는 방식은 실제 연결 오류를 숨깁니다.
확인 순서
설정 한 개를 개발 환경에서 비워 오류에 해당 키 이름만 보이는지 확인합니다. 다시 채우고 dev 서버를 재시작해 Client Component에서 인스턴스를 가져옵니다. Fast Refresh 후 duplicate-app 오류가 없는지, production build가 서버 전용 모듈을 섞지 않는지 확인합니다. 앱 초기화 성공은 로그인·DB 읽기·Storage 쓰기 권한 성공을 뜻하지 않습니다.
직접 확인할 결과
전체 모듈 구문/누락 설정 검사
실제 Next.js 빌드·클라우드 연결 미실행
검증 범위와 기준일
공식 문서 확인일: 2026-09-13. 웹 SDK 예제는 모듈형 API 기준입니다. 이 글의 코드·구조 정적 검토와 실제 클라우드 인증·저장·배포 검증을 구분합니다. 본인 개발 Firebase 프로젝트의 실제 인증·권한·배포 요청은 이 편집 환경에서 실행하지 않았습니다.
이어서 학습하기
- Firebase 실무 로드맵: Auth, Firestore, Storage, Functions
- Firebase Authentication 사용 기준: 로그인 유지와 비밀번호 재설정
공식 문서
이 글이 도움이 되었나요?
Firebase 학습 순서
필수 13개 · 전체 19개
읽음 기록 관리
전체 과정 목차 (19개)
- 필수 길잡이 · Firebase 실무 로드맵: Auth, Firestore, Storage, Functions
- 필수 학습 · Firebase 초기화 구조: Next.js firebase.ts 설계 기준 현재 글
- 필수 학습 · Firebase Authentication 사용 기준: 로그인 유지와 비밀번호 재설정
- 필수 학습 · Firebase 보안 규칙 설계: Firestore와 Storage 권한 관리하기
- 필수 학습 · Firestore CRUD 사용법: 컬렉션 구조와 읽기 쓰기 흐름
- 필수 학습 · Firebase Auth Context 설계: 로그인 권한과 라우팅 관리하기
- 필수 학습 · Firebase Storage 이미지 업로드 사용법: 상품 이미지 관리 흐름 만들기
- 필수 학습 · Firebase Custom Claims 사용법: 관리자 권한 구분하기
- 필수 학습 · Firebase Functions v2 사용법: 트리거 배포 Secret 처리
- 필수 학습 · Firestore seed data 설계: 리뷰 더미 데이터 구조 잡기
- 선택 참고 · Firebase 배포 제외 파일 설정: firebase.json의 ignore 사용법
- 선택 참고 · Firebase Firestore 인덱스 삭제 질문 해결: 배포 중 안전하게 판단하기
- 선택 참고 · Firebase Auth unauthorized-domain 오류 해결: 로그인 도메인 설정 확인
- 선택 참고 · Firebase permission-denied 오류 해결: Firestore Rules 체크리스트
- 선택 참고 · Firebase Storage 이미지 오류 해결: 403·404·token·Rules 확인법
- 선택 참고 · Firebase CORS 오류 해결: Storage 이미지 업로드가 막힐 때 확인할 설정
- 필수 선수 · Firebase 실무 오류 해결 모음: Storage, Firestore, Auth 체크리스트
- 필수 학습 · Firestore undefined 오류 해결: 선택 필드가 저장을 막을 때
- 필수 학습 · Firestore arrayUnion 중첩 배열 오류: 배열을 그대로 넘기면 실패하는 이유
새 글 받아보기
RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.