본문 바로가기
Java

인증 방식 종류 총정리 : 쿠키 vs 세션 vs 토큰(JWT)

by JDH0715 2023. 9. 9.

 

 

인증 방식 종류 총정리 :  쿠키 vs 세션 vs 토큰(JWT)

 

 

 


 

 

인증 방식 종류 3가지

: 서버가 클라이언트 인증하는 대표적인 방식 3가지가 있음.

1) 쿠키(Cookie) 기반 인증

2) 세션(Session) 기반 인증

3) 토큰(Token) 기반 인증

 

 

 

✅ 인증 방식 사용 이유 : 왜 쿠키, 세션, 토큰을 사용하는가?

HTTP의 2가지 주요한 특징인 '무상태성', '비연결성'을 보완하기위해 사용.

요청 처리 후, 연결을 끊어버리기 때문에 상태정보/통신상태가 남아있지 않아, 클라이언트 식별 불가능.

  모든 요청이 이전 요청독립적으로 다뤄진다.

→ 로그인을 하더라도 이전 요청이 끝나고 새로운 요청이 들어오면,

     서버는 누구인지 알지 못하기 때문에 계속 로그인해야함 (요청이 들어올때마다 계속해서 누구인지 매번 알려줘야함.)

 

📌 HTTP의 2가지 주요 특징

http의 이러한 단점을 보완하기위해 쿠키, 세션, 토큰이라는 기술 활용하게 됨.

특징 설명
무상태성
(stateless)
서버에서 클라이언트 상태 저장 X
- 클라이언트 측에서 해당 정보 기억.
- 클라이언트 측에서 매 요청마다
  이전상태까지 모두 포함해 서버에 보냄.
- 반대말 : stateful (상태유지/상태성) 
비연결성
(Connectionless)
서버-클라이언트 연결 유지 X (단발성 연결)
- http는 일정시간 내 요청이 없을 시,
  서버와 연결을 끊어버림.
- 반대말 : Persistent Connection (지속 연결)

 

 

 

쿠키(Cookie) 기반 인증

 

📌 쿠키(Cookie) 란?

: 웹 사이트 접속 시, 서버에 의해 사용자의 브라우저에 저장되는 정보 (작은 기록 정보 파일)

 

📌 쿠키의 특징

  • Key-Value 형식의 문자열 덩어리 : 이름, 값, 유효시간(쿠키 유지시간), 도메인(쿠키를 전송할 도메인), 경로(쿠키를 전송할 요청 경로)로 구성.
  • 쿠키에 담긴 데이터는 브라우저에서 관리 : 쿠키를 클라이언트 측의 컴퓨터에 남겨 필요할 때마다 재사용
  • 특정 호스트에서 생성된 쿠키는 이후 모든 요청마다 서버로 전송됨.
  • 쿠키는 만료 기간 동안 파일로 저장되므로 브라우저를 종료해도 정보가 남음 : 쿠키의 기한이 정해지지않고, 지우지 않는다면 반영구적으로 유지.
  • 주로, 로그인 정보 / 비회원 장바구니 정보/ 언어 설정 등을 저장하는 용도로 활용.

 

📌 쿠키의 형태

이미지 출처 : https://inpa.tistory.com

 

📌 쿠키 기반 인증 동작 방식

1. 클라이언트(브라우저)가 서버에 로그인 요청

2. 서버는 요청을 받아 회원DB에서 사용자 확인 후(유효성검사 : 아이디/비번 검사)
응답 헤더에 Set-Cookie 옵션을 통해 쿠키를 포함해 응답 전송 (로그인 완료)
( 응답에는 사용자가 찾는 페이지 정보, 데이터, 브라우저에 저장된 쿠키 등이 포함.)


3. 쿠키가 브라우저에 저장됨.

( 서버는 쿠키에 담긴 정보를 통해, 클라이언트가 누군지 식별하거나, 추천 광고를 띄움 )

4. 이후, 라이언트는 요청을 보낼 때마다, 저장된 쿠키를 요청 헤더의 Cookie에 자동으로 추가하여 요청

5. 서버는 HTTP 요청에 담긴 쿠키를 읽어 클라이언트 식별 & 응답.

 

 

📌 쿠키 기반 인증 단점

  1. 보안에 취약함. (요청 시, 쿠키값을 그대로 보내기 때문에 유출/조작/사생활침해 위험 O)
  2. 용량 제한이 있어 많은 정보를 담을 수 없다.
  3. 웹 브라우저마다 쿠키에 대한 지원 형태가 다름 →  브라우저 간 공유 불가능 (네이버에서 준 쿠키는 네이버에만 보내짐)
  4. 쿠키의 사이즈가 커질수록 네트워크에 부하가 심해짐.

 

 

 


✅ 세션(Session) 기반 인증

 

📌 세션(Session) 이란?

: 브라우저 종료 전까지 클라이언트의 요청을 유지하게 해주는 기술.

사용자가 브라우저를 닫아, 서버와 연결을 끝내는 시점까지세션(Session)이라고 함.

세션은 쿠키를 기반으로 하지만, 쿠키가 클라이언트 측에 저장되는것과는 다르게 세션은 서버 측에 저장  (쿠키의 보안 이슈를  보완)

 

 

📌 세션 기반 인증 특징

  •  비밀번호 등 사용자의 민감한 인증 정보를 브라우저가 아닌 서버 측에 저장/관리 (세션 정보는 메모리, 디스트, DB등에 저장)
  • 키 값만 클라이언트 측에 보냄 : 나머지 민감한 정보는 클라이언트에 보내지 않고, 모두 서버에 저장/관리.
  • 클라이언트는 쿠키를 통해 세션Id를 기억 : 클라이언트마다 unique한 세션Id가 주어지며, 세션 객체에 데이터를 담아 관리 가능.
  • 서버는 세션Id를 통해 클라이언트 식별 : 클라이언트 요청 쿠키에 담긴 세션ID ↔ 세션 저장소에 담긴 ID  대조 & 인증 상태 판단.
  • 브라우저가 서버에 접속해 종료할 때까지 세션 유지 : 세션은 브라우저 종료시 만료시간과 상관없이 삭제
  • 형태 : Key(세션Id)-Value(세션 생성 시간, 마지막 접근 시간, User가 저장한 속성 등이 Map 형태로 저장) 

 

📌 세션의 구조

이미지 출저 : https://inpa.tistory.com/

 

 

📌 세션 기반 인증 동작 방식

 

 

1. 클라이언트(브라우저)가 서버에 로그인 요청

2. 서버는 요청을 받아 유효성 확인 후(아이디/비번 검사), 클라이언트의 정보를 담은 세션 생성 (로그인 완료)

3. 이후, 서버는 sessionId를 담은 쿠키 생성 & 
HTTP 헤더에 set-cookie 옵션을 통해 쿠키를 포함한 응답 전송. 


4. 클라이언트는 해당 쿠키를 쿠키 저장소에 저장한 후, 인증이 필요한 요청마다 헤더에 쿠키를 실어 보냄.

5. 서버는 HTTP 요청에 담긴 쿠키를 읽고, 쿠키 안의 sessionId로 세션 조회/클라이언트 식별 후, HTTP 응답.

 

 

 

📌 세션 기반 인증 장단점

[ 장점 ]

  • 각 사용자마다 고유한 세션ID가 발급되기때문에 요청이 들어올 때마다 매번 회원정보를 확인(로그인)할 필요 X
  • 쿠키를 포함한 요청이 외부에 노출되도, 세션ID는 개인정보를 담지 않기때문에 상대적으로 안전 (보안 우수)
  • 서버에서 클라이언트의 상태를 유지하므로, 강제 로그아웃 등 제재 가능.
  • 서버에서 클라이언트의 상태 정보를 가지고있으므로, 클라이언트가 정보를 변경시키더라도 안전.

[ 단점 ]

  • 사용자 수에 따른 메모리/디스크/DB 부하 : 서버에서 클라이언트의 상태를 모두 유지해야하므로 클라이언트 수가 많아지면 부하가 심해진다.
  • *로드 밸런싱을 통한 서버 확장 시, 세션 관리 어려움 : 사용자가 많아지면 로드밸런싱을 통한 서버 확장을 해야하는데 이때 세션 관리가 어려워짐. ( 로드밸런싱을 하는 경우, 각 서버마다 각자의 책상(메모리)가 있게되는데 만약 로그인은 1번 서버에서 하고, 이메일 페이지로 이동하는 요청을 3번 서버에서 하면, 3번 서버의 책상에는 해당 사용자의 티켓이 없기때문에 세션 유지 X. 해결책으로 레디스나 MemCached 같은 메모리형 DB 서버를 사용하면 되지만(공용 메모리를 두어 사용자 인가를 담당시킴), 세션의 근본적인 문제를 해결해주진 못함.)
  • CORS 방식 사용 시, 쿠키/세션 관리 어려움 : 웹브라우저에서 세션관리에 사용하는 쿠키는 단일도메인/서브도메인에서만 작동하도록 설계되어있으므로, 브라우저가 다른 서버끼리 요청을 주고받을 수 있게끔해주는 CORS 방식을 사용시, 쿠키/세션관리가 어려움.
  • 멀티 디바이스 환경에서 로그인 시, 중복 로그인 처리X : 모바일, 브라우저 공동 사용 시, 중복 로그인처리가 되지않은 등 신경 쓸 문제가 많음.

  * 로드밸런싱(Load Balancing) : 서버가 처리해야 할 업무/요청(Load)을 여러 대의 서버로 나누어 처리하는 것(Balancing)

 

📌 쿠키과 세션의 차이점

  저장위치 보안 생명주기 속도
쿠키 (Cookie) 로컬 보안성 비교적 낮음
(탈취, 변조 가능)
브라우저 종료시에도
파일로 남음.
비교적 빠름
(파일에서 읽기 때문에)
세션 (Session) 로컬/서버 비교적 안전 브라우저 종료 시 삭제. 비교적 느림
(요청마다 서버에서
처리해야하기 때문에)

 

 

 

 

 

 

✅ 토큰(Token) 기반 인증 / JWT (JSON Web Token)

 

📌 토큰(Token) 이란?

: 서버에서 클라이언트를 구분할 수 있도록하는 유일한 값 (유니크한 정보를 담은 암호화 데이터)

 

[ 토큰 기반 인증 ]

토큰 기반 인증에서는 사용자가 서버에 접속 시, 해당 사용자가 인증됐다는 의미로 서버에서 토큰(Token)을 부여한다.

이 토큰은 고유한 값으로, 이후 사용자가 서버에 요청을 보낼때 HTTP 헤더에 토큰을 심어 보내면 

서버는 토큰만 보고 사용자 유효성 검증 & 식별하는 방식.

 

 

📌 토큰 기반 인증의 특징

  • 토큰은 서버가 아닌 클라이언트에 저장되기때문에 서버의 부담 감소 (세션의 단점 보완)
  • 웹에는 쿠키/세션이 있지만 앱에는 없기때문에, 앱-서버 통신/인증 시 가장 많이 사용됨.
  • 토큰 기반 인증 방법으로 많은 웹 서버들이 JSON포맷을 이용하는 JWT를 주로 사용함.

 

 

📌 토큰 기반 인증 동작 방식

 

1. 클라이언트(브라우저)가 서버에 로그인 요청

2. 서버는 아이디/비번을 확인해 유효한 사용자인지 검증 후, 토큰 생성/응답.

3. 클라이언트는 토큰을 저장하고, 이후 인증이 필요한 API를 사용할 때 토큰을 함께 전송.

4. 서버는 토큰이 유효한지 검증 후, 클라이언트가 요청한 내용 처리/응답.

 

 

📌 JWT (JSON Web Token) 이란?

: 인증 정보들을 암호화시킨 JSON 토큰 (JSON으로 된 웹 토큰)

JWT는 JSON 데이터를 Base64 URL-safe Encode 를 통해 인코딩하여 직렬화한 것이다.

 

[JWT 기반 인증 ]

JWT 토큰(Access Token)을 HTTP 헤더에 실어 보내 서버가 클라이언트를 식별하는 방식.

발급받은 JWT를 이용해 인증하려면, HTTP 요청 헤더  Authorization 키값에 Bearer + JWT 토큰값을 넣어 보내야한다.

 

 

📌 JWT 구조

JWT는 "." 을 구분자로 헤더(header), 내용(payload), 서명(signature)로 구성됨.

 

1) 헤더 (header) : 토큰 타입(typ) / 해싱 알고리즘 지정(alg) 정보를 담음.

해더의 구성

이름 설명
typ 토큰의 타입
alg 해싱 알고리즘

 

 

2) 내용 (payload) : 토큰과 관련된 정보를 담음. 내용의 한덩이를 클레임(claim)이라 하며, Key-Value 형태로 이루어짐. 클레임은 등록된 클레임/공개클레임/비공개 클레임으로 나뉨. 등록된 클레임은 토큰에 대한 정보를 담는 데 사용.

내용의 구성

이름 설명
iss 토큰 발급자 (issuer)
sub 토큰 제목 (subject)
aud 토큰 대상자 (audience)
exp 토큰 만료 시간 (expiration)
nbf 토큰 활성 날짜 (Not Before)
iat 토큰 발급 시간 (issued at)
jti JWT 고유 식별자

 

3) 서명 (signature) : 헤더, 내용 인코딩 값 + 비밀키(SECRET JEY)를 더한 후 서명해시값 생성.

토큰 조작/변경 확인 용도로 사용.

 

 

 

📌 JWT 종류

  1. Access Token : 보호된 정도블에 접근할 수 있는 권한 부여에 사용됨.
  2. Refresh Token : 액세스 토큰의 유효기간 만료 시 새로운 액세스 토큰을 발급.

Access Token과 Refresh Token은 똑같은 형태의 JWT이다. JWT(Access Token)를 통한 인증 방식은 제 3자에게 탈취될 경우 보안이 취약하다는 단점이 있다. 유효기간이 짧으면 자주 로그인해 새로운 토큰을 발급받아야한다는 불편함이 있고, 유효기간이 길면 탈취시 보안에 취약해진다는 문제가 생긴다. 이를 해결해기위해 탄생한것이 Refresh Token이다.

 

클라이언트가 처음 로그인을 완료했을때, Access Token과 Refresh Token을 동시에 발급 받는다.

(탈취될 수 있는 상황을 고려해)실제 권한을 얻는데 사용하는 Access Token 보다 Refresh Token은  더 긴 유효기간을 가지며, Access Token이 만료됐을 시 새로 발급해주는 역할을 한다.

 

Refresh Token의 유효기간이 만료되면 사용자는 새로 로그인 해야하며, 탈취될 가능성을 고려해 적절한 유효기간(보통 2주)설정이 필요하다. 만약 Refresh Token이 유출되어 다른 사용자가 새로운 Acces Token을 발급받았을 때는 충돌방지를 위해 두 토큰 모두 서버에서 폐기해야한다.

 

 

 

 

 

📌 JWT 동작 방식 (JWT 토큰 갱신 과정)

*Note : 리프레시 토큰은 DB에 저장하는 정보이므로 엔티티와 리포지터리르 추가해야함! 

 

1. 클라이언트(브라우저)가 서버에 인증 요청

2. 서버는 클라이언트가 전달한 정보를 바탕으로 인증 정보가 유효한지 확인 후, 액세스 토큰 / 리프레시 토큰을 생성해 클라이언트에게 전달. 클라이언트는 토큰 저장.

3. DB에 리프레시 토큰 저장.

4. 클라이언트에서 인증이 필요한 API 호출 시, 액세스 요청과 함께 API 요청

5. 서버는 액세스 토큰이 유효한지 검사 후, 요청 내용 처리.

6. (시간이 지나 액세스 토큰이 만료된 후) 클라이언트에서 만료된 액세스 토큰과 함께 서버에 API 요청 전송.

7. 서버는 액세스 토큰이 유효한지 검사 후, 토큰이 만료되었다는 에러 전달.

8.  (만료 에러를 전달받은) 클라이언트는 저장된 리프레시 토큰과 함께 새로운 액세스 토큰 발급 요청 전송.

9. 서버는 클라이언트가 보낸 리프레시 토큰이 유효한지 DB에서 리프레스 토큰 조회/비교 

10. 유효한 리프레시 토큰일 시, 새로운 액세스 토큰 생성/응답. 

이후, 클라이언트는 다시 4번과 같이 API 요청.

 

 

📌 토큰(JWT) 기반 인증 장단점

    [ 장점 ]

  • 무상태성(Stateless) : 토큰은 클라이언트 측에 저장되기 때문에 서버는 완전한 무상태(Stateless)이다. 클라이언트에서는 사용자의 인증 상태를 유지하면서 이후 요청을 처리해야하는데 이것 상태 관리(stateful)라고 한다. 이렇게하면 서버 측에서는 인증 정보를 저장/유지할 필요가 없기 때문에 완전한 무상태(stateless)로 효율적인 검증이 가능하다.
  • 확장성(Scalabitity - 시스템의 확장성) : 클라이언트와 서버가 독립적이기 때문에 사용자 수 증대에 유연한 대응 가능. 사용자 정보가 서버측에 저장되었을 때 서버확장을 하여 분산처리를 하는 경우, 사용자가 처음 로그인한 서버에만 요청을 해야하지만 토큰을 사용하면 어떠한 서버에 요청을 보내도 문제 없다. 
  • 확장성(Extensibility - 기능의 확장성 ) : 서버 확장 시, 상태 관리를 신경 쓸 필요가 없으니(stateless) 서버 확장에 용이함. 각각의 API에서 인증을 해야하는 세션 기반 인증과 달리, 토큰 기반 인증은  토큰을 가지는 주체가 클라이언트이기 때문에 하나의 토큰으로 여러 서버에게 요청 전송 가능. Google 로그인 등 토큰 기반 인증을 사용하는 다른 시스템에 접근로그인 방식 확장 가능 (같은 소셜계정으로 다른 웹에서 로그인 가능)
  • 무결성(Integrity)토큰 발급 이후 토큰 정보를 변경하는 행위를 할수 없음. 즉, 토큰의 무결성이 보장됨. 토큰이 변경될 시, 서버는 유효하지 않은 토큰으로 판단.
  • 별도의 저장소 필요없음
  • 데이터 위변조 방지 : header와 payload를 가지고 signature 를 생성하므로 데이터 위변조 불가능.
  • 모바일 어플리케이션 환경에서도 잘 동작 : 모바일은 세션 사용 불가.

 

    [ 단점 ]

  • 토큰 길이 : 쿠키/세션과 달리, 토큰 자체의 데이터 길이가 길어, 인증 요청이 많아 질수록 네트워크 부하 증가.
  • Payload 자체는 암호화 불가능 : 유저의 중요한 정보(패스워드 등)는 담을 수 없음.
  • 토큰 탈취 시, 대처 어려움 : 탈취당한 토큰을 무효화할 방법이 없기때문에 (토큰은 한번 발급되면 만료기간까지 사용 가능), 사용 기간 제한을 설정하는 식으로 극복 (Access Token의 유효기간을 짧게하고 Refresh Token을 발급해서 Access Token이 탈취당했을 시 피해를 최소화.)
  • 특정 사용자의 접속 강제 만료 어려움 : 쿠키/세션 기반 인증은 서버측에서 쉽게 삭제가능하지만 토큰은 불가능.

 

TIP

세션을 대체하기에 JWT는 큰 결점이 있기때문에 현업에서는 JWT를 사용하지 못한다.

세션은 Stateful해 부담되지만, 구현만 하면 상태를 언제든지 제어할 수 있다.

(ex. 멀티 로그인 시, 기존에 로그인된 기기에서 로그아웃되도록 기존 세션 종료 가능)

하지만 JWT 방식에선 토큰을 다시 뺏거나 통제할 수 없기 때문에 제어가 불가능하다. (+ 해커가 토큰을 탈취해도 토큰 무효화 불가능)

이러한 이유로 실 서비스 중, JWT만으로 인가를 구현하는 곳은 많지 않다.

 

 

 

 

참고자료 :

https://star7sss.tistory.com/911

https://kbwplace.tistory.com/165

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC#jwt_json_web_token_%EC%9D%B4%EB%9E%80

https://coding-plant.tistory.com/157

https://code-lab1.tistory.com/298

https://chrisjune-13837.medium.com/web-%EC%BF%A0%ED%82%A4-%EC%84%B8%EC%85%98%EC%9D%B4%EB%9E%80-aa6bcb327582

https://pangtrue.tistory.com/223

https://cookiee.tistory.com/532

 

스프링 부트 3 백엔드 개발자 되기: 자바 편

https://product.kyobobook.co.kr/detail/S000201766024

 

스프링 부트 3 백엔드 개발자 되기: 자바 편 | 신선영 - 교보문고

스프링 부트 3 백엔드 개발자 되기: 자바 편 |

product.kyobobook.co.kr