๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Node.js

Node.js / ํ† ํฐ(Token)

JWT(JSON Web Token)

์ธํ„ฐ๋„ท ํ‘œ์ค€ ์ธ์ฆ ๋ฐฉ์‹์œผ๋กœ, JSON ๊ฐ์ฒด์— ์ธ์ฆ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ํ† ํฐ์œผ๋กœ ์•”ํ˜ธํ™”ํ•œ ๊ฒƒ

* ํ† ํฐ(Token) : ์ถœ์ž…์ฆ ์—ญํ• ์„ ํ•˜๋Š” ๋„๊ตฌ๋กœ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†Œ์ง€ํ•˜๊ณ  ์žˆ์Œ

 

 

๊ตฌ์กฐ

 

๊ฒ€์ฆ ๋ฐฉ์‹

  1. Header์™€ Payload๋ฅผ ๊ฐ๊ฐ base64๋กœ ์ธ์ฝ”๋”ฉ
  2. ์ธ์ฝ”๋”ฉํ•œ Header์™€ Payload๋ฅผ ํ•ฉ์ณ์„œ, Secret(์„œ๋ฒ„๋งŒ ์•Œ๊ณ  ์žˆ๋Š” ๋น„๋ฐ€ ํ‚ค)์œผ๋กœ ์„œ๋ช…(Signature ์ƒ์„ฑ)
  3. ์„œ๋ฒ„๋Š” ์ „๋‹ฌ๋ฐ›์€ JWT์˜ Signature๊ฐ€ Secret์œผ๋กœ ๋‹ค์‹œ ๊ณ„์‚ฐํ•œ ๊ฒƒ๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ  
    → ์ผ์น˜ํ•˜๋ฉด ์œ„์กฐ๋˜์ง€ ์•Š์€ ์œ ํšจํ•œ ํ† ํฐ์œผ๋กœ ํŒ๋‹จ

* ์ด ๋•Œ base64 ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹์€ ์–ผ๋งˆ๋“ ์ง€ ๋””์ฝ”๋”ฉ์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—, payload์— ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ๋„ฃ์ง€ ์•Š๋„๋ก ํ•ด์•ผํ•œ๋‹ค.

 

 

๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์—์„œ ํ† ํฐ์˜ ์œ ํšจ์„ฑ์„ ํ™•์ธํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. base64๋กœ ์ธ์ฝ”๋”ฉํ•˜๋Š” ์‚ฌ์ดํŠธ๋Š” ์—ฌ๊ธฐ

 

https://jwt.io/

 

 

ํ† ํฐ์˜ ์ข…๋ฅ˜

  • ์•ก์„ธ์Šค ํ† ํฐ : ๊ถŒํ•œ ์ธ์ฆ์šฉ
  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ : ์•ก์„ธ์Šค ํ† ํฐ ์žฌ๋ฐœ๊ธ‰์šฉ

 

ํ† ํฐ ์ธ์ฆ์˜ ํ๋ฆ„

1) ์ •์ƒ์ ์œผ๋กœ ์ธ์ฆ์ด ์™„๋ฃŒ๋์„ ๋•Œ 

 

2) ํ† ํฐ ์ธ์ฆ์— ์ด์ƒ์ด ์ƒ๊ฒผ์„ ๋•Œ

 

 

 


 

 


์‹ค์Šต์€ ์ฟ ํ‚ค ๊ธฐ๋ฐ˜ ์ธ์ฆ๊ณผ ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

๋‘˜๋‹ค ์ด์ „ ์„ธ์…˜ ์‹ค์Šต์—์„œ ํ–ˆ๋˜ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์˜ ์„ธ์…˜ ๋ถ€๋ถ„์„ ํ† ํฐ์œผ๋กœ ์žฌ๊ตฌํ˜„ํ•˜๋„๋ก ํ–ˆ๋‹ค.

 

์‹ค์Šต - ์ฟ ํ‚ค ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹

์„œ๋ฒ„๊ฐ€ ์ธ์ฆ ํ›„ ํด๋ผ์ด์–ธํŠธ์— ์ฟ ํ‚ค๋กœ ํ† ํฐ์„ ์ฃผ๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

  • ํด๋ผ์ด์–ธํŠธ๋Š” ์ด ์ฟ ํ‚ค๋ฅผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ž๋™์œผ๋กœ ์ €์žฅํ•จ.
  • ์ดํ›„ ์š”์ฒญ๋งˆ๋‹ค ์ž๋™์œผ๋กœ Cookie ํ—ค๋”์— ์ฟ ํ‚ค๋ฅผ ํฌํ•จํ•จ.
  • ์‚ฌ์šฉ์ž๋Š” ์‹ ๊ฒฝ ์•ˆ ์จ๋„ ๋จ (๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•Œ์•„์„œ ์ฟ ํ‚ค ์ „์†ก).

 

 

server.js

const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');

const users = [
  {
    user_id: 'test',
    user_password: '1234',
    user_name: 'ํ…Œ์ŠคํŠธ์œ ์ €',
    user_info: '์ €๋Š” ํ…Œ์ŠคํŠธ์œ ์ €์ž…๋‹ˆ๋‹ค...',
  },
];

const app = express();
app.use(
  cors({
    origin: ['http://127.0.0.1:5500', 'http://localhost:5500'],
    methods: ['POST', 'GET', 'DELETE', 'OPTIONS'],
    credentials: true, // ์ฟ ํ‚ค ์ €์žฅ์„ ์œ„ํ•ด ํ•„์š”
  }),
);

app.use(cookieParser());
app.use(express.json());
// app.use(
//   session({
//     // ์•”ํ˜ธํ™”๋ฅผ ์œ„ํ•ด ์„ค์ •ํ•˜๋Š” ๋น„๋ฐ€ ์ฝ”๋“œ
//     secret: 'session secret',
//     resave: false, // request๊ฐ€ ๋  ๋•Œ๋งˆ๋‹ค ์„ธ์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•ญ์ƒ ๋‹ค์‹œ ์ €์žฅํ• ์ง€ ์—ฌ๋ถ€ (๋ณ€๊ฒฝ์ด ์—†์–ด๋„)
//     // ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ์„ธ์…˜์„ ์ €์žฅํ• ์ง€ ์—ฌ๋ถ€ (์„ธ์…˜์— ์•„๋ฌด ๋‚ด์šฉ์ด ์—†์–ด๋„ ์ €์žฅํ• ์ง€)
//     saveUninitialized: false,
//     name: 'session_id',
//   }),
// );
const secretKey = 'ozcodingschool';

 

session๋ง๊ณ  jwt์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— session ๋ถ€๋ถ„์€ ์‚ญ์ œํ•˜๊ณ  jwt ๋ชจ๋“ˆ์„ require๋กœ ๋ถˆ๋Ÿฌ์™”๋‹ค.

๊ทธ ์™ธ express()๋กœ ์„œ๋ฒ„ ๊ฐ์ฒด ์ƒ์„ฑ์ด๋‚˜ cors ์„ค์ • ๋ถ€๋ถ„, ์ฟ ํ‚ค๋‚˜ json ๋ถ€๋ถ„์€ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ session ๋ถ€๋ถ„์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ† ํฐ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— secretKey ๊ฐ’์„ ์ƒ์„ฑํ–ˆ๋‹ค.

 

 


 

 

app.post()

// ๋ผ์šฐํŒ…
app.post('/', (req, res) => {
  const { userId, userPassword } = req.body;

  const userInfo = users.find(
    (el) => el.user_id === userId && el.user_password === userPassword,
  );

  if (!userInfo) {
    res.status(401).send('๋กœ๊ทธ์ธ ์‹คํŒจ');
  } else {
    // sign() : ํ† ํฐ ์ƒ์„ฑ ํ•จ์ˆ˜
    // expiresIn : ํ† ํฐ์˜ ์œ ํšจ๊ธฐ๊ฐ„
    // ์ง€๊ธˆ์€ 10๋ถ„์œผ๋กœ ์„ค์ •
    const accessToken = jwt.sign({ userId: userInfo.user_id }, secretKey, {
      expiresIn: 1000 * 60 * 10,
    });
    console.log(accessToken);
    // ์„ธ์…˜ ๋ถ€๋ถ„ ์‚ฌ์šฉX
    // req.session.userId = userInfo.user_id;
    
    // ํ† ํฐ ๊ฐ’์„ ์ฟ ํ‚ค๋กœ ์ €์žฅ
    res.cookie('accessToken', accessToken);
    res.send('ํ† ํฐ ์ƒ์„ฑ ์™„๋ฃŒ');
  }
});

 

 

์ ˆ๋Œ€ 127.0.0.1์„ localhost๋กœ ๋ฐ”๊พธ๋Š”๊ฑธ ์žŠ์–ด์„  ์•ˆ๋ผ....

 

 

 

์ผ๋‹จ accessToken๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌ์„ฑ๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ฉด

 

 

์ด๋ ‡๊ฒŒ ๋‚˜์˜จ๋‹ค... ์ผ๋‹จ  ์„ ๊ธฐ์ค€์œผ๋กœ ๋‚˜๋ˆ„๋ฉด

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJ1c2VySWQiOiJ0ZXN0IiwiaWF0IjoxNzQ3MzI1MDM1LCJleHAiOjE3NDc5MjUwMzV9.
U-SYp3267fZKH23SL5r_Gw298PthzjdMHuOe6uY0I3g

 

์ค‘๊ฐ„๋ถ€๋ถ„์ธ eyJ1c ~~ ๋ถ€๋ถ„์ด payload ๋ถ€๋ถ„์ด ๋œ๋‹ค. ์ด๊ฑธ ์œ„์— ์–ธ๊ธ‰ํ•œ base64 ์ธ์ฝ”๋”ฉ ์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•ด๋ณด๋ฉด 

 

 

userId ๊ฐ’์„ ์ž˜ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!

์ด ๋•Œ iat๋Š” ํ† ํฐ์ด ์–ธ์ œ ์ƒ์„ฑ๋๋Š”์ง€, exp๋Š” ์–ธ์ œ ๋งŒ๊ธฐ๋˜๋Š”์ง€์˜ ๊ฐ’์ด๋ผ์„œ

exp - lat๋ฅผ ๊ณ„์‚ฐํ•ด๋ณด๋ฉด 600000(๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋ผ 10๋ถ„์„ ์˜๋ฏธ)์ด ๋‚˜์˜จ๋‹ค

 

์•„๋ฌดํŠผ ์ฟ ํ‚ค๋„ ์ž˜ ์ƒ์„ฑ๋˜๊ณ  ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค! 

 

 

 


 

 

app.get()

app.get('/', (req, res) => {
  // ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น ๋ฌธ๋ฒ• ์ด์šฉ
  const { accessToken } = req.cookies;
  // verify() : ํ† ํฐ์„ ๊ฒ€์ฆํ•  ๋•Œ ์‚ฌ์šฉ
  // payload ๋ถ€๋ถ„์„ base64ํ˜•์‹์„ ๋””์ฝ”๋”ฉํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค
  const payload = jwt.verify(accessToken, secretKey);
  const userInfo = users.find((el) => el.user_id === payload.userId);
  return res.json(userInfo);
});

 

 

login.js์—์„œ get ๋ฉ”์†Œ๋“œ ์š”์ฒญ ์‹œ ์œ ์ €์ •๋ณด๋ฅผ ๋ Œ๋”๋งํ•˜๋„๋ก ํ–ˆ๋Š”๋ฐ, ์ž˜ ์‹คํ–‰๋˜๊ณ ์žˆ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค!

 

 


 

 

app.delete()

app.delete('/', (req, res) => {
  // ์ฟ ํ‚ค์— ํ† ํฐ ์ •๋ณด๊ฐ€ ๋“ค์–ด์žˆ์œผ๋ฏ€๋กœ ์ฟ ํ‚ค๋งŒ ์‚ญ์ œ
  res.clearCookie('accessToken');
  res.send('ํ† ํฐ ์‚ญ์ œ ์™„๋ฃŒ');
});

 

 

 

์•„๋ฌดํŠผ ์ฟ ํ‚ค ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹์˜ server.js ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค

๋”๋ณด๊ธฐ
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');

const users = [
  {
    user_id: 'test',
    user_password: '1234',
    user_name: 'ํ…Œ์ŠคํŠธ์œ ์ €',
    user_info: '์ €๋Š” ํ…Œ์ŠคํŠธ์œ ์ €์ž…๋‹ˆ๋‹ค...',
  },
];

const app = express();
app.use(
  cors({
    origin: ['http://127.0.0.1:5500', 'http://localhost:5500'],
    methods: ['POST', 'GET', 'DELETE', 'OPTIONS'],
    credentials: true, // ์ฟ ํ‚ค ์ €์žฅ์„ ์œ„ํ•ด ํ•„์š”
  }),
);

app.use(cookieParser());
app.use(express.json());
const secretKey = 'ozcodingschool';

// ๋ผ์šฐํŒ…
app.post('/', (req, res) => {
  const { userId, userPassword } = req.body;

  // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ userInfo์— ๋‹ด์Œ
  const userInfo = users.find(
    (el) => el.user_id === userId && el.user_password === userPassword,
  );

  if (!userInfo) {
    res.status(401).send('๋กœ๊ทธ์ธ ์‹คํŒจ');
  } else {
    // expiresIn : ํ† ํฐ์˜ ์œ ํšจ๊ธฐ๊ฐ„
    // ์ง€๊ธˆ์€ 10๋ถ„์œผ๋กœ ์„ค์ •
    const accessToken = jwt.sign({ userId: userInfo.user_id }, secretKey, {
      expiresIn: 1000 * 60 * 10,
    });
    console.log(accessToken);
    res.cookie('accessToken', accessToken);
    res.send('ํ† ํฐ ์ƒ์„ฑ ์™„๋ฃŒ');
  }
});

app.get('/', (req, res) => {
  const { accessToken } = req.cookies;
  // verify() : ํ† ํฐ์„ ๊ฒ€์ฆํ•  ๋•Œ ์‚ฌ์šฉ
  // payload ๋ถ€๋ถ„์„ base64ํ˜•์‹์„ ๋””์ฝ”๋”ฉํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค
  const payload = jwt.verify(accessToken, secretKey);
  const userInfo = users.find((el) => el.user_id === payload.userId);
  return res.json(userInfo);
});

app.delete('/', (req, res) => {
  // ์ฟ ํ‚ค์— ํ† ํฐ ์ •๋ณด๊ฐ€ ๋“ค์–ด์žˆ์œผ๋ฏ€๋กœ ์ฟ ํ‚ค๋งŒ ์‚ญ์ œ
  res.clearCookie('accessToken');
  res.send('ํ† ํฐ ์‚ญ์ œ ์™„๋ฃŒ');
});

app.listen(3000, () => console.log('์„œ๋ฒ„ ์‹คํ–‰'));

 

 

 


 

 

 

์‹ค์Šต - Bearer Token ๋ฐฉ์‹

์ฟ ํ‚ค์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ , ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ณ€์ˆ˜(localStorage, sessionStorage, ๋˜๋Š” React state ๋“ฑ)์— ์ €์žฅํ•ด ์ง์ ‘ Authorization ํ—ค๋”์— ๋ถ™์ด๋Š” ๋ฐฉ์‹

  • ๋กœ๊ทธ์ธ ์‹œ ์„œ๋ฒ„์—์„œ **ํ† ํฐ(JWT ๋“ฑ)**์„ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„.
  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ด ํ† ํฐ์„ js ๋ณ€์ˆ˜์— ์ €์žฅ.
  • ์ดํ›„ API ์š”์ฒญ ์‹œ ์ง์ ‘ ํ—ค๋”์— ํฌํ•จ์‹œํ‚ด.

 

 

app.post()


server.js

// ๋ผ์šฐํŒ…
app.post('/', (req, res) => {
  const { userId, userPassword } = req.body;

  // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ userInfo์— ๋‹ด์Œ
  const userInfo = users.find(
    (el) => el.user_id === userId && el.user_password === userPassword,
  );

  if (!userInfo) {
    res.status(401).send('๋กœ๊ทธ์ธ ์‹คํŒจ');
  } else {
    const accessToken = jwt.sign({ userId: userInfo.user_id }, secretKey, {
      expiresIn: 1000 * 60 * 10,
    });
    // ์‘๋‹ต์œผ๋กœ ๋ฐ”๋กœ ํ† ํฐ์„ ์ „์†ก
    res.send(accessToken);
  }
});

 

์ด๋ฒˆ์—” ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์‘๋‹ต์œผ๋กœ ํ† ํฐ์„ ์ „์†กํ–ˆ๋‹ค.

 

 

login.js

// ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฟ ํ‚ค ๋Œ€์‹  ๊ด€๋ฆฌํ•ด์ค„ ๋ณ€์ˆ˜
let accessToken = '';

function login() {
  const userId = idInput.value;
  const userPassword = passwordInput.value;
  return axios
    .post('http://localhost:3000', { userId, userPassword })
    .then((res) => (accessToken = res.data));
}

 

๋ฐ”๋กœ ํ† ํฐ์„ ์ „์†กํ–ˆ์œผ๋ฏ€๋กœ ์‘๋‹ต์„ ๋ฐ›์•„์˜จ ๋’ค ์ฝ˜์†”์ฐฝ์— ์ถœ๋ ฅํ–ˆ๋‹ค.

 

 

์‘๋‹ต์ด ์ž˜ ๋„์ฐฉํ•œ ๊ฒƒ๊นŒ์ง€ ํ™•์ธํ–ˆ์œผ๋‹ˆ ์ด์ œ ์ฟ ํ‚ค ๋Œ€์‹  ๋ณ€์ˆ˜์— ์ €์žฅํ•ด ๋ถˆ๋Ÿฌ์˜ค๋„๋ก ํ•ด์•ผ๋œ๋‹ค.

 

 


 

app.get()

 

login.js

function getUserInfo() {
  return axios.get('http://localhost:3000', {
    // ์ด๊ฒŒ ์ •ํ•ด์ง„ ์–‘์‹์ด๋ฏ€๋กœ ์ด๋ ‡๊ฒŒ ๋ณด๋‚ด์ค˜์•ผํ•จ!!
    headers: { Authorization: `Bearer ${accessToken}` },
  });
}

 

 

server.js

app.get('/', (req, res) => {
  const accessToken = req.headers.authorization.split(' ')[1];
  const payload = jwt.verify(accessToken, secretKey);
  const userInfo = users.find((el) => el.user_id === payload.userId);
  return res.json(userInfo);
});

 

 

์ง€๊ธˆ ์ฝ”๋“œ์—์„œ๋Š” ๊ตณ์ด Bearer๋ฅผ ์จ์„œ ๊ตณ์ด ๊ตณ์ด ๊ตณ์ด... split(' ')[1]ํ•ด์„œ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ๋Š”๋ฐ ๋‹จ์ˆœ ๊ธฐ์ˆ ์ ์œผ๋กœ๋Š” ํ˜„์žฌ ์ฝ”๋“œ์—์„œ๋Š” ์•ˆ์จ๋„ ๋˜๊ธดํ•˜์ง€๋งŒ ํ‘œ์ค€์— ๋งž์ถ”๊ธฐ ์œ„ํ•ด ์“ด๋‹ค๊ณ  ํ•œ๋‹ค. 

* Authorization ํ—ค๋”๋Š” HTTP ํ‘œ์ค€์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๋ฐฉ์‹์˜ ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์žˆ๋Š”๋ฐ ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ Bearer ํ† ํฐ ๋ฐฉ์‹์ด๋ผ Bearer๋ฅผ ๋จผ์ € ์“ฐ๊ณ  ๊ทธ ๋‹ค์Œ ํ† ํฐ์„ ์“ฐ๋Š” ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

 


 

 

app.delete()

 

์‚ฌ์‹ค ์ง€๊ธˆ์€ ๊ทธ๋ƒฅ ๋ณ€์ˆ˜์— ๋‹ด์•„๋‘๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— delete() ๋ผ์šฐํŒ… ์ž์ฒด๊ฐ€ ํ•„์š”๊ฐ€ ์—†๋‹ค.

๊ทธ๋ž˜์„œ ํด๋ผ์ด์–ธํŠธ(login.js) ์—์„œ ๊ทธ๋ƒฅ accessToken ๊ฐ’์„ ๋น„์›Œ๋‘๋ฉด ํ•ด๊ฒฐ๋œ๋‹ค.

 

login.js

function logout() {
  accessToken = '';
}

logoutBtn.onclick = () => {
  logout();
  renderLoginForm();
};

 

 

 


 

 

 

์ฟ ํ‚ค vs ์„ธ์…˜ vs ํ† ํฐ 

 

 

'Node.js' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Node.js / ์„ธ์…˜(Session)  (0) 2025.05.14
Node.js / ์ฟ ํ‚ค(Cookie)  (0) 2025.05.14
Node.js / ๋„คํŠธ์›Œํฌ ๊ธฐ์ดˆ  (0) 2025.05.12