로그인에 관하여(쿠키와 세션, JWT)

최윤석·2023년 3월 2일
1

CS

목록 보기
3/3
post-thumbnail

⭐포스팅 목표

해당 포스팅은 웹 개발에서 빼놓을 수 없는 기능인 로그인에 대해 다룬다.

로그인 기능을 몇 차례 구현해봤지만 기능을 구현하며 쿠키와 세션, JWT 등 어떤 방식으로 로그인을 구현할 것이며 이들의 차이에 대해 고민해본 적이 없다.

로그인 방식을 선택하는 것은 백엔드 개발자의 몫이고 프론트엔드는 그저 로그인 기능을 잘 구현해서 유저가 불편하지만 않게 만들면 된다는 생각이 있었기 때문이다.

하지만, 로그인을 이해하는 것은 웹 개발 전반에 대한 이해도를 높일 수 있으며 보안에 대한 이해도, 사용자 경험 향상 등 프론트엔드 개발자에게도 많은 도움이 될 것이다.

따라서 이번 포스팅에서는 로그인에 주로 활용되는 쿠키와 세션, JWT의 차이점과 이 둘의 장단점에 대해 알아본다.

이번 포스팅은 이론에 대해서만 다룰 것이며, 3월 원티드 F.E. 프리온보딩(로그인) 수강 이후 실습 파트에 대한 내용을 포스팅 할 것이다.




🍪쿠키와 세션

왜 쿠키와 세션 방식으로 로그인을 구현하나요?

클라이언트와 서버는 HTTP 프로토콜을 사용하여 통신한다.

HTTP 프로토콜에는 비연결성(Connectionless)무상태성(Stateless)라는 특징이 있다.

HTTP 프로토콜은 요청과 응답을 처리하기 위해 각각의 요청이 독립적인 연결을 생성하고 종료한다.

이러한 특징을 비연결성이라고 하며, 비연결성으로 인해 클라이언트에서 로그인에 성공하더라도 이전 요청에 대한 데이터를 잊어버린다.

이를 무상태성이라고 한다.

HTTP 프로토콜비연결성무상태성 특징을 해결하고 클라이언트와 서버 간 상태 정보를 유지하기 위해 쿠키와 세션방식을 사용한다.

HTTP 프로토콜에 대한 자세한 내용은 이후 포스팅에서 다루도록 한다.


쿠키

쿠키는 클라이언트 측에서 상태 정보를 저장하는 방식이다.

서버는 사용자의 웹 브라우저에 쿠키를 보내며 브라우저는 서버에서 보낸 쿠키를 저장하고 이후 요청과 함께 동일한 서버로 다시 전송할 수 있다.

쿠키는 주로 세션 관리, 개인화, 트래킹 을 위해 사용된다.


쿠키 생성 방법

쿠키는 다음과 Set-Cookie를 사용하여 생성할 수 있다.

Set-Cookie: <cookie-name>=<cookie-value>

위의 방식으로 생성한 쿠키는 아래와 같이 HTTP header를 통해 클라이언트에 전송된다.

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

클라이언트는 서버에서 전송받은 쿠키를 저장하며, 이후 서버에 보내는 요청마다 HTTP HeaderCookie를 포함하여 전송한다

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

즉, 생성된 Cookie는 모든 요청에 포함되어 전송되기 때문에 성능이 떨어지는 원인이 될 수 있다.

이를 해결하기 위해, HTML5에서는 웹 스토리지 API(localStorage, sessionStorage)또는 indexdDB를 사용한다.

이에 대해서는 뒤에서 알아보자.


쿠키의 생명주기

Session Cookie(세션 쿠키)

세션 쿠키는 브라우저를 닫으면 삭제되는 쿠키를 말한다.

만료 기간을 설정하지 않으면 세션 쿠키로 동작한다.

주로 인증 정보 등의 임시 데이터를 저장하는데 사용한다.

Persistent Cookie(영속 쿠키)

Max-Age 또는 Expires 속성을 통해 만료 기간을 설정한 쿠키를 말한다.

영속 쿠키는 브라우저가 종료되도 삭제되지 않으며 만료 기간이 지나면 자동으로 삭제된다.

주로 사용자 설정이나 환경 등을 저장하는데 사용한다


Secure과 HttpOnly

SecureHttpOnly 속성은 쿠키의 보안을 강화하기 위해 사용된다.

Secure

쿠키를 HTTPS(SSL/TLS) 프로토콜을 통해서만 전송하도록 설정하는 속성이다.

HTTPS 프로토콜을 사용하면 클라이언트와 서버 간의 통신 내용이 암호화되므로 쿠키를 탈취하는 공격을 어렵게 만든다.

따라서 로그인 정보와 같은 민감한 정보를 다룰 때는 반드시 secure 속성을 설정해야 합니다.

하지만, Secure속성을 사용하더라도 민감한 정보는 쿠키에 저장하면 안된다.

HttpOnly

쿠키가 JavaScriptDocument.cookie API로 부터 접근될 수 없도록 설정하는 속성이다.

이 속성을 사용하면, 웹 사이트가 XSS(Cross-Site Scripting) 공격을 방지한다.

이외에도 Domain, Path, SameSite 속성이 있다.


쿠키의 특징

장점

  • 구현이 쉽다.
  • 서버에 요청을 보낼 때마다 쿠키 정보를 함께 전송하므로, 로그인 상태를 유지할 수 있다.
  • 개인화된 서비스 제공이 가능하다. (ex. 이전 방문 페이지나 검색어를 저장하여 추천 서비스에 활용)
  • 클라이언트에 저장되므로 서버 부하를 줄인다.

단점

  • 클라이언트 측에서 조작이 가능하다.
  • 보안에 취약점이 있다.
  • 용량이 4KB이하로 제한되어있다.

사용 예시

  • 로그인 상태 유지.
    로그인 정보를 쿠키에 저장하여 다음에 사요자가 사이트에 방문할 때마다 로그인을 다시 하지 않도록 한다.
  • 사용자 설정 저장.
    사용자가 이전에 선택한 옵션을 저장하고, 다음에 해당 페이지를 방문했을 때, 이전과 동일한 옵션을 보여준다.
  • 비회원 장바구니 정보 저장.

참고자료
MDN HTTP Cookie
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies


세션

앞서 살펴본 쿠키는 클라이언트에 저장되고 관리된다.

이러한 특징은 서버의 자원을 사용하지 않기 때문에 서버의 부하를 줄일 수 있다는 장점이 있다.

하지만 사용자의 개인 기기에 저장되기 때문에 쿠키 정보가 탈취되거나 임의 조작되는 등 보안의 위험이 존재한다.

따라서 민감한 정보를 쿠키에 저장하는 것은 위함하다.

이를 해결하기 위해 세션이라는 개념이 등장한다.

세션은 쿠키를 기반으로 동작하지만, 정보를 서버 측에서 관리한다는 점에서 차이가 있다.

서버는 클라이언트에 Session ID값을 부여하고 정보는 서버에 저장한다.

이후 클라이언트의 요청에 따라 서버에서 Session ID를 조회하여 클라이언트 정보를 가져와 사용한다.


세션의 특징

장점

  • 보안성이 높다.
    클라이언트 측에서 직접 접근할 수 없으며, 서버에서 관리하기 때문에 보안상 이점이 있다.
  • 서버에서 직접 관리하기 때문에, 클라이언트 측에서 세션 데이터를 변경할 수 없다.
  • 대용량 데이터의 전송이 가능하다.

단점

  • 서버에 부하가 증가한다.
    세션 정보를 서버에서 관리하기 때문에 사용하기 때문에 사용자가 많아지면 서버에 부하가 걸린다.
  • 쿠키에 비해 속도가 느리다.
    서버의 처리가 필요하기 때문에 쿠키에 비해 속도가 느리다.

사용 예시

  • 로그인 정보, 장바구니 정보
    서버에 저장해야 하는 정보를 클라이언트가 매번 보내지 않고, 세션에 저장하여 관리한다.

  • 사용자 인증
    로그인에 성공한 사용자는 서버에서 생성한 세션 ID를 사용하여 인증을 진행한다.


쿠키와 세션의 차이

쿠키와 세션의 가장 큰 차이점은 사용자의 정보가 저장되는 위치이다.

쿠키는 클라이언트, 세션은 서버에 저장된다.

보안은 세션이 우수하고, 속도는 쿠키가 더 빠르다.

쿠키는 브라우저를 종료해도 유지될 수 있으며, 만료기간이 종료되어도 브라우저가 해당 쿠키를 인식하지 못하게 되는 것일 뿐 파일 자체가 삭제되지 않는다.

세션은 브라우저의 메모리에 저장되므로 브라우저가 종료되면 삭제된다.

단, 서버 측 세션이 사라지는 것이 아니라 클라이언트 측 세션ID가 사라지는 것이다.


쿠키/세션 방식의 단점

  1. 서버 측에 데이터를 저장하기 때문에 사용자가 많아지면 서버에 부하가 심해진다.
  2. 서버가 에러가 발생하는 경우 세션에 저장된 데이터가 모두 손실된다.
  3. 사용자의 증가로 인해 로드밸런싱을 통한 서버를 확장시, 세션 관리가 어렵다.
  4. 중복 로그인 처리 등 구현이 복잡하다.

이러한 쿠키/세션 방식의 단점을 극복하기 위해 JWT(Json Web Token) 방식이 도입됐다.


💰JWT

JWT는 웹 토큰 기반의 인증 방식 중 하나이다.

기존의 쿠키/세션 방식의 단점인 서버 측 자원 소모와 확장성이 제한된다는 등의 단점을 보안하기 위해 등장하였다.

서버 측에서 토큰을 발급하여 클라이언트에게 전달하면, 이후에는 클라이언트 측에서 해당 토큰을 가지고 인가를 수행한다.

즉, 서버는 세션을 유지할 필요가 없으며 클라이언트는 토큰을 사용하여 언제든 인증이 가능하다.

Authentication(인증) vs Authorization(인가)

인증은 사용자가 누구인지 확인하는 과정으로, 사용자가 제공한 정보를 검증하여 사용자의 신원을 확인한다.
인가는 인증된 사용자가 특정 자원에 접근할 수 있는 권한이 있는지를 확인하는 과정이다.
이때, 사용자의 인증 정보를 이용하여 검증한다.


JWT와 쿠키의 차이

JWT의 인증 방법은 Cookie와 유사하지만 몇 가지 차이점이 있다.

JWT쿠키
전송 방식Authorization 헤더Cookie 헤더
보안서명(signature)된 토큰 사용(위조 방지)서명되지 않은 값(조작 가능)
서버 확장성서버에서 세션을 관리하지 않아도 됨서버에서 세션을 관리하므로 확장성이 떨어짐
만료 시간만료 시간을 포함시킬 수 있으며
토큰이 만료되면 자동으로 만료됨
만료 시간을 설정해도
브라우저를 닫거나 쿠키를 삭제하기 전까지 유지됨

JWT의 구성

JWT는 각각의 구성 요소( HEADER, PAYLOAD, SIGNATURE )가 .으로 구분되어 있다.

참고자료
JWT
https://jwt.io/

1. HEADER

헤더에는 토큰의 타입과 SIGNATURE생성에 사용된 알고리즘이 담긴다.

  • "alg" : 사용된 알고리즘 (예: HMAC SHA256 또는 RSA)
  • "typ" : 토큰의 타입 (JWT)

2. PAYLOAD

페이로드는 Claim(클레임)이라고도 불리며 사용자의 정보와 같은 데이터를 담는다.

표준으로 정해진 Claim은 다음과 같다.

  1. registered claim

    • "iss"(issuer) : 토큰 발급자
    • "sub"(subject) : 토큰 제목(주로 유저 식별자 등)
    • "aud"(audience) : 토큰 대상자
    • "exp"(expiration time) : 토큰 만료 시간
    • "nbf"(not before) : 토큰 활성화 시간
    • "iat"(issued at) : 토큰 발급 시간
    • "jti"(JWT ID) : JWT 고유 식별자
  2. public claim
    공개용으로 사용하기 위한 claim으로 특정 프로젝트나 조직에서 사용하는 claim을 자유롭게 정의해서 사용할 수 있다.

  3. private claim
    JWT를 사용하는 개발자나 프로젝트에서만 사용되는 claim을 정의해서 사용할 수 있다.
    이를 위해 claim 이름 앞에 일반적으로 발행자(issuer)의 도메인 이름을 추가해 claim 충돌을 방지하는 것이 좋습니다.

단, Payload는 암호화되지 않기때문에 민감한 정보를 포함하면 안된다.

3. SIGNATURE

시그니처는 HeaderPayload를 합친 문자열과 서버에서 발급한 Secret Key를 사용하여 생성된다.

이를 통해 JWT의 위변조 여부를 확인한다.


JWT의 특징

장점

  • JWT는 무상태성(Stateless)을 가지고 있기 때문에, 세션을 유지할 필요가 없다.
    서버에서 사용자 정보를 저장하지 않으므로, 서버 부하가 적다.
  • JWT는 JSON 형태로 구성되어 파싱하기 쉽고, 다양한 프로그래밍 언어에서 지원된다.
  • JWT는 URL, POST 변수, HTTP 헤더 어디서든 전송이 가능하다.

단점

  • 한 번 발급된 토큰을 취소할 수 없다.
    만료시간을 설정하여 일정시간이 지나면 토큰이 만료되도록 구현해야 한다.
  • 페이로드는 인코딩되어 있지만 암호화되어 있지 않기 때문에, 정보가 노출될 위험이 있다.
  • 토큰 크기가 커질 수 있다.

사용 예시

  • 사용자 인증 정보를 저장하고 전달하는 용도로 많이 사용된다.
  • OAuth 2.0 프로토콜에서 사용된다.
  • REST API 인증에서 많이 사용된다.



웹스토리지에 대한 내용이 추가될 예정입니다.

profile
프론트엔드를 공부하고 있는 주니어 개발자입니다.

0개의 댓글