Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

쿠키? 그거 먹는 건가요? 본문

🎨 프론트엔드

쿠키? 그거 먹는 건가요?

Chamming2 2021. 2. 15. 22:15

혹시 페이스북을 사용해 보신 적 있으신가요?

페이스북을 사용해 보신 분들이라면 들어갈 때마다 로그인을 수행하는 대신 항상 로그인 상태가 유지되고 있는 것을 알고 계실 것입니다.

바로 이런 기능이 "쿠키" 를 활용해 구현된 기능인데요, 오늘은 쿠키를 활용하는 방법에 대해 알아보겠습니다.

쿠키(Cookie)란?

쿠키는 키 - 값 쌍으로 이루어진 작은 데이터입니다.

서버는 브라우저에 쿠키를 전달하고, 브라우저는 쿠키를 저장해 두었다가 다음 번 요청부터 보관하고 있던 쿠키를 서버에 전달합니다.

[자동 로그인의 대략적인 원리]

쿠키는 주로 세션 관리나 트래킹 등 용도로 사용되는데요, 트래킹의 예시로 현재 창에서 개발자 도구를 열고 document.cookie 를 입력해 보면 카카오 애드핏과 구글 애널리틱스 등 트래킹 도구에서 여러분의 접속 정보를 저장하고 있는 것을 확인할 수 있습니다.

서버에서 쿠키 전달하기

본격적으로 쿠키를 생성해 보겠습니다.

다음 커맨드를 통해 node.js 테스트 환경을 세팅해 주세요.

npm init -y // node.js 프로젝트를 생성합니다.
// 필요한 디펜던시를 설치합니다.
npm i express cookie-parser
// express : 서버 생성용 라이브러리
// cookie-parser : 요청 헤더의 쿠키 파싱용 라이브러리
const express = require("express");
const app = express();

app.listen(5000, () => {
  console.log("server is running on 5000");
});

app.get("/", (req, res) => {
  //res.setHeader("Set-Cookie", ["id=chanmin"]); -> res.cookie와 동일한 역할입니다.
  res.cookie("id", "chanmin");
  res.send();
});

서버에서 클라이언트로 쿠키를 전달하기 위해서는 응답 헤더Set-Cookie 속성을 활용하는데요,

5000번 포트에 간단한 서버를 구축하고 요청이 들어오면 id=chanmin 이라는 쿠키를 전달해 보겠습니다.

Postman(https://www.postman.com/) 이라는 툴을 활용하면 간단하게 http 요청을 테스트할 수 있습니다.

클라이언트에서 받은 쿠키를 확인하려면 요청 헤더Cookie 속성을 확인하면 되는데요,

이제부터는 클라이언트가 서버에 요청을 보낼 때마다 해당 쿠키를 요청 헤더에 포함해 자동으로 전달하게 됩니다.

쿠키의 수명

Expires 옵션을 통해 쿠키 정보를 

다만 쿠키의 수명은 영원하지 않습니다.

쿠키는 세션(Session) 쿠키와 영속(Permanent) 쿠키로 구분할 수 있는데요, 세션 쿠키는 브라우저가 종료될 때 함께 소멸됩니다.

다만 영속 쿠키는 브라우저를 종료하더라도 서버가 지정한 시간까지 브라우저 저장소에 저장됩니다.

 

이번에는 쿠키의 수명을 설정해 보겠습니다.

const express = require("express");
const app = express();

app.listen(5000, () => {
  console.log("server is running on 5000");
});

app.get("/", (req, res) => {
  //res.setHeader("Set-Cookie", ["id=chanmin; Expires=10000"]);
  res.cookie("id", "chanmin", { maxAge: 10 * 1000 }); // 10초 뒤에 소멸됩니다.
  res.send("응답 전송!");
});

응답 헤더에서 Expires 라는 속성을 사용하면 쿠키는 영속 쿠키가 되며 지정한 날짜에 브라우저에서 소멸됩니다.

정말로 소멸되는지 한번 확인해 보겠습니다.

const express = require("express");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cookieParser());

app.listen(5000, () => {
  console.log("server is running on 5000");
});

app.get("/", (req, res) => {
  console.log(
    "요청 시간 : ",
    new Date().toLocaleString(),
    "/ 쿠키 : ",
    req.cookies // 클라이언트가 전송한 쿠키를 출력합니다.
  );
  res.cookie("id", "chanmin", { maxAge: 10 * 1000 }); // 10초 뒤에 소멸됩니다.
  res.send("응답 전송!");
});

쿠키의 수명을 10초로 설정했었는데요, 약 13초가 지난 후 다시 요청을 보내보니 쿠키 객체가 null 이 된 것을 확인할 수 있었습니다.

쿠키의 범위

인터파크에서 쇼핑을 하고 있다고 생각해 보세요.

물건을 다 담고 장바구니에서 결제를 하려는데, 어이쿠! 로그인이 초기화되었네요.

이런 불상사가 일어나지 않게 하려면 쿠키의 범위도 꼼꼼히 확인해줘야 합니다.

쿠키를 사용할 수 있는 범위는 Path 속성을 통해 지정할 수 있는데요, 지정한 경로와 하위 경로에서만 쿠키를 사용할 수 있습니다.

예를 들어 Path=/shop 이라고 쿠키의 범위를 설정하면 /pay나 /main 같은 다른 경로에서는 쿠키를 사용할 수 없습니다.

Path 속성에 따른 쿠키 범위 예시 : Path = /shop 일때

1. /pay : 쿠키 사용 불가

2. /shop : 쿠키 사용 가능

3. /shop/basket : 쿠키 사용 가능

 

따라서 특별한 이유가 없다면 Path = / 처럼 루트 경로로 설정해 모든 서브페이지에서 쿠키를 활용할 수 있도록 하는 것을 권장합니다.

쿠키의 보안

마지막 주제인 보안은 꽤나 흥미로운데요, 페이스북에서 무료하게 놀고 있을 때 갑자기 팝업이 하나 뜹니다.

20만원을 준다니! 바로 눌러야겠죠?

<form method = "post" action = "facebook.com/chanmin/title=불법도박에/desc=어서오세요" />

하지만 이 팝업을 누르는 순간 숨어있던 폼에 의해 피드에 불법토토 광고를 올리게 됩니다.

이와 같은 공격 방식을 CSRF(Cross-site request forgery) 공격이라고 부르는데요, CSRF 방지 토큰이라는 장치를 통해 공격을 막을 수 있기는 합니다. 그러나 모든 폼에 CSRF 방지 토큰을 설정하는 것은 손이 많이 가기 때문에 쿠키에 특수한 기능을 추가하기로 합니다.

 

바로 samesite=strict 라는 속성으로, 이 옵션을 적용하면 요청을 전송한 오리진을 확인한 후 사이트 외부에서 전송된 요청일 경우 쿠키를 포함하지 않습니다.

samesite=strict 를 적용했을 때

- www.facebook.com/chanmin/post 오리진에서 글 작성 요청을 보냄 -> 요청에 쿠키를 포함함!!

- www.불법광고.com 오리진에서 글 작성 요청을 보냄 -> 요청에서 쿠키를 제외함!

 

samesite 옵션을 활용하면 이렇게 외부 오리진에서 쿠키를 통한 요청을 차단할 수 있습니다.

다만, 아직은 모든 브라우저에서 지원하지는 않으니 사용에 유의해야 합니다.

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆