Node.JS 서버에 구글 소셜 로그인 기능 넣기 2/2 - 코딩

소스코드

이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.

git clone https://github.com/a-mean-blogger/google-oauth.git
cd google-oauth
git reset --hard 514441a
npm install
atom .

- Github에서 소스코드 보기: https://github.com/a-mean-blogger/google-oauth/tree/514441a77e60d669e462ea429ec52c40f8d78704


Google OAuth client ID와 secret를 사용하여 구글 소셜 로그인 기능을 구현해 봅시다. Google OAuth client ID와 secret가 없다면 이전 글을 읽고 준비를 하시기 바랍니다.

이 강의는 MEAN Stack 강의 시리즈의 게시판 만들기/게시판 Login 기능 추가까지를 읽은 분들을 대상으로 합니다. 즉, 기본적인 node.js Express 사이트 제작 지식과 passport 패키지에 대한 기본적인 지식을 알고 있는 사람들을 대상으로 합니다. 만약 해당 내용을 모르신다면 MEAN Stack 강의 시리즈를 먼저 읽고 진행해 주시기 바랍니다.

이번에 만들 사이트는 main 페이지 그리고 login 페이지의 2 페이지 밖에 없습니다. 처음 사이트에 접속하면 아래와 같이 main 페이지가 표시됩니다.

로그인 링크를 누르면 auth 페이지로 이동하고, 구글 login 링크가 있습니다.

google login 링크를 누르면 구글을 통해 로그인한 후 다시 main 페이지로 돌아옵니다.

처음과 같은 main 페이지지만, 로그인이 되었기 때문에 구글에서 읽어온 정보로 'Welcome {name}'을 표시하고, logout 링크를 표시합니다.

환경 변수 설정

코딩에 앞서 Google OAuth client ID를 GOOGLE_CLIENT_ID, secret을 GOOGLE_SECRET로 환경 변수에 저장합니다.

환경 변수 없이 테스트하고 싶으신 분들은 아래 코드에서 process.env.GOOGLE_CLIENT_ID와 process.env.GOOGLE_SECRET를 각각 client ID와 secret으로 변경하시면 되겠습니다.

프로젝트 생성 및 Package 설치

프로젝트 폴더를 생성합니다. 해당 폴더에서 command line(cmd, git bash 등)에 아래 명령어 입력하여 node.js 프로젝트를 생성합니다.

$ npm init --yes

프로젝트에 필요한 package들도 설치해줍니다.

$ npm install express express-session ejs passport passport-google-oauth2 --save

passport-google-oauth2가 이번 강의의 핵심 패키지입니다. 나머지 패키지들은 이미 MEAN Stack 강의 시리즈에서 설명을 하였습니다.

폴더 구조

코드

// index.js

var express   = require('express');
var app       = express();
var passport  = require('passport');
var session   = require('express-session');

app.set('view engine', 'ejs');
app.use(session({secret:'MySecret', resave: false, saveUninitialized:true}));

// Passport setting
app.use(passport.initialize());
app.use(passport.session());

// Routes
app.use('/', require('./routes/main'));
app.use('/auth', require('./routes/auth'));

// Port setting
var port = 3000;
app.listen(port, function(){
  console.log('server on! http://localhost:'+port);
});

특별히 설명할 것은 따로 없습니다. 다만, express session 설정이 반드시 passport session 위에 있어야 합니다. 아래에 있으면 로그인이 되지 않습니다.

// config/passport.js

var passport         = require('passport');
var GoogleStrategy   = require('passport-google-oauth2').Strategy;

passport.serializeUser(function(user, done) {
  done(null, user);
});
passport.deserializeUser(function(user, done) {
  done(null, user);
});

passport.use(new GoogleStrategy(
  {
    clientID      : process.env.GOOGLE_CLIENT_ID,
    clientSecret  : process.env.GOOGLE_SECRET,
    callbackURL   : '/auth/google/callback',
    passReqToCallback   : true
  }, function(request, accessToken, refreshToken, profile, done){
    console.log('profile: ', profile);
    var user = profile;

    done(null, user);
  }
));

module.exports = passport;

Passport를 설정하는 부분입니다. 자세한 설정법은 passport-google-oauth2 패키지 github 페이지(https://github.com/mstade/passport-google-oauth2)에서 확인 할 수 있습니다.

callbackURL 부분은 구글에 로그인이 이루어 진 후 구글이 다시 사이트로 돌려보내는 주소를 설정하는 부분입니다. 그러므로 사이트는 해당 route를 가지고 있어야 합니다. 다음 파일에서 해당부분을 설명합니다.

간략히 코드의 진행 순서를 설명드리면,

  1. 구글 로그인이 성공.
  2. new GoogleStrategy의 callback function이 실행. 여기서 done(null, user)를 통해 user를 passport.serializeUser에 전달
  3. passport.serializeUser에서 user를 session에 저장.
  4. 이 후 서버에 request가 오는 경우 매번 passport.deserializeUser를 실행하여 session에서 user를 꺼내 user를 복원.

즉 1-3번은 로그인 이후 단 한번만 실행되고, 4번은 이후 request마다 실행됩니다. 위 코드에서는 별도의 user 구조 없이 구글에서 보낸 profile을 그대로 user 모델로 사용하고 있습니다.

만약 사이트의 정해진 user 모델이 있고, DB에 저장하는 경우, new GoogleStrategy의 callback function에서 DB의 user를 찾거나 생성해 주고, 자신의 용도에 맞게 session에 user를 저장할지(위 코드는 session에 user의 전체 정보를 저장합니다), 아니면 매번 DB에서 읽어 올지를 결정하면 됩니다(이 경우 passport.serializeUser에서는 user의 db id만 사용하고, passport.deserializeUser에서 저장된 db id값으로 DB에서 user를 읽어오게 코드를 수정합니다).

console.log('profile: ', profile)를 통해 구글이 어떤 값을 전달하는지 확인해 볼 수 있게 하였습니다. 아래와 같은 정보가 전달됩니다.

provider는 'google'로 이 정보가 구글에서 왔다는 것을 알려줍니다. subid는 google에서 유저를 특정할 수 있는 고유 아이디입니다.

만약 user를 DB에 저장하여 관리한다면 이 두값을 이용하여 DB에 해당 값을 가진 user가 없다면 user를 생성하고, 해당 값을 가진 user가 있다면 그 user를 가져와서 사이트에 로그인시키면 되겠습니다.

// routes/auth.js

var express  = require('express');
var router   = express.Router();
var passport = require('../config/passport.js');

router.get('/login', function(req,res){
  res.render('auth/login');
});

router.get('/logout', function(req, res) {
  req.logout();
  res.redirect('/');
});

router.get('/google',
  passport.authenticate('google', { scope: ['profile'] })
);

router.get('/google/callback',
  passport.authenticate('google'), authSuccess
);

function authSuccess(req, res) {
  res.redirect('/');
}

module.exports = router;

중요하게 살펴봐야 할 곳은 /google route과 /google/callback route입니다.

/google route에서 passport.authenticate('google', { scope: ['profile'] })를 실행하면 구글 로그인페이지로 이동하여 로그인이 이루어지게 됩니다. 로그인이 성공하면 config/passport.js에서의 callbackURL 설정에 따라 /google/callback 페이지로 이동하게 되고, 여기서 authSuccess callback function이 호출됩니다.

// routes/main.js

var express  = require('express');
var router   = express.Router();

router.get('/', function(req,res){
  res.render('main', {user: req.user});
});

module.exports = router;

main page는 req.user를 user로 view에 전달하는데, 로그인이 되어 있다면 req.user에는 user의 정보가 들어가고, 로그인이 되어 있지 않다면 req.user는 아무런 값이 없습니다.

<!-- views/main.ejs -->

<h1>Main Page</h1>

<% if(!user){ %>
  <a href="auth/login">Login</a>
<% } else { %>
  <p>Welcome <%= user.displayName %></p>
    <a href="auth/logout">Logout</a>
<% } %>

user의 값의 유무를 판단하여 로그인이 되어 있으면 displayName을 표시하고 logout 링크를 보여줍니다. 아니라면 login 페이지 링크를 보여줍니다.

<!-- views/auth/login.ejs -->

<h1>Auth Page</h1>

<a href="google">Google Login</a>

로그인 페이지에는 /auth/google 페이지로 이동할 수 있는 링크가 있습니다.

댓글

P
Peter Kim 2020.09.07
와우 업데이트 된거 뭐없나 2주에 한번씩 눈팅하러 오는 사람입니다! 회원가입자한테는 새글알림 메일도 보내주시면 좋겠어요 ㅠㅠ 이번글도 너무 반갑네요! 빨리 따라해봐야지!
혹시 node.js 로 메일링서버 만들기 나 기타 재밌는 강의 부탁드립니다! 개처럼열심히 홍보하고 있어요!!
I
Ian H 2020.09.08
@Peter Kim,
안녕하세요. 주기적으로 방문해주셔서 감사합니다^^ 새글 알림 기능은 구현했었다가.. 무료 SMTP 서비스를 찾지 못해서 숨겨져 있습니다 ㅠㅠ 
요즘 업데이트가 거의 없어서 죄송합니다. 반성하고 좀더 자주 업데이트할 수 있도록 하겠습니다 ㅠㅠ
빡경 2020.09.21
로그아웃하고 다시 구글로그인폼으로 들어가서 다른아이디로 로그인하고싶은데  뭐가남아있는지 계속 그전에 로그인했던 아이디로만 되고 그게 안되네요 억지로 크롬에서 로그아웃하면 되긴하는데 IE로 들어가서 할경우에는 그것도 불가능해서요
I
Ian H 2020.09.21
@빡경,
브라우저에 로그인된 구글계정이 한개면 최조 로그인 이후로는 구글 로그인버튼을 누르면 자동으로 로그인됩니다.
다른 아이디로 로그인하려면 google.com으로 가서 완전히 로그아웃하시거나, 다른 로그인을 추가하시면됩니다.
위 부분은 google.com에 의해 처리되므로 바꿀 수 없고, 모든 사이트의 구글로그인은 동일한 방식으로 작동합니다.
이 답변이 이해가 잘 안되시면 댓글남겨주세요. 더 상세히 설명드릴게요.
빡경 2020.09.21
@Ian H,
한번 실습해보시면 connect.sid 세션아이디가 로그아웃햇음에도 잘사라지지않는데 오류인가요!? 저만의 오류는 아닌것같아서요!
I
Ian H 2020.09.22
@빡경,
connect.sid는 로그인할때 생기고 로그아웃할때 사라지는 것이 아니라,  app.use(session(...))을 사용하면 사이트에 접속시 생성되고 계속유지됩니다.
로그아웃상태에서 connect.sid를 강제로 지운 후에 페이지를 새로고침해보세요. 로그인이 되지도 않았는데 connect.sid는 이미 존재합니다. 로그인, 로그아웃과는 무관합니다^^;
빡경 2020.09.23
@Ian H,
local login 때처럼 currentUser 를 통해 <이메일(로그인한 사용자)> logout  이렇게 nav를 만들고 싶은데 구글에서 넘겨주는 profile에는 이메일정보가 없는데 어떻게해야하나요?
빡경 2020.09.23
@Ian H,
두개만 더 여쭤보고 싶습니다!  1. mongoose에서 find했을떄 결과값이 없으면 []가 출력되는데 ex) user.find({name:"IanH"}, fucntion(err, result) {               if문을 통해서 result의 결과값이 없으면 user 새로만들어주고 있으면 그냥 지나가게 하고싶은데               []는 if(result), if(result == null)가 전부 통과가 됩니다 어떻게 조건을 설정해주어야 하나요?
2. 버튼을 클릭할때마다 schema의 배열 속성(like : [{type:string}])에, 클릭한 속성을 한개 한개씩 수정하고 싶은데      $set? 으로는 불가능한것 같은데 어떻게해야할지 잘 모르겠습니다
I
Ian H 2020.09.23
@빡경,
이메일을 받으려면 routes/auth.js 파일에서 passport.authenticate('google', { scope: ['profile','email'] })와 같이 email을 scope에 추가해주면 됩니다.
1. if(result.length === 0)을 사용하면 결과값이 []인 경우를 잡을 수 있습니다. 혹은 User.find 함수 대신 User.findOne 함수를 사용하면 조건에 맞는 결과값 하나만 찾기 때문에 if(result == null)를 사용할 수 있습니다. 
2. $push를 사용할 수 있습니다. https://docs.mongodb.com/manual/reference/operator/update/push/ 참고해주세요
빡경 2020.09.23
@Ian H,
와 정말 명확하시네요.. 감명받았습니다.  자주 댓글로 여쭤봐도 되나요..? 질문이 많을것같아서요 ㅠㅠ
I
Ian H 2020.09.25
@빡경,
언제든지 질문하셔도 됩니다^^ 제 블로그 보시면 알겠지만 전 질문에 답해주는 것을 좋아하는 편이거든요 ㅋ
다만 본인의 발전을 위해선 영어로 구글링하는 것이 더 좋습니다. 1번같은 경우에 how to check array is empty, 2번은 how to add a value in array in mongoose 으로 구글링 하시면 정말 쉽게 찾을 수 있는 답변들입니다.
빡경 2020.09.29
@Ian H,
감사합니다 하나 부탁드릴게 있는데, 그 게시물강좌에서 파일 업로드를 array로 여러개 할 수 있는 강좌가 너무 듣고싶습니다!!
I
Ian H 2020.09.30
@빡경,
https://www.a-mean-blog.com/ko/blog/단편강좌/_/Node-JS-Multer로-파일-업로드 에 강의 업로드하였습니다. 기다려주셔서 감사합니다!
잉어 2021.02.15
안녕하세요 좋은 강의 잘 봤습니다. 게시판 강좌를 전부 따라하고 그 후에 이 글을 보게 되었는데 본 강좌에서의 Google Login을 고급강좌에서의 MongoDB로 사용하려면 어떤식으로 수정이 필요한지 여쭈어보고 싶습니다. 다양한 방법을 시도중인데 계속 실패중입니다ㅠ
I
Ian H 2021.02.15
@잉어,
안녕하세요^^
1. user가 google과 연결된 경우 확인할 수 있게 user schema에 googleId 항목을 추가합니다. 2. config/passport.js의 function(request, accessToken, refreshToken, profile, done){ ... }에서 DB를 검색해 profile.id와 일치하는 user.googleId를 가진 user를 찾습니다. 3. user가 없다면 새로운 user를 생성하고, 생성된 user를 이용해 done(null, user);합니다. 4. user가 있다면 해당 user를 찾고, 찾은 user를 이용해 done(null, user);합니다.
한번 해보시고 잘 안되면 다시 댓글남겨주세요^^
잉어 2021.02.16
@Ian H,
답변 감사합니다! 대댓글에 말씀해주신대로 고급강의 마지막편을 기준으로 한 파일에서 어캐 시도를 해보려하는데 구글로그인까지만 되고 연동시 Cast to ObjectId failed만 계속 뜨네요ㅠ 제대로 연결이 되지 않는 문제가 잘 해결되지 않는 것 같아요...
잉어 2021.02.16
@Ian H,
1. user가 google과 연결된 경우 확인할 수 있게 user schema에 googleId 항목을 추가합니다. DB를 검색해 profile.id와 일치하는 user.googleId를 가진 user를 찾습니다. << 혹시 이부분에 대해서 자세히 설명부탁 드릴수 있을까요? 
I
Ian H 2021.02.16
@잉어,
지금 user schema에 username, password, name, email이 있잖아요? 여기에 googleId 을 추가합니다.
passport.use(new GoogleStrategy(   {     clientID      : process.env.GOOGLE_CLIENT_ID,     clientSecret  : process.env.GOOGLE_SECRET,     callbackURL   : '/auth/google/callback',     passReqToCallback   : true   }, function(request, accessToken, refreshToken, profile, done){     console.log('profile: ', profile);     var user = profile;
    done(null, user);   } ));
에서 var user = profile;를 지우고
User.findOne({googleId: profile.id}, function (err, user) {     if(user){         return done(null, user);     }      else {         var newUser={            username: profile.id,            password: /* PASSWORD_NOT_REQUIRED_FOR_GOOGLE_LOGIN */,            googleId: profile.id,            name: profile.displayName         };         User.create(newUser, function (err, user) {           return done(null, user);         });     } }
이런식으로 작성하는 거죠. 이때 newUser의 username의 중복체크를 해주어야 하고, password는 현재 required인데 google login은 password가 없죠. 이건 만드는 사이트에 따라서 처리를 해주어야 합니다.  일반적인 username/password 로그인을 없애고 구글 로그인만 남기면 password 항목을 완전히 지울 수 있죠. 아니면 google 첫 로그인 시에 password입력을 받는 form을 보여서 password값을 받을 수도 있구요. 그 외 다양한 방법으로 해결할 수 있습니다.
잉어 2021.02.17
@Ian H,
헉 이렇게 상세하게 알려주시다니 정말 감사합니다! 참고가 많이 되었습니다. 구글로그인시 기본비밀번호 형식으로 구현하려하는데 계속 허가되지않음(unauthorized)이 떠서 여러 방면으로 문제점을 알아보는 중입니다. ㅠㅠ 
I
Ian H 2021.02.18
@잉어,
user.password 항목에는 반드시 bcrypt로 생성된 해쉬가 들어가야 합니다. 또 도움이 필요하면 댓글 남겨주세요^^
E
E.on_이언 2021.03.09
@Ian H,
안녕하십니까! 구글 로그인 따라 하면서 많은 도움 받았습니다!  한 가지 궁금한 점은 위에 말씀해주신대로 코드를 수정해서 써보니  Cast to ObjectId failed 오류는 해결되었습니다 ㅠ 그런데 화면이 메인으로 돌아가지 않고  Unauthorized만 보이네요 ㅠㅠ 여기에서 어떡해야 메인으로 가는지 궁금해서 댓글 남깁니다! ㅠㅠ  newUser 스키마에 user.password 부분은 따로 입력받는게 없어서 bcrypt로 해봐도 Cannot read property 'password' of null 이 오류만 나오네요 ㅠㅠ 
I
Ian H 2021.03.09
@E.on_이언,
안녕하세요^^ 
Cannot read property 'password' of null 오류는 현제 user 가 null이기 때문에 null의 .password를 읽을 수 없어 발생하는 오류입니다. user.password를 사용하는 부분에서 어떻게 user가 null이 되었는지 코드를 잘 살펴보세요.
만약 잘 안되시면 가지고 계신 코드를 github에 올려주시면 제가 한번 확인해 보겠습니다!
I
Ian H 2021.03.10
@E.on_이언,
1.  profile.id은 string이 맞습니다.  var newUser 위에 console.log('typeof profile.id: ', typeof profile.id); 를 추가해서 한번 확인해 보세요.
2. User.create(newUser, function (err, user) { ... }) 는 db에 데이터를 생성한 후 db에서 생성된 데이터를 찾아 user로 return합니다. 이때 db에서 온 user는 newUser와 달리 db에서 생성된 id를 가지고 있죠. 그러므로 newUser가 아닌 user를 사용하는 것이 맞습니다.
근데 왜 user를 넣으면 안되느냐, 제가 테스트해봤는데, 게시판만들기 코드의 User Schema는 username에 길이 제약이 4-12로 정해져있습니다. 근데 googleid는 더 길죠. 그래서 error가 나게 되고, user가 undefined 가 되어버립니다.
이건 return done(null, user); 위에 console.log('err: ', err);console.log('user: ', user); 를 넣으면 확인할 수 있습니다.
지금 newUser를 넣어서 잘 되고 있다고 말씀하셨는데, 아마 db에는 아무런 user가 생성되지 않고 있을 수 도 있으니 확인해보세요^^
E
E.on_이언 2021.03.11
@Ian H,
아 그렇군요 .. 저도 짧은 지식으로 코드를 고치고 있기에 100% 메커니즘을 이해하진 못했습니다 ㅠㅠ  저는 user db에 profile.id,profile.displayName 들어가긴 했습니다. 댓글보고 코드 좀 더 이해해보도록 하겠습니다. 위에 쓴 댓글은 혼선방지를 위해 삭제하겠습니다. 감사합니다!! 
I
Ian H 2021.03.11
@E.on_이언,
또 궁금하신 것 있으시면 댓글 남겨주세요^^ 감사합니다!
이건우 2021.07.02
안녕하세요.. 지금현재 구글로 oauth를 구현하기위해 진행중입니다. 
만약 사이트의 정해진 user 모델이 있고, DB에 저장하는 경우, new GoogleStrategy의 callback function에서 DB의 user를 찾거나 생성해 주고, 자신의 용도에 맞게 session에 user를 저장할지 (위 코드는 session에 user의 전체 정보를 저장합니다), 
아니면 매번 DB에서 읽어 올지를 결정하면 됩니다 (이 경우 passport.serializeUser에서는 user의 db id만 사용하고, passport.deserializeUser에서 저장된 db id값으로 DB에서 user를 읽어오게 코드를 수정합니다).   의 내용이 나오는데요.. 전자의 경우 DB에  저장을  ``` passport.serializeUser(function(user, done) {   done(null, user); }); ```  여기서 해주는부분일까요 ? 그렇다면 user라는것이 현재 연결된 db의 user테이블인것일까요 ? 그리고 저장이될때  user 모델에부합되게끔 저장이되는것일까요 ?  그리고 찾거나 생성해준다 하셨었는데  passport 공식문서처럼 , findorcreate를 안해줘도된단 이야기일까요 ? 
I
Ian H 2021.07.02
@이건우,
안녕하세요^^
여기서 해주는부분일까요 ?  --> 새로운 유저를 DB에 저장하려고 하는거죠? passport.serializeUser에 저장하셔도 됩니다.
그렇다면 user라는것이 현재 연결된 db의 user테이블인것일까요 ?  --> passport.serializeUser(function(user, done){...})에서 user는 rhttps://www.a-mean-blog.com/images/v58ullkevxxp97ynfjeb/google_oauth_coding_001.png 의 profile의 형태를 띄고 있습니다.
그리고 저장이될때 user 모델에부합되게끔 저장이되는것일까요 ? -->  그러므로 DB에 저장할때 가지고 계신 user모델에 맞게 새로 user object를 생성해 주어야 합니다.
그리고 찾거나 생성해준다 하셨었는데  passport 공식문서처럼 , findorcreate를 안해줘도된단 이야기일까요 ?  --> user 전체를 session에 저장하는 경우에는 passport.deserializeUser(function(user, done){...}) 에서 user가 user 전체를 가지고 있기 때문에 db에서 찾을 필요가 없지만, passport.serializeUser(function(user, done){...}) 에서 user.id만 session에 저장하는 경우에는 passport.deserializeUser(function(user, done){...})에서 user가 user.id이기 때문에 db에서 찾아야 합니다.
https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize#answer-27637668 이 글도 한번 참고해 보세요.
이건우 2021.07.03
@Ian H,
답변 감사합니다. 문득 코드분석하다가 궁금한것이  `passReqToCallback=true`라 해두셨는데 특별히 이유같은게 있을까요 ? 오히려 콘솔로그로 찍어보니까 `console.log('profile: ', profile, 'request :', request)`  결과가 한쪽에는(false) `request : ya29.a0ARrdaM94wlKbg0C8II_K8VkaEpND8IUWH6Oe8rEW9Aq_niuHkgw_Zb2QOjtxr-hIkERLzRz_NSFB9eOPLY1rjQhVLqQWEOgn9tBtWelcimebdNBf1iPGtvPYA050uanNvIilmrx3CzAr7fHm5V27B3hCNUUsow` 이런결과가 true일경우는 엄청난양의 req가 나왔는데 ..  둘다 여부에 따라 작동하는것은 문제가없었습니다.. 왜 true와 false를 따로 나뉘어서 하셨는지 궁금하네요..  어디서 금방검색하기론 `(req, id, password, done) => {};` 이런 콜백을 받는다고 하였는데 (트루일경우) 그렇다면 그 콜백받은 저 인자들이 어떤역할을 더 해주는것일까요 ? 
I
Ian H 2021.07.04
@이건우,
사실 위 예제에서는 passReqToCallback 가 true일 필요는 없습니다.  강의 작성시 제가 참고한 예제에서 해당세팅이 있어서 제코드에도 그대로 넘어오게 되었네요.
passReqToCrequest가 true인 경우에는 callback함수에 function(request, accessToken, refreshToken, profile, done)의 5가지 파라메터들이 전달되고, false인 경우에는 function(accessToken, refreshToken, profile, done)의 네가지 파라메터들이 전달됩니다.
그러므로 passReqToCrequest를 false로 하고 파라메터를 function(request, accessToken, refreshToken, profile, done) 이렇게 두면, 사실 첫번째 파라메터인 request에는 accessToken이 들어가게 되서 `request : ya29.a0ARrdaM94wlKbg0C8II_K8VkaEpND8IUWH6Oe8rEW9Aq_niuHkgw_Zb2QOjtxr-hIkERLzRz_NSFB9eOPLY1rjQhVLqQWEOgn9tBtWelcimebdNBf1iPGtvPYA050uanNvIilmrx3CzAr7fHm5V27B3hCNUUsow` 이런 값이 보이게 된겁니다
P
Peter Kim 2021.07.03
전에 블로그로 댓글남겼었는데,  개인 메일 서버 운영? 저만의 독자적인 그 메일 서버, 그리고 페이지 전체적인 뭔가 독자 파일서버? 같은거 후에 이어서 공부해보고 싶습니다 ㅠㅠ 바쁘셔서 어려우시다면 간단하게 이런거 이런거 보시면 좋을것 같ㅇ다고 길만 좀 잡아주실수 있으실까요?
P
Peter Kim 2021.07.03
사례가능하빈다!
I
Ian H 2021.07.04
@Peter Kim,
안녕하세요! 저는 REST API 디자인과 backend 개발 및 frontend 개발을 업으로 삼고 있어서 메일서버, 파일서버 '개발'에 대해서는 크게 아는 것이 없습니다^^;
저는 메일기능, 파일기능등이 필요하면 해당 기능을 제공해주는 서비스를 찾아서 사용합니다^^;
P
Peter Kim 2021.07.12
스승님 그러시다면 그 해당기능을 연동하는 방법을!  포스팅까지는 아니더라도 언질만 해주시더라도 반가울것강ㅌ습니다 혹은 그런 기능들을 예로 몇가지를 들어주시고 이런건 이렇게 받아먹는거라는 언질만이라도 ㅠㅠ
I
Ian H 2021.07.12
@Peter Kim,
파일서비스는 https://www.a-mean-blog.com/ko/blog/Node-JS-첫걸음/게시판-만들기-고급/게시판-파일첨부-기능-만들기-5-서드파티-API-Box-com-사용-하기 에서 소개된 https://box.com 을 사용하실 수 있을 것 같구요(무료),
이메일 서비스는 저도 아직 무료 서비스를 찾고 있는 중입니다^^;
이런 서드파티 서비스들은 각각 서비스마다 사용법이 다르기 때문에 해당 사이트의 공식 문서를 보고 적용하는 방법밖에는 없습니다.
무도인 2021.08.18
안녕하세요. 너무 잘봤습니다! 궁금한게, 로그아웃의 경우, 로그아웃후 로그인 버튼을 누르면 다시 구글 로그인화면이 나오는게 아니라 자동으로 로그인이 되던데 이부분은 혹시 어떻게 해결하는지 알수 있을까요?
I
Ian H 2021.08.18
@무도인,
안녕하세요! 구글에서 로그아웃하시면 됩니다.
로그인 버튼을 누르기 전에 이미 구글에 로그인 되어 있다면 역시 구글 로그인 화면이 나오지 않습니다.
즉 구글 로그인 화면은 버튼을 누르는 순간 구글에 로그인이 되어 있다면 바로 로그인이 되고, 버튼을 누르는 순간 구글에 로그인 되어 있지 않다면 로그인 화면이 뜨는 것입니다.
무도인 2021.08.19
@Ian H,
아 그렇네용. 답변 감사드려용!!
I
Ian H 2021.08.19
@무도인,
👍 방문해 주셔서 감사합니다^^ 
댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP