일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Next.js
- 백준
- iP
- firebaseui
- 파이썬
- React
- css
- 자바스크립트
- leetcode189
- 커스텀알림
- 프로토타입
- react-firebaseui
- Spread
- mac
- leetcode977
- nvmrc
- nvm
- youtube iframe
- 파이어베이스로그인
- yarn-berry
- 기초
- JS
- 리액트
- 커스텀알락
- react-native
- Rest
- 구조분해할당
- TCPvsUDP
- Python
- 다리놓기
- Today
- Total
JadeCode
[혼프] 혼자하는 프로젝트 1. firebase-auth 적용기 본문
MEALTI - mealtime(식사시간) - 식비기록가계부 커뮤니티
작년 2학기, 캡스톤 디자인이라는 수업에서 팀 프로젝트를 했다. 하지만 리액트 네이티브를 처음 도입해봤고, 새로운 시도였기 때문에 별로 마음에 들지 않았다. 피그마에 디자인이 남아있기도 해서 혼자 firebase로 적용해보겠다고 생각했다.
firebase로그인 with firebaseui
next-firebase-auth를 사용할까 하다가 firebaseui로 하면 더 쉬울 것 같아서 react-firebaseui를 하려고 했다가.
https://github.com/gladly-team/next-firebase-auth#readme
위의 깃에서 example이 있길래 클론받아서 동작시켜 봤다.
firebase에서 프로젝트 생성하고, firebaseConfig를 저장하고, 적용시키는 것 부터 했다.
process.env.~~로 시작하는 코드를 보니 .env파일은 보안이 중요해서 깃에 올리지 않은 걸로 보인다.
그래서 직접 생성한 파이어베이스 프로젝트 정보로 나도 .env 파일을 만들어 npm run dev를 해 봤다.
하지만 프로젝트를 살펴보니 "react-firebaseui/StyledFirebaseAuth"에 내가 진짜 원하는 파이어베이스 로그인 방법이 있길래, 최소한의 라이브러리를 사용하고자 react-firebaseui를 도입하려했다.
https://www.npmjs.com/package/firebaseui
https://github.com/firebase/firebaseui-web#react-dom-setup
일단 패키지를 다운받고 사용법을 알아보려 깃으로 갔다.
리액트에서 사용할 것이기 때문에 React DOM Setup으로 확인 해 봤다.
https://github.com/firebase/firebaseui-web-react
npm install --save react-firebaseui
npm install --save firebase
위의 코드로 설치하라 했다. 하지만
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: new_project@0.1.0
npm ERR! Found: react@18.2.0
npm ERR! node_modules/react
npm ERR! react@"18.2.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@">=15 <=17" from react-firebaseui@6.0.0
npm ERR! node_modules/react-firebaseui
npm ERR! react-firebaseui@"*" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
이런 오류가 뜨는 것이다. 정말...
이 때부터 알아차려야 했다. react-firebaseui를 사용하면 안된단걸...
하지만 나는 일단 해보자 라는 생각으로
npm install --save react-firebaseui --legacy-peer-deps
로 리액트 파이어베이스 유아이를 깔았다.
문서에 나와있는 대로
// Import FirebaseAuth and firebase.
import React from 'react';
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
// Configure Firebase.
// 내 프로젝트 정보.
const config = {
apiKey: 'AIzaSyAeue-AsYu76MMQlTOM-KlbYBlusW9c1FM',
authDomain: 'myproject-1234.firebaseapp.com',
// ...
};
firebase.initializeApp(config);
// Configure FirebaseUI.
const uiConfig = {
// Popup signin flow rather than redirect flow.
signInFlow: 'popup',
// Redirect to /signedIn after sign in is successful. Alternatively you can provide a callbacks.signInSuccess function.
signInSuccessUrl: '/signedIn',
// We will display Google and Facebook as auth providers.
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID,
firebase.auth.FacebookAuthProvider.PROVIDER_ID,
],
};
function SignInScreen() {
return (
<div>
<h1>My App</h1>
<p>Please sign-in:</p>
<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()} />
</div>
);
}
export default SignInScreen
코드를 실행해 봤지만 돌아오는 것은 참담했다.
엄청난 구글링 끝에 원인을 알아냈다.
https://github.com/firebase/firebaseui-web-react/issues/172
https://github.com/firebase/firebaseui-web-react/pull/173
많은 사람들이 같은 오류를 겪고 있었고, merge가 되었냐는 질문을 보아하니 아직 반영이 안된 것 같았다.
진짜 똑똑하고 착한 사람들이 react-firebaseui를 쓰지 말고 직접 컴포넌트를 만들어서 쓰라고 코드도 올려 줬다.
//MartinXPN 사람의 답변
import { useEffect, useRef, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import 'firebaseui/dist/firebaseui.css';
import {auth} from "firebaseui";
interface Props {
// The Firebase UI Web UI Config object.
// See: https://github.com/firebase/firebaseui-web#configuration
uiConfig: auth.Config;
// Callback that will be passed the FirebaseUi instance before it is
// started. This allows access to certain configuration options such as
// disableAutoSignIn().
uiCallback?(ui: auth.AuthUI): void;
// The Firebase App auth instance to use.
firebaseAuth: any; // As firebaseui-web
className?: string;
}
const StyledFirebaseAuth = ({uiConfig, firebaseAuth, className, uiCallback}: Props) => {
const [firebaseui, setFirebaseui] = useState<typeof import('firebaseui') | null>(null);
const [userSignedIn, setUserSignedIn] = useState(false);
const elementRef = useRef(null);
useEffect(() => {
// Firebase UI only works on the Client. So we're loading the package only after
// the component has mounted, so that this works when doing server-side rendering.
setFirebaseui(require('firebaseui'));
}, []);
useEffect(() => {
if (firebaseui === null )
return;
// Get or Create a firebaseUI instance.
const firebaseUiWidget = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebaseAuth);
if (uiConfig.signInFlow === 'popup')
firebaseUiWidget.reset();
// We track the auth state to reset firebaseUi if the user signs out.
const unregisterAuthObserver = onAuthStateChanged(firebaseAuth, user => {
if (!user && userSignedIn)
firebaseUiWidget.reset();
setUserSignedIn(!!user);
});
// Trigger the callback if any was set.
if (uiCallback)
uiCallback(firebaseUiWidget);
// Render the firebaseUi Widget.
// @ts-ignore
firebaseUiWidget.start(elementRef.current, uiConfig);
return () => {
unregisterAuthObserver();
firebaseUiWidget.reset();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [firebaseui, uiConfig]);
return <div className={className} ref={elementRef} />;
};
export default StyledFirebaseAuth;
MartinXPN 진짜 똑똑한 사람이다. 이 사람의 코드를 쓰니 실행이 잘 되었다.
결과
그래서 최종 나의 firebase-auth코드이다.
Email로그인은 따로 회원가입 없이 로그인이 가능하다!!
// pages/auth/login.tsx
// Import FirebaseAuth and firebase.
import StyledFirebaseAuth from "StyledFirebaseAuth";
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import { fireAuth } from "clientApp";
import { useRouter } from "next/router";
function Login() {
const router = useRouter();
// Configure FirebaseUI.
const uiConfig = {
// Popup signin flow rather than redirect flow.
signInFlow: "popup",
// 이메일 인증과 구글 인증
signInOptions: [
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
requireDisplayName: true,
buttonColor: "#FFBC58", // 원하는 버튼 색깔
},
firebase.auth.GoogleAuthProvider.PROVIDER_ID, // 구글
],
callbacks: {
signInSuccessWithAuthResult: (res: any) => {
setCurrentUser(res.additionalUserInfo.profile);
router.push("/");
return false;
},
},
};
return (
<>
<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={fireAuth} />
</>
);
}
export default Login;
// clientApp.ts
// 초기화 및 사용
import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import "firebase/compat/auth";
import firebaseConfig from "firebaseConfig.json";
const app = firebase.initializeApp(firebaseConfig);
const fireAuth = firebase.auth();
export { fireAuth };
// firebaseConfig.json
// 처음 프로젝트 생성하면 보여주는 것 ~
{
"apiKey": "앱 키",
"authDomain": "앱 도메인",
"databaseURL": "데이터베이스 url",
"projectId": "프로젝트 아이디",
"storageBucket": "스토리지 버킷",
"messagingSenderId": "메세지센더아이디",
"appId": "앱 아이디",
"measurementId": "아이디"
}
// StyledFirebaseAuth.tsx
// https://github.com/firebase/firebaseui-web-react/pull/173
import { useEffect, useRef, useState } from "react";
import { onAuthStateChanged } from "firebase/auth";
import "firebaseui/dist/firebaseui.css";
import { auth } from "firebaseui";
interface Props {
// The Firebase UI Web UI Config object.
// See: https://github.com/firebase/firebaseui-web#configuration
uiConfig: auth.Config;
// Callback that will be passed the FirebaseUi instance before it is
// started. This allows access to certain configuration options such as
// disableAutoSignIn().
uiCallback?(ui: auth.AuthUI): void;
// The Firebase App auth instance to use.
firebaseAuth: any; // As firebaseui-web
className?: string;
}
const StyledFirebaseAuth = ({
uiConfig,
firebaseAuth,
className,
uiCallback,
}: Props) => {
const [firebaseui, setFirebaseui] = useState<
typeof import("firebaseui") | null
>(null);
const [userSignedIn, setUserSignedIn] = useState(false);
const elementRef = useRef(null);
useEffect(() => {
// Firebase UI only works on the Client. So we're loading the package only after
// the component has mounted, so that this works when doing server-side rendering.
setFirebaseui(require("firebaseui"));
}, []);
useEffect(() => {
if (firebaseui === null) return;
// Get or Create a firebaseUI instance.
const firebaseUiWidget =
firebaseui.auth.AuthUI.getInstance() ||
new firebaseui.auth.AuthUI(firebaseAuth);
if (uiConfig.signInFlow === "popup") firebaseUiWidget.reset();
// We track the auth state to reset firebaseUi if the user signs out.
const unregisterAuthObserver = onAuthStateChanged(firebaseAuth, (user) => {
if (!user && userSignedIn) firebaseUiWidget.reset();
setUserSignedIn(!!user);
});
// Trigger the callback if any was set.
if (uiCallback) uiCallback(firebaseUiWidget);
// Render the firebaseUi Widget.
// @ts-ignore
firebaseUiWidget.start(elementRef.current, uiConfig);
return () => {
unregisterAuthObserver();
firebaseUiWidget.reset();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [firebaseui, uiConfig]);
return <div className={className} ref={elementRef} />;
};
export default StyledFirebaseAuth;
// 이메일 인증 시 원하는 색깔로 바꾸기 !important 원하는컬러 자리에 색상코드
.firebaseui-button {
background-color: #원하는컬러 !important;
color: white !important;
}
.firebaseui-textfield.mdl-textfield .firebaseui-label:after {
background-color: #원하는컬러 !important;
}
.firebaseui-form-links > a {
color: #원하는컬러;
}
.mdl-progress > .progressbar {
background-color: #원하는컬러 !important;
}
.mdl-progress > .bufferbar {
background-image: linear-gradient(
90deg,
hsla(0, 0%, 100%, 0.7),
hsla(0, 0%, 100%, 0.7)
),
linear-gradient(90deg, #원하는컬러, #원하는컬러) !important;
z-index: 0;
left: 0;
}
.mdl-progress:not(.mdl-progress--indeterminate) > .auxbar,
.mdl-progress:not(.mdl-progress__indeterminate) > .auxbar {
background-image: linear-gradient(
90deg,
hsla(0, 0%, 100%, 0.9),
hsla(0, 0%, 100%, 0.9)
),
linear-gradient(90deg, #원하는컬러, #원하는컬러) !important;
}
이틀 간의 고생 끝에 결국 성공했다!!
'개발' 카테고리의 다른 글
[혼프] 혼자하는 프로젝트 3. firebase storage (0) | 2023.03.31 |
---|---|
[혼프] 혼자하는 프로젝트 2. firebase store (0) | 2023.03.30 |
React-Query 도입에 대한 고민 (0) | 2023.03.16 |
[styled-components] 타입스크립트 적용, 다크모드 (0) | 2023.03.14 |
console.log에 색깔 넣기 (0) | 2023.03.04 |