네임스페이스화된 API에서 모듈식 API로 업그레이드

현재 compat 라이브러리부터 버전 8 이하까지 네임스페이스화된 Firebase Web API를 사용하는 앱은 이 가이드의 안내에 따라 모듈식 API로 이전하는 것이 좋습니다.

이 가이드는 사용자가 네임스페이스화된 API 사용에 익숙하며 업그레이드 및 향후 모듈식 앱 개발에 webpack 또는 Rollup과 같은 모듈 번들러를 사용한다는 가정을 바탕으로 합니다.

개발 환경에서 모듈 번들러를 사용하는 것이 좋습니다. 이 기능을 사용하지 않으면, 웹 크기 축소와 관련한 모듈식 API의 주요 이점을 활용할 수 없습니다. SDK를 설치하려면 npm 또는 yarn이 필요합니다.

이 가이드의 업그레이드 단계는 가상의 웹 앱을 기반으로 합니다. AuthenticationCloud Firestore SDK 사용 예시를 통해 지원되는 모든 Firebase 웹 SDK를 업그레이드하는 데 필요한 개념과 실용적인 단계를 익힐 수 있습니다.

네임스페이스화된(compat) 라이브러리 정보

Firebase 웹 SDK에서는 두 가지 유형의 라이브러리를 사용할 수 있습니다.

  • Modular - 웹 앱을 가능한 한 빠르고 작게 만들기 위해 Tree Shaking(사용하지 않는 코드 삭제)을 촉진하도록 설계된 새로운 API 노출 영역입니다.
  • 네임스페이스화(compat) - 이전 버전의 SDK와 완벽하게 호환되는 친숙한 API 노출 영역을 사용하면 모든 Firebase 코드를 한 번에 변경하지 않고도 업그레이드할 수 있습니다. compat 라이브러리는 네임스페이스화된 라이브러리에 비해 크기 또는 성능상의 이점이 거의 없습니다.

이 가이드는 업그레이드를 촉진하기 위해 compat 라이브러리를 활용한다는 가정을 바탕으로 합니다. 이러한 라이브러리를 사용하면 모듈식 API로 리팩터링된 코드와 함께 네임스페이스화된 코드를 계속 사용할 수 있습니다. 즉, 업그레이드 프로세스를 진행하면서 앱을 더 쉽게 컴파일 및 디버그할 수 있습니다.

Firebase 웹 SDK에 아주 적게 노출되는 앱(예: Authentication API를 간단히 호출하는 앱. compat 라이브러리를 사용하지 않고 이전의 네임스페이스화된 코드를 리팩터링하는 것이 실용적입니다. 이러한 앱을 업그레이드하는 경우 compat 라이브러리를 사용하지 않고 '모듈식 API'에 대한 이 가이드의 안내를 따를 수 있습니다.

업그레이드 프로세스 정보

업그레이드 프로세스의 각 단계에는 범위가 지정되므로 앱의 소스 수정을 완료한 후 중단 없이 컴파일하고 실행할 수 있습니다. 요약하면, 다음을 수행하여 앱을 업그레이드합니다.

  1. 앱에 모듈식 라이브러리와 compat 라이브러리를 추가합니다.
  2. 코드의 가져오기 문을 compat으로 업데이트합니다.
  3. 단일 제품 (예: Authentication)의 코드를 다음과 같이 리팩터링합니다. 사용할 수 있습니다
  4. 선택사항: 이 시점에서 Authentication compat 라이브러리와 compat 코드를 삭제합니다. Authentication 동안 계속하기 전에 Authentication의 앱 크기 이점을 실현하세요.
  5. 각 제품의 함수를 리팩터링합니다 (예: Cloud Firestore, FCM 등)을 모듈식 스타일로 변환하고 컴파일 및 테스트를 거쳐야 합니다.
  6. 초기화 코드를 모듈식으로 업데이트합니다.
  7. 앱에서 남은 compat 문과 compat 코드를 모두 삭제합니다.

SDK의 최신 버전 다운로드

시작하려면 npm을 사용하여 모듈식 라이브러리와 compat 라이브러리를 가져오세요.

npm i firebase@10.13.1

# OR

yarn add firebase@10.13.1

가져오기를 compat으로 업데이트

종속 항목을 업데이트한 후에도 코드가 계속 작동하도록 하려면 가져오기 문을 변경하여 각 가져오기의 'compat' 버전을 사용합니다. 예를 들면 다음과 같습니다.

이전: 버전 8 이하

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

이후: compat

// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

모듈식으로 리팩터링

네임스페이스화된 API는 점으로 체이닝된 네임스페이스 및 서비스 패턴을 기반으로 하지만 모듈식 접근방식은 코드가 함수를 중심으로 구성됩니다. 모듈식 API에서 firebase/app 패키지와 기타 패키지는 패키지의 모든 메서드를 포함하는 포괄적인 내보내기를 반환하지 않습니다. 대신 패키지는 개별 함수를 내보냅니다.

모듈식 API에서는 서비스가 첫 번째 인수로 전달되며, 함수는 이 서비스의 세부정보를 사용해 나머지 작업을 수행합니다. 이것이 어떻게 작동하는지 AuthenticationCloud Firestore API 호출을 리팩터링하는 두 가지 예

예시 1: Authentication 함수 리팩터링

이전: compat

compat 코드는 네임스페이스화된 코드와 동일하지만 가져오기는 변경되었습니다.

import firebase from "firebase/compat/app";
import "firebase/compat/auth";

const auth = firebase.auth();
auth.onAuthStateChanged(user => { 
  // Check for user status
});

이후: 모듈식

getAuth 함수는 firebaseApp를 첫 번째 매개변수로 사용합니다. onAuthStateChanged 함수는 네임스페이스화된 API처럼 auth 인스턴스에서 체이닝이 되지 않지만, 대신 auth를 첫 번째 매개변수로 사용하는 무료 함수입니다.

import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
  // Check for user status
});

인증 메서드 getRedirectResult 처리 업데이트

모듈식 API에는 getRedirectResult에 브레이킹 체인지가 포함되어 있습니다. 리디렉션 작업이 호출되지 않으면 모듈식 API는 null 사용자와 함께 UserCredential을 반환했던 네임스페이스화된 API와는 달리 null을 반환합니다.

이전: compat

const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
  return null;
}
return result;

이후: 모듈식

const result = await getRedirectResult(auth);
// Provider of the access token could be Facebook, Github, etc.
if (result === null || provider.credentialFromResult(result) === null) {
  return null;
}
return result;

예시 2: Cloud Firestore 함수 리팩터링

이전: compat

import "firebase/compat/firestore"

const db = firebase.firestore();
db.collection("cities").where("capital", "==", true)
    .get()
    .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch((error) => {
        console.log("Error getting documents: ", error);
    });

이후: 모듈식

getFirestore 함수는 firebaseApp을 첫 번째 매개변수로 사용합니다. 여기서는 이전 예시의 initializeApp에서 반환됩니다. 쿼리를 구성하는 코드는 모듈식 API에서 매우 다릅니다. 체이닝이 되어 있지 않으며 query 또는 where과 같은 메서드는 이제 무료 함수로 노출됩니다.

import { getFirestore, collection, query, where, getDocs } from "firebase/firestore";

const db = getFirestore(firebaseApp);

const q = query(collection(db, "cities"), where("capital", "==", true));

const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
});

Firestore DocumentSnapshot.exists에 관한 참조 업데이트

모듈식 API에는 firestore.DocumentSnapshot.exists 속성이 메서드로 변경된 브레이킹 체인지가 포함되어 있습니다. 이 기능은 문서가 있는지 테스트한다는 점에서 본질적으로 동일하지만 아래에 표시된 것과 같이 최신 메서드를 사용하도록 코드를 리팩터링해야 합니다.

이전: compat

if (snapshot.exists) {
  console.log("the document exists");
}

이후: 모듈식

if (snapshot.exists()) {
  console.log("the document exists");
}

예시 3: 네임스페이스화된 코드 및 모듈식 코드 스타일 결합

업그레이드 중에 compat 라이브러리를 사용하면 모듈식 API용으로 리팩터링된 코드와 함께 네임스페이스화된 코드를 계속 사용할 수 있습니다. 즉, 사용자는 Authentication를 리팩터링하는 동안 Cloud Firestore의 기존 네임스페이스화된 코드 또는 다른 Firebase SDK 코드를 두 코드를 모두 사용하여 앱을 성공적으로 컴파일할 수 있습니다. 있습니다. 이는 제품 네임스페이스화된 API 코드 및 모듈식 API 코드도 마찬가지입니다. Cloud Firestore로, 새 코드 스타일과 이전 코드 스타일이 compat 패키지를 가져옵니다.

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { getDoc } from 'firebase/firestore'

const docRef = firebase.firestore().doc();
getDoc(docRef);

앱이 컴파일되지만 앱에서 compat 문과 코드를 완전히 삭제할 때까지는 모듈식 코드의 앱 크기 이점을 얻을 수 없습니다.

초기화 코드 업데이트

모듈식 구문을 사용하려면 앱의 초기화 코드를 업데이트해야 합니다. 앱의 모든 코드 리팩터링을 완료한 이 코드를 업데이트하는 것이 중요합니다. 이는 firebase.initializeApp()가 compat API와 모듈식 API의 전역 상태를 초기화하지만 모듈식 initializeApp() 함수는 모듈식 상태만 초기화하기 때문입니다.

이전: compat

import firebase from "firebase/compat/app"

firebase.initializeApp({ /* config */ });

이후: 모듈식

import { initializeApp } from "firebase/app"

const firebaseApp = initializeApp({ /* config */ });

compat 코드 삭제

모듈식 API의 크기 이점을 활용하려면 결국 모든 호출을 위에 표시된 모듈식 스타일로 변환하고 코드에서 import "firebase/compat/* 문을 모두 삭제해야 합니다. 작업을 완료한 후에는 네임스페이스화된 API 스타일의 firebase.* 전역 네임스페이스 또는 다른 코드에 대한 참조가 더 이상 없어야 합니다.

window에서 compat 라이브러리 사용

모듈식 API는 브라우저의 window 객체가 아닌 모듈과 연동하도록 최적화되었습니다. 이전 버전의 라이브러리에서는 window.firebase 네임스페이스를 사용하여 Firebase를 로드하고 관리할 수 있었습니다. 이 방법은 미사용 코드를 제거할 수 없으므로 앞으로 권장되지 않습니다. 그러나 모듈식 업그레이드 경로를 즉시 시작하지 않으려는 개발자를 위해 자바스크립트 SDK의 compat 버전은 window와 연동됩니다.

<script src="https://www.gstatic.com/firebasejs/10.13.1/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.13.1/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.13.1/firebase-auth-compat.js"></script>
<script>
   const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
   const db = firebaseApp.firestore();
   const auth = firebaseApp.auth();
</script>

호환성 라이브러리는 내부적으로 모듈식 코드를 사용하면서 네임스페이스화된 API와 동일한 API를 제공합니다. 즉, 자세한 내용은 네임스페이스화된 API 참조 및 네임스페이스화된 코드 스니펫을 참조할 수 있습니다. 그러나 이 방법은 장기적으로 권장되지 않으며, 완전 모듈식 라이브러리로 업그레이드하는 시작점으로 사용하시기 바랍니다.

모듈식 SDK의 이점 및 제한사항

완전히 모듈화된 SDK는 이전 버전에 비해 다음과 같은 장점이 있습니다.

  • 모듈식 SDK를 사용하면 앱 크기를 상당히 줄일 수 있습니다. 최신 자바스크립트 모듈 형식을 채택하여 앱에 필요한 아티팩트만 가져오는 '트리 쉐이킹' 방식을 지원합니다. 앱에 따라 모듈식 SDK를 사용하여 트리 쉐이킹 작업을 수행하면 네임스페이스화된 API로 빌드한 앱에 비해 KB를 80% 줄일 수 있습니다.
  • 모듈식 SDK는 지속적인 기능 개발의 이점을 계속해서 누릴 수 있는 반면, 네임스페이스화된 API는 이점을 누리지 못합니다.