우아한테크코스 4기/프로젝트

토큰과 세션(3) - 선택

giron 2022. 8. 29. 16:00
728x90

현재 저희 공식팀의 서비스는 지식 공유 게시판(약간 stackoverflow느낌)의 웹 플랫폼입니다. 저희 서비스에서는 세션과 토큰 중 어떤 게 적합한 인증방식일지 고민해봤습니다.

일반적인 오해

전통적으로 웹사이트는 쿠키를 사용한 세션 인증을 사용하고 모바일 앱/SPA는 Authorization 헤더와 함께 토큰 인증을 사용하지만 반드시 그런 것은 아니다. Authorization Header와 Cookies는 전송 메커니즘에 관한 것입니다. 토큰과 세션은 기본적으로 서버 측이든 클라이언트 측이든 권한 부여 상태가 처리되는 위치에 관한 것입니다. 예를 들어, 서버는 쿠키를 통해 JWT 토큰을 발행하거나 "Authorization" 헤더에 상태 저장 세션 ID가 제공될 것으로 예상할 수 있다.

출처: https://www.authgear.com/post/session-vs-token-authentication

그럼 언제 토큰, 언제 세션을 사용하는 게 좋을까?

전통적인 웹서비스에서는 ID/PW로 인증을 확인받고 세션을 유지하는 방식을 취해왔습니다. 이 방식은 쿠키를 날린다거나 세션 유효기간이 만료되면 재인증해야 하는 번거로움이 있습니다.물론 이런 번거로움이 나쁘다는 것이 아니라, 유저의 사용환경상 그러는 편이 나은 선택일 것입니다. 웹은 어디서건 접속할 수 있고, 때문에 본인만 사용하는 PC라는 것을 확인할 수 없기 때문에 적절한 시점에 로그아웃을 해줘야 보안상 안전할 것입니다.

그러나 앱 사용환경은 조금 다릅니다. 은 스마트폰을 통해 설치하며, 스마트폰은 ‘자신의 것’이라는 것에 컨센서스가 있기 때문입니다. 따라서 앱-서버간 인증에서는 매번 로그아웃을 하는 것은 일부상황(보안수준이 매우 높아야 하는 금융 혹은 private 서비스)을 제외한 유저에게 더욱 번거로운 경험이라고 생각됩니다.

출처: https://techblog.woowahan.com/2617/

차이점

주요 차이점은 세션 기반 인증은 서버가 세부 사항을 저장하고, 반면에 토큰 기반은 클라이언트가 토큰을 가지고 있는 형태이다. 두 방법 모두 취약점이 있고, 자신의 요구와 응용 프로그램에 더 적합한 방법을 결정해야 한다. 토큰은 대역폭이 크기 때문에 저장해서 사용하는 것보단 대역폭이 작은 세션을 사용하는 게 좋을 것 같다.

*네트워크 성능에 미치는 요소 - 대역폭(bandWidth), 소요 시간(Latency)

소요시간 = 전파시간 + 전송시간 + 큐잉시간

전파시간 = 거리 / 광속

전송시간 = 크기 / 대역폭

생각 정리

보안적으로 봤을 때는 토큰이나 세션이나 탈취당할 위험은 비슷하다. 다만 탈취 당한 이후의 액션에 대해서 차이가 있다.

왜냐하면 토큰같은 경우는 탈취를 당하면 강제로 로그아웃 시키거나 만료시키는 방법이 없기 때문이다. 따라서 토큰을 사용한다면 애초에 탈취당하지 않도록 하는 방법을 강구해야 할 것 같다. 리프레시토큰의 재발급 요청 메서드를 엑세스토큰이 만료되었을 때만 올 수 있도록 처리하는 방법도 있을 것 같다. 혹은 엑세스토큰을 함께 요청으로 받고, 엑세스토큰의 만료일과 payload를 확인하는 방식으로 처리할 수 있지 않을까 생각이 든다! (payload의 값은 유효하지만 만료만 된 경우는 탈취당했다고보기 어렵다는 판단하에..!)

반면에 세션을 사용한다면 그만큼 보틀넥이되므로 확장에 대한 단점은 무시할 순 없다. 하지만 세션은 스토리지에 정보가 저장되므로 탈취가 당했다고 인지하면( ex) 접속 ip주소가 바뀌었다던지) 세션을 날려서 재로그인 또는 비밀번호 변경을 하도록 요청할 수 있다. 보틀넥 현상도 스토리지를 이중화하면 어느 정도는 해결되지 않을까 생각된다.

즉, 토큰같은 경우는 확장성이 좋고, 트래픽이 몰릴 경우가 빈번한 서비스에서 사용하는 것이 좋다고 생각한다. 사내 내부 서비스에서 검증을 할 때는 상대적으로 토큰이 외부에 노출될 경우가 적기 때문에 굳이 세션스토리지를 갖지 않아도 되는 토큰 방식이 좋아보인다.

예를 들어 배달의 민족처럼 이벤트로 트래픽이 몰릴 가능성이 있는 경우 토큰을 사용하는 편이 좋다고 생각한다. 또한 앱이라는 점도 다른 외부 PC혹은 모바일에서 본인의 계정에 접속할 일은 적기 때문에 강제 로그아웃이 크게 필요하지 않는 부분이다.

반면에 네이버같은 경우는 트래픽이 갑자기 몰릴 경우가 적고 본인만 사용하는 pc가 아니기 때문에 적절한 때에 강제 로그아웃이 필요하다. 따라서 세션을 사용해도 나쁘지 않은 선택이라고 생각한다.


2022-08-30 좋은 글을 찾아 소개하려고 합니다.

https://github.com/boojongmin/memo/issues/7

과거의 한 회사에서는 browser용 API app용 API를 따로 제공했다.왜냐하면 browser는 로그인이후 session을 이용했고 app은 로그인후 엑세스 토큰으로 통신을 하였기 때문이다.
이때 이걸 선택한 이유는 2가지로 생각이 된다.
1. app은 cookiejar 기능이 없기 때문에 브라우저랑 다르게 동작해야한다.(사실 cookiejar 구현체를 쓰면 쉽긴한데...암튼...)
2. app은 http 호출하여 json 형태로 응답하고 웹은 서버에서 http 호출시 html 형태로 응답하기 때문에 response content/type 미스매칭
사실 이때는 나도 이렇게 생각할 수 밖에 없었던거 같다그래서 앱/웹 두벌을 만들기 인력/시간이 부족한 스타트업은 웹뷰를 이용한 앱을 많이 선택할 수 밖에 없었던게 당연한 흐름이였던거 같다.
하지만 몇년전 한회사에서 나는사용자에게 제공할 앱은 flutter를 이용하여 ios/android를 개발하고운영툴은 웹으로 vuejs로 개발을했었다.
나는 vuejs는 할 수 있으니 spring을 이용하여 api를 만들고 vuejs로 화면을 그리고 프론트와 백엔드간 api를 통해 데이터를 주고 받고 개발을 하였다.
이때 웹은 JWT를 이용하였는데 이때 느낀 신선함은 flutter 앱개발자에게도 동일한 api를 제공해도 된다는 점이였다.
즉 웹/앱 구별하여 api를 두벌 뽑을 필요가 없었다.
기술이 모던해지면서 vue나 reactjs와 같은 기술이 나왔고 이 Single Page Application(SPA)를 통해 web도 이제는 app과 비슷해졌고 이로 인해 백엔드 개발자는 좀 더 api 개발시에 효율을 느낄 수 있었다.
즉 나는 session 베이스는 response content type이 html일 때 자연스럽고response type이 application/json일때는 JWT을 더 선호한다는 것이다.(무조건 이렇게 해야한다고 할 수 없지만 내 기준은 이렇다)

추가 2022-09-06

해당 문제에 대해서 대부분 토큰이 좋다고 토론을 했다. 그러다가 문득 얘기중 인사이트를 얻고 정리하려고 한다.

앞서 말한 유효성을 차단하는 문제때문에 리프레시 토큰을 저장한다고 한다. 그렇다면 토큰의 장점이 사라지는 게 아닌가 했지만 (이 질문을 할때 떠올랐다 ㅋㅋ) 리프레시 토큰을 저장하는 경우는 엑세스 토큰이 만료될 때, 요청이 온다. 따라서 세션을 사용하면 매번 요청이 올때마다 저장소를 찌르지만 토큰을 저장할 경우 엑세스 토큰이 만료될 때만 찌르기 때문에 같이 저장을 한다고 하더라도 이득이 있을 것같다. 

즉, 리프레시 토큰을 저장하고 리프레시 토큰을 검증할 때, 엑세스토큰과 리프레시 토큰을 함께 보내서 -> 액세스 토큰이 유효한데 만료만 되었다면 리프레시 토큰과 함께 발급해주는 방향이 최선이라고 생각이 된다!!!

Reference

구구

https://www.baeldung.com/cs/tokens-vs-sessions

https://docs.oracle.com/cd/E19462-01/819-4669/adrbc/index.html

https://www.interviewarea.com/faq/does-google-use-sessions-or-jwt

728x90