구현한 기능
핵심 기술
npm install firebase
// src폴더안에 api폴더 안에 firebase.js파일
// 불필요한 내용들은 삭제한 상태다.
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: "AIzaSyDrbqC7UbsTf9DC3vBEl9JMhv--G3-V7B0",
authDomain: "shopping-5c758.firebaseapp.com",
databaseURL: "https://shopping-5c758-default-rtdb.asia-southeast1.firebasedatabase.app",
projectId: "shopping-5c758",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// env.local이라는 파일이고 왼쪽 처럼 네이밍을 해서 위의 코드를 넣어준다.
// REACT_APP_을 꼭 붙이고, 그 뒤에 원하는 이름을 작성하면 된다.
REACT_APP_FIREBASE_API_KEY=AIzaSyDrbqC7UbsTf9DC3vBEl9JMhv--G3-V7B0
REACT_APP_FIREBASE_AUTH_DOMAIN=shopping-5c758.firebaseapp.com
REACT_APP_FIREBASE_DB_URL=https://shopping-5c758-default-rtdb.asia-southeast1.firebasedatabase.app
REACT_APP_FIREBASE_PROJECT_ID=shopping-5c758
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DB_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
};
const app = initializeApp(firebaseConfig);
import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DB_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
};
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const provider = new GoogleAuthProvider();
export function login() {
signInWithPopup(auth, provider)
.then((result) => {
const user = result.user;
console.log(user)
})
.catch(console.error);
}
import { getAuth, signInWithPopup, GoogleAuthProvider,signOut,onAuthStateChanged } from "firebase/auth";
import { initializeApp } from "firebase/app";
// docs에 나와 있는 대로 import를 하고
import { getDatabase, ref, child, get, DataSnapshot } from "firebase/database";
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.REACT_APP_FIREBASE_DB_URL,
projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
};
const app = initializeApp(firebaseConfig);
const auth = getAuth();
const provider = new GoogleAuthProvider();
export async function login() {
return signInWithPopup(auth, provider)
.then((result) => {
const user = result.user;
// console.log(user)
return user
})
.catch(console.error);
}
export async function logout() {
return signOut(auth).then(()=> null)
}
//아래에서 adminuser를 만들었고, adminuser는 비동기 함수 이기 때문에 여기도 async를 붙여 주고,
// user가 true라면, 즉 로그인을 했다면 adminuser함수를 호출을 하는 코드를 작성해서 인자로 들어온 callback함수의
// 인자로 넣어 준다.
export function onUserStateChange(callback) {
onAuthStateChanged(auth, async (user) => {
const updatedUser = user ? adminuser(user) : null
callback(updatedUser)
});
}
//import한 getDatabase를 활용하여 데이터 베이스를 가져오고
const database = getDatabase(app)
// 그리고 adminuser함수를 만든다. adminuser함수는 firebase의 database에서 data를 가져온다
// 즉 네트워크 통신이 이루어지기 때문에 비동기 처리를 위해 async를 붙여 준다.
async function adminuser(user) {
// docs에 나와있는대로 ref를 활용하여 초기화된 database를 가져오고, 그 중 database에 들어
// 있는 admins라는 배열을 가져올 것이다.그리고 데이터를 잘 가지고 왔다면 snapshot이 전달이 될
//것이고,snapshot이 존재 한다면 val를 이용해서 snapshot에 있는 value를 가지고 와
// admins라는 변수에 넣어 준다.
// 그리고 isAdmin이라는 변수에는 로그인한 사용자의 uid값을 넣어서 할당해 주고
// 최종적으로 adminuser함수의 인자로 들어온 user정보 객체 안에, isAdmin을 추가해 준다.
return get(ref(database, 'admins'))//
.then((snapshot) => {
if(snapshot.exists()) {
const admins = snapshot.val()
console.log(admins)
const isAdmin = admins.includes(user.uid)
return {...user, isAdmin}
}
// admin이라는 데이터가 존재하지 않거나 데이터를 잘 받아오지 못하였을 경우에는 그냥 User를 리턴한다.
return user;
})
}
```
```jsx
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import {HiShoppingBag} from 'react-icons/hi'
import {GiClothes} from 'react-icons/gi'
import { login, logout, onUserStateChange } from "../api/firebase";
import UserInfo from './UserInfo';
export default function Navbar() {
const [user, setUser] = useState()
// console.log(user)
const handleLogin = () => {
login().then(user=> setUser(user))
}
const handleLogout = () => {
logout().then(user=> setUser(user))
}
//firebase에서 로직을 구현을 했고, navbar에서 onUserStateChange를 호출할때 들어온 인자는 사용자가 admin이면 isAdmin이 true
// 라는 것이 포함되어 전달이 될 것이고, 그걸 상태값으로 업데이트 해주면 어드민사용자로 로그인이 된걸 확인할 수 있다.
useEffect(()=>{
onUserStateChange((user) => {
// console.log(user)
setUser(user)
})
},[])
return (
<header className='flex justify-between border-b border-gray-300 p-2'>
<Link to='/' className='flex items-center text-3xl text-logo'>
<HiShoppingBag />
<h1>뉴이어</h1>
</Link>
<nav className='flex items-center gap-4 font-semibold'>
<Link to='/products'>상품</Link>
<Link to='/carts'>장바구니</Link>
<Link to='/products/new' className='text-2xl'>
<GiClothes/>
</Link>
{user && <UserInfo user={user}/>}
{!user && <button onClick={handleLogin}>Login</button>}
{user && <button onClick={handleLogout}>LogOut</button>}
</nav>
</header>
)
}
```
코드를 입력하세요
개발자 도구를 살펴 보면 isAdmin이 true인 것을 확인해 볼 수 있다.