웹 백엔드

Node.js - cookie & session

토리쟁이 2024. 2. 21. 22:20

 

 

 

이번 포스팅에서는 cookie와 session의 이론적인 부분을 정리해보고 node.js에서 직접 사용해 볼 것이다.


 

우리가 알아 채지 못하는 부분도 있겠지만, cookie는 웹 서핑을 할 때 굉장히 빈번하게 사용된다. 예를 들어, "오늘 그만 보기"와 같은 공지/광고의 옵션은 해당 옵션을 선택하면 만료일이 24시간인 쿠키를 생성하여 처리할 수 있고, 자동 로그인 옵션은 자동 로그인 여부를 쿠키에 저장하여 처리할 수 있다.

 

 

그렇다면, 왜 cookie를 사용하는 것일까?

 

HTTP 프로토콜의 특징이자 약점을 보완하기 위해서 사용한다.

HTTP는 비연결지향적(요청을 보내고 응답을 준 뒤, 연결을 끊는 특성)이고 상태가 없는(연결을 끊는 순간, 상태 정보는 유지하지 않는 특성 statelss) 특징을 가지고 있다. 비연결지향이라는 특성으로 인해 서버 리소스의 낭비를 줄일 수 있다는 것은 장점이지만, 통신할 때마다 새로 커넥션을 생성하기 때문에 클라이언트 측면에서는 상태 유지를 위해 통신할 때마다 어떤 절차를 거쳐야 하는 단점이 있다. (그렇게 되면, 페이지의 이동이 일어날 때마다 인증을 다시 받아야 하는 대참사 발생...)

 

따라서, 이러한 단점을 보완하고자 cookie와 session을 사용하는 것이다.

 

 

이제, 개념적인 부분을 자세하게 살펴보자.

 

 

 

Cookie

  • 웹 브라우저(클라이언트)에 저장되는 키와 값이 들어있는 작은 데이터 파일
  • 이름, 값, 만료일, 경로 정보 등으로 구성되어 있음
  • cookie는 클라이언트의 상태 정보를 local에 저장했다가 요청할 때 참조됨
  • cookie는 서버 측에서 만료 날짜/시간을 지정하여 정해진 시간동안 데이터(상태 정보)를 유지 가능 (→ 로그인 상태 유지에 활용)
    • 브라우저가 종료되어도, 쿠키 만료일이 되기 전까지는 쿠키는 사라지지 않음
  • 쿠키는 서버에서 Http Response Header에 Set-Cookie 속성을 이용하여 클라이언트에게 쿠키를 제공함
  • 클라이언트가 따로 요청하지 않아도 브라우저가 Request시에 Request Header를 넣어서 자동으로 서버에 전송
  • 쿠키는 브라우저에 저장되기 때문에 중요한 정보는 cookie에 저장하면 안 됨
  • (암호화를 하더라도 충분히 복호화가 가능하므로, 민감한 정보는 주의할 것-)
  • 클라이언트에 총 300개의 쿠키 저장 가능
  • 하나의 도메인 당 20개의 쿠키를 가질 수 있음
  • 하나의 쿠키는 4KB(=4096byte)까지 저장 가능

 

 

 

 

 

Cookie의 동작 방식

 

 

 

 

현재 브라우저에 저장된 쿠키 정보를 확인하는 방법은 다음과 같다.

브라우저에서 우클릭 후, 검사 클릭 (개발자 도구 들어가기) → application → Storage → Cookies

 

 

 

 

이제, 이론적인 부분을 공부했으니, 직접 사용해볼 것이다.

보통, cookie는 백엔드에서 자주 사용되지만 그렇다고 해서 프론트에서 사용할 수 없는 것은 아니다.

그러니, 프론트와 백엔드 둘 다 cookie를 사용해보는 실습을 해볼 것이다.

 

 

 

Cookie 사용하기

 

프론트에서의 cookie 사용

  • document 객체의 cookie를 이용해서 cookie 객체 사용
  • <script>
          // cookie 설정(쿠키명, 만료일, 경로)
          // 설정한 경로의 하위경로에서만 쿠키 사용 가능
          document.cookie = "user = sesac; expires 21 Feb 2024 /12:00:00 GMT; path=/"// 반드시 형식 맞출 것
          console.log(document.cookie);
        </script>
  • cookie 설정시, 쿠키명=값; 만료일; 경로가 들어간다.
  • 반드시 형식 맞출 것-
  • 만료일은 expires에 들어가는데, expires 값과 브라우저의 시간을 비교해서 해당 시간이 되면 자동으로 삭제 처리가 된다.

 

 

백엔드에서의 cookie 사용

  • 모듈 설치 필요
    • npm install cookie-parser
  • cookieParser 모듈 불러오기
    • const cookieParser = require("cookie-parser");
  • cookieParser 미들웨어 설정
    • // ver1. 암호화되지 않은 쿠키
      app.use(cookieParser());
    • // ver2. 암호화된 쿠키
      app.use(cookieParser("secretKey123")); // 인자로 아무 문자열이나 넣으면 됨
  • cookie 생성
    • // res.cookie(쿠키이름, 쿠키값, 설정옵션)
      res.cookie("myCookie", "cookie!", cookieConfig); //  설정옵션 객체를 따로 선언하여 사용하였음(아래 참고)
    • // 쿠키 설정을 위한 객체 선언
      const cookieConfig = {
        /*
          -maxAge: 쿠키의 수명, 1000이 1초인 밀리초 단위로 작성
          - expires: 쿠키 만료 날짜, GMT 시간 설정
          -httpOnly: http 통신만 접근 허용 (true/false)
          - path: '/abc', // 쿠키가 해당 경로와 그 하위 경로에서만 활성화 (default: '/')
          - secure: https로 통신하는 경우에만 쿠키 전송 (true/false)
          - signed: 쿠키의 암호화 설정 (true/false)
          */
        // maxAge:60*1000*60*24 // 하루
        maxAge: 60 * 1000,
        httpOnly: true,
        signed: true, // 암호화 설정
      };
    • cookie 설정 옵션으로는 maxAge, expires, httpOnly, path, secure, signed가 있으며, cookie 미들웨어 설정시 인자로 임의의 문자열을 전달한 경우, 반드시 암호화 관련 옵션인 signed를 true로 설정해야 한다.
    • 경로 설정: 쿠키를 전송할 요청 경로를 설정, cookie가 해당 경로와 그 하위 경로에서만 활성화(default:'/')
  • cookie 값 확인
    • 요청 정보의 cookies에 담겨 있음 
    • console.log(req.cookies); // ver1. 암호화되지 않은 쿠키일 때
      console.log(req.signedCookies); // ver2. 암호화된 쿠키일 때
  • cookie 삭제
    • // 쿠키 삭제하기
      // res.cookie(쿠키이름, 쿠키값, 설정옵션) : 반드시, res.cookie()로 설정했던 인자와 똑같이 작성할 것!
      res.clearCookie("myCookie", "cookie!", cookieConfig); // 이름이 "myCookie"이고 값이 "cookie!"이며, 설정 옵션이 cookieConfig인 쿠키를 삭제
  •  정리) 암호화하지 않은 쿠키의 사용
    • 미들웨어 설정: app.use(cookieParser());
    • 쿠키 생성: res.cookie(쿠키이름, 쿠키값, 옵션);
    • 쿠키 확인: req.cookies
    • 쿠키 삭제: res.clearCookie(쿠키이름, 쿠키값, 옵션);
      • 생성시와 동일하게 작성해야 한다. (단, expires와 maxAge 옵션은 일치하지 않아도 괜찮다.)
  • 정리) 암호화된 쿠키의 사용
    • 미들웨어 설정: app.use(cookieParser('임의의 문자열'));
    • 쿠키 생성: res.cookie(쿠키이름, 쿠키값, 옵션 signed:true 필수);
    • 쿠키 확인: req.signedCookies
    • 쿠키 삭제: res.clearCookie(쿠키이름, 쿠키값, 옵션);
      • (암호화되지 않은 쿠키의 삭제와 동일함)

 


 

 

Cookie에 대해 공부해 보았으니, 이제 Session에 대해 공부해보자.

 

Session이란 무엇일까?

 

 

 

Session

  • session은 쿠키를 기반으로 하며, 서버 측에서 관리함 → 즉, 웹 서버에 저장되는 쿠키
  • 서버에서는 클라이언트를 구분하기 위해 세션 ID를 부여하며, 사용자가 웹 브라우저를 통해 접속한 시점부터 ~ 연결을 끝내는 시점까지의 시간 동안, 일련의 요구를 하나의 상태로 보고 그 상태를 유지시키는 기술(ex- 로그인 유지)
  • 접속 시간에 제한을 두어, 일정 시간 응답이 없을 경우, 유지 중단 설정 가능
  • 사용자에 대한 정보를 서버에 두기 때문에 cookie보다 보안성 ↑ good
    • 브라우저를 닫거나, 서버에서 세션을 삭제했을 때만 삭제가 됨
  • but, 사용자가 많아질수록 서버 메모리 차지가 많아져 서버 과부하가 발생할 수 있음(성능 저하의 요인)
  • 저장 데이터에 제한X (단, 서버 용량이 허용하는 한에서-)
  • 클라이언트가 Request를 보내면, 해당 서버의 엔진이 클라이언트에게 유일한 ID를 부여함(고유성) → 세션 ID

 

 

 

 

Session의 동작 방식

 

 

 

 

위의 내용을 살펴보면, session은 cookie 기반으로 되어 있기 때문에 cookie와 유사한 점이 많다는 것을 알 수 있다.

그렇다면, 둘의 차이점은 무엇일까?

 

 

 

Cookie VS Session

구분 Cookie Sessoin
정보 저장 위치 클라이언트(브라우저) 로컬 서버 메모리
보안성 비교적 취약 비교적 안전
속도 비교적 빠름 비교적 느림
라이프 사이클 브라우저 종료시에도 정보 유지 가능 브라우저 종료시 만료기간에 상관없이 삭제

 

  • 쿠키는 서버의 자원을 전혀 사용하지 않지만, 세션은 서버의 자원을 사용한다.
  • 세션은 쿠키를 이용해서 session ID만 저장하고 그것으로 구분하여 서버에서 처리하는 반면, 쿠키는 클라이언트 로컬에 저장되기 때문에 변질되거나 request에서 스니핑 당할 우려가 있어서 보안에 취약하다.
  • 쿠키는 파일로 저장되기 때문에 브라우저를 종료해도 정보가 유지될 수 있지만, 세션은 브라우저가 종료되면 만료기간이 남아있어도 삭제된다.
  • 쿠키는 쿠키에 정보가 있기 때문에 서버 요청시 속도가 빠르고, 세션은 정보가 서버에 있기때문에 별도의 처리(session ID를 이용해서 서버에서 다시 데이터 참조 필요)가 요구되어 비교적 속도가 느리다.

 

 

 

그렇다면, 세션을 두고 쿠키를 사용하는 이유는 무엇일까?

 

세션은 비교적 보안성이 좋다는 장점이 있으나, 서버의 자원을 사용하기 때문에 무분별하게 많이 생성하여 사용하게 된다면, 서버의 메모리가 감당할 수 없을 상황에 처할 수 있고, 속도가 느려질 수 있기 때문이다.

그렇기 때문에, 자원관리 차원에서 쿠키와 세션을 적절하게 병행하여 사용한다면, 서버 자원의 낭비를 막고 빠른 속도의 처리가 가능하다.

 

 

이제, Node.js에서 session을 직접 사용해보자.

 

Session 사용

  • 설치 필요
    •  
    • npm install express-session
  • express-session 모듈 불러오기
    • const session = require("express-session")
  • session 미들웨어 설정
    • 설정 옵션으로는 secret(필수), resave, saveUninitialized, cookie, secure, name 등이 있음
    • const sessionConfig = {
        /*
      - secret: 안전한 쿠키 전송을 위한 서명값(필수)
      - resave: 세션 수정사항이 생기지 않더라도 매 요청마다 세션을 다시 저장할지 (false 권장)
      - saveUninitialized: 세션에 저장할 내용이 없더라도 처음부터 세션을 생성할지 (false 권장)
      - cookie: 세션 쿠키에 대한 설정(cookie.js 참고 {maxAge, ...})
      - secure: https에 대한 세션을 주고 받을지 (true/false)
      - name: 세션 쿠키의 이름 설정(default: connect.sid)
      */
        secret: "secretKey", // 필수
        resave: false,
        saveUninitialized: false,
        cookie: {
          // maxAge:60*1000,
          httpOnly: true,
        },
      };
    • app.use(session(sessionConfig));
  • session 생성(설정)
    • // req.session.키이름 = "값";
        req.session.name = "tori";
  • session 확인
    • console.log(req.sessionID)
      console.log(req.session);
      console.log(req.session.name);
  • session 삭제
    • // req.session.destroy(callback함수) ;
      req.session.destroy((err) => {
          if (err) {
            res.status(500).send("server err");
            throw err;
      }
      });
  • 정리)
    • 미들웨어 설정: app.use(session(설정옵션));
    • 세션 생성: req.session.키이름="값";
    • 세션 확인: req.session
    • 세션 삭제: req.destroy(cb)

 

 


 

+)

 

저장에 쓰이는 캐시(Cache)도 자주 등장하는 개념인데, 쿠키와 세션, 캐시는 어떠한 차이가 있을까?

캐시(Cache)는 웹 페이지를 빠르게 렌더링하기 위해서 웹 페이지 요소를 저장하는 임시 저장소이고,

쿠키&세션은 사용자의 정보를 저장하기 위해 사용된다.

 

 

캐시(Cache)

  • 캐시는 이미지, 비디오, 오디오, css, js파일 등 데이터나 값을 미리 복사해 놓는 리소스 파일들의 임시 저장소
  • 저장 공간이 작고 비용이 비싸지만, 빠른 성능을 제공함
  • 이전에 사용된 데이터가 다시 사용될 가능성이 높으면, 캐시 서버에 있는 데이터를 사용함으로써 페이지 로딩 속도가 빨라짐
  • 캐시 히트(hit): 캐시를 사용할 수 있는 경우
  • 캐시 미스(miss): 캐시를 사용할 수 없는 경우

 

 

 

 

 

 


참고

쿠키와 세션

https://jeong-pro.tistory.com/80

https://dev-coco.tistory.com/61

https://interconnection.tistory.com/74