Node.JS로 인증/인가를 구현할 때는 지금까지 사용해 온 방식을 사용할 수도 있지만 Passport라는 모듈을 이용해서 구현하면 훨씬 깔끔하게 인증/인가 부분을 구현할 수 있습니다.

그래서 이제부터는 Passport 모듈을 이용해서 구현해 보겠습니다.

Passport를 이용해서 만들 앱은 이메일과 비밀번호를 이용해서 로그인하는 것과 구글 아이디를 이용하는 OAuth 로그인을 할 수 있는 앱을 구현해 보겠습니다.

우선 기본적인 Express App 구조 생성

프로젝트 폴더 생성

models, views, controllers, services

필요한 모듈 설치

yarn add dotenv express nodemon body-parser cookie-parser cors mongoose passport passport-local passport-google-oauth20 passport-kakao bcryptjs ejs

express 코드 작성

// server.js

const mongoose = require("mongoose");
const express = require("express");
const path = require("path");
require("dotenv").config();

const app = express();
const port = 3000;

const { MONGO_USERNAME, MONGO_PASSWORD } = process.env;

app.use("/static", express.static(path.join(__dirname, "public")));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());

mongoose
  .connect(`mongodb+srv://${MONGO_USERNAME}:${MONGO_PASSWORD}@test.vi6echp.mongodb.net/`)
  .then(() => console.log("mongodb connected"))
  .catch((err) => console.log(err));

app.listen(port, () => {
  console.log(`Listening on ${port}...`);
});

Model 생성

// models/users.model.js

const mongoose = require("mongoose");

const userSchema = mongoose.Schema({
  // 일반 로그인
  email: { type: String, trim: true, unique: true },
  password: { type: String, minLength: 5 },
  // 구글 로그인
  googleId: { type: String, unique: true, sparse: true },
});

const User = mongoose.model("User", userSchema);

module.exports = User;

로그인 회원가입을 위한 화면

// server.js

// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
<!-- login.ejs -->

<section class="prompt">
  <h1>Login</h1>
  <form action="/login" method="post">
    <section>
      <label for="email">Email</label>
      <input type="text" id="email" autocomplete="email" required autofocus />
    </section>
    <section>
      <label for="current-password">Password</label>
      <input type="password" id="current-password" name="password" autocomplete="current-password" required />
    </section>
    <input type="hidden" />
    <button type="submit">Login</button>
  </form>
  <p class="help">Don't have an account? <a href="/signup">Signup</a></p>
</section>
<!-- signup.ejs -->

<section class="prompt">
  <h1>Signup</h1>
  <form action="/signup" method="post">
    <section>
      <label for="email">Email</label>
      <input type="text" id="email" name="email" autocomplete="email" required />
    </section>
    <section>
      <label for="new-password">Password</label>
      <input type="password" id="new-password" name="password" autocomplete="new-password" required />
    </section>
    <input type="hidden" />
    <button type="submit">Sign up</button>
  </form>
  <p class="help">Already have an account? <a href="/login">Login</a></p>
</section>
// server.js

app.get("/login", (req, res, next) => {
  res.render("login");
});

app.post("/login", (req, res, next) => {});

app.get("/signup", (req, res, next) => {
  res.render("signup");
});

app.post("/signup", (req, res, next) => {});

회원가입 버튼을 누를 때

// server.js

app.post("/signup", async (req, res, next) => {
  const user = new User(req.body);
  console.log(req.body); // email password

  try {
    await user.save(); // database save
    return res.status(200).send({ success: true });
  } catch (error) {
    console.log(error);
  }
});

로그인 버튼을 누를 때