1. 쿠키
1) 개념
쿠키는 브라우저가 가지고 있는 데이터 그이상 그이하도 아니다. MDN 웹문서에는 쿠키를 아래와 같이 기술하고 있다.
HTTP 쿠키(웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송합니다.
MDN 웹문서에서 아주 잘 설명해놨다. 그러면 쿠키는 왜 필요할까? 이는 HTTP의 'stateless' 특성 때문이다. HTTP는 클라이언트의 요청 내용을 기억하지 않기 때문에 클라이언트는 매 요청마다 자신의 정보를 서버에게 알려줄 필요가 있다. 쿠키는 클라이언트가 서버에게 정보를 제공할때 사용하는 수단중 하나다. 즉, 쿠키는 클라이언트의 상태를 알려주는 데이터다.
쿠키에 대한 개념은 아래 세 가지만 기억하면 된다.
- key-value 형태의 데이터
- 브라우저가 저장하는 데이터
- 만료 시간이 무한일 경우(세션 쿠키) 브라우저가 종료돼야 쿠키도 없어진다
2) 쿠키 생성 과정
기본적으로 브라우저는 매 요청마다 서버에 쿠키를 동봉해서 보낸다. 따라서 서버에 요청을 보낼때 쿠키가 있을때와 없을때로 나눌 수 있다.
- 쿠키가 없거나 만료되었을 때 : 서버가 응답을 보낼때 쿠키를 새롭게 설정해서 같이 보낸다.
- 쿠키가 있을때 : 쿠키로 사용자 상태 정보를 식별한다.
3) express에서 cookie 사용
express에서 'cookie-parser'라는 페키지를 통해 쿠키를 아주 간편하게 사용할 수 있다. 아래 코드는 공식문서의 샘플 코드를 그대로 가져온 것이다.
var express = require('express')
var cookieParser = require('cookie-parser')
var app = express()
app.use(cookieParser())
app.get('/', function (req, res) {
// Cookies that have not been signed
console.log('Cookies: ', req.cookies)
// Cookies that have been signed
console.log('Signed Cookies: ', req.signedCookies)
})
app.listen(8080)
단순히 미들웨어로 등록만 해놓으면 'req.cookies'에 쿠키 값들이 저장된다.
cookieParser 구문
// 구문
cookieParser(secret)
- secret에 문자열을 저장해놓으면 쿠키값이 '서명'된다. 서명된 쿠키는 req.signedCookies에 저장된다. 특이사항으로는 서버에서 쿠키를 보낼때 {signed: true} 옵션을 추가해줘야 한다.
- secret이 비어있으면 쿠키는 req.cookies에 저장된다.
서버에서 cookie 설정
res.cookie(key, value, option)
- key, value에 원하는 키/값을 설정하면 된다.
- option : 객체 형태로 옵션 설정
- expires : 날짜 만료 기간. Date 객체로 날짜 명시
- httpOnly : true 설정시 자바스크립트로 쿠키에 접근할 수 없음.
- maxAge : 초단위 만료 기간
- secure : HTTPS일 경우에만 쿠키 전송
4) 쿠키로 초단간 로그인 구현
로그인이라고 말하기 무안한 수준이기는 하지만.. 아주 단순하게 쿠키 여부로 사용자를 식별하는 방법이다. 아래와 같이 오직 두 개의 화면만이 존재한다.
전체 소스코드는 여기서 확인할 수 있다. 직접 해보면 알겠지만 서버는 클라이언트한테 쿠키가 없을때만 쿠키를 보내주고, 쿠키가 있는 요청에 대해서는 쿠키를 보내지 않는 것을 확인할 수 있다. 또한 클라이언트는 매 요청마다 서버에게 쿠키를 동봉해서 보낸다. 로그아웃은 서버에서 clearCookie를 통해 클라이언트의 쿠키를 지우기만 하면 된다. 참고로 브라우저에서 쿠키 확인은 [개발자 도구 - Application]에서 가능하다.
2. 세션
1) 개념
쿠키와 세션의 차이는 '데이터 저장 장소'에 있다. 쿠키는 데이터를 브라우저 단에서 저장하지만, 세션은 데이터를 서버 단에서 저장한다. 쉽게 말해서 서버에 각 클라이언트의 개인 저장소를 만들어주는 개념으로 생각하면 된다. 그런데 HTTP는 상태를 저장하지 않기 때문에 각 클라이언트를 식별해주는 값이 필요하다. 이는 쿠키로 해결할 수 있다. 서버는 클라이언트를 식별하기 위해 '세션 쿠키'만 보내주고, 클라이언트가 세션 쿠키를 가지고 요청을 보내면 서버가 세션 쿠키로 사용자를 식별해 개인 저장소를 제공하는 것이다.
그런데 세션을 사용하기 위해서는 특정 클라이언트가 누구인지 확인할 필요가 있다. 따라서 클라이언트는 자신이 누구인지 알려주기 위한 최소한의 정보는 가지고 있어야 한다. 이 역할을 '세션 쿠키'가 한다. 클라이언트가 로그인 폼을 작성해서 서버에 제출하면, 서버는 받은 데이터로 회원인지 확인하고 맞으면 세션 쿠키를 보내준다. 서버는 요청에 세션쿠키가 있으면 로그인한 사용자로 판단하고, 없으면 로그인하지 않은 사용자로 판단한다. 아래는 세션 쿠키의 개념을 도식화한 것이다.
세션에 대해서는 아래 네 가지만 기억해놓자.
- 세션은 서버에 저장된다.
- 서버는 세션쿠키로 클라이언트를 식별한다.
- 세션쿠키의 형태는 일반적으로 'connectid: 값' 이다.
- 세션 '쿠키'이기 때문에 브라우저가 종료되면 세션쿠키도 사라진다.
2) express에서 session 사용
express 'express-session'이라는 패키지를 통해 세션을 아주 간편하게 사용할 수 있다. 세션도 세션쿠키를 필요로 하기 때문에 'cookieParser'와 같이 사용하는게 좋다. 아래와 같이 미들웨어로 등록만 해놓으면 각 사용자별로 'req.session'이라는 고유 공간이 생긴다.
const express = require('express')
const session = require('express-session')
var app = express()
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
}));
구문은 아래와 같다.
session(options)
- options
- resave: 요청이 왔을때 세션에 수정사항이 생기지 않아도 다시 저장할지 여부
- saveUninitialized: 세션에 저장할 내역이 없더라도 세션을 저장할지 여부
- secret: 쿠키 암호화
- cookie: 쿠키 설정과 동일(httpOnly, secure 등)
- name: 세션쿠키 이름 (connect.sid가 디폴트)
- store: 세션 저장소. 메모리가 디폴트.
- req.session : 세션값들을 다 볼 수 있음
- req.sessionID : 세션 아이디 확인 (세션쿠키 value)
- req.session.destroy() : 세션 모두 제거
store 옵션에 주목할 필요가 있다. 세션에 store를 설정해주지 않으면 서버 메모리에 저장된다. 메모리 용량은 크지 않기 때문에 일반적으로 DB에 연결해주는데, 다른 패키지를 설치해야 한다. 자세한 내용은 여기서 확인할 수 있다.
3) 세션으로 초간단 로그인 구현
사실 쿠키와 크게 다를게 없다. 세션에 데이터를 추가하는 것을 보여주기 위해 페이지를 하나 추가했다. 따라서 뷰는 총 세 개다.
여기는 쿠키와 비슷하다. 달라진 점은 로그인 후에 '세션 데이터 보기'와 '세션 데이터 추가' 링크가 추가됐다. 세션 데이터 추가를 클릭하면 내부적으로 'req.session.addData = addData' 를 해준다. '세션 데이터 보기'를 데이터 추가 전후로 비교해보면 아래와 같다.
'세션 데이터 보기'는 단순히 'req.session'에 있는 값들을 다 출력해준다. charles 사용자에게만 추가된 것을 꼭 기억하기를 바란다. 세션은 '개인 저장 공간'이다.
전체 소스코드는 여기서 확인할 수 있다.
'Node.js + Express' 카테고리의 다른 글
[ Node.js + Express ] JWT (0) | 2022.05.21 |
---|---|
[ Express ] nunjucks 사용법 정리 (0) | 2022.05.18 |
[ Express ] Express 첫 시작, 라우팅과 미들웨어 (0) | 2022.05.12 |
[ Node.js ] 모듈 시스템 (module.exports와 exports) (0) | 2022.05.11 |