💋 인트로
안녕하세요. 우아한테크코스 5기 깃짱이라고 합니다.
이번 포스팅에서는, 애플리케이션에서 인증을 구현하기 위해 사용되는 쿠키, 세션, 토큰에 대해서 설명하려고 합니다.
인증을 통해서 서버는 유저가 누구인지 알 수 있다.
쿠키, 세션, 토큰은 모두 인증을 위해서 사용하는 개념이다.
어떤 개념인지 하나씩 보면서, 알아가보자!
💋 쿠키(Cookie)
✔️ 개념
서버
가 사용자의웹 브라우저
에 전송하는 데이터- 서버에서 사용자를
기억
하기 위해서 브라우저에 저장할 데이터를 응답과 함께 브라우저에 전송 - 브라우저는 그 데이터를 저장해 놓았다가,
동일한 서버
에 요청 시 함께 자동으로 전송함.
✔️ 특징
- 쿠키는
도메인
에 따라 제한이 된다. - 브라우저는, 유튜브한테 받은 쿠키는 유튜브로만 보낸다.
- 쿠키는
유효 기간
이 있다. - 설정하기에 따라 하루, 한 달 혹은 영원히… 서버가 정한 기간 만큼 유효하다.
- 인증 뿐만 아니라,
여러 정보
를 저장할 수 있다. - 웹사이트의 언어 설정을 바꾸면, 웹사이트는 사용자가 선택한 언어를 저장한 쿠키를 주기도 한다. 그러면, 다음 방문 때 쿠키를 요청과 함께 서버로 보내고, 서버는 쿠키가 기억해둔 언어 설정의 페이지를 제공할 수 있다.
세션과 토큰을 이해하기 위해서는 먼저 HTTP 프로토콜의 Stateless 속성에 대해 이해해야 한다.
💋 HTTP 프로토콜의 속성: Stateless
✔️ 개념
- 서버로 가는 모든 요청은 독립적이다.
- 각 요청은 이전에 보내진 요청과의 연결고리가 없다.
- 서버는 요청에 대한 응답을 보내고 나면, 요청을 보낸 사용자를 기억하지 않는다.
✔️ HTTP 프로토콜은 Stateless해서 확장성이 좋다!
언뜻 생각해보면, 이전 요청을 기억하지 않는다는게 안좋게 느껴질 수 있다.
하지만, Stateless
하다는 것은 서버가 클라이언트의 상태를 유지할 필요가 없다는 것을 뜻한다.
상태를 유지하거나 관리한다는 것은, 클라이언트의 상태를 데이터베이스에 저장하고 때에 따라 업데이트하고, 삭제하기도 해야 한다는 뜻이다.
- Stateful한 경우
서버1 안에 클라이언트A의 이전 요청을 저장해, 이후의 요청에서 계속 누적된 정보를 바탕으로 요청을 처리하고 있기 때문에 클라이언트A는 계속해서 서버1로만 요청을 보내야 한다. 서버1에 장애가 발생하면, 클라이언트A의 요청은 정상적으로 처리되지 못한다.
- Stateless한 경우
모든 서버가 같은 기능을 하고, 상태를 보관하지 않기 때문에 서버1이 고장났을 때는 서버2를 호출하면 된다.
따라서, Stateless한 속성 때문에 서버의 수평 확장에 굉장히 유리하다.
💋 세션
✔️ 인증 플로우
세션을 사용한 인증 방식은 아래와 같은 플로우로 진행된다.
- 클라이언트는 아이디 + 비밀번호를 서버에 보낸다.
- 서버는 아이디 + 비밀번호의 내용이 맞다면, 세션 데이터베이스에 유저를 생성하고, Session ID(별도의 ID)를 Set-Cookie를 통해 쿠키에 넣어서, 응답에 함께 보낸다.
- Session ID는 쿠키를 통해 브라우저로 들어오고, 브라우저에 저장된다. (참고: F12 관리자 페이지에서 Application 탭에 들어가면, 현재 브라우저에 저장된 쿠키를 확인할 수 있다.)
- 동일한 웹사이트(서버)의 다른 페이지에 접속하면, 브라우저는 Session ID가 포함된 쿠키를 항상 자동으로 요청과 함께 서버로 보낸다.
- 서버는 쿠키에서 Session ID를 확인하고, 세션 데이터베이스를 확인해 클라이언트가 누구인지 알게 된다.
✔️ 특징
세션 방식을 통해서, 서버는 클라이언트를 기억하는 것처럼 진행되지만, 앞서 설명했듯 HTTP 요청은 Stateless하다. 따라서 위의 과정은 하나의 요청이 끝나고, 다른 페이지로 이동하게 되면 위의 플로우를 매번 반복하게 된다.
세션 방식의 중요한 특징은, 중요한 유저의 정보(비밀번호
…)는 모두 서버에 저장되어 있다는 것이다. 클라이언트는 오직 세션 ID만 가지고 있다.
✔️ 장점
서버는 로그인된 유저의 모든 정보를 저장하기 때문에, 이 정보를 사용해 새로운 기능을 추가할 수 있다.
- 특정 유저를 로그아웃 시키고 싶을 때, 세션을 삭제해버릴 수 있다.
- 세션에 로그인된 기기의 정보를 함께 저장하면, 로그인된 디바이스를 모두 보여줘서 원하지 않는 디바이스를 로그아웃 시킬 수 있고, 넷플릭스처럼 계정의 공유 숫자를 제한할 수 있다.
✔️ 한계점
- 서버는 로그인한 유저들의 모든 세션 ID를 데이터베이스에 저장해야 하기 때문에, 데이터베이스를 사고, 유지해야 한다.
- 유저가 많아질 수록, 데이터베이스도 커져야 할 것이다.
- 요청이 들어올 때마다, 서버는 쿠키를 받아서 세션 ID를 확인하고, 세션 ID에 해당하는 유저를 데이터베이스에서 조회해야 다음 작업을 수행할 수 있기 때문에, 많은 리소스가 들어간다.
세션 방식을 살펴보았을 때, 앞서 설명한 쿠키는 세션 ID를 전달하기 위한 매개체로만 사용된다. 쿠키는 브라우저에만 존재하기 때문에, 안드로이드나 iOS 애플리케이션을 만들 때는 세션 ID를 전달하기 위해 쿠키가 아닌 다른 매개체를 선택해야 한다.
이때, 토큰
을 사용해 정보를 전달할 수 있다.
💋 토큰
✔️ 개념
- 서버에 보내기 위한
String
- 토큰에 세션 ID 등을 담아서 보낼 수 있다.
✔️ 쿠키 VS 토큰
쿠키와 토큰은 모두 인증에 필요한 정보를 브라우저 → 서버로 전달하기 위한 수단이라는 공통점이 있다.
쿠키는 서버에서 응답에 함께 보내지면 브라우저가 자동으로 이후 요청에 해당 쿠키를 함께 보내준다.
하지만 토큰 방식은 브라우저가 자동으로 보내주는 것이 아니기 때문에 프론트엔드 코드에서 직접 토큰을 요청에 포함시켜 보내주어야 한다.
💋JWT(Json Web Token)
✔️ 개념
JWT는 단지 토큰 형식
중 하나다.
JWT 역시 토큰이기 때문에, 본질은 그저 String
이다. 아래와 같이 아주 복잡하게 생겼다.
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIyIiwiZXhwIjoxNjk1MjgyMzEyfQ.lgNhB8MH3cO3j2F7Vc4ehXjNtp0-1lpNp7kDVlVDjsHuIMLzVuLTUECy_y4rjZZRoB4qEIc4aJmoiMat8OgLFw
JWT는 세 부분으로 구성되어 있으며, 각 부분은 Base64로 인코딩되어 있다.
첫 번째 부분은 헤더
(Header)이며, 토큰의 유형과 알고리즘 등을 포함한다.
두 번째 부분은 페이로드
(Payload)이며, 토큰에 담길 정보를 포함한다.
세 번째 부분은 서명
(Signature)이며, 토큰의 유효성을 검증하기 위한 서명이다.
인증 플로우를 보면, 세션 방식과의 차이점이 더 잘 이해될 것이다.
✔️ 인증 플로우
JWT를 사용한 인증 플로우는 아래와 같이 진행된다.
- 클라이언트는 아이디 + 비밀번호를 서버에 보낸다.
- 서버는 아이디 + 비밀번호의 내용이 맞다면, 유저의 정보 가운데 식별할 수 있는 것 (예를 들어 아이디라던가…)을 택해서, String 형태로 유저에게 응답한다. 길이 제한이 있는 쿠키와 다르게 JWT는 제약이 없어서, 진짜진짜 길게 보내도 된다.
- 유저는 인증을 받기 위해서, 이후 요청에 토큰을 함께 서버로 보낸다.
- 서버는 토큰을 받으면, 토큰이 조작되었는지 서명을 통해 검증하고(별도의 알고리즘이 있음), 토큰이 유효하다면 유저를 인증해준다.
JWT 방식을 사용해서 인증을 하게 되면, 서버는 세션 데이터베이스를 가질 필요가 없어서, 유저를 인증하기 위해서 많은 일을 하지 않아도 된다.
✔️ 특징
JWT에서는 서버는 유저를 인증하는데 필요한 정보를 토큰에 저장해, 클라이언트에게 준다.
클라이언트가 페이지를 요청하면 서버는 해당 토큰이 유효한 지만 검증하고, 데이터베이스를 거칠 필요가 없다.
중요한 건, JWT 방식에서는 서버는 단지 토큰이 조작되었는지만을 서명을 통해서 확인한다는 것이다.
✔️ 장점
서버는 생성된 토큰을 추적하지 않고, 단지 요청과 함께 받은 토큰이 유효한지만 검사할 뿐이다. 따라서 데이터베이스를 별도로 구매하고 유지할 필요가 없다.
✔️ 한계점
생성된 토큰에 대해 제어할 수 없기 때문에, 세션 방식과 같은 강제 로그아웃과 같은 기능을 할 수 없다. 토큰이 만료될 때까지 기다릴 뿐이다.
JWT는 암호화된 것이 아니기 때문에, 토큰에 민감한 정보(예: 비밀번호)를 저장하면 안된다. 대신, 토큰에는 클라이언트 식별자나 권한과 같은 필요한 정보만 포함시키는 것이 좋다.
💋 세션 VS JWT
여기까지 읽었다면, 쿠키는 단지 정보를 전달하는 매개체일 뿐이고, 로그인을 위한 인증에 사용하는 방식은 크게 세션 방식과 JWT를 사용한 방식이라는 것을 알게 되었을 것이다.
둘 중 어떤 방식을 사용해야 할까?
서비스의 성격에 따라서 유저의 로그인을 서버 측에서 강제할 필요가 있다면 세션 방식이 적합할 것이다.
그렇지 않고, 처음 시작하는 서비스라면 별도로 데이터베이스의 관리가 필요하지 않은 JWT 방식을 사용하는 것이 합리적일 것이다.
하지만, 서비스의 규모가 커져서 유저가 많아지고 유저를 더 효율적으로 관리해야 한다면 세션을 사용하는 방식으로 옮겨갈 수 있을 것이다.
💋 참고자료
- https://www.youtube.com/watch?v=tosLBcAX1vk
- 인프런 강의자료 (김영한님)
- https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies
- https://fierycoding.tistory.com/69
- https://hudi.blog/refresh-token/
도움이 되었다면, 공감/댓글을 달아주면 깃짱에게 큰 힘이 됩니다!🌟
'WEB > Application' 카테고리의 다른 글
[WEB] 웹의 발전 과정: WWW부터 CGI, Servlet, JSP, Framework까지 (2) | 2023.09.12 |
---|---|
[OAuth] OAuth 2.0의 개념과 과정 (3) | 2023.08.12 |