Passport 활용! Facebook 로그인

송은석·2021년 5월 31일
0
post-thumbnail

환경: React(next.js), nodeJS(express.js)

passport를 활용하면 회원관리가 쉬워진다고 해서 써봤습니다.

후후.. 안쉬웠습니다.

생각보다 오래 걸렸으니깐 어려웠던 걸로..

그렇지만 하고나서 왜 편하다고 했는지는 알 수 있었습니다. 반복되는 패턴을 알게 되었기 때문!

다운 받는 내용들은 다른 블로그들에 많이 설명되어 있으니깐 개인적으로 어려웠던 부분들을 위주로 살펴보겠습니다.


1. 프론트 (React)

먼저 프론트 단에서는 페이지 하나만 있으면 됩니다. 클릭하면 sns의 로그인 페이지로 보내줄! 정말 간단하게는 다음과 같으면 됩니다.

import React from 'react';
import Link from 'next/link';
import { AiFillFacebook } from 'react-icons/ai';

const SocialLogin = () => (
  <div>
    <Link href="http://localhost:3065/auth/kakao">
      <a>
        <RiKakaoTalkFill style={{ fontSize: '100' }} />
      </a>
    </div>
);
    
export default SocialLogin;

위 코드에서 짚고 넘어가야 하는 것은,

  1. axios로 비동기 통신을 하지 않고 href 태그를 통해서 이동한다는 점입니다. 첫 요청 이후 필요한 콜백 요청을 axios는 다룰 수 없기 때문입니다. (콜 백 필 요 합 니 다)

  2. 그리고 axios를 거치지 않고 바로 백단으로 요청을 보내기 때문에 백단 포트번호인 3065로 주소를 적어줍니다.(react로 구성된 프론트단의 포트번호는 3000입니다.) 이후 여기의 코드에서 사용되는 모든 포트번호는 백단의 포트번호라고 생각하면 됩니다.

2. 백 (nodeJS)

제가 구성한 파일과 폴더를 얘기하자면, 아래 사진과 같습니다.

"제가 구성한" 이라고 굳이 말한 이유는, 꼭 이렇게 하지는 않아도 되기 때문입니다. 위 폴더 파일 구성과 함께 백단을 구성해 보겠습니다.

passport 폴더

먼저 모든 passport파일들을 모아줄 index.js 파일을 작성합니다.

// /passport/index.js
const passport = require('passport');
const { User } = require('../models');
const facebook = require('./facebook');

module.exports = () => {
    passport.serializeUser((user, done) => {
      //req.login의 user가 여기로 들어감
        done(null, user.id);
    });
    // 로그인 성공 후 요청 시 매번 시행되어 사용자 정보를 복구함.
    passport.deserializeUser(async (id, done) => {
        try {
            const user = await User.findOne({ where: { id } })
            done(null, user); // 매번 req.user에 유저 정보를 넣어줌
        } catch (error) {
            console.error(error);
            done(error);
        }
    });
    facebook();
};

로그인되면서 passport는 처음 serializeUser을 실행하여 로그인을 하고, 이후에는 deserializeUser를 통해 프론트에 서버의 유저 정보를 전달합니다. 꼭 적어주어야 하는 부분입니다.

그리고 import한 facebook파일을 통하여 facebook 소셜 로그인이 가능하게 됩니다. 한번 살펴볼까요!

// /passport/facebook.js
const passport = require('passport');
const FacebookStrategy = require('passport-facebook').Strategy;

module.exports = () => {
    passport.use(new FacebookStrategy({
      clientID: '페이스북 클라이언트 아이디',
      clientSecret: '페이스북 시크릿',
      callbackURL: 'http://localhost:3065/auth/facebook/callback',
      profileFields: ['id', 'displayName', 'email'],
      passReqToCallback: true,
    },  (req, accessToken, refreshToken, profile, done) => {
    	//db 연결 어떻게 할지 서술
    }
    }));
  };

페이스북에서 발급받은 clientID와 clientSecret를 적어주고(물론 dotenv 같은 것을 활용하는 것이 좋습니다.) callbackURL을 적어줍니다. 역시 백단의 포트번호 3065를 적습니다.

아래 "//db 연결 어떻게 할지 서술" 이라고 주석을 달며 얼렁뚱땅 생략한 부분은 페이스북으로 부터 유저 데이터를 받아서 데이터베이스에 사용하는 부분입니다.

멋있게 strategy라고 하는데, 개인의 db에 맞게 적절하게 짜면 됩니다.

이렇게 passport 폴더 부분은 마무리되었습니다.

routes 폴더

이번엔 routes 폴더의 auth.js 파일을 같이 살펴보겠습니다.
코드는 다음과 같습니다.

const express = require('express');
const passport = require('passport');

const router = express.Router();

// 페이스북
router.get('/facebook', passport.authenticate('facebook', {
    authType: 'rerequest', scope: ['public_profile', 'email']
}));

router.get('/facebook/callback', passport.authenticate('facebook', {
  failureRedirect: '/' }), function(req, res) {
    res.redirect('http://localhost:3000');
});


module.exports = router;

get api가 두 개 있습니다.
처음의 get으로 페이스북에 요청을 보내고,

이후 페이스북으로부터 페이지를 받아 로그인 한 뒤 성공하면

두번째 get을 통해 유저 정보를 받고 res.redirect 안의 페이지로 이동을 하게 됩니다. 백단에서 나오는 유일한 포트 번호 3000의 페이지입니다^^
로그인 후 위치하고 싶은 주소를 적어주면 됩니다.

app.js

대망의 마지막 파일!

후후 블로그 글 작성하는 게 쉬운 일이 아니었네요.

어쨌든 코드를 함께 보시죠!

const express = require('express');
const session = require('express-session');
const passport = require('passport');
const authRouter = require('./routes/auth');
const passportConfig = require('./passport');
const app = express();

passportConfig();

app.use(passport.initialize());
app.use(passport.session());

app.use('/auth', authRouter);

app.listen(3065, () => {
    console.log('서버 실행 중');
});

생략된 부분이 많이 있습니다만, 핵심은 nodeJS를 실행시킬 때 가장 먼저 실행되는 파일인 app.js에서
위에서 작성한 auth 라우터passport 폴더의 내용들이 실행될 수 있도록 하는 것입니다.

이상으로 passport로 facebook 로그인하는 과정을 간략하게 알아보았습니다.
궁금하신 부분 있으시다면 댓글로 달아주세요! 감사합니다.

profile
Done is better than perfect🔥

0개의 댓글