diff --git a/_posts/2023-12-06-jwt.md b/_posts/2023-12-06-jwt.md
new file mode 100644
index 0000000..33a9329
--- /dev/null
+++ b/_posts/2023-12-06-jwt.md
@@ -0,0 +1,207 @@
+---
+layout: post
+title: 세션 인증과 JWT를 이용한 토큰 인증 방식
+author: 이윤선
+categories: 기술세미나
+banner:
+ image: https://raw.githubusercontent.com/Kernel360/blog-image/main/2023/1206/4.png
+ background: "#000"
+ height: "100vh"
+ min_height: "38vh"
+ heading_style: "font-size: 4.25em; font-weight: bold; text-decoration: underline"
+tags: [세션, JWT, 인증과 인가, Access Token, Refresh Token, RTR,기술세미나]
+---
+
+이번 포스팅에서는 세션과 JWT를 이용한 인증 방식에 대해서 알아보겠습니다.
+세션과 JWT를 다루기 전에 먼저 알고 넘어가야하는 중요한 개념이 있는데요, 바로 인증과 인가입니다.
+
+## 인증과 인가
+### 인증
+``인증(Authentication)``은 쉽게 말해서 로그인 이라고 할 수 있습니다.
+클라이언트가 이 사이트에 가입된 회원임이 맞는지 아이디와 패스워드 등을 통해서 말 그대로 ``인증`` 받는 것이지요.
+예를들어, Github에 이메일과 패스워드를 통해서 로그인을 했다고 가정해본다면 Github 서버는 사용자가 입력한 로그인 정보를 통해서 Github에 가입된 회원이 맞는지 검증하고 확인한 것입니다.
+위와 같이 **클라이언트가 이 사이트에 가입된 회원이 맞는지를 검증하는 과정**을 ``인증`` 이라고 할 수 있습니다.
+
+### 인가
+```인가(Authorization)``` 로그인이 된 사용자. 즉, **인증이 된 사용자가 서비스를 이용하면서 특정 자원에 접근이 가능한지를 확인 하는 과정** 입니다.
+Github 로그인을 통해 인증이 되었다면 나의 리포지토리 설정 페이지 처럼 로그인을 해야만 접근가능한 페이지에 접근을 할 수 있게 됩니다.
+Github가 내가 로그인되어 있음을 확인하고 이 페이지에 접근 가능하도록 ``인가``를 해주었기 때문에 접근이 가능한 것 입니다.
+
+
+이제 우리는 ``인증``과 ``인가``가 무엇인지 알게되었습니다.
+그렇다면 로그인을 통해 ``인증``을 한 사용자를 식별하기 위해서 사용자의 로그인 정보는 어디에 저장을 해야할까요?
+로그인 정보를 어디서 보관하는지에 따라 세션 인증 방식과 토큰 인증 방식으로 나눌 수 있습니다.
+
+
+
+
+## 세션 인증 방식과 토큰 인증 방식
+### 세션 인증 방식
+
+
+위 사진을 간략하게 정리하자면 다음과 같습니다.
+1. 사용자가 로그인에 성공하면 **서버는 세션정보를 생성**합니다.
+2. **세션정보는 서버 내 세션 저장소에 보관**되고 **세션ID를 발급하여 사용자 브라우저에 응답**하게 됩니다.
+> 세션 저장소는 서버 내의 메모리일 수도 있고 데이터베이스일 수도 있습니다.
+> 하지만 데이터베이스에 인증정보를 저장하는 것은 매 요청마다 데이터베이스 연결해야하는 치명적인 단점이 있기 때문에 주로 접근이 빠른 메모리에 저장하게 됩니다.
+
+3. 사용자 브라우저는 세션ID란 이름의 쿠키로 저장되고 앞으로 **모든 요청에 세션ID를 담아 서버로 요청**을 보냅니다.
+4. 브라우저가 요청을하면 **서버는 요청의 세션ID를 확인해서 세션저장소에서 세션ID와 맞는 유저정보를 찾아 확인하고 인가**를 해줍니다.
+
+이처럼 **서버에 로그인 되어있음이 지속되는 이 상태**를 ``세션`` 이라고 합니다.
+
+하지만 이 세션 방식은 조금만 생각해봐도 허점이 있다는 것을 알 수 있습니다.
+
+
+### 대표적인 세션 인증 방식의 문제점
+#### 1.사용자가 동시에 서버에 많이 접속할 경우
+
+
+첫 번째로 사용자가 동시에 많이 접속한다면 세션저장소 즉 **메모리에 많은 세션정보가 저장되게되고 서버는 많은 부하를 받게 됩니다.**
+또한 많은 부하로 인해 서버가 꺼져버리기라도 한다면, 즉 서버가 재부팅 되어야 하는 상황이 오면 메모리에 저장된 휘발성 세션정보가 다 손실 되어 사용자는 재 로그인을 하게 되어야 합니다.
+
+#### 2. 서버를 여러대두고 운영한다면
+
+
+두 번째로 여러대의 서버두고 운영한다면 각각의 서버가 세션저장소를 가지고 있을 것이고 요청이 들어올 때 로드밸런서를 통해 여러 서버들 사이에 요청을 분산될 것 입니다.
+만약 사용자A가 로그인은 1번 서버에서 했고 로그인 이후 기능의 요청은 3번 서버로 간다면 3번 세션저장소에는 사용자A의 세션정보가 없기 때문에 세션유지가 되지 않습니다.
+그렇다고 사용자 요청이 각자 할당된 서버로만 보내지게 하는 것도 굉장히 번거롭고 까다로운 작업입니다.
+**서버가 복잡한 구성과 환경속에서 어떤 상태를 기억해야한다는 것**이 이 세션 방식의 두번째 문제입니다.
+
+그래서 이러한 세션방식의 문제점을 해결하고자 고안된 방식이 토큰 인증 방식인 ``JWT`` 입니다.
+
+
+
+### 토큰 인증 방식 : JWT
+
+
+세션 인증 방식은 서버에 인증정보를 저장하는 방식이라면, 토큰 인증 방식은 **인증정보를 클라이언트가 직접 보관하는 방식**입니다.
+여기서 클라이언트가 직접 보관하고있는 인증정보를 ``JWT``라고 합니다.
+
+``JWT``는 **Json Web Token**의 약자로 웹에서 사용되는 토큰 형식의 전자 서명된 문자열을 의미하며 ``JWT``를 자세히 살펴보면 다음과 같이 Base64로 인코딩 된 문자열 형태로 구성되어 있는 것을 확인할 수 있습니다.
+
+
+
+그럼 이 알 수 없는 인코딩 문자열을 무엇을 의미하는 것 일까요?
+
+위 사진에서 인코딩된 문자열이 빨간색 . 보라색 . 하늘색 총 세 부분으로 이루어져 있는 것을 확인할 수 있습니다.
+
+
+
+이 암호화 된 문자열을 디코딩 해보면 세 부분으로 나뉘는데 각각 헤더, 페이로드, 시그니처로 구분됩니다.
+
+제일 먼저 두 번째 구성요소인 페이로드를 살펴보겠습니다.
+페이로드에는 누가 누구에게 발급했는지, 이 토큰이 언제까지 유효한지, 그리고 서비스가 사용자에게 이 토큰을 통해 공개하기 원하는 내용. 이를테면 사용자의 닉네임이나 서비스상의 레벨, 관리자 여부 등을 서비스 측이 원하는대로 담을 수 있습니다.
+이렇게 토큰에 담긴 사용자 정보 등의 데이터를 ``Claim``이라고 합니다.
+
+``Claim``은 특별한 암호화도 아니고 Base64로 인코딩 되어 있기 때문에 사용자가 자바스크립트나 복호화 사이트에서 손쉽게 디코딩해서 내부를 알 수 있는데요, 사용자가 예를들어 토큰의 유효기간을 임의로 늘린다던지, 관리자 여부를 true로 바꿔 관리자 권한으로 인가를 받는다던지 등 이 ``Claim`` 내용들을 조작해서 악용할 수 있다는 생각이 드실 수 있다고 생각됩니다.
+
+이 것들을 막기위해 첫 번째 구성요소인 헤더와 세 번째 구성요소인 시그니처가 존재합니다.
+
+
+
+
+첫 번째 구성요소인 헤더를 디코딩하면 두 가지 정보가 담겨있습니다.
+먼저 타입. 토큰의 타입인데 여기에는 언제나 고정값으로 ``JWT``가 들어갑니다. 타입이 ``JWT``여야 ``JWT``인것이죠.
+다른 하나는 alg, 알고리즘의 약자인데 여기에는 세 번째 구성요소인 시그니처를 만드는데 사용되는 알고리즘(HS256, HS512등 여러 암호화 방식)이 지정됩니다.
+
+첫 번째 구성요소인 **헤더**와 두 번째 구성요소인 **페이로드** 그리고 **서버만 알고있는 비밀키** 이 셋을 이 암호화 알고리즘에 넣고 암호화 시키면 세 번째 구성요소인 **시그니처**가 나오게 되는 것 입니다.
+
+암호화는 인코딩만 가능하고 디코딩은 불가한 단방향으로 이루어지기 때문에 클라이언트에서 토큰 정보를 탈취하더라도 서버만 알고있는 비밀 키를 찾아 낼 방법이 없습니다.
+또한 페이로드의 문자가 단 하나만 수정되어도 시그니처 값이 완전히 달라지며 만약 페이로드를 수정되었다고 해도 유효한 시그니처가 나올라면 서버만 알고있는 비밀 키를 알고 있어야 되기 때문에
+조작 자체가 불가능한 것이지요.
+
+실제로 서버는 ``JWT``가 담겨 요청이온 정보를 확인할 때 헤더와 페이로드 값을 서버의 비밀키로 돌려봐서 계산된 결과값이 시그니처 값과 일치하는 결과가 나오는지 확인합니다.
+만약 페이로드 정보가 서버가 아닌 누군가에 의해 조작되었다면 요청을 거부합니다.
+시그니처와 계산값이 일치하고 유효기간도 지나지 않았다면 그 사용자는 로그인 된 회원으로서 ``인가``를 받는겁니다.
+
+
+
+## 세션의 상태유지와 토큰의 무상태 프로토콜
+토큰인증방식은 서버는 사용자들의 상태를 따로 저장할 필요 없이 비밀키만 가지고 있으면 요청이 들어올 때 마다 토큰을 확인해서 요청을 걸러낼 수 있습니다.
+
+이처럼 **시간에 따라 바뀌는 어떤 상태값을 갖지 않는 것**을 ``stateless`` **무상태**라고 하고,
+서버에서 상태값을 갖는 세션은 반대로 ``stateful`` 이라고 합니다.
+
+그렇다면 항상 세션보다 ``JWT``가 우선적일까요? 안타깝게도, 세션을 대체하기에는 ``JWT``에 큰 결점이 있습니다.
+
+세션처럼 ``stateful``해서 모든 사용자의 상태를 기억하고 있다는 건 구현되기 부담되고 고려사항도 많지만 서버에서 클라이언트들의 상태를 언제든 제어할 수 있다는 의미로 해석할 수 있습니다.
+
+
+
+예를들어 사용자A를 강제 로그아웃 시키려면 세션저장소에서 사용자의 세션 ID를 삭제 시켜 기존 세션을 없애고 다음 요청부터 세션정보가 없어 사용자A에 대한 요청이 거부됩니다.
+
+하지만 ``JWT``는 인증 정보를 클라이언트가 가지고 있고 서버는 사용자의 상태정보를 전혀 저장하고 있지 않기 때문에 이미 발급된 토큰정보를 제어할 수 없습니다.
+
+
+
+최악의 상황으로 만료기간이 살아있는 ``JWT``를 해커에게 탈취 당하더라도 탈취 당한 토큰을 무효화할 수 있는 방법이 없다는 것 입니다.
+
+
+
+## Access Token과 Refresh Token
+이런 점을 나름대로 보완하기 위해서 보통 ``엑세스 토큰``의 만료시간을 짧게 설정합니다.
+지금까지 설명 드렸던 토큰을 ``엑세스 토큰``이라고 생각하시면 됩니다.
+
+예를 들어 ``엑세스 토큰``의 만료시간을 10분만 설정해둔다고 가정해보겠습니다.
+토큰의 만료시간을 10분으로 짧게 설정했기 때문에 금방 로그인이 만료되며 해커가 토큰이 탈취하더라도 서비스를 이용할 수 없게 될 것 입니다.
+
+그렇다면 일반 사용자는 토큰 정보가 탈취되는 문제점 때문에 매번 10분 마다 재 로그인을 해야되는게 아니냐는 생각이 드실텐데요.
+그래서 로그인을 하면 만료기간이 짧은(보통 한시간 내) ``엑세스 토큰``과 만료기간이 상대적으로 긴(보통 2주이하) ``리플래시 토큰``을 함께 발급합니다.
+
+이 둘을 구현하는 방법은 여러 방법들이 있지만, 실제로 E2E 프로젝트 때 제가 소속했었던 Anabada 팀에서 구현한 방법을 소개 해드리겠습니다.
+
+
+1. 클라이언트에서 로그인 요청을 보내면 서버에서 ``엑세스 토큰``과 ``리플래시 토큰``을 발급. 레디스에 ``리플래시 토큰``의 정보를 저장 후 사용자에게 ``엑세스 토큰``과 ``리플래시 토큰``을 반환합니다.
+2. 이후 매 요청마다 ``엑세스 토큰``을 HTTP 요청정보에 담아보내고 서버는 이 ``엑세스 토큰`` 검증을 통해 ``인가``를 주어 로그인 상태로 서비스를 이용할 수 있도록 합니다.
+3. 서비스를 이용하다가 시간이 흘러 ``엑세스 토큰``이 만료되고 만료된 ``엑세스 토큰``을 서버에 요청하면 서버는 토큰이 만료되었다는 응답을 반환합니다.
+4. 클라이언트는 ``엑세스 토큰``이 만료되었다는 응답을 보고 ``리플래시 토큰``을 서버에 전송합니다.
+5. 서버는 요청 받은 ``리플래시 토큰``과 레디스에서의 해당 사용자의 ``리플래시 토큰`` 정보를 비교하여 만료기한이 유효한지, 해당 사용자의 리플래시 토큰인지 확인한 후 ``엑세스 토큰``을 **재발급**하여 사용자에게 반환합니다.
+6. 만약 ``리플래시 토큰``도 만료되었다면 로그인창으로 이동시킵니다.
+
+레디스에 리플래시 토큰 정보를 저장한다는 것이 서버에서 상태정보를 저장하는 세션방식과 동일하지 않냐라는 생각을 하실 수 있는데요.
+먼저 서버에서 요청이 올때마다 세션저장소에서 인증정보를 확인하는 세션 방식과 달리 ``엑세스 토큰``이 만료되었을 때만 레디스를 확인하여 최대한 네트워크 비용을 줄였습니다.
+또한 ``JWT``를 사용하되, 서버에서 사용자의 인증정보를 최소한으로 저장하여 클라이언트를 제어할 수 있는 방법을 고안했습니다.
+
+
+
+## RTR 전략
+마지막으로 RTR은 ``리플래시 토큰``마저 탈취당할 수 있다는 것을 고려한 방식으로 ``엑세스 토큰``을 재발급할 때 ``리플래시 토큰``도 같이 갱신 시켜버리는 방식 입니다.
+따라서 ``엑세스 토큰``을 1회만 재발급할 수 있습니다.
+
+**RTR의 핵심은 ``리플래시 토큰``을 1회용으로 구현하는 것입니다.**
+
+
+
+
+## 마무리
+이번 주제에서 세션에 문제점 때문에 고안된 ``JWT``에 대해 알아봤지만 ``JWT``도 극복할 수 없는 단점이 있다는 것을 확인할 수 있었습니다.
+세션과 토큰 인증 방식중 ' 이 방식이 제일 보안이 훌륭해 ! ' 라고는 할 수 없습니다.
+
+세상에 완벽한 보안은 없고, 그것이 여전히 해킹이 발생하고 있는 이유입니다.
+
+JWT가 세상에 나온 것 처럼 앞으로도 많은 보안이슈를 해결하기 위한 방법들이 나올 것 이고 그 방법들을 생각하는건 개발자가 해야할 몫 이라고 생각합니다.
+
+**현재 시스템의 환경과 상황을 고려해서 제일 알맞은 보안 방법을 찾아야하고 가장 적합한 보안 방식을 선택**하여 적용하는 것이 가장 중요할 것 입니다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+