03. 로그인 페이지 생성하기
01. Firebase에 대해서
Firebase란?
모바일 및 웹 애플리케이션을 만들기 위해 구글에서 개발한 플랫폼이다.
대부분의 앱을 만들때 필요한 부분들
인증 / 데잉터베이스 / 스토리지 / 푸시알림 / 배포 등등
을 자동으로 만들어주는 플랫폼이다.
firebase를 이용한 앱 구조

02. Firebase와 애플리케이션 연결하기
- firebase 사이트 firebase 바로가기
- 회원가입 & 로그인
콘솔로 이동
- 프로젝트 생성








- firebase연결하기
npm install firebase
firebase.js 파일 생성

export default app;
추가
03. 로그인 페이지를 위한 경로 생성 및 Navbar 생성하기
router, Layout 생성
| const Layout = () => { |
| return ( |
| <> |
| <NavBar /> |
| <br /> |
| <br /> |
| <br /> |
| <Outlet /> |
| </> |
| ) |
| } |
| |
| const App = () => { |
| return ( |
| <BrowserRouter> |
| <Routes> |
| <Route path="/" element={<Layout />}> |
| <Route index element={<MainPage />}/> |
| <Route path="login" element={<LoginPage />}/> |
| <Route path="/pokemon/:id" element={<DetailPage />}/> |
| </Route> |
| </Routes> |
| </BrowserRouter> |
| ) |
| } |
04. 로그인 페이지 UI 생성하기
| import React from 'react' |
| const LoginPage = () => { |
| return ( |
| <section className="bg-gray-50 min-h-[90vh] flex items-center justify-center"> |
| <div className="bg-gray-100 flex rounded-2xl shadow-lg max-w-3xl p-5 items-center"> |
| <div className="md:w-1/2 px-8 md:px-16"> |
| <h2 className="font-bold text-2xl ">Pokemon</h2> |
| <p className="text-xs mt-4 text-[#002D74]">포켓몬 사이트에 오신걸</p> |
| <p className="text-xs mt-4 text-[#002D74]">환영합니다.</p> |
| <p className="text-xs mt-4 text-[#002D74]">로그인 해주세요.</p> |
| </div> |
| <div className="md:block hidden w-1/2"> |
| <img |
| alt="login" |
| className="rounded-2xl" |
| src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/7.png" |
| /> |
| </div> |
| </div> |
| </section> |
| ); |
| } |
| |
| export default LoginPage |
05. Styled Component 에 대해서 알아보기
컴포넌트 생성후에 스타일 정의한것을 입힐수있음
props로 스타일링 정의가능
06. Navbar 컴포넌트 UI 생성하기
| import React from 'react' |
| import styled from 'styled-components' |
| |
| const NavBar = () => { |
| return ( |
| <NavWrapper> |
| <Logo> |
| <Image |
| alt="Pokemon Logo" |
| src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/25.png" |
| onClick={() => (window.location.href = "/")} |
| /> |
| </Logo> |
| </NavWrapper> |
| ); |
| } |
| |
| const NavWrapper = styled.nav` |
| position: fixed; |
| top: 0; |
| left:0; |
| right:0; |
| display: flex; |
| justify-content: space-between; |
| align-items: center; |
| padding: 0 36px; |
| letter-spacing: 16px; |
| z-index: 100; |
| ` |
| const Logo = styled.a` |
| padding: 0; |
| width: 50px; |
| margin-top: 4px; |
| ` |
| const Image = styled.img` |
| cursor: pointer; |
| width: 100%; |
| `; |
| |
| export default NavBar |
스크롤시 NavBar 색깔 변경
여러가지 구현방법이 있지만.
스크롤이라는 이벤트가 발생하면 어떠한 함수를 호출할 건지 리스너를 등록한다.
이것을 이벤트 리스너등록이라고 한다.
이 리스너를 등록했기때문에 마우스 스크롤을 할 때마다 함수가 호출된다.
해당 컴포넌트를 사용하지 않는다면 리스너를 제거해주어야한다.
state와 이벤트리스너 등록/제거
| const [show, setShow] = useState(false); |
| |
| const listner = () => { |
| if(window.scrollY > 50) { |
| setShow(true); |
| } else { |
| setShow(false) |
| } |
| } |
| |
| useEffect(() => { |
| window.addEventListener("scroll", listner); |
| |
| return () => { |
| window.removeEventListener("scroll", listner) |
| } |
| }, []) |
styled-component에서 props 다루는법
- 컴포넌트에서 props 등록
<NavWrapper show={show}>
- styled-component 스타일 정의에서 props를 조건절로 사용
background: ${props => props.show ? "#090b13": "transparent"};
07. Firebase를 이용해서 로그인하기
로그인버튼 styled-component
| const Login = styled.a` |
| background: rgba( 0, 0, 0, .6); |
| padding: 8px 16px; |
| text-transform: uppercase; |
| letter-spacing: 1.55px; |
| border: 1px solid #f9f9f9; |
| color: #f9f9f9; |
| border-radius: 4px; |
| transition: all .2s ease 0s; |
| |
| &:hover { |
| background-color: #f9f9f9; |
| color: #000; |
| border-color: transparent; |
| } |
| ` |
Firebase SDK로 로그인 과정 처리
Firebase Authentication 설정

빌드 > Authentication > 시작하기

Sign-in method > Google

구글 사용설정 enable하고 저장까지 완료해야한다.
구글 로그인 연결
firebase docs
구글 로그인 예시
| import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth"; |
| |
| const auth = getAuth(); |
| signInWithPopup(auth, provider) |
| .then((result) => { |
| |
| const credential = GoogleAuthProvider.credentialFromResult(result); |
| const token = credential.accessToken; |
| |
| const user = result.user; |
| |
| |
| }).catch((error) => { |
| |
| const errorCode = error.code; |
| const errorMessage = error.message; |
| |
| const email = error.customData.email; |
| |
| const credential = GoogleAuthProvider.credentialFromError(error); |
| |
| }); |
| |
| const handleAuth = () => { |
| signInWithPopup(auth, provider) |
| .then(result => { |
| console.log(result) |
| }) |
| .catch(error => { |
| console.error(error); |
| }) |
| } |
| |
| ... |
| <Login onClick={handleAuth}>로그인</Login> |
08. Firebase를 이용한 로그인 상태 체크(onAuthStateChanged)
Firebase SDK로 인증상태 체크하는 리스너 등록하기
| useEffect(() => { |
| |
| const unsubscribe = onAuthStateChanged(auth, (user) => { |
| console.log("user", user); |
| if (!user) { |
| |
| navigate("/login"); |
| } else if (user && pathname === "/login") { |
| navigate("/"); |
| } else { |
| } |
| }); |
| |
| return () => { |
| unsubscribe(); |
| }; |
| }, [pathname]) |
09. 로그아웃 기능 구현하기

프로필 표시
UI
| <SignOut> |
| <UserImg |
| src={userData.photoURL} |
| alt="" |
| /> |
| <DropDown onClick={handleSignOut}>로그아웃</DropDown> |
| </SignOut> |
로그인시 유저데이터 state에 저장하기
| const [userData, setUserData] = useState({}); |
| |
| |
| const handleAuth = () => { |
| signInWithPopup(auth, provider) |
| .then(result => { |
| setUserData(result.user) |
| }) |
| .catch(error => { |
| console.error(error); |
| }) |
| } |
로그아웃 handleSignOut
| |
| const handleSignOut = () => { |
| signOut(auth) |
| .then(() => { |
| setUserData({}); |
| }) |
| .catch(error => { |
| alert(error.massage); |
| }) |
| } |
10. 데이터 유지하기
localStorage에 userData 값을 담아서 페이지를 refresh해도 userData가 계속 남을수 있도록 저장할것이다.
local storage에 데이터 저장
mozilla localStorage docs
로그인시에 setUserData할때 같이 넣어주면되는데
localStorage item에는 객체를 넣어줄 수 없으므로
JSON.stringify()
을 해줘서 문자열로 바꿔서 넣어주고
쓸때는 JSON을 parse해서 사용함
localStorage.setItem("userData", JSON.stringify(result.user))
| |
| const handleAuth = () => { |
| signInWithPopup(auth, provider) |
| .then(result => { |
| setUserData(result.user) |
| localStorage.setItem("userData", JSON.stringify(result.user)) |
| }) |
| .catch(error => { |
| console.error(error); |
| }) |
| } |

다시 로그인하면 로컬스토리지에 넣어진것을 확인 할 수 있다.
데이터 유지하기: useState 초기값 변경
새로고침시에 userData가 다시 빈객체가 되는데
이것은 초기값을 다시 지정해주면 된다.
| const initialUserData = localStorage.getItem("userData") ? |
| JSON.parse(localStorage.getItem("userData")) : {}; |
| |
| ... |
| const [userData, setUserData] = useState(initialUserData); |