ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 쿠키와 세션 그리고 JWT
    개발 모음집/Docs 2022. 12. 30. 10:42

    🍪 쿠키

    쿠키는 웹 사이트 서버에서 유저의 컴퓨터로 보내는 작은 임시 파일입니다. 해당 웹에 필요한 정보들을 가지고 있다가 필요한 이벤트에 데이터를 반환합니다.

    처음 쿠키가 만들어진 건, 정확한 통계 값을 구하기 위해서 였다고 합니다. 방문자가 이전에도 왔던 방문자인지, 처음 온 방문자인지를 확인하기 위함이었다고 해요. 쿠키가 없던 이전에는 한 명의 유저가 index 페이지를 100번 reload 하면 100명이 방문했던 것으로 표현되었다고 해요. 방문자를 확인하는 데이터를 통해 우리는 이를 구분할 수 있게 된 거죠. 먹고 남은 쿠키 부스러기 마냥 작은 파일들이라 하여 cookie라는 이름이 붙었다고 합니다.

    이렇게 만들어진 cookie는 단순히 통곗값만 내는 것으로 끝나지 않았습니다. 웹사이트에서 로그인이 지속 되는 것도, 하루 동안 광고 글을 숨기는 것도, 장바구니의 상품들이 계속 저장되어 있는 것도 모두 cookie 를 통해 이루어지는 것이죠. 유저가 사용한 검색정보나 구매 아이템을 저장해둔다면 유저가 어떤 것을 많이 찾고 있는지, 무엇을 좋아하는 지 등을 알 수 있겠죠? 그만큼 웹 페이지에서 cookie 는 매우 중요하고 유용한 것입니다.

    하지만 cookie 에도 단점은 존재했습니다. cookie 의 파일들은 모두 유저의 웹 브라우저에 저장이 됩니다. 즉 유저가 원한다면 삭제도 하고, 변경하는 것도 가능하게 되는 거죠. 단순 데이터야 그렇다 치더라도 개인정보 등의 민감한 데이터를 cookie 에 둘 수 없게 된 거죠. 그렇게 session 과 cookie 를 함께 병용하여 쓰는 세션 쿠키 방식이 구현되었습니다.

    ䷍ 세션

    session 역시 필요한 데이터를 저장해둔다는 점에서는 cookie 와 같습니다. cookie 가 client-side 의 데이터 저장소라면, session 은 server-side 의 데이터 저장소이죠.

    개인정보와 같은 민감한 데이터는 session 에 모아두고 인증 절차가 완료되면 서버와 클라이언트에 절차가 완료되었다는 확인 데이터를 남기는 것이죠. 물론 cookie 에는 누구도 알아보지 못하도록 해시화 된 값으로요. 이를 통해 cookie 의 장점은 계속 이어가면서, 단점을 보완할 수 있게 되었습니다.

     

     

    session 은 메모리나 하드디스크 혹은 데이터베이스 등 다양하게 저장하는 것이 가능하지만 모두 장단점이 존재했어요. 데이터베이스로 갈수록 용량 문제는 해결되지만 요청-응답에 걸리는 시간이 늘어납니다. 메모리는 반대로 요청-응답은 빠르지만 많은 요청은 처리할 수가 없죠.

    이러한 문제를 개선하기 위해 나타난 것이 JWT 와 같은 token 방식입니다. token 은 인증 과정은 세션 쿠키와 비슷하지만, 서버에 확인 데이터를 남기지 않습니다. 로그인이 완료되면 이후 인증 과정은 cookie 에 남겨진 해시 토큰만으로도 확인이 가능하므로 요청-응답 속도가 훨씬 빨라집니다.

    🤔 그럼 이제 JWT만 쓰면 되는가.

    아니요. 일단 JWT 를 통해 cookie 만으로 장기적인 로그인 유지가 가능하지만, 이것도 완벽하다고 볼 수는 없습니다.

    넷플릭스를 생각해볼까요? 스마트폰으로 보던 것을 좀 더 큰 화면에서 보기 위해 태블릿으로 프로필 접속을 했다고 합시다. 넷플릭스는 유저의 환경에 변화가 있음을 캐치하고 태블릿의 접속이 완료됨과 동시에 모바일은 로그아웃 화면으로 변하게 되죠. 이러한 앱에서는 server 에 환경이 변화되었다는 데이터를 남겨야 하기 때문에 JWT 보다는 세션-쿠키 방식이 훨씬 적합합니다. 어떻게 해서 token 데이터가 탈취된다면 server 에서 컨트롤 할 수 있는 부분이 없기 때문에 데이터의 만료날짜가 마냥 기다릴 수 밖에 없는 것도 단점입니다. 이러한 경우는 세션-쿠키server 에서 제어가 가능합니다.

     

     

    최근에는 메모리형 데이터베이스나 access, refresh 토큰 등을 통해 해당 인증과정의 부족한 부분들을 차츰 개선하고 있는 상황입니다. 물론 명확한 단점 문제가 해결된 것은 아니기에 각 인증 방식을 이론적으로 공부하고 구현하는 앱에 맞는 방식을 채택하여 사용하는 것이 가장 중요하다고 생각되네요.

    🍌 스티키 세션

    1. 쿠키 또는 세션을 사용하여 트래픽을 분산하는 기능입니다
    2. Sticky Session이 나오게 된 배경
      1. 일반적으로 대용량 트래픽을 장애 없이 처리하기위해 여러 대의 서버에 적절히 트래픽을 분배하는 로드 밸런서를 사용합니다. 

    이렇게 로드 밸런싱이 필요한 서비스에는 세션 관리에 문제가 생길 수도 있습니다.

    1. 먼저 로그인 요청을 A 서버로 보냅니다.
    2. A 서버의 세션에는 martin이라는 값이 저장됩니다.
    3. A 서버에서는 로그인 성공이라는 응답을 보냅니다.
    4. 동일한 클라이언트는 로드 밸런서에 새로운 요청을 보냅니다.
    5. 그러나 이 요청은 C 서버로 전달됩니다.
    6. C 서버의 세션에는 이 사용자가 로그인 한 사용자라는 정보가 없기 때문에, 조회 실패 후 로그인 페이지로 리다이렉트 하도록 응답을 보냅니다.

    위의 설명과 같이, 방금 로그인을 했는데 다시 로그인을 하라는 사태가 발생할 수 있습니다.

    이러한 세션 관리의 문제를 해결하기 위해 Sticky Session을 사용합니다.

    Sticky Session의 개념

    Sticky Session이란 특정 세션의 요청을 처음 처리한 서버로만 전송하는 것을 의미합니다.

    위의 그림과 같이 첫 요청 이후의 모든 요청을 특성 서버로 고정하는 방법으로 세션을 관리합니다. 일반적으로 Sticky Session을 유지하기 위해 Cookie를 사용하거나 클라이언트의 IP tracking하는 방식이 있습니다.

    Sticky Session의 단점

    • 로드 밸런싱이 의도한대로 잘 동작하지 않을 수도 있습니다.
    • 특정 서버만 과부하가 올 수 있습니다.
    • 특정 서버 Fail시 해당 서버에 붙어있는 세션들이 모두 소실될 수 있습니다.

    Sticky Session의 단점을 해결하는 방안

    Session들을 하나로 묶어 클러스터로 관리

    각 WAS들은 세션을 각각 가지고 있지만, 이를 하나로 묵어 하나의 클러스터로 관리하는 방법이 있습니다. 이 상태에서 하나의 WAS가 fail이 발생하면 해당 WAS가 들고 있던 세션은 다른 WAS로 이동되어 관리됩니다. 다만, 각 서버마다 세션 클러스터링 방식이 다르고 지원하는 방식이 다르기 때문에 현재 사용하고 있는 WAS의 session clusturing 부분을 보고 확인해야 합니다. 그리고 이 방식은 새로운 서버가 하나 추가될 때마다 기존에 존재하던 WAS에 새로운 서버의 IP/PORT를 입력해서 클러스터링 해줘야 하는 단점이 있습니다.

    Session Server 분리

    위의 그림과 같은 방식은 새로운 서버를 생성하더라도 해당 서버에만 세션 서버의 정보를 적어주고 연결해주면 되기 때문에 기존 서버의 수정이 발생하지 않는다는 장점이 있습니다. 다만 세션 서버의 중요성이 올라가고, 세션 서버가 죽는 순간 모든 세션이 사라지기 때문에 세션 서버의 다중화도 고려해보아야 할 점입니다.

     

    Reference : https://kchanguk.tistory.com/146

    🌮 JWT

    JWT는 JSON Web Token의 약자로 전자 서명 된 URL-safe (URL로 이용할 수있는 문자 만 구성된)의 JSON입니다.

    전자 서명은 JSON 의 변조를 체크 할 수 있게 되어 있습니다.

     

    JWT는 속성 정보 (Claim)를 JSON 데이터 구조로 표현한 토큰으로 RFC7519 표준 입니다.

     

    JWT는 서버와 클라이언트 간 정보를 주고 받을 때 Http 리퀘스트 헤더에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증합니다.

     

    이때 사용되는 JSON 데이터는 URL-Safe 하도록 URL에 포함할 수 있는 문자만으로 만듭니다.

     

    JWT는 HMAC 알고리즘을 사용하여 비밀키 또는 RSA를 이용한 Public Key/ Private Key 쌍으로 서명할 수 있습니다.

     

    JWT는 세 파트로 나누어지며, 각 파트는 점로 구분하여 xxxxx.yyyyy.zzzzz 이런식으로 표현됩니다. 순서대로 헤더 (Header), 페이로드 (Payload), 서명 (Sinature)로 구성합니다. Base64 인코딩의 경우 “+”, “/”, “=”이 포함되지만 JWT는 URI에서 파라미터로 사용할 수 있도록 URL-Safe 한  Base64url 인코딩을 사용합니다.

     

    Header는 토큰의 타입과 해시 암호화 알고리즘으로 구성되어 있습니다. 첫째는 토큰의 유형 (JWT)을 나타내고, 두 번째는 HMAC, SHA256 또는 RSA와 같은 해시 알고리즘을 나타내는 부분입니다. Payload는 토큰에 담을 클레임(claim) 정보를 포함하고 있습니다. Payload 에 담는 정보의 한 ‘조각’ 을 클레임이라고 부르고, 이는 name / value 의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개의 클레임 들을 넣을 수 있습니다.클레임의 정보는 등록된 (registered) 클레임, 공개 (public) 클레임, 비공개 (private) 클레임으로 세 종류가 있습니다.마지막으로 Signature는 secret key를 포함하여 암호화되어 있습니다.

     

    1. 사용자가 id와 password를 입력하여 로그인을 시도합니다.

    2. 서버는 요청을 확인하고 secret key를 통해 Access token을 발급합니다.

    3. JWT 토큰을 클라이언트에 전달 합니다.

    4. 클라이언트에서 API 을 요청할때  클라이언트가 Authorization header에 Access token을 담아서 보냅니다.

    5. 서버는 JWT Signature를 체크하고 Payload로부터 사용자 정보를 확인해 데이터를 반환합니다.

    6. 클라이언트의 로그인 정보를 서버 메모리에 저장하지 않기 때문에 토큰기반 인증 메커니즘을 제공합니다.

    인증이 필요한 경로에 접근할 때 서버 측은 Authorization 헤더에 유효한 JWT 또는 존재하는지 확인한다.

    JWT에는 필요한 모든 정보를 토큰에 포함하기 때문에 데이터베이스과 같은 서버와의 커뮤니케이션 오버 헤드를 최소화 할 수 있습니다.

    Cross-Origin Resource Sharing (CORS)는 쿠키를 사용하지 않기 때문에 JWT를 채용 한 인증 메커니즘은 두 도메인에서 API를 제공하더라도 문제가 발생하지 않습니다.

     

    일반적으로 JWT 토큰 기반의 인증 시스템은 위와 같은 프로세스로 이루어집니다.

     

    처음 사용자를 등록할 때 Access token과 Refresh token이 모두 발급되어야 합니다.

     

    JWT 장점

    JWT 의 주요한 이점은 사용자 인증에 필요한 모든 정보는 토큰 자체에 포함하기 때문에 별도의 인증 저장소가 필요없다는 것입니다. 분산 마이크로 서비스 환경에서 중앙 집중식 인증 서버와 데이터베이스에 의존하지 않는 쉬운 인증 및 인가 방법을 제공합니다. 개별 마이크로 서비스에는 토큰 검증과 검증에 필요한 비밀 키를 처리하기위한 미들웨어가 필요합니다. 검증은 서명 및 클레임과 같은 몇 가지 매개 변수를 검사하는 것과 토큰이 만료되는 경우로 구성됩니다.토큰이 올바르게 서명되었는지 확인하는 것은 CPU 사이클을 필요로하며 IO 또는 네트워크 액세스가 필요하지 않으며 최신 웹 서버 하드웨어에서 확장하기가 쉽습니다.

     

    JSON 웹 토큰의 사용을 권장하는 몇 가지 이유는 다음과 같다.

    • URL 파라미터와 헤더로 사용

    • 수평 스케일이 용이

    • 디버깅 및 관리가 용이

    • 트래픽 대한 부담이 낮음

    • REST 서비스로 제공 가능

    • 내장된 만료

    • 독립적인 JWT

     

    JWT 단점

    • 토큰은 클라이언트에 저장되어 데이터베이스에서 사용자 정보를 조작하더라도 토큰을 직접 적용할 수 없습니다.

    더 많은 필드가 추가되면 토큰이 커질 수 있습니다.

    • 비상태 애플리케이션에서 토큰은 거의 모든 요청에 대해 전송되므로 데이터 트래픽 크기에 영향을 미칠 수 있습니다.

     

    다음과 같은 상황에서 JWT 가 유용하게 사용 될 수 있습니다.

     

    • 회원 인증:

    JWT 를 사용하는 가장 흔한 시나리오 입니다. 사용자가 로그인을 하면, 서버는 사용자의 정보를 기반으로한 토큰을 발급합니다.그 후, 사용자가 서버에 요청을 할 때 마다 JWT를 포함하여 전달합니다. 서버는 클라이언트에서 요청을 받을때 마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 사용자가 요청한 작업에 권한이 있는지 확인하여 작업을 처리합니다. 서버에서는 사용자에 대한 세션을 유지 할 필요가 없습니다. 즉, 사용자가 로그인되어있는지 안되어있는지 신경 쓸 필요가 없고, 사용자가 요청을 했을때 토큰만 확인하면 되므로 세션 관리가 필요 없어서 서버 자원과 비용을 절감할 수 있습니다.

     

    • 정보 교류:

    JWT는 두 개체 사이에서 안정성 있게 정보를 교환하기에 좋은 방법입니다. 그 이유는, 정보가 서명이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지, 또 정보가 도중에 조작되지는 않았는지 검증할 수 있습니다.

     

Designed by Tistory.