2021. 10. 31. 01:13ㆍTIL(Today-I-Learned)/Firebase
# 학습 전 나의 상태
파이어베이스라는 것을 배우게 되는데 이름은 들어봤지만 정확히 어떤 것인지 모른다.
서버를 만들지 않고 서버를 이용할 수 있다는 점이 좋다. 왜냐.. 서버가 나에겐 좀 어렵다 느껴지기 때문이다.
파이어베이스 활용 방법을 잘 익혀서 내일배움단 학습이 끝나면 개인적으로 앱을 만들고 배포까지 진행할 것이다.
그래서 집중해서 잘 듣고 정리해 봐야겠다.
# 오늘의 학습 내용
Firebase란?
- 구글에서 만든 서버리스 서비스
- 서버리스? 서버가 없다는 것이 아닌, 서버를 직접 만들 필요가 없다는 것이다. 직접 구현할 필요 없이 기능을 제공하는 곳
- 학습하면서 사용하게 될 데이터베이스, 이미지 파일 서버는 물론 푸쉬 알람, 로그인 인증 기능 등등 다양한 기능들이 있다.
프로젝트 생성하기
- 파이어베이스 가입 (https://firebase.google.com/?hl=ko)
- 프로젝트 생성
우리는 현재 리액트 네이티브를 이용하기 때문에 웹을 선택한다.
이때 호스팅 설정에 체크 하지 말 것 !!
프로젝트 내 앱을 생성하면 최정적으로 연결 정보를 준다.
앱이 완성되면 콘솔에서 설정 버튼을 눌러준다.
설정에 들어가서 쭉 ~ 내려보면 아래와 같이 사용할 접속 정보가 코드로 존재한다.
firebaseConfig 는 연결할 때 필요한 key 값이다.
파이어베이스 도구 설치 및 연결
expo install firebase
파이어베이스를 이용할 수 있도록 도와주는 expo 도구를 설치한다.
설치가 완료되면 firebaseConfig.js 파일을 생성하고 나의 접속 코드를 입력한다.
const firebaseConfig = {...} 이 안에는 나의 접속 정보 코드를 넣어주고, 추가로 리얼타임 데이타베이스에 들어가면 있는 URL 주소를 복사해 databaseURL: "url주소" 로 추가해준다.
파일 저정소 스토리지(Storage)
- 파일 저장소
- 이미지 및 사용할 파일을 올려두고, 필요할 때마다 꺼내 쓰는 용도로 사용하면 된다.
파일 저장소(Storage)를 생성하고 image 폴더를 만들고 그 안에 이미지를 업로드 해보았다.
이렇게 파일을 올리기만 해도 이미지가 저장된 주소를 제공해준다.
리얼타임 데이터베이스 - 설정, 전체 데이터 읽기
- 데이터를 JSON 형태로 저장/관리 한다.
- 리얼타임 데이터베이스를 만들기 해서 만들어 준다
- 진행 중인 프로젝트 안에서 data.json 파일을 업로드 해보자
- 데이터베이스 안에서 직접 수정 가능하다
이미지 저장은 파일 저장소 스토리지
JSON 데이터는 리얼타임 데이터베이스
App 에서 데이터베이스 불러오기
firebase_db.ref('/tip').once('value').then((snapshot) => {
let tip = snapshot.val();
})
- 이 코는 파이어베이스 측에서 정해놓은 API 사용방법이다
- ref('/tip') 이 부분에서 /tip 영역에 가지고 오고 싶은 데이터의 주소를 넣어주면 된다
- 조회한 데이터는 snapshot 부분에 담겨서 {} 내부에서 사용할 수 있다
- 실제 필요한 데이터는 snapshot.vla()로 가져와 변수에 담아 사용할 수 있다
위 코드를 MainPage.js에 useEffect 안에 넣어줘서 앱이 열리고 화면을 그리고 데이터를 불러오고 불러온 데이터를 다시 그려내도록 한다
여기서 변한 코드가 있다. 바로 setTimeout 함수를 사용하지 않고 파이어베이스 API의 실행 완료 시간에 맡겨두었다.
따라서 파이어베이스로부터 데이터를 가져올 때까지 준비중... 이라는 화면이 보여지고 준비가 되면 불러온 데이터들이 보여지게 되는 자연스러운 서비스 환경을 사용자들에게 제공할 수 있다.
useEffect(()=>{
//헤더의 타이틀 변경
navigation.setOptions({
title:'나만의 꿀팁'
})
firebase_db.ref('/tip').once('value').then((snapshot) => {
console.log("파이어베이스에서 데이터 가져왔습니다!!")
let tip = snapshot.val();
setState(tip)
setCateState(tip)
getLocation()
setReady(false)
});
// setTimeout(()=>{
// let tip = data.tip;
// setState(tip)
// setCateState(tip)
// getLocation()
// setReady(true)
// },500)
},[])
특정 데이터 읽기, 쓰기
현재 메인 화면에 꿀팁을 누르면 상세 화면으로 이동하게 된다.
꿀팁 상세 데이터를 볼 수 있는 이유는 꿀팁 컨텐츠 전체를 상세 페이지로 넘겨주고 있기 때문이다.
Card.js에서 전체 데이터를 상세 페이지로 넘겨주는 것이 아닌, tip idx 번호만 넘겨주고 DetailPage.js 에서 idx로 정보를 서버로부터 조회하고 뿌려주려고 한다.
Q. 그냥 전체 데이터를 뿌려주면 되는데 왜 특정 데이터만 조회하고 뿌려주려고 하는가?
A. 디테일 페이지엔 보통 자세한 내용에 대한 데이터와 댓글 정도의 데이터가 담겨 있는데 이 데이터들도 실시간으로 변경될 수 있다.
그때그때 변경된 데이터가 항상 반영되는 파이어베이스 데이터베이스로부터 가져와야 한다.
만약 큰 데이터들이 페이지를 이동할 때마다 따라다니면 무거워질 수 있기 때문에 idx 번호만 넘겨서 필요한 데이터를 서버로부터 그때그때 오도록 해야한다.
Card.js에서 DetailPage.js 전달 데이터로 idx를 넘겨준다.
import React from 'react';
import {View, Image, Text, StyleSheet,TouchableOpacity} from 'react-native'
//MainPage로 부터 navigation 속성을 전달받아 Card 컴포넌트 안에서 사용
export default function Card({content,navigation}){
return(
//카드 자체가 버튼역할로써 누르게되면 상세페이지로 넘어가게끔 TouchableOpacity를 사용
<TouchableOpacity style={styles.card} onPress={()=>{navigation.navigate('DetailPage',{idx:content.idx})}}>
<Image style={styles.cardImage} source={{uri:content.image}}/>
<View style={styles.cardText}>
<Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
<Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
<Text style={styles.cardDate}>{content.date}</Text>
</View>
</TouchableOpacity>
)
}
DetailPage.js에서 넘겨받은 idx 팁 상세 데이터를 조회한다.
useEffect(()=>{
console.log(route)
navigation.setOptions({
title:route.params.title,
headerStyle: {
backgroundColor: '#000',
shadowColor: "#000",
},
headerTintColor: "#fff",
})
//넘어온 데이터는 route.params에 들어 있습니다.
const { idx } = route.params;
firebase_db.ref('/tip/'+idx).once('value').then((snapshot) => {
let tip = snapshot.val();
setTip(tip)
});
},[])
앱에 데이터를 저장하기
데이터를 언제 저장할까?
나만의 꿀팁 앱에서 팁 찜하기 버튼을 눌렀을 때이다.
그럼 어떻게 팁 찜하기를 저장해야 할까?
먼저 사용자가 어떤 꿀팁을 찜했는지 저장해야한다.
어떤 데이터들이 저장될까?
번호, 이미지, 제목, 내용 등 전체 데이터가 저장된다.
그런데 어떤 사용자가 저장했는지 어떻게 구분할까?
이때 사용자마다 고유한 ID 값 정도의 데이터가 필요하다.
expo는 사용자들의 고유 아이디를 생성할 수 있게 해준다.
expo install expo-constants
import Constants from 'expo-constants';
console.log(Constants.installationId)
new 버전
expo install expo-application
import * as Application from 'expo-application';
const isIOS = Platform.OS === 'ios';
...
const like = async () => {
let uniqueId;
if(isIOS){
let iosId = await Application.getIosIdForVendorAsync();
uniqueId = iosId
}else{
uniqueId = Application.androidId
}
console.log(uniqueId)
}
방금 위에서 저장할 내용은 전체 내용이라고 이야기했다.
const [tip, setTip] = useState()
이 상태에 데이터가 저장되어 관리된다.
const [tip, setTip] = useState({
"idx": 9,
"category": "재테크",
"title": "렌탈 서비스 금액 비교해보기",
"image": "https://firebasestorage.googleapis.com/v0/b/sparta-image.appspot.com/o/lecture%2Frental.png?alt=media&token=97a55844-f077-4aeb-8402-e0a27221570b",
"desc": "요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ",
"date": "2020.09.09"
})
그리고 찜하기, 공유하기, 링크 등 함수를 만들어주고 버튼을 눌렀을 때 onPress로 실행되게 해준다.
const like = () => {
// like 방 안에
// 특정 사용자 방안에
// 특정 찜 데이터 아이디 방안에
// 특정 찜 데이터 몽땅 저장!
// 찜 데이터 방 > 사용자 방 > 어떤 찜인지 아이디
const user_id = Constants.installationId;
firebase_db.ref('/like/'+user_id+'/'+ tip.idx).set(tip,function(error){
console.log(error)
Alert.alert("찜 완료!")
});
}
const share = () => {
Share.share({
message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`,
});
}
const link = () => {
Linking.openURL("https://spartacodingclub.kr")
}
return (
...
<View style={styles.buttonGroup}>
<TouchableOpacity style={styles.button} onPress={()=>like()}><Text style={styles.buttonText}>팁 찜하기</Text></TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={()=>share()}><Text style={styles.buttonText}>팁 공유하기</Text></TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={()=>link()}><Text style={styles.buttonText}>외부 링크</Text></TouchableOpacity>
</View>
...
)
}
찜을 눌렀을 때 아래와 같이 데이터베이스에 저장된다.
# 학습중 에러문제/해결방법
첫 번째 문제 firebaseConfig.js 파일을 만들고 코드를 넣었는데
undefined is not an object (evaluating 'firebase.apps.length')
라는 에러가 나왔다. 이 문제를 해결하기 위해 강의자료와 구글링을 했고
첫 번째 방법으로
import * as firebase from 'firebase/app';
이거를 아래와 같이 변경하는 방법이었다.
import firebase from 'firebase/app';
그렇지만 이 문제를 해결되지 않았다.
도대체 방법이 뭘까 싶어 강의를 다시 보면서 따라도 해보았지만 몇 일째 해결하지 못했었다.
그러던 중 friebase를 다시 설치해보자 라는 생각이 들었고,
먼저 npm i firebase 를 해 설치를 했지만 err..
다음으로 expo install firebase 를 해 설치를 했지만 err..
마지막으로 강의 자료에서 우연히 firebase 버전을 확인할 수 있었다.
그래서 yarn add firebase@7.9.0 으로 설치를 하니 문제가 해결되었다.
정말.. 간단한.. 문제였는데 이거로 몇 일을 고생했으니.. 허무했다.
그리고 이어진 두 번째 문제 왠걸.. 데이터가 안불러와진다.. 준비중만 계속....
이번 에러를 살펴보니
FIREBASE FATAL ERROR: Cannot parse Firebase url. Please use https://<YOUR FIREBASE>.firebaseio.com
databaseURL이 잘못 되었다는 것이다..
뭐지? 왜지? 난 파이어베이스에 나와있는 주소를 넣었는데?!!
뭔가 이상해서 보니 마지막 부분에 firebaseio.com이 아닌 다른 것으로 되어있었다.
그래서 이걸 어떻게 하나 찾아보니 파이어베이스에서 프로젝트를 만들고 리얼타임 디비를 만들때 미국이 아닌 지역을 선택해서 https://<databaseName>.<region>.firebasedatabase.app 이런 형태의 주소가 만들어진 것이다.
그래서 디비를 지우고 다시 만들때 미국을 선택해서 firebaseio.com이 나오도록 했더니 데이터를 정상적으로 불러오게 되었다.
https://firebase.google.com/docs/database/web/start
자바스크립트에서 설치 및 설정 | Firebase Documentation
Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register 의견 보내기 자바스크립트에서 설치 및 설정 Firebase 실시간
firebase.google.com
# 학습을 마치며
파이어베이스 안에서 데이터를 저장하는 방법에 대해서는 이해가 간다.
그런데 이것을 코드로 작성해서 불러오는 것들에 대해서는 아직 미숙하다고 생각한다.
지속적으로 사용하면서 반복숙달하는 것 외에는 방법이 없는 것 같다.
그래도 서버를 따로 만들지 않고 이렇게 이용할 수 있다는 것이 신기하고 잘 활용한다면 편리할 것 같다.
# 시청 또는 참고
- 스파르타코딩클럽 앱 개발 종합반 수업 중..