카카오 로그인 기능에 이어서 페이스북 로그인 기능도 추가했다. 페이스북 로그인 기능 또한 리액트용 라이브러리를 사용하면 빠르게 구현할 수 있었고,클라이언트에 컴포넌트 추가 이후의 후처리는 카카오 로그인 때문에 수정해 뒀던 서버 단의 로그인 관련 API를 그대로 사용하면 됬었기 때문에 빠르게 진행할 수 있었다.🔥
facebook for developers에 로그인 한뒤 앱 만들기를 통해 페이스북과 연결할 앱을 추가할 수 있으며, 기능 선택 시 여러 옵션이 있지만, 로그인 기능이 필요하므로 3번째 옵션을 선택해주었다.
npm install react-facebook-login
import React from 'react';
import styled from 'styled-components';
import { FaFacebookSquare } from 'react-icons/fa';
import FacebookLogin from 'react-facebook-login/dist/facebook-login-render-props';
const FaceBookLoginButton = styled.button`
{...styled-components}
`;
const ButtonInnerDiv = styled.div`
{...styled-components}
`;
const ButtoninnerText = styled.h3`
{...styled-components}
`;
const FaceBookLogin = ({ oAuthLoginHandler }) => {
const responseFacebook = (response) => {
const { id, email } = response; //페이스북 응답객체에서 id와 email을 할당한 후
oAuthLoginHandler(Number(id), email); // props로 내려준 oAuthLoginHandler라는 함수에 인자로 넘겨준다.
};
return (
<FacebookLogin
appId={FACEBOOK_APP_ID} // 페이스북 앱 등록 후, 생성되는 앱 아이디를 넣어준다.
autoLoad={false} // 자동 실행 여부를 정해줄 수 있다.
fields="name,email,picture" // fields 설정
callback={responseFacebook}
render={(renderProps) => (
<FaceBookLoginButton>
<ButtonInnerDiv onClick={renderProps.onClick}>
<FaFacebookSquare
style={{
marginRight: '23px',
fontSize: '26px',
}}
/>
<ButtoninnerText>페이스북 계정으로 로그인</ButtoninnerText>
</ButtonInnerDiv>
</FaceBookLoginButton>
)}
></FacebookLogin>
);
};
export default FaceBookLogin;
모듈 사용 시 공식 문서의 기본 가이드 방식대로
( import FacebookLogin from 'react-facebook-login')
으로 해버리면 라이브러리 자체에서 설정되있는 버튼 디자인을 사용해야하므로, 임의로 스타일과 구조에 변화를 주고싶다면import FacebookLogin from 'react-facebook-login/dist/facebook-login-render-props'
로 모듈을 추가해주면 된다. 그후 컴포넌트 옵션에render
를 추가해준 후 내부에 원하는대로 넣어주면 된다.
(응답 객체에는 컴포넌트 옵션 중 fields
에 들어간 항목들과, 토큰 등이 담겨져있다.)
로그인이 끝난 뒤엔 상단의 코드를 보면 props로
oAuthLoginHandler
라는 함수를 받은 뒤 id와 email을 인자로 넘겨주는것을 볼 수 있는데, (여기서 id와 email은 페이스북 계정으로 로그인 시 응답해주는 유저 객체이다.) 카카오톡 로그인 방식과 마찬가지로 request객체에 담아서 리덕스 사가의 loginUser 액션으로 전달되고 사가 함수에 의해 서버의 로그인 api로 POST요청을 보낸다.
/ server/ routes/ api/ ~ / user_login.js
import express from "express";
import User from "../../../models/User"; //Mongo DB의 User 모델을 불러온다.
const router = express.Router();
router.post("/", (req, res) => {
// 소셜 로그인 시
if (req.body.oAuthId) { //요청 body에 oAuthId 키가 존재하는지 체크한다.
//만일 존재한다면, DB에 해당 oAuthId를 갖고있는 유저를 탐색한다.
User.findOne({ oAuthId: req.body.oAuthId }, (err, user) => {
if (!user) {
const userSchema = new User(req.body);
// 계정 생성
userSchema.save((err, _) => {
if (err) return res.json({ success: false, err });
return res.status(200).json({
registerSuccess: true,
});
});
}
//JWT 토큰 발급
user.generateToken((err, user) => {
if (err) return res.status(400).send(err);
// save Token at Cookie
res
.cookie("x_auth", user.token) //쿠키에 JWT토큰을 넣어준다.
.status(200)
.json({ loginSuccess: true, userId: user._Id, token: user.token });
});
});
return;
} else { // 일반 로그인 시
//Find Email at DB
User.findOne({ email: req.body.email }, (err, user) => {
if (!user) {
return res.json({
loginSuccess: false,
message: "해당 이메일에 해당하는 유저가 없습니다.",
});
}
//Check Password
user.comparePassword(req.body.password, (err, isMatch) => {
if (!isMatch)
return res.json({
loginSuccess: false,
message: "비밀번호가 틀렸습니다.",
});
//Make Token
user.generateToken((err, user) => {
if (err) return res.status(400).send(err);
//save Token at Cookie
res
.cookie("x_auth", user.token)
.status(200)
.json({ loginSuccess: true, userId: user._Id, token: user.token });
});
});
});
}
});
export default router;
이후 카카오 로그인과 동일하게 로그인 API로 POST 요청 시 request body에 oAuthId 키가 존재하는지 체크한다. 만일 존재한다면, DB에 해당 oAuthId를 갖고있는 유저를 탐색한다. 만일 존재하지 않는다면, 계정을 생성한 뒤 JWT토큰을 발급하여 쿠키에 넣어준다.