상권's

Firebase 사용하기 (2. Firestore) 본문

~2022 작성 글/TIL

Firebase 사용하기 (2. Firestore)

라마치 2022. 12. 16. 11:29

이전 글에 이어 오늘은 프로젝트에서 직접 사용했던 Firestore 코드에 대해서 정리해보겠습니다.

 

저는 프로젝트에서 크게 Authentication과 Firestore에 접근하는 코드를 사용했습니다. Authentication으로 로그인할 경우, 자체적으로 제공하는 프로필 사진, email, 전화번호, displayName 등 사용자의 정보를 읽고, 수정할 수 있습니다. Firestore는 collection과 doc으로 이루어져있으며, collection은 다수의 doc을 가질 수 있으며, doc 또한 collection을 가질 수 있습니다.

 

먼저, 제가 직접 사용한 Authentication 메소드에 대해 알아보겠습니다.

createUserWithEmailAndPassword(email, password)

auth.createUserWithEmailAndPassword(userEmail + '@test.com', `${tempArr.join('')}`)
	.then((result) => {
    	console.log(result)
     })

첫번째는 회원가입하는 로직입니다. 이를 통해서 Authentication에 사용자를 추가할 수 있습니다. email 로그인 방식을 사용하고 있어, 위처럼 email 형식에 맞게 첫번째 인자로 넣어주고, 두번째 인자로 비밀번호를 넣었습니다.

 

성공적으로 계정이 생성되면 자동으로 로그인 처리가 됩니다. 사용자의 정보를 다음과 같이 읽을 수 있습니다.

const user = auth.currentUser;

displayname과 프로필 사진은 다음 메소드로 수정할 수 있습니다.

user.updateProfile({
	displayName: nickName,
	photoURL: ''
})

저희는 displayName을 닉네임으로 사용했습니다. 다음으로는 email 변경 메소드입니다.

user.updateEmail(userEmail + '@test.com')
	.then((result) => {
})

비밀번호는 다음과 같이 수정할 수 있습니다.

 user.updatePassword(password)
 	.then((result) => {
 })

익명 로그인입니다. 저희는 프로젝트에서 회원가입 절차 진행 시 익명 로그인으로 시작 후, 모든 입력이 성공적으로 이루어졌을 때 Authentication 로그인을 다시 진행했습니다.

auth.signInAnonymously()
	.then((result) => {
})

이렇게 익명 로그인을 할 경우, auth.curentUser를 출력해보면 anonymous : true를 확인하실 수 있습니다.

 회원 탈퇴 메소드는 다음과 같습니다.

user.delete().then((result) => {
})

 

마지막으로 회원탈퇴 로직입니다.

user.delete().then((result) => {
})

이렇게 제가 프로젝트에서 사용했던 Authentication 메소드를 정리해보았습니다.

 

이제는 Firestore v8 메소드에 대해 알아보겠습니다.

먼저 만들어져있는 collection 하위에 doc과 field를 만드는 메소드입니다.

db.collection('user').doc(123456).set({
	필드에 들어갈 데이터
})

위의 코드는 user collection에 doc명을 123456으로 '필드에 들어갈 데이터'를 객체로 저장합니다. 이러한 방법으로 저희는 user collection에 사용자 정보를 저장했습니다.

 

여기서 doc은 user collection 내부에서 유니크한, 단 하나뿐인 값이여야 합니다. 이러한 이유로 다시 저 코드를 동작시킨다면 doc명이 중복되어 정상적으로 doc과 필드가 생성되지 않습니다. doc을 사용자가 특정하지 않고 Firestore에서 자동으로 유니크 값이 생성될 수 있는데, 이 경우에는 doc을 제외하고 다음과 같이 사용하면 됩니다.

db.collection('user').set({
	필드에 들어갈 데이터
})

기존에 존재하는 doc을 명시하고 set을 할 경우, 기존에 있던 데이터는 새로운 데이터로 대체됩니다.

특정 키 밸류 값을 변경하기 원할 경우 collection과 doc을 특정한 후, 변경하기 원하는 키와 변경할 밸류를 update하면 됩니다.

db.collection('user').doc(number).update({
      변경할 키: 변경할 밸류
    }).then((result) => {
})

collection의 모든 데이터나, 특정 doc의 데이터를 찾기 위해서는 get 메소드를 사용합니다.

const stores = await db.collection('store').get();
const data = stores.docs.map(doc => doc.data());


db.collection('store').get()
	.then((result) => {
    	result.docs.map(doc => doc.data())
    })
})

위의 두 방법은 store collection에 존재하는 모든 doc과 필드의 값을 찾아옵니다. Firebase의 메소드는 이처럼 async/await, then/catch문으로 동기/비동기로 데이터를 호출할 수 있습니다.

 

이처럼 특정 doc을 지정하지 않았을 경우, 정상적으로 Firestore의 값을 찾아오면 docs라는 배열에 각 데이터가 담깁니다. 각 데이터를 data()함으로써 개발자가 사용할 수 있는 정보로 변환됩니다. 두 번째 방법의 경우, 프로젝트에서는 state나 특정 변수에 담아 사용할 수 있습니다.

 db.collection('user').doc(특정값).get()
 	.then((result) => {
    	let data = result.data()
})

특정 doc을 지정하는 경우, 불러온 데이터를 사용하기 위해서는 위와 같이 성공적으로 리턴하는 값을 data()하면 사용할 수 있는 정보로 변환할 수 있습니다.

 

이로써 doc을 특정하느냐에 따라서 리턴값을 data()하냐, 리턴값의 내부의 docs의 내부에 값들을 data()하는 냐로 구분할 수 있습니다.

 

collection의 모든 doc들 중에 특정 조건에 충족하는 doc을 찾는 방법도 있습니다.

db.collection('store').where('키', '==', '값').get()
	.then((data) => {
    	data.forEach((doc) => {
			doc.data()
        });
})

 이 코드를 통해 키의 밸류가 값과 동일한 field를 가진 doc을 찾을 수 있습니다.

정렬도 가능합니다.

const stores = await db.collection('store').orderBy('orderCount', 'desc').get();
        const data = stores.docs.map(doc => doc.data());
})

하지만 정렬의 경우, 색인을 추가해야지만 사용할 수 있습니다.

색인 추가 시 필수적으로 두 개의 키 값과 정렬 방법을 넣어야 합니다. 여기에서 하나만 사용할 경우에는 두번째 키 값은 임의의 키를 넣어도 무방합니다.

 

마지막으로 트랜잭션입니다. Firestore 또한 트랜잭션으로 처리 도중에 실패 시 모든 실행을 되돌릴 수 있습니다.

const beforeUser = db.collection('user').doc(beforeNumber);
const afterUser = db.collection('user').doc(phone);

db.runTransaction((transaction) => {
      let userData = userInfo;
      return transaction.get(afterUser).then((data) => {
        	if(!data.exists) 
          		transaction.delete(beforeUser);
          		return transaction.set(afterUser, userData);
        	} else {
          		return Promise.reject(error)
        	}
	})
})

Firestore 트랜잭션의 경우, 먼저 트랜잭션 내부에 사용할 데이터를 명시해야 합니다. beforeUser와 afterUser를 호출하진 않지만 명시한 후, runTransaction 내부에서 사용할 수 있습니다. if 문 내부의 return이 실질적으로 then으로 확인할 수 있는 데이터를 리턴합니다.

 

마지막으로 Firestore 필드에 배열이 있을 경우 배열에 값을 추가하는 메소드입니다.

firebase.firestore.FieldValue.arrayUnion(배열에 넣을 데이터)

이렇게 제가 프로젝트에서 사용했던 Firestore 메소드에 대해서 알아보았습니다.

제가 사용했던 메소드는 v8 방식이니 사용하는 버전을 꼭 확인하시고 참고 부탁드립니다. 더 자세한 정보는 공식홈페이지에서 확인할 수 있습니다.

Comments