cookie와 session

Yunhye Park·2023년 11월 8일
0
post-thumbnail
post-custom-banner

cookie

쿠키는 웹 브라우저에 저장되는 값이다. 고로 브라우저를 종료해도 해당값 보존된다. 브라우저를 껐다 켜는 것과 상관없이 특정 상태가 유지되는 예시로 뭐가 있을까? 먼저 자동 로그인이나 아이디 저장이 있겠다.

또 다른 예시로는 '오늘만 보지 않기' '일주일 간 보지 않기' 같은 팝업창이다.

쿠키 예시

이런 경우는 만료일을 설정하여 특정 기간에만 쿠키를 동작하게 한다. 직접 삭제하는 방식으로도 쿠키를 제거할 수 있다.

쿠키를 프론트와 백 모두 생성할 수 있는데, 클라이언트-서버 방식으로 개발을 진행한다면 프론트에서 독자적으로 생성과 사용을 하지 말고 서버에서 쿠키를 생성해 이를 포함하여 응답으로 전달하는 게 좋다. 주거니받거니!

브라우저에서 쿠키 확인

쿠키 화면

개발자도구의 애플리케이션 혹은 응용프로그램에서 찾아볼 수 있다.
이름, 값, 도메인, 경로, 만료일 등으로 구성되었다.

쿠키 동작 방식

  1. F : 쿠키 요청 🤚
  2. B : 쿠키 생성 -> HTTP 헤더에 쿠키 포함해서 응답 🎁
    (이때 본래 하던 응답들 ex. res.send은 별개이므로 클라이언트에 보낼 응답이 있다면 쿠키와 별개로 작성해줘야 한다.)

쿠키 사용법

이걸 직접 사용하려면 모듈 설치부터 해줘야 한다.

npm i cookie-parser

이걸 불러와 미들웨어로 걸어주면 사용할 수 있다.

일전에 쿠키는 이름, 값, 도메인, 경로, 만료일 등으로 구성되었다고 했다. 서버에서 응답으로 쿠키를 돌려줄 때에 이름, 값, 만료일을 포함한 옵션을 인자로 넘겨준다.

옵션은 객체로 만들어 보내는데, 몇 가지 자주 사용하는 키를 소개하자면 아래와 같다.

  • httpOnly: 기본값은 false다. true 값 설정 시 자바스크립트에서 document.cookie와 같은 DOM 방식으로 쿠키에 접근할 수 없다. 즉 서버에서만 쿠키를 조작할 수 있다. 클라이언트에 저장되었는데도 말이다.

  • maxAge : ms단위로 만료일을 설정한다. 연산식으로도 작성 가능해서 만약 24시간을 설정하고 싶다면 작은 단위로 쪼갠다고 생각하자. 1시간은 60분이고, 1분은 60초고, 1초는 1000밀리초다. 즉 24 * 60 * 60 * 1000으로 작성하면 된다.

  • 만약 모든 유저에게 일괄적으로 설정하고 싶다면 expires 키를 사용한다. 이건 full로 날짜 입력후 T 뒤에 원하는 시간을 24시간제로 입력하면 된다. 따옴표 잊지 말자.
    ex. '2023-11-08T20:00'

  • path : 쿠키 설정할 경로를 지정할 수 있다. 예를들어 /search라고 입력했다면, url이 http://naver.com/search부터 해당된다. http://naver.com/ 같은 경로는 해당 쿠키가 생기지 않는단 의미다.

  • secure : 기본값 false. true일 시, 보안 서버인 https에서만 쿠키를 동작할 수 있게 한다.

  • signed : 기본값 false. true면 쿠키를 암호화하는데 req.signedCookies에서 조회할 수 있다.

const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use('view engine', 'ejs');

const cookieConfig = {maxAge: 30000};

app.get('/', (req, res) => {
    res.render('index');
});

app.get('/set', (req, res) => {
    res.cookie('key', 'value', cookieConfig)
    res.send('set cookie')
});

코드 설명

1) 먼저 cookie-parser 모듈을 불러와 미들웨어로 걸어줬다. 서버에서 쿠키를 읽고 해석하기 위함이다.

2) 옵션으로 설정할 객체를 cookieConfig라는 변수로 만들었는데 30000인 걸 보아하니 30초가 만료기간이다. 즉 쿠키 생성하고 30초 지나면 쿠키가 사라진다.

3) /set 라우터에 접속하면 30초 만료인 쿠키가 생성된다. 화면에는 set cookie라는 글자를 띄울 모양이다.

🤔 그런데 ejs 화면이 실행되질 않는다?

ejs를 뷰 엔진으로 쓴다면 기본적으로 views 폴더 안으로 경로가 설정되어있다. 그런데 해당 폴더에 넣지 않았다면 에러가 발생하고 만다. 이걸 몰랐어서 수업 중에 잠시 애먹었다.

아래는 제대로 접속해서 쿠키를 생성한 모습이다.

30초 쿠키 설정

🔸 쿠키는 만료 전까지 클라이언트에 계속 남아있어서 생성 이후로는 쿠키가 포함된 상태로 서버에 request한다. 그런데 현재 상태에서 정보를 업데이트할 필요가 있다면? 당연히 쿠키도 업데이트하여 HTTP 헤더 포함한 후 응답한다.

🔸 자동 로그인, 아이디 저장, 기간 팝업창 같은 데이터를 매번 서버에 저장한다면 메모리 부담이 상당해 성능에 문제가 발생할 여지가 높다. 그래서 클라이언트에 저장해두는 거다.

🔸 클라이언트는 브라우저별로 존재한다. 즉 엣지와 크롬은 각각의 클라이언트다. 여기에 시크릿모드까지 사용한다면 총 4개의 클라이언트를 활용할 수 있다.

💡 하루 동안 보지 않기 모달창 구현

하루 동안 보지 않기 모달창을 구현하려고 한다. 체크박스를 선택하고 닫기 버튼을 눌렀다면 새로고침 하거나 브라우저 종료 후 재접속 해도 만료 기간인 하루가 지나기 전엔 모달창이 뜨지 않아야 한다. 즉 프론트 단에서 쿠키가 있을 경우엔 모달 창을 보여주지 않는다는 조건을 달아줘야 한다.

이때 옵션객체에 httpOnly: true 값을 넘긴 케이스라고 하자. 프론트 단에서 document.cookie로 쿠키 유무를 파악할 수 없다. 그럼 어떻게 할까? 서버에서는 res.cookie를 통해 쿠키를 생성해 결과로 보내고, req.cookies.쿠키 이름으로 클라이언트에 있는 쿠키를 받아온다.

이걸 활용해 서버 측에서 쿠키 존재 여부를 담은 변수를 전달하면 되겠다. {result: req.cookies.만든 쿠키 이름}

ejs를 사용 중이라면 ejs 문법으로 그 변수를 가져올 수 있다. 그런데 JS의 조건문 안에서 사용해야 하니까 변수를 문자열로 감싸줘야 한다.if (!'<%= result %>')


session

웹 서버에 저장되는 쿠키라고 보면 된다. 서버에 저장하기 때문에 브라우저를 종료하면 해당 저장값도 사라진다. 대표적인 예시는 로그인 유지 기능이 있겠다. 로그아웃 버튼을 누르지 않아도 창을 완전히 닫기만 하면 다시 접속했을 때 로그인이 되어있지 않은 걸 본 적 있을 거다.

세션 동작 방식

  1. 클라이언트가 서버 접속 시 세션 ID 발급 🔑
    (앞서 언급했듯 브라우저 각각 다른 클라이언트로 인식해서 세션 ID가 다르다)

  2. 세션 ID를 클라이언트에 저장 후 서버에 요청할 때 ID도 서버에 전달

  3. 서버는 세션 ID로 세션에 있는 클라이언트 정보 가져와서 응답

세션 사용법

쿠키와 마찬가지로 모듈을 설치해준다.

npm i express-session

쿠키는 빈 인자로 호출하고 따로 변수를 만들어 설정해줬는데, 세션은 아예 미들웨어 걸 때부터 객체를 생성해 설정해준다. 이때에 자주 쓰는 키도 알아보자.

  • secret : 컴퓨터가 세션에 접근할 수 있게 해주는 작업.

  • resave : 요청이 있을 때마다 세션을 다시 저장할지.

  • saveUninitialized : 클라이언트가 처음 접속할 때 세션을 초기화할지.

  • cookie : httpOnly, maxAge, secure 등 쿠키에서 쓰던 key를 그대로 쓸 수 있다. 만료 시간을 설정해두면 10분 간 활동 없을 시 자동 로그아웃 같은 기능을 넣을 수 있다.

마찬가지로 30초 만료 기간을 두고 세션을 만들어본다.

const session = require('express-session');
app.use(session({
    secret: 'secret key',
    resave: false,
    saveUninitialized: true,
    cookie: {
        httpOnly: true,
        maxAge: 30000
    }
}));

app.get('/', (req, res) => {
    res.send('Hello world!')
})

app.get('/set', (req, res) => {
    req.session.user = 'une'
    res.send("set session");
})

app.get('/get', (req, res) => {
    res.send({id:"", user: req.session.user});
})

app.listen(port, () => {
    console.log(`${port} is open`)
})

세션은 req.session.세션이름에 값을 할당해 이를 저장한다. 세션은 브라우저가 종료되면 자동으로 사라지긴 하지만, 유저가 로그아웃 버튼을 누를 때에도 세션을 삭제해줘야 할 것이다. 이때 destroy 메서드를 이용한다.

// 생략

    req.session.destroy((err) => {
        if(err) throw err;
      
        res.send({result: true, msg:'로그아웃 되었습니다.'});
    })

에러가 있는지 확인하고, 없을 경우엔 프론트 단에 로그아웃을 판별할 수 있는 플래그 역할의 값과 유저에게 보여줄 메시지도 같이 전달한다.


  • 세션 로그아웃 기능을 애먹으면서 풀었던 것 같은데 막상 복습해보니 쿠키는 기억이 선명한데 세션 부분이 흐릿하다. 유저 로그인 유지를 세션으로 구현하려면 어떻게 했더라..

    • 세션은 전역에 생성해야 하니까 index.js에서 객체를 생성한다. 유저가 로그인할 때 유저 레코드 중 PK를 req.session.새이름에 할당한다.

    • 세션 값을 기준으로 유저의 로그인 상태를 value로 넣어서 id 값 등을 프로필 화면에 보여주거나 유저가 작성한 글 확인 등을 허용한다.

  • 요 내용을 이번 프로젝트에서 구현해봐야지~! 재밌겠다.

profile
일단 해보는 편
post-custom-banner

0개의 댓글