이전 포스팅에서는 Java Spring을 통해서 Resource Server 부분을 구현해보았는데요. 이번에는 React를 이용하여 Firebase OAuth Client 부분을 구현해 보도록 하겠습니다.
7~8(Spring 영역) 을 제외한 나머지 부분입니다.
프론트엔드에서 파이어베이스를 사용하려면 먼저 Firebase Setting을 해야합니다.
https://console.firebase.google.com 의 자신의 Firebase 프로젝트 페이지에서 웹으로 시작을 눌러봅시다.
이름을 정하고 마지막으로 가면 다음과 같은 설정을 볼 수 있습니다. 해당 부분은 firebase 초기화에 사용합니다.
var firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", measurementId: "" };
Firebase를 설치를 위해 프로젝트에서 다음 명령어를 실행합시다.
// use npm npm install -i firebase@8.10.0 // use yarn yarn add firebase@8.10.0
현재 npm에 올라간 최신 버전은 9버전입니다.. 공식홈페이지에서 9버전은 아직 beta라고 하였기 때문에 정식버전인 8 버전을 설치하도록합시다.
Firebase 인증 키를 주입해서 Firebase를 초기화해봅시다. (firebaseAuth.js)
import firebase from 'firebase/app'; import 'firebase/auth'; const firebaseConfig = { apiKey: "", authDomain: "", projectId: "", storageBucket: "", messagingSenderId: "", appId: "", measurementId: "" }; // Initialize Firebase firebase.initializeApp(firebaseConfig); export const auth = firebase.auth();
우리는 firebase의 auth를 사용할 것이기 떄문에 auth를 export 하였습니다.
firebase.auth().signInWithPopup
메서드는 로그인 방법별 Provider(Google, Facebook등)을 파라미터로 받고 Promise 객체를 리턴합니다. 사용자는 팝업을 통해 로그인을 수행하며 사용자 로그인이 완료되면 Promise에 결과를 받을 수 있습니다.
실제로 해당 메서드가 동작되면 팝업을 띄워 사용자를 로그인 하게 합니다. 로그인이 완료되면 로그인 결과를 Promise로 받을 수 있습니다.
export const signInGoogle= () => { const provider = new firebase.auth.GoogleAuthProvider(); return auth.signInWithPopup(provider); }
export const signOut = () => { return auth.signOut(); }
로그 아웃은 auth.signOut()
을 통해 실행합니다.
대부분의 WebApplication의 경우 User 정보는 Global로 공유해서 사용합니다. Redux등 다양한 기술을 사용할 수 있지만 이번 예제에서는 ContextAPI를 이용하여 하위 컴포넌트에 유저 정보를 전달해주는 AuthProvider Component를 만들어 보겠습니다.
export const UserContext = React.createContext( null ); export const defaultHeaders = { 'Content-Type': 'application/json', 'Accept': 'application/json', }; export const AuthProvider = ({ children }) => { const [user, setUser] = useState(null); const [registerFormOpen, setRegisterFormOpen] = useState(false); useEffect(() => { auth.onAuthStateChanged(async (firebaseUser) => { if(firebaseUser) { // 토큰을 가져온다. const token = await firebaseUser.getIdToken(); // Header에 인증 정보 추가 defaultHeaders.Authorization = `Bearer ${token}`; // 로그인 시도 (백엔드 API 구현 필요) const res = await fetch("/users/me", { method: "GET", headers: defaultHeaders, }); // 로그인 성공시 user를 넘겨줌 if(res.status === 200) { const user = await res.json(); setUser(user); } } else { // 로그아웃시 Header에서 delete defaultHeaders.Authorizations; setUser(null); } }); }, []); // 컴포넌트 첫 로딩시만 실행되도록 [] return ( <UserContext.Provider value={{ user, setUser }}> {children} </UserContext.Provider> ); };
export const UserContext = React.createContext( null );
에서는 User 정보를 담을 Context UserContext를 생성합니다.
<UserContext.Provider value={{ user, setUser }}> {children} </UserContext.Provider>
의 코드를 통해 AuthProvider 하위 컴포넌트에서 AuthProvider에서 선언한 state user, setUser
를 ContextAPI를 통해 사용할 수 있습니다.
auth.onAuthStateChanged
메서드는 이벤트 리스너로 Firebase를 통해 로그인이나 로그아웃이 발생하면 이벤트를 감지하여 사용자 정보를 커스텀 이벤트에 넘겨줍니다. (로그아웃시 null)
위의 코드에서는 useEffect
에서 auth.onAuthStateChanged
를 사용해 컴포넌트 로딩시에 이벤트를 등록하도록 하였습니다.
onAuthStateChange 내부에서는 JWT토큰을 가져와 Header에 집어 넣고 로그인을 시도합니다. 성공시 setUser를 user를 변경해줍니다. 해당 변경은 ContextAPI를 통해 모든 하위 컴포넌트에 적용됩니다.
function Child() { const { user } = useContext(UserContext); return ( <div> {user ? ( <div > <p>{user.email} </p> </div> ) : ( <div > <p>로그인을 해주세요</p> </div> )} {user ? ( <button onClick={signOut}>Sign Out</button> ) : ( <button onClick={signInGoogle}>Sign in With Google</button> )} </div> ); }
하위 컴포넌트에서 user를 useContext
를 통해 가져오고 로그인시 사용자 이메일 주소를 뿌려주고 로그인을 안했을시 로그인을 해달라는 메세지를 뿌려주었습니다.
2장에서 선언한 로그인 로그아웃 메서드를 Button에 사용하였습니다.
AuthProvider와 Child를 적용한 최종 App.js는 다음과 같습니다.
function App() { return ( <AuthProvider> <Child/> </AuthProvider> ); }
https://github.com/Quickeely/OauthSample 에서 회원가입페이지가 포함된 전체 코드를 확인하실 수 있습니다.
couchcoding
2022-12-07
[React - 1] 리액트의 특징
가장 많이 사용하는 프론트엔드 프레임워크는 당연 리액트입니다. 프론트엔드 개발영역이 크지 않던 시절엔 프론트엔드 구인 광고에는 약 70% 이상이 리액트 개발자를 원하고 있습니다. 리액트는 어떤 이유로 가장 인기있는 프레임워크가 되었을까요? 이번 포스팅에서는 리액트의 ...
프론트엔드
couchcoding
2022-12-07
[React-2] 설치하기 & package.json
이전 포스팅에서는 React가 어떤 특징을 가지는 프레임워크인지 알아보았습니다. 이번 포스팅에서는 React를 실제로 다루기 위해서 개발환경을 구성하도록 해보겠습니다. ...
프론트엔드
couchcoding
2022-12-07
프론트엔드 테스트 해야할까? - (1)
그러나 프론트엔드의 중요성이 강조되고, 백엔드의 다양한 기능들이 프론트엔드로 옮겨오면서 프론트엔드가 점점 더 중요해지고, 프론트엔드를 관리 할 필요성이 생기기 시작했죠. 이 과정에서 React, Vue등 다양한 프론트엔드 프레임워크가 생기기 시작합니다. typescr...
프론트엔드
couchcoding
카우치코딩 공식 계정입니다.