웹 개발을 할 때 세션과 쿠키를 사용하는 이유는 무엇일까요?
세션과 쿠키를 사용하는 이유는 아래와 같은 HTTP 프로토콜의 두 가지 특성(Connectionless, Stateless)에서부터 시작됩니다.
1. Connectionless(비연결성)
HTTP 프로토콜은 인터넷상에서 데이터를 주고 받기위한 서버/클라이언트 모델을 사용합니다. 클라이언트는 request를 보내고 서버는 요청을 처리하여 response를 보내게 되는데 response를 받은 클라이언트는 연결 상태가 유지되지 않고 끊어버립니다. 이러한 작동방식은 많은 사용자들의 요청을 처리하기 위해 적합합니다.
2. Stateless(비상태성)
서버는 한번 끊어진 클라이언트의 상태 정보를 저장하지 않습니다. 따라서 어떠한 클라이언트의 상태정보를 알고 싶으면 매번 새로운 연결을 시도해야 합니다.
이러한 HTTP 프로토콜의 두 가지 특성은 불편함을 초래하게 됩니다. 특정 사이트에 특별한 권한을 가진 사용자만 이용하게 하고 싶을 때 서버는 클라이언트에 대한 인증정보를 매번 확인해야 합니다. 이러한 점은 서버를 느리게 만드는 요인이 됩니다. 이런 불편한 점들을 해결하기 위한 방법이 세션과 쿠키입니다.
쿠키(Cookie)
쿠키는 키와 값을 가지고 클라이언트(브라우저)에 저장되어있는 작은 데이터 파일입니다. 서버가 다음 통신에서 참조할 키와 값을 저장하여 클라이언트에 보내어 유효 시간 동안 클라이언트에 저장됩니다.
쿠키의 동작 순서
- 클라이언트가 서버에 페이지를 요청(request)
- 서버는 클라이언트의 정보를 확인하여 쿠키를 생성하여 응답 헤더에 저장하여 응답(response)
- 클라이언트는 유효기간 동안 쿠키를 저장하고 있다가 다음 요청 때 쿠키를 요청 헤더에 저장하여 요청(request)
- 서버는 쿠키를 확인하여 인증 또는 적합한 페이지를 클라이언트에 응답(response)
쿠키의 치명적인 단점은 요청 헤더 또는 응답 헤더에 중요한 정보를 담아서 전송한다면 Wireshark와 같은 네트워크 스니퍼 도구를 활용하여 간단하게 확인할 수 있어 해킹의 위험성이 존재합니다. 이러한 치명적 단점을 보완하기 위해 나온 것이 세션(Session)입니다.
세션(Session)
세션은 클라이언트마다 쿠키에 JSESSIONID라는 키와 값을 부여하여 요청 때마다 서버에서 JSESSIONID를 통해 사용자를 구분하여 사용자에게 적절한 페이지를 응답해주는 기술입니다.
즉, 서버에서 사용자의 중요정보를 담은 세션 객체를 JSESSIONID로 구분하여 저장하고 있는 것입니다.
따라서 해커는 JSESSIONID는 알 수 있지만, 사용자의 중요정보는 알 수가 없어 일반적인 쿠키보다 보안이 좋습니다.
세션의 동작 순서
- 클라이언트가 서버에 페이지를 요청
- 서버는 request-header에 JSESSIONID를 확인하여 존재하지 않으면 클라이언트에게 JSESSIONID를 생성하여 응답
- 클라이언트는 다음 요청 때 JSESSIONID를 request-header에 포함하여 요청
- 서버는 JSESSIONID를 통해 세션에 담긴 사용자의 정보를 확인하여 적절한 페이지를 응답
세션과 쿠키의 차이점
세션과 쿠키의 가장 큰 차이점은 저장 위치에 따른 보안성입니다.
쿠키는 중간에서 탈취하여 중요정보를 확인할 수 있기 때문에 인증, 인가등의 보안이 중요한 기능에서는 세션을 사용하고 그렇지 않은 기능에서는 쿠키를 사용하는 것이 안전합니다.
세션 | 쿠키 | |
저장 위치 | 서버 | 클라이언트 |
저장 형식 | 객체 | 텍스트 |
만료 기간 | 브라우저 종료시까지 | 직접 설정 |
보안 | 좋음 | 나쁨 |
토큰(Token)
앞서 설명해드린 것처럼 쿠키는 브라우저에 저장되어 있는 작은 데이터 파일이고 세션은 쿠키에 JSESSIONID를 부여하여 사용되는 기술입니다. 그렇다면 브라우저가 아닌 네이티브 앱(iOS, Android)에서는 어떻게 세션을 사용할 수 있을까요?
쿠키를 대체할 수 있는 도구가 바로 토큰입니다. (물론 네이티브 앱뿐만이 아닌 브라우저 상에서도 사용될 수 있습니다.)
토큰(Token)은 단지 길이가 긴 문자열(String)입니다. 사용자마다 토큰을 부여하여 JSESSIONID를 대체할 수 있습니다.
다만, 세션과 다르게 토큰은 사용자를 구분할 순 있지만 사용자의 정보까지 담을 수는 없기 때문에 사용자마다 부여된 토큰을 세션 DB에 저장하여 사용자의 정보가 필요할 때마다 세션 DB에서 해당 사용자의 정보를 조회해야 합니다.
토큰(Token)의 동작 순서
- 클라이언트는 자신의 식별정보(아이디, 패스워드, 토큰)를 서버에 보낸다.
- 서버는 식별정보를 확인하여 세션 DB에서 해당 클라이언트의 토큰을 찾아 클라이언트에 보낸다
- 클라이언트는 다음 요청 때마다 토큰을 함께 보낸다.
- 서버는 토큰을 확인하여 클라이언트를 식별한다.
토큰만을 사용하여 클라이언트를 구분하기 위해서는 매번 연결 때마다 해당 토큰을 세션 DB에서 확인해주어야 합니다.
이러한 반복되는 작업을 귀찮을뿐더러 서버에 부담이 될 수도 있습니다.
이러한 토큰의 단점을 보완할 수 있는 것이 JWT(JSON Web Token)입니다.
JWT(JSON Web Token)
JWT(JSON Web Token)은 JSON 형태로 이루어진 헤더(Header), 페이로드(Payload), 서명(Signature)으로 이루어져 있습니다. 클라이언트가 서버에 JWT를 보내면 서버는 서명(Signature)을 확인하여 적합한 인가인지 확인할 수 있고 페이로드를 통해 DB에 접근하지 않고도 유저의 정보를 확인할 수 있습니다.
JWT(JSON Web Token)의 동작 순서
- 클라이언트가 아이디와 패스워드를 통하여 로그인을 시도
- 서버는 요청을 확인하고 적합하면 유저의 정보가 담긴 JWT를 발급하여 클라이언트에 전달
- 클라이언트는 다음 요청 때마다 JWT를 함께 전달
- 서버는 서명(Signature)을 통하여 적합한 토큰인지 확인 후에 페이로드(Payload)에서 유저의 정보를 확인
다만 JWT는 서버가 관리할 수 없기 때문에 클라이언트에 대한 제어가 어렵고 정보의 양이 많아질수록 페이로드(Payload)의 크기가 커져서 서버에 부담이 될 수 있습니다. 또한 JWT는 BASE64등의 알고리즘에 의해 인코딩 되어 있기 때문에 디코딩된다면 클라이언트의 정보가 노출될 수 있습니다.
틀린 부분이 있다면 지적 부탁드립니다.
'Programming > Web' 카테고리의 다른 글
[Network] 3-way handshake, 4-way handshake의 개념 및 동작 원리 (0) | 2022.03.13 |
---|---|
Javascript, JQeury를 이용한 달력 만들기 (1) | 2021.10.16 |
CSS 프로그레스 바(progress bar) (0) | 2021.10.12 |
<button> 버튼 태그가 작동 안될 때 (0) | 2021.10.10 |
CSS 테두리만 있는 말풍선 그리기 (0) | 2021.10.10 |
댓글