데브코스 웹풀스택 과정/TIL

1002 쿠키와 세션 그리고 JWT(토큰 발행 및 쿠키담기, 유효기간 설정)

thinktank911 2025. 10. 2. 11:40

jwt의 개념과 역할 그리고 구현법에 대해 배웠다. 인증과 인가 절차는 모든 사이트에서 보안상 중요 요소이므로 앞으로 구현할 때 꼭 필요한 부분이라 유익했다. 잘 숙지하고 있어야겠다.


로그인 세션 - 인증과 인가

"로그인(=인증) 세션이 만료되었습니다"

 

우리는 사이트를 접속할 때 위의 문구를 많이 봤을 것이다. 이때, 인증은 무엇이며 세션이 만료되었다는 말을 무슨 의미인지 살펴보겠다.

 

인증과 인가

  • 인증(=로그인) Authentication
    : 관리자든 고객이든 인증을 통해서 사이트에 가입된 사용자라는 걸 증명하는 것
  • 인가 Authorization
    : 인증 후, 페이지 접근 권한 (다르게) 부여
    예) 같은 사이트 내에 관리자 / 고객 에 따라 접근할 수 있는 페이지가 다르다.

쿠키와 세션 차이

  • 쿠키와 세션 둘 다 로그인을 유지시켜주는 기능이라는 점에서 공통점이 있다.

 

쿠키

  • 웹에서 서버와 클라이언트가 주고받는 데이터 중 하나
  • 정확히는 생성은 웹 서버가 해서 웹 브라우저 주면, 브라우저가 자기 메모리에 저장해두고,
    다음에 같은 웹서버 방문 시 쿠키 들고 요청하러 감

   1) 사용자가 로그인  ➡️ 서버가 쿠키를 구워준다.
   2) 사용자 ↔️ 서버가 쿠키를 핑퐁

  • 장점
    • 서버가 저장하지 않음 ➡️ 서버 저장 공간 아낄 수 있다
    • http 특성 중 하나인 Stateless => RESTful하다(무상태성)
  • 단점
    • 보안에 취약하다.

 

세션

  • 로그인이 되어 있는 상태를 말한다.
  • 쿠키에 넣어서 보내기에 너무 중요한 내용은 서버가 가진 금고(세션)에 넣어두고 그 금고번호(세션ID)만 쿠키에 넣어서 통신

  1) 사용자가 로그인 ➡️ 서버가 금고 만들어 정보 저장. 금고 번호를 준다.
  2) 사용자 ↔️ 서버가 번호만 가지고 대화

  • 장점 
    • 보안에 비교적 강하다.
  • 단점 
    • 서버가 저장 ➡️ 서버 저장 공간을 쓴다
    • Stateless 하지 않다. ➡️ RESTful하지 않음

JWT 개념, 특징

JSON Web Token
: JSON 데이터를 웹에서 안전하게 보관하는 토큰

  • 토큰이 있으면 인증을 성공한다.
  • 신분 증명 역할(권한 나눠가짐)

 

개념

  • JSON 형태의 데이터를 안전하게 전송하기 위한 (웹에서 사용하는) 토큰
    ➡️ 토큰을 가진 사용자가 증명을 하기 위한 수단
    cf. 토큰 : (인증용) 입장 가능한 유저 / (인가용) 관리자 권한&일반 유저 권한

장점

  • 암호화가 되어 있어 보안에 강하다.
  • HTTP 특징을 잘 따랐다: Stateless 하다.
  • 서버가 상태를 저장하지 않는다. ➡️ 서버 부담 줄여줄 수 있다.
    cf. 토큰을 발행하는 서버를 따로 만들어줄 수도 있음

구조(feat. jwt.io)

  • 참조 링크 : https://www.jwt.io/
    • 발행된 jwt 입력 시 decoded(복호화) 해서 내용을 확인하거나 encoded(암호화) 해주는 사이트
 

JSON Web Tokens - jwt.io

JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).

www.jwt.io

  • 구조 확인 가능
    - 헤더/페이로드(정보/데이터)/베리파이 시그니처 를 각각 인코딩해서 . 으로 구분
  1. 헤더 - 토큰을 암호화하는 데 사용한 암호화 알고리즘(alg-hs256), 토큰 형태(typ-jwt)
  2. 페이로드 - JSON 형태, 사용자 정보(이름, 주소, ...비밀번호x)
  3. 시그니처 - 헤더와 페이로드 가 들어있다고 보증한 서명
    ➡️ 데이터(페이로드)가 바뀌면 시그니처 서명값도 바뀐다.
    ➡️ 기존에 서명한 데이터가 아니므로 받아주지 않는다.
    ➡️ JWT 보안이 높은 이유

 

 

JWT 인증-인가 절차

  1. 클라이언트가 로그인 요청 시 서버가 내부 로직을 확인한다.
  2. 서버가 JWT 즉, 토큰을 발행한다. 이때, 발행시점을 포함한다.
  3. 발행한 토큰을 쿠키에 동봉해 클라이언트에게 전달한다. (다음 요청 때 요구하기 위함)
  4. 클라이언트가 재로그인을 요청할 때 header에 JWT를 포함해 요청한다.
  5. 서버는 클라이언트가 보낸 JWT에서 서명(시그니처)이 일치 하는지 확인 후 일치하면 사이트 접속 인가를 해준다.
  6. 일치하지 않으면 403에러 블록을 던져준다.

JWT 인증-인가 절차

 

 

JWT 구현해보기

jsonwebtoken 설치

  •  npm i jsonwebtoken 

토큰 발행

  •  jwt.sign(암호화할 페이로드 객체, 나만의 암호키) 
var jwt = require('jsonwebtoken');

var token = jwt.sign({foo : 'bar'}, 'shhhhh');
// token 생성 = jwt 서명을 했다.(페이로드, 나만의 암호키) + SHA256

console.log(token)

 

토큰 검증 (복호화)

  •  jwt.verify(토큰, 나만의 암호키) 
// 검증
// 만약 검증에 성공하면, 페이로드 값을 확인할 수 있음!
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded); // { foo: 'bar', iat: 1759329821 } // iat : issuedat - 발행시간

.env(environment : 환경 변수 '설정값')

개념
: 개발하다가 포트넘버, 데이터베이스 계정, 암호키...등등 외부에 유출되면 안 되는 중요한 환경 변수들을 따로 관리하기 위한 파일
cf. 깃허브에 올라가면 안되는 값

  • .env 파일은 환경 변수 파일 -> 프로젝트 최상위 패키지에 존재
  • 설치 : npm i dotenv 
  • .env 파일에 저장한 PRIVATE_KEY를 process.env.PRIVATE_KEY로 꺼낸 사용한다.

.env 파일에 PRIVATE_KEY 저장

var dotenv = require('dotenv');

dotenv.config();

var token = jwt.sign({foo : 'bar'}, process.env.PRIVATE_KEY);

youtube에 jwt 적용해보기

  • jsonwebtoken과 dotenv 모듈을 셋팅한다.
  • 토큰 발행 :   jwt.sign(암호화할 페이로드 객체, 나만의 암호키, 옵션) 
    • 옵션 객체{}를 열어 유효기간(expiredIn), 발행인(issuer) 설정 가능
    • 제대로 옵션이 포함되었는지 확인하려면 jwt.io에서 토큰을 직접 넣어서 확인 가능하다.
  • 서버가 클라이언트한테 token 발행할 때 쿠키에 동봉해서 보내준다.
// jwt 모듈
const jwt = require('jsonwebtoken')

// dotenv 모듈
const dotenv = require('dotenv')
dotenv.config();



if(loginUser && loginUser.pwd === pwd){
    // token 발급 / 유효기간 설정
    const token = jwt.sign({
        email : loginUser.email,
        name : loginUser.name
    }, process.env.PRIVATE_KEY, {
        expiresIn : '30m',
        issuer : 'yj'
    });

    // 쿠키에 토큰 담기 - 토큰 변수에 토큰 담기
    res.cookie("token", token, {
        httpOnly : true
    })

    res.status(200).json({
        message : `${loginUser.name}님 환영합니다.`,
    })
}
else{
    res.status(403).json({  // 인증 안됨
        message : "아이디 또는 비밀번호가 일치하지 않습니다."
    })
}

cookie 설정

쿠키에 jwt 값 담아주기

// 쿠키에 토큰 담기 - 토큰 변수에 토큰 담기
res.cookie("token", token)

cookie 설정 변경

  • postman 쿠키 탭 컬럼에 Secure와 HttpOnly를 확인할 수 있다.
  • Secure : https 환경인지 묻는 것
    • https는 암호화된 페이지
  • HttpOnly : 프론트엔드가 아니라 API 호출만 허락할건지 묻는 것 ➡️ true로 변경
    • 브라우저에서 쿠키에 접근하는 보안공격을 방지하기 위함. ex> XSS 공격(프론트엔드 공격 : 웹 브라우저 js 접근 = 공격)

403 에러

  • 권한을 허가하지 않을 때 보내는 상태코드 에러로 로그인 실패 시 403 에러 상태 코드를 보내준다.

※ gitignore 파일 만들기

.git init 폴더가 있는 프로젝트 최상위 루트에 .gitignore 파일을 만든다.

그 안에 버전관리에 포함하지 않을 파일을 패턴에 맞게 작성해 준다. 

  표준 Glob 패턴을 사용한다.

  아무것도 없는 라인이나, "#"으로 시작하는 라인은 무시한다.

  슬래시(/)로 시작하면 하위 디렉토리에 적용되지(Recursivity) 않는다.

  디렉토리는 슬래시(/)를 끝에 사용하는 것으로 표현한다.

  느낌표(!)로 시작하는 패턴의 파일은 무시하지 않는다.

 

<설정 예시>

# 확장자가 .a인 파일 무시

*.a



# 윗 라인에서 확장자가 .a인 파일은 무시하게 했지만 lib.a는 무시하지 않음

!lib.a



# 현재 디렉토리에 있는 TODO파일은 무시하고 subdir/TODO처럼 하위디렉토리에 있는 파일은 무시하지 않음

/TODO



# build/ 디렉토리에 있는 모든 파일 무시

build/



# doc/notes.txt 파일은 무시하고 doc/server/arch.txt 파일은 무시하지 않음

doc/*.txt



# doc 디렉토리 아래 모든 .pdf 파일 무시

doc/**/*.pdf

 

더 쉬운 셋팅법

gitignore.io라는 사이트에서 자신의 프로젝트에  맞는 .gitignore 파일 자동으로 생성해준다.

운영체제, 개발 환경(IDE), 프로그래밍 언어 옵션을 넣으면 간단히 생성해준다.

https://www.toptal.com/developers/gitignore/

 

gitignore.io

Create useful .gitignore files for your project

www.toptal.com