본문 바로가기

개발관련 지식들

쿠키(cookie), 세션(Session), 케쉬(Cache), 인증(Authentication), 인가(Authorization, 다른 말로 권한 부여), JWT(Json Web Token)

참고: https://www.youtube.com/results?search_query=%EC%84%B8%EC%85%98

참고(세션과 JWT):  https://www.youtube.com/watch?v=1QiOXWEbqYQ

쿠키: 사이트를 방문할때 브라우저에 저장되는 내용들을 담는 공간. 브라우저는 내 컴퓨터에 있는 소프트웨어이므로 내가 가지고 있는 정보임. 쿠키에는 한계가 있음. 내가 임의로 고치거나 지울수 있고, 남이 훔쳐보거나 도둑질도 가능함. 즉, 민감한 개인정보를 쿠키북에 적어서 다니는 것은 불안함. 따라서 남이 보았을때 큰 문제가 없고 그다지 민감한 정보가 아닌 사항들, 해당 쿠키의 사용자가 직접 조작해도 서버측에서는 문제가되지 않는 내용들이 쿠키에 담기게 된다.

세션:  서버가 기억하는 사용자의 로그인된 상태 (로그인 시점부터 로그아웃까지의 기간,상태). 서버가 클라이언트를 식별할 수 있는 인증 기술이 세션이다(즉 세션이란 상태, 기술의 이름이다). 하나의 웹사이트 내에서 여러 페이지를 돌아다녀도 다시 로그인하지 않고 서비스를 계속적으로 이용할 수 있는 것은 세션과 쿠키의 조합으로 가능한것.(참고로 아이디 자동완성, 공지 메시지 하루 안보기, 로그인 하지 않은  체로 쇼핑몰에서 카트담기 하는 기능등 사용자의 편의를 위하되 조작되거나 가로체여도 큰 일없는 그런 정보를 이용한 서비스는 브라우저의 쿠키가 있어 가능하고 비밀번호 자동완성은 쿠키와 세션의 조합으로 가능한 것임)

 

따라서 웹개발자는 사이트를 만들때 해당 정보가 세션에 저장될지 쿠키에 저장될지 분별할 수 있어야 함.

캐쉬: 다시 가져오는데 비용이 드는 데이터를 한번 가지고 후에는 임시저장소인 케쉬에 저장해두는 저장공간(캐쉬라는 용어는 컴퓨터의 메모리 부분이나 안드로이드 등에서 흔히 쓰이는 용어임)

웹캐쉬는 주로 이미지 같은 데이터를 불러올때 데이터 사용량, 시간이 소요되기 때문에 사용자가 여러번 방문할 것 같은 사이트에는 그 사이트를 사용자의 컴퓨터 혹은 중간 역할을 하는 서버에 저장해둠(웹 브라우저의 저장공간을 말하기도 함).

=================================================================================

서버를 프로그래밍할때 인증(Authentication)과 인가(Authorization, 권한부여)를 어떻게 프로그래밍 할지가 중요함.

인증(Authentication): 쉽게 생각하여 로그인이라고 보면 됨

인가(Authorization, 권한부여): 인증을 받은 사용자가 이후에 서비스의 여러 기능들을 사용할 때 (로그인후 친구목록을 보거나 이전 사용 기록을 보는 행위 등),  서버가 내가 로그인되어 있음을 확인하고 허가를 해주는 것. 즉, 로그인 상태에서 서버가 클라이언트의 요청을 허가해주는 것을 인가(Authorization) 라고 함

(용어가 햇갈릴 수 있는데 인증이 되면 인가가 되면서 응~ 어떠~와~ "Author와~~" 이기 때문에 Authorization을 인가라고 기억하면 쉬움)

JWT는 인증(Authentication)보다는 인가(Authorization)와 관련된 기술임.

=====================================================================================

세션(Session)과 JWT의 차이점.

특정 웹사이트에 로그인(Authentication)한 후 사이트 안에서의 요청마다 다시 로그인을 할 수 없는 노릇이니 로그인 상태를 유지시키기 위한 기술이 필요하다. 이때 사용될 수 있는 기술이 세션이나 JWT(Json Web Token)이다.

즉, 세션,  JWT는 로그인 상태를 유지하기 위한 기술이다. 세션은 상태를 유지하므로 stateful 하고 JWT는 상태를 유지하지 않으므로 stateless하다.

로그인 상태를 어떻게 유지할까에 대한 고민으로부터 JWT개념이 생겨났습니다(세션도 마찬가지임)

로그인이란 기본적으로 꽤 무거운 작업입니다. 일단 DB에 저장된 사용자 계정의 해시값등을 꺼내온 후에 이것들이 사용자의 암호를 복잡한 알고리즘으로 계산한 값과 일치하는지 확인하는 과정을 거쳐야 합니다. 즉, 계산 자체도 빡세고 DB에서 뭘 꺼내오는 것도 무거운 작업이라는 것. 즉 어떠한 요청마다 이러한 로그인 확인 작업을 하는 것은 무거운 일이라는 것입니다. 그리고 매 요청마다 id와 pw가 실려서 날라다니는 것은 매우 위험한 일입니다.  이를 해결하기 위한 방법중 하나가 전통적인 세션방식이고 다른 하나가 JWT이다. 

1. 세션: 사용자가 로그인에 성공하면 서버는 "세션 표딱지"를 출력함. 이 세션 표딱지를 반으로 찢어서 반은 클라이언트(브라우저)에게 보냄. 이것이 바로 클라이언트가 가지는 쿠키, 즉 세션 ID이다(쿠키=세션ID). 브라우저는 이후 요청을 보낼 때마다 요청에 표딱지를 실어 보냄. 그 표딱지의 반쪽이 서버의 책상위에 있으면 인가(Authorization)가 되는 것임!!! 그리고 반은 자기 책상(메모리)에 둠. 경우에 따라서는 서랍(하드디스크), 창고(DB)에 넣음. 뭘 넣고 꺼내는 작업이 얼마나 빠른지를 가지고 책상, 서랍, 창고라고 하는 것임. 

세션방식의 인가(Authorization)는 몇가지 문제를 가진다. 첫째는 많은 사용자가 있다면 메모리 자체의 공간의 문제가 있을 수 있고 메모리라는것이 휘발성이 있기때문에 에러 발생시 기존에 로그인 되어있던 사용자들의 접속이 모두 튕겨질수 있다는 것이다. 그렇다고 데이터를 서랍(하드디스크)에 넣으면 그 속도가 느려질 것이다. 더 큰 문제는 서비스가 커졌을때 서버를 여러개 두었을 때다. 서버마다 각각의 책상과 서랍을 가지고 있고 사용자 정보를 어느 서버에 저장하는지도 이슈가 되고 공통책상(MemCached메모리형 데이터베이스 서버)을 둔다고 해도 이 메모리 공간이 엎어지면 문제가 생기는 것임. 이러한 이슈로 인해 인가(Authorization)를 다루는 해결책으로 JWT방식이 등장함. JWT에서는 사용자가 로그인하면 사용자에게 Token이라는 표를 출력해줌. 찢어서 주지않고 그냥 줍니다. 즉 서버가 로그인 상태를 기억하지 않는 Stateless입니다. 이 토큰은 암호화된 3가지 데이터를 이어 붙인것임(영상보면 자세한 설명나옴) 간단하게 말하면 토큰의 정보를 서버가 가지고 있는 비밀키와 함께 돌려보아 사용자의 정보를 확인하여 인가(Authorization)를 해주는 것임. 즉 JWT는 시간에 따라 바뀌는 상태값을 가지지 않으므로 Stateless이고 세션은 stateful임. 하지만 JWT도 단점이 있다. 상태를 기억하고 있지않아 사용자를 제어할 수 없다는 것, 이에대한 대안책도 있지만 세션없이 쓰이는 JWT는 현재로써는 없다. 

🔎 세션(Session)

브라우저를 통해 서버에 접속할 때 서버는 세션 id를 쿠키에 담아 되돌려주고, 사용자는 세션 id를 담은 쿠키인 세션 쿠키를 이후 요청부터 계속해서 함께 전달함으로 서버가 클라이언트를 식별할 수 있게 하는 기술이 세션 기반 인증 방식인데 보통 세션이라고 한다. 즉 세션은 앞에서 살표보았듯이 사용자의 로그인 상태를 의미하기도 하지만 인증 방식을 두고도 세션이라고 하는 이중의 의미를 가진다. 

클라이언트가 HTTP요청을 보낼 때 쿠키에 세션 id가 없다면 서버는 세션 id를 생성 해 쿠키에 담아서 돌려준다. 다시 HTTP 재요청을 할 때 쿠키를 보내기 때문에 서버에서는 세션 id를 통해 클라이언트를 식별할 수 있는 것이다.

📌 쿠키 vs 세션

세션은 HTTP의 stateless 속성을 보완한다는 점에서 쿠키와 자주 비교되곤 한다(복습. HTTP프로토콜의 3가지 특징. 1. 서버와 클라이언트 구조를 가진다 2. Stateless하다 3.Connectionless하다). 쿠키의 유형에는 영구 쿠키와 세션 쿠키가 있어 만료시기가 각각 다르지만 세션은 대부분의 경우 브라우저 종료 시 만료된다. 쿠키와 세션의 가장 큰 차이는 저장 위치이다. 쿠키는 클라이언트에 저장되고, 세션은 서버에 저장된다. 그러나 서로 반대 되는 개념이 아니라 세션 id를 쿠키에 담아서 통신한다는 점에서 세션은 쿠키를 사용하는 방식이라고 볼 수 있다.

📌 세션의 단점

세션기반 인증 방식을 사용할 때 중앙 세션 관리 시스템에서 하나의 문제가 시스템 전체로 확산된다는 문제점이 있다. 또 다른 문제점은 사용자가 많아짐에 따라 세션 DB와 서버를 확장해야 한다는 점이다. 예를 들어 내가 사용하고 있는 어떤 웹사이트에 사용자가 많아져 세션DB를 A와 B로 나누었다고 가정해보자. 나에 대한 정보는 세션 A에 저장되어 있었다. 그렇다면 앞으로 해당 웹페이지에 request를 보낼 때 세션 A에서만 통신하도록 하는 추가적인 기술이 필요할 것이다.


🔎 JWT

위의 단점을 어느 정도 해결할 수 있는 기술이 JWT이다. JWT는 JSON Web Token의 약자로 이상한 형태(Encoded된)의 문자열이다.

📌 구성

.을 기준으로 구분되어 header, payload, signature로 구성 되어 있다. JWT는 암호화되지 않아서 누구나 확인할 수 있기 때문에 중요한 정보를 JWT에 담으면 안된다.

  • header: typ와 alg라는 정보가 존재하는데 typ의 값은 JWT이고 alg signature를 해싱하기위한 알고리즘이다.
{
	"alg": "HS256", 
	"typ": JWT 
}
  • payload: 토큰에서 사용할 조각들인 클레임이 존재한다. 토큰의 목적에 따라 클레임이 달라진다. registered claim에는 토큰 만료시간, 토큰 발급 날짜 등을 작성할 수 있다.
  • signature: 토큰을 인코딩하거나 유효성 검사를 할 때 필요한 암호화 코드이다.

📌 동작방식

쉽게 설명하자면 JWT는 일종의 확인서이다. 우리가 어떤 웹사이트에 로그인을 해서 성공적으로 Authentication이 이루어지면 서버는 싸인된 확인서(JWT)를 우리에게 제공한다. 그러면 앞으로 요청 때마다 JWT를 서버에게 같이 보여주면서 권한을 확인받는 것이다. 서버는 JWT만 확인해 Authorization하기 때문에 세션 DB에 저장할 필요가 없다.

📌 JWT 저장위치

JWT를 웹에서 저장하기 위해서는 브라우저 저장소에 저장하는 방식과 쿠키에 저장하는 방식을 사용할 수 있다. 로컬 스토리지와 세션 스토리지 같은 브라우저 저장소에 JWT를 저장한다면 스크립트 공격(XSS)에 취약해진다. 쿠키에 저장할 때 http-only 를 사용한다면 HTTPS로만 쿠키가 전달되기 때문에 보안을 강화할 수 있고, CSRF(Cross Site Request Forgery) 문제에 대해서는 CSURF같은 라이브러리를 사용함으로 해결할 수 있다.


🔎 세션 vs JWT

세션방식에서 서버는 로그인 된 유저의 정보를 모두 저장하고 있어서 유저들의 통제가 JWT보다 비교적 쉽다. 만약 PC와 모바일기기에서 동시 접근하는 것을 막고 싶을 때 강제 로그아웃 시키는 기능은 세션을 통해 구현이 가능하다.

JWT(Json Web Token)를 서버가 발급하고나면 JWT를 관리하지 않는다. 오직 JWT를 받았을 때 JWT가 유효한 것인지만 확인하기 때문에 서버 자원과 비용을 절감할 수 있다. 그러나 JWT가 수명이 길어서 제 3자에게 탈취당할 경우가 발생할 수 있다. 이를 보완한 방법 중 하나로 access token & refresh token 방식이 있는데 두개의 토큰 모두 JWT(Json Web Token)이다.

📌 access token & refresh token

access token & refresh token 방식은 토큰들에 유효기간을 주어서 보안을 강화시킨 것이다. access token은 유효기간이 짧은 토큰이고, refresh token은 access token보다 유효기간이 긴 토큰이다.

  1. 사용자가 로그인을 하면 서버로부터 access token, refresh token 2개의 토큰을 받는다. 이때 서버는 refresh token을 안전한 저장소에 저장한다.
  2. 서버로부터 받은 access token의 유효 기간이 지나지 않은 경우 사용자가 어떤 요청을 보낼 때 access token을 함께 보내고 서버는 유효한 지 확인 후 응답을 보낸다.
  3. 서버로부터 받은 access token의 유효 기간이 지난 경우 사용자는 refresh token과 함께 요청을 보내고, 저장소에 저장되어 있던 refresh token과 비교한 후에 유효하다면 새로운 access token과 응답을 함께 보낸다.