220812
갓규리쌤의 수업을 바탕으로 작성되었습니다.
Cookie 란?
웹 브라우저(클라이언트)에 저장되는 키와 값이 들어있는 작은 데이터 파일이다. 이름, 값, 만료일, 경로 정보로 구성되어있다.
쇼핑몰 등의 사이트에서 팝업으로 뜨는 '오늘 하루동안 보지않기' 등의 창이 우리가 쉽게 볼 수 있는 쿠키라고 생각하면 쉽다.

⇒ console에서 Application으로 가면 cookies를 확인 할 수 있다.
Cookie의 동작 방식
클라이언트가 페이지를 요청
→ 서버에서 쿠키 생성
→ HTTP 헤더에 쿠키를 포함시켜 응답
→ 브라우저가 종료되어도 쿠키만료 기간이 있다면 클라이언트에서 보관하고 있음
→ 같은 요청을 할 경우 HTTP 헤더에 쿠키를 함께 보냄
→ 서버에서 쿠키를 읽어 이전 상태 정보를 변경 할 필요가 있을 때 쿠키를 업데이트하여 변경된 쿠키를 HTTP헤더에 포함시켜 응답
참고로 헤더는 utf파일같은거 설정하거나 .json등의 정보를 담고있는게 헤더이다. Network에서 확인가능하다. 어떻게 통신하고 응답받았는지 확인 할 수 있다.

쿠키의 만료기간이 없으면 브라우저가 종료될때 쿠키가 사라지고, 만료기간이 있다면 만료 기간까지 클라이언트에서 쿠키를 보관하고 있다.
ex) 하루동안 보지 않겠습니다. 등의 시간 설정.
쿠키는 데이터 파일이므로 읽고, 수정하고, 삭제하는것들이 다 가능하다.
Cookie 의 사용예시
팝업창 하단에 볼 수 있는 '오늘 그만보기' 나 쇼핑몰이나, 검색사이트 등의 로그인 유지도 쿠키를 사용하는 예시라고 볼 수 있다.
Cookie 사용하기
init, ejs와 express만 설치하면 된다.
- index.js와 views 폴더를 만들어준다.
<index.js>
const express = require('express');
const app = express();
app.set('view engine', 'ejs');
app.get('/', (req,res) => {
res.render("index");
});
app.listen(8000, () => {
console.log('sercer : ', 8000):
});
HTTP때는 헤더를 따로 설정했어야했다. 근데 expresss는 res객체에 쿠키가 있다. 알아서 헤더에 담아서 보내준다.
npm i cookie-parser 설치후에 index에 불러온다.
const cookieParser = require("cookie-parser");

호스트로 바디를 받도록 하겠습니다는 app.use이다. app.use(cookieParser());는 쿠키를 이용하겠다고 적어주는것이다. 위에 뜨는 팝업에 secret은 사용할 비밀키를 작성해달라고 뜨는것이다.
어떻게해서 비밀키가 작동되는지(?) 궁금하면 node.js 홈페이지 가서 확인하면 된다.

res.cookie('key', 'value');로 쿠키를 보내준다. 이름에 key들어가고, 값에 value들어간다.

만일 로컬에서 쿠키를 설정하면 서버까지 안거쳤기 때문에 쿠키는 사라진다.
const express = require("express");
const cookieParser = require("cookie-parser");
const app = express();
app.set("view engine", "ejs");
app.use(cookieParser('1234'));
const cookieConfig = {
//cookieConfig는 키, 밸류 외에 설정을 보낼 수 있다.
maxAge : 30000,
//밀리초 단위로 들어가는데 30000을 설정하면 30초만료 쿠키를 생성한다.
path: '/',
httpOnly: true,
//통신할때만 접속할 수 있다. 기본값은 false임
signed: true,
//쿠키를 암호화 시킨다.
};
app.get("/", (req,res) => {
req.session.name = "홍길동";
res.cookie('key', 'value', cookieConfig);
res.render("index");
});
app.listen(8000, ()=>{
console.log( "Server : ", 8000 );
});

→ Expire가 날짜로 바뀌어있음을 볼 수 있다. 30초가 지나면 쿠키는 사라진다.
app.get("/get", (req,res) => {
console.log(req.cookies);
res.send(req.cookies);
//req가 클라이언트가 서버한테 요청하는것임. 어떤 요청인지 궁금하면console.log(Req)로 확인하면됨
})
→ 쿠키 어떤거 있는지 보여주는것이다. 근데 클라이언트한테 있는 쿠키를 보여주는거니까 클라이언트한테 받기 위해서 req.cookies이다.
<views 폴더 - cookie.ejs >
app.get("/cookie", (req,res)=> {
res.render("cookie");
})
→ "/cookie" 경로에 접속하면 cookie.ejs 파일을 불러와서 보여준다.(랜더링 해준다.)
<cookie.ejs>
<html>
<head>
<script>
console.log(document.cookie);
</script>
</head>
</html>

→ 쿠키를 확인 할 수 있다. document.cookie에 쿠키 정보가 담긴다.
<html>
<head>
<script>
console.log(document.cookie);
document.cookie = "user=sesac; expires=Sat, 13 Aug 2022 13:00:00 GMT; path=/";
console.log(document.cookie);
</script>
</head>
</html>
클라이언트에서 쿠키 설정⇒ user: sesac을 확인 할 수있다.
<index.js>

먼저 호스트(user=sesac)가고 그 다음에 쿠키가 가면 여러개의 쿠키가 연결되어 나오는것을 볼 수 있다.
( 이부분 아무래도 user=sesac이라는 호스트가고 쿠키에서 key와 value가고 key2,value2 간다는것을 쓰고 싶었나본데 아니라면 수정을 해야겠다. )
위의 상황에서 cookie.ejs 는 아래와 같이 코드를 작성해서 확인 할 수 있다.
<html>
<head>
<script>
console.log(document.cookie);
</script>
</head>
</html>
만약 이럴때 key2의 값을 클라이언트가 갖고오고 싶다면 어떻게 해야할까.
<html>
<head>
<script>
var cookieArr = document.cookie.split(";");
// for (var i =0; i < cookieArr.length;i++ ) 와 아래 for문은 동일하다.
//cookieArr가 갖고있는인덱스 만큼 도는것이다.
for( var i in cookieArr ){
console.log(cookieArr[i]);
}
</script>
</head>
</html>
;으로 split 하고 for문 돌면서 key가 key2인 친구를 찾아야한다.
(와우.. 뭐라는건지 지금보니까 모르겠다... 나중에 이해하는대로 추가)
그런데 이렇게 for문을 설정하면 만료기한 등의 옵션을 설정할 수 없다.
<html>
<head>
<script>
console.log(document.cookie);
document.cookie = "user=sesac; expires=Sat, 13 Aug 2022 13:00:00 GMT; path=/";
→ 위와 같은 형태로 명확하게 날짜를 적어주어야한다. 만일 path등의 다른 옵션을 지정하고 싶다면 ;으로 나눠서 지정을 해주면 된다. 그럼 아래와 같이 내가 설정한 path /와 Expires가 나온다.
(추가)
document.cookie로 쿠키는 여러개 생성할 수 없다. 텍스트 파일이니까 중간만 바꿀 수 없고, 수정하고 싶다면 다시 다 덮어써야한다.
>>>
Session
session이란 웹 서버에 저장되는 쿠키이다.
세션은 상태유지라고 보면된다. 한번 연결이 되면 그 상태를 계속해서 유지하는것이다. 연결을 끝낼때까지!
연결을 끝냈다 : 브라우저를 껐다.
쿠키보다 보안이 좋은 편이다. 쿠키는 클라이언트에 저장이 되기 때문에 우리가 볼 수 있는데, 세션은 서버에 저장이 되기 때문에 우리가 볼 수 없어서 보안이 좋다.
쿠키는 저장에 제한이 있다. 그러나 세션은 서버에 저장하는거라 서버의 용량이 무한하다면 무한하게 저장 할 수 있다.
Session의 동작 방식
클라이언트가 서버에 접속시 세션id를 발급받는다
→ 클라이언트는 세션id에 대해 쿠키를 사용해서 저장하고, 가지고 있다.
→ 클라이언트는 서버에 요청할 때, 이 쿠키의 세션 id를 서버에 전달해서 사용한다.
→ 서버는 세션 id를 전달받아서 별다른 작업 없이 세션 id로 세션에 있는 클라이언트 정보를 가져온다.
→ 클라이언트 정보를 가지고 서버 요청을 처리하여 클라이언트에게 응답한다.
: 세션은 서버에서 만들어진다. 아이디만 클라이언트에게 보낸다. 키를 보내고 값은 클라이언트가 모른다.
클라이언트가 요청할 때 서버가 키를 가지고 찾아서 값을 보내주는 것이다.
Cookie and Session
쿠키와 세션은 저장되는곳이 다르다.
가장 큰 차이점은 속도이다. 우리눈으로 확인하기는 어렵지만, 실제로 쿠키가 조금 더 빠르다. 클라이언트에 저장이 되어있기 때문에 바로 저장한것을 가져와서 사용 할 수있다. 서버에 요청하지 않아도 된다.
반면, 세션은 서버 아이디를 기반으로 찾아야하기 때문에 몇단계를 거쳐야하므로 세션이 더 느리다.
Session사용하기
npm i express-session
설치해준다.
<index.js>
app.get("/", (req,res) => {
req.session.name = "홍길동";
res.cookie('key', 'value', cookieConfig);
res.cookie('key2', 'value2', cookieConfig);
res.render("index");
});
app.get("/get", (req,res) => {
console.log( req.session.name);
console.log(req.cookies);
res.send(req.cookies);
})
/get으로 가면 console에 홍길동이 뜨고, 다른페이지를 가도 계속 유지가 됨을 확인 할 수 있다.

세션은 연결된 상태를 유지하면서 값이 저장되는 거라서 연결이 끊기면 저장된 값이 사라진다. 브라우저를 끔으로써 연결을 끄는 것이다. 그렇기 때문에 브라우저를 끄면 네임에 저장된 홍길동이 console 에서 사라진다.

app.get("/destroy", (req,res)=> {
// res.render("cookie");
req.session.destroy(function(err){
res.send("삭제");
})
req.session.name = "";
})
destroy는 모든 정보를 한번에 지워준다. (초기화)
get → destroy에서 삭제하고, 다시 get으로 오면 세션이 지워졌음을 확인 할 수있따. 세션이 저장되어있던걸 모두 다 없애준것이다.
근데 내가 하나만 없애고 싶다면? 값을 빈값으로 따로 설정해 주어야한다.
req.session.name = "";
하나만 삭제하고 싶은것은 그때 그 값이 빈값이 되도록 설정해주면 된다.
<index.js>
app.get("/", (req,res) => {
req.session.key = "value";
req.session.name = "1";
req.session.num = "2";
res.cookie('key', 'value', cookieConfig);
res.cookie('key2', 'value2', cookieConfig);
res.render("index");
});
localhost:nnnn/get으로 가고, 그 후 localhost:nnnn/distroy를 가준다.
그리고 /get을 가보면 세션이 비어있음을 확인 할 수있다.

app.get("/destroy", (req,res)=> {
req.session.name = "";
res.send("123");
})
req.session.name = ""; 해주고 위와같이 get - distroy - get으로 가면, name 이 비어있다.

<index.js>
//로그인 페이지 보이겠지 버튼 눌렀을때 포스트 ~!
app.get("/login", (req,res) => {
res.render("login");
});
//로그인 성공시 세션에 아이디 넣고 redirect:이동한다는것임 프로필로 했기때문에 그 get으로 가는것이다.
//폼정보를 보내준다
//검사 후 나온 결과가 flag라면 성공은 id 정보값을 제대로 넣은친구를 프로필페이지로 리다이렉트하는거임.
//프로필 redirect는 /profile로 우리가 치는거랑 다음. 실패시 다시 로그인페이지가 보이는것이다.
app.post("/login", (req,res) => {
var flag = true;
if (flag) {
req.session.id = req.body.id;
res.redirect("/profile");
}else res.redirect("/login");
});
app.get("/profile", (req,res) => {
if (req.session.id == undefined || req.session.id ==""){
res.redirect("/login");
return false;
}
req.session.id
res.render("profile");
});
app.get("/main", (req,res) => {
});
app.listen(8000, ()=>{
console.log( "Server : ", 8000 );
});
만약 세션에 아이디가 없거나 비어있으면 이 사람은 로그인 성공자가 아니다. 그러므로 로그인으로 redirect 보낸다.
근데 정상이면 그 아이디를 가지고, db검색이나 프로필정보를 가져온다. render 프로필정보를 볼 수있게 되는것이다. 지금까지 우리가 한건 프로필이 무조건 post로 받았기 때문에 링크 접속은 can not post 됐던 것이다.
위와같이 하면 로그인을 정상적으로 성공한사람이라면 /profile해도 볼 수 있다.
만약 내가 창을 껐다켜서 아이디 undifined 나오면 로그인부터 하라고 다시 로그인페이지로 간다.
분명 수업때는 다 이해간줄알았는데, 보니까 아닌거같다.. 내가 쓰고도 이해안가는게 태반이다. 프로젝트에 세션을 잘 사용 할 수 있을까..
*피드백받아서 수정되었습니다. 왕감사!!