Node 강의/숙련

1-9 쿠키와 세션

kagan-draca 2024. 9. 7. 17:59

1. 쿠키와 세션

쿠키(Cookie) : 브라우저가 서버로부터 응답으로 Set-Cookie헤더

                        받은 경우 해당 데이터를 저장한 뒤 모든 요청에 포함하여 보냅니다.

 

ex) naver.com 같은 웹 사이트를 방문할 때 마다

      이전에 방문했던 정보를 기억하는 데이터 파일입니다.

 

여러 사이트공유할 수 있기 때문에 보안에 취약할 수 있습니다.

 

쿠키는 userId=user-1321;userName=sparta 와 같이 문자열 형식으로 존재하며

쿠키 간에는 세미콜론(;)으로 구분됩니다.

 

세션(Session) : 쿠기를 기반으로 구성된 기술입니다. 클라이언트 마음대로 데이터를 확인 할 수 있던

                           쿠키와는 다르게 세션은 데이터를 서버에만 저장합니다.

 

세션은 일반적으로 세션 Id를 쿠키를 이용해 클라이언트에게 전달하여,

서버는 이 세션 Id를 사용해 저장된 세션 데이터조회합니다.

 

세션을 통해 사용자의 상태 정보를 서버에 저장하면, 서버는 사용자의 상태를 추적할 수 있게 됩니다.

 

보안성은 좋으나, 반대로 사용자가 많은 경우 서버에

저장해야 할 데이터가 많아져서 서버 컴퓨터가

감당하지 못하는 문제가 생기기 쉽습니다.

 

쿠키와 마찬가지로 세션 역시 만료 기간이 있습니다.

 

2. 쿠키(Cookie) 만들기

 

서버가 클라이언트의 HTTP 요청(Reqest)수신할 때,

서버는 응답(Response)과 함께 Set-Cookie라는 헤더

함께 전송할 수 있습니다.

 

그 후 쿠키는 해당 서버에 의해 만들어진

응답(Response)과 함께 Cookie HTTP 헤더 안에

포함전달 받습니다.

 

express를 이용한 쿠키 할당

import express from "express";

const app = express();
const PORT = 5001;

app.use(express.json());

app.get("/set-cookie", (req, res) => {
  let expires = new Date();
  expires.setMinutes(expires.getMinutes() + 60);
  // 만료 시간을 60분으로 설정합니다.

  res.cookie('name','sparta',{
    expires : expires
  })
  return res.end();
});

app.listen(PORT, () => {
  console.log(PORT + "의 서버가 연결 됐습니다!");
});

 

위와 같이

 

app.get('/set-cookie', (req, res)=> {

    res.cookie('name','sparta',{

       ~~~~

    })

    return res.end()

});

 

로 쿠키를 할당할 수 있습니다.

 

localhost:5001/set-cookie에 접속하면,

아무런 리턴 값이 없는걸 볼 수 있습니다.

 

하지만, F12를 누른 후 Cookies를 확인해보면,

 

Cookies 안해당 주소와 이름이 sparta인 쿠키가 있는 걸 볼 수 있습니다.

 

그리고 해당 이름의 쿠키의 Expires가 1시간 뒤로 설정된 것을 볼 수 있습니다.

 

3. req를 이용하여 쿠키 접근하기

 

클라이언트서버에 요청(Request)을 보낼 때 자신이 보유하고 있는 쿠키를 자동으로 서버에 전달 합니다.

여기서 클라이언트가 전달하는 쿠키 정보는 Request header에 포함 돼 서버에 전달되게 됩니다.

 

그럼 서버에서는 어떠한 방식으로 쿠키를 사용할 수 있는가?

 

쿠키는 req.headers.cookie에 있습니다. req.headers는 클라이언트가 요청한 Request헤더(header)를 의미 합니다.

 

req.headers.cookie를 이용하여 쿠키 조회하기

 

app.get("/get-cookie", (req, res) => {
  const cookie = req.headers.cookie;
  console.log(cookie);
  return res.status(200).json({ cookie });
});

 

app.js에 추가해줍니다.

 

localhost:5001/get-cookie

에 접속하면 cookie가 Response된 것을 확인할 수 있습니다.

 

만약, 해당 쿠키를 제거하고 다시 접속하면

아무 쿠키도 Response 되지 않은 것을 확인할 수 있습니다.

 

4. Cookie-parser 미들웨어 적용하기

 

cookie-parser 미들웨어는 요청에 추가된 쿠키를 req.cookies 객체만들어 줍니다.

 

먼저, 터미널에서

 

yarn add cookie-parser

 

를 import 해줍니다.

 

 

그 후,

import cookieParser from "cookie-parser";

 

app.use(cookieParser());

 

을 코드에 추가시켜줍니다. 그리고 기존 app.get('/get-cookie" (req, res)=>) 를

 

app.get("/get-cookie", (req, res) => {
  const cookies = req.cookies;
  console.log(cookies);
  return res.status(200).json({ cookie : cookies });
});

 

위와 같이 수정해줍니다.

 

수정된 app.js 전체코드

import express from "express";
import cookieParser from "cookie-parser";

const app = express();
const PORT = 5001;

app.use(cookieParser());
app.use(express.json());

app.get("/set-cookie", (req, res) => {
  let expires = new Date();
  expires.setMinutes(expires.getMinutes() + 60);
  // 만료 시간을 60분으로 설정합니다.

  res.cookie("name", "sparta", {
    expires: expires,
  });
  return res.end();
});

app.get("/get-cookie", (req, res) => {
  const cookies = req.cookies;
  console.log(cookies);
  return res.status(200).json({ cookie : cookies });
});

app.listen(PORT, () => {
  console.log(PORT + "의 서버가 연결 됐습니다!");
});

 

다시 서버에서 Client의 쿠키를 확인해보면,

 

key가 name이고, value가 sparta인 객체를 확인할 수 있습니다

이를 바탕으로 key에 따른 value 호출 방식을 통해

value를 가공할 수 있습니다.

 

5. 세션(Session) 만들기

 

쿠키의 경우 Clinet에게 노출되기 때문에 조작되거나 권한을 탈취당해 악의적인 용도로 사용될 수 있습니다.

 

그렇다면, 쿠키에는 어떤 정보를 담아야 할까요?

 

바로, 사용자가 누구인지 확실하게 구분할 수 있는 정보를 넣어줘야 합니다.

 

그래야 민감한 정보는 서버에서만 관리하고, 사용자 식별 정보를 통해 사용자의 정보를 반환할 수 있게 됩니다.

 

/set-session API를 호출했을 때 name=sparta의 정보를 서버에 저장하고,

저장한 시간 정보를 쿠키로 반환받는 API와

 

/get-session API를 호출했을 때 쿠키의 시간 정보를 이용하여

서버에 저장된 name 정보를 출력하는 API를 만들어보겠습니다.

→ 이렇게 구현한다면, 해당 시간을 기준으로 사용자가 누구인지 확실하게 구분할 수 있겠죠?

 

1) /set-session API 만들기

 

let session = {};

을 전역으로 만들고

app.get("/set-session", (req, res, next) => {
  // 현재는 sparta라는 이름으로 저장하지만,
  // 나중에는 복잡한 사용자의 정보로 변경될 수 있습니다.
  const name = "sparta";
  const uniqueInt = Date.now();
  // 세션에 사용자의 시간 정보 저장
  session[uniqueInt] = { name };
  res.cookie("sessionKey", uniqueInt);
  return res.status(200).end();
});

 

localhost:5001/set-session에 접속하면

 

 

Name이 sessionKey이고, value가 숫자인 데이터가 새로 생긴 것을 볼 수 있습니다.

 

이때, value는 Client가 접속한 시간 정보입니다.

 

이제 Name인 sessionKey이고, value가 시간 정보인 쿠키를 바탕으로

서버의 데이터를 조회해봅시다.

 

2) /get-session API 만들기

app.get("/get-session", (req, res, next) => {
  const { sessionKey } = req.cookies;
  // 클라이언트의 쿠키에 저장된 세션키로 서버의 세션 정보를 조회합니다.
  const name = session[sessionKey];
  return res.status(200).json({ name });
});

 

localhost:5001/get-session에 접속하면

 

name이 "sparta"인 데이터만 출력되는 걸 확인할 수 있습니다.

 

왜냐하면, 

let session = {
    //set-session이라는 API를 1번 호출하면
    //name : "spata"
};

  const name = session[sessionKey];

에서 sessionKey에 해당하는 Value인 시간 정보를 바탕으로,

app.get('set-session')

에서 

  const name = "sparta";

으로 지정된 값이 반환되기 때문입니다.

 

ex) 쿠키가 없다는 가정하에,

localhost:5001/get-session, localhost:5001/set-session, localhost:5001/get-session을 순서대로 실행하면

 

1. localhost:5001/get-session

 

아무 쿠키도 없는 것을 확인할 수 있습니다.

 

2. localhost:5001/set-session

쿠키가 생성되고,

 

3. localhost:5001/get-session

해당 쿠키가 조회된 걸 볼 수 있습니다.

 

3) 전체 APP.js 코드

import express from "express";
import cookieParser from "cookie-parser";

const app = express();
const PORT = 5001;

app.use(cookieParser());
app.use(express.json());

let session = {
    //set-session이라는 API를 1번 호출하면
    //name : "spata"
};

app.get("/set-cookie", (req, res) => {
  let expires = new Date();
  expires.setMinutes(expires.getMinutes() + 60);
  // 만료 시간을 60분으로 설정합니다.

  res.cookie("name", "sparta", {
    expires: expires,
  });
  return res.end();
});

app.get("/get-cookie", (req, res) => {
  const cookies = req.cookies;
  console.log(cookies);
  return res.status(200).json({ cookie: cookies });
});

app.get("/set-session", (req, res, next) => {
  // 현재는 sparta라는 이름으로 저장하지만,
  // 나중에는 복잡한 사용자의 정보로 변경될 수 있습니다.
  const name = "sparta";
  const uniqueInt = Date.now();
  // 세션에 사용자의 시간 정보 저장
  session[uniqueInt] = { name };
  res.cookie("sessionKey", uniqueInt);
  return res.status(200).end();
});

app.get("/get-session", (req, res, next) => {
  const { sessionKey } = req.cookies;
  console.log(session);
  // 클라이언트의 쿠키에 저장된 세션키로 서버의 세션 정보를 조회합니다.
  const name = session[sessionKey];
  return res.status(200).json({ name });
});

app.listen(PORT, () => {
  console.log(PORT + "의 서버가 연결 됐습니다!");
});