⚠️ 문제의 발견
기존에는 access token을 사용해 로그인 기능을 구현했다. 하지만 1시간마다 토큰이 만료되어 로그인이 풀린다는 단점이 있었음. 이 문제를 보완하기 위해 refresh token을 사용한 로그인 연장 기능을 추가했다.
로컬에서 개발 후 dev 브랜치로 머지했고 테스트 사이트로 모바일 테스트를 하던 중 문제가 발생했다. 데스크탑과 달리 모바일 브라우저(크롬, 사파리)에서는 토큰이 만료된 후 로그인 연장이 되지 않는다..!
참고: 로그인 연장 로직
토큰이 필요한 요청을 보냈는데 access token이 만료되어서 에러가 발생하면 새 토큰 발급 요청을 보낸다.
서버는 쿠키에 있는 refresh token을 사용해 새 토큰을 발급 후 응답으로 보낸다.
새로 발급 받은 access token을 localStorage에 저장한다.
새 access token을 사용해 이전에 보낸 동일한 요청을 다시 보낸다.
문제 파악하기
문제를 발견한 후 모바일 개발자 도구를 열어 다시 테스트를 진행했다. 확인하고 싶은 사실은 1) 로그인 성공 후 응답으로 토큰이 잘 들어오는지, 2) 토큰 만료 시 로그인 연장이 잘 되는지 두 가지.
1. 토큰은 잘 들어오는가?
우선 로그인 성공했을 때 토큰이 응답으로 잘 들어오는지 확인했다. access token과 refresh token이 각각 응답으로 잘 오는 것을 확인했고, localStorage에 access token도 저장되고 있었다.
2. access token이 만료됐을때 로그인 연장은 잘 되는가?
그 다음 토큰이 만료됐을때 로그인 연장이 잘 되는지 테스트 했다.
데스크탑 크롬 브라우저 ✅ (잘됨)
데스크탑 사파리 브라우저 ❌ (안됨)
모바일 크롬, 사파리 브라우저 ❌ (안됨)
테스트 결과 모바일 브라우저 뿐만 아니라 사파리 데스크탑 브라우저에서도 동일한 문제가 발생한 것을 발견했다. 즉 모바일 브라우저만의 문제가 아니었음…
🖊️ 문제 정의
개발자 도구를 열어서 확인한 사실은 두 가지
응답으로 쿠키가 잘 들어온다. 하지만 로그인 연장은 안된다.
모바일 뿐만 아니라 사파리 데스크탑 브라우저에서도 동일한 문제가 발생한다.
이를 바탕으로 문제를 더 명확하게 정의를 하면 아래와 같다.
데스크탑 크롬 브라우저에서는 로그인 연장이 잘 되지만, 데스크탑 사파리, 모바일 크롬 및 사파리 브라우저에서는 로그인 연장에 실패함
🔍 원인 찾기
개발자 도구를 통해 확인한 사실을 바탕으로 브라우저의 쿠키 저장과 관련된 문제라고 추측했다. 모바일과 데스크탑에서 모두 동일한 문제가 발생한 ‘사파리’와 ‘쿠키’를 키워드로 이것저것 구글링 하다 사파리는 서드파티 쿠키 차단이 기본값으로 적용된다는 글을 발견했다. 👉 관련글(사파리, 이제 써드파티 쿠키 차단이 기본값으로 적용)
그래서 브라우저의 서드 파티 쿠키 설정 때문에 쿠키 저장이 제대로 되지 않는것인지 궁금해졌다. 테스트 해본 브라우저 중 유일하게 로그인 연장이 잘 되고있는 크롬 브라우저의 설정을 확인했는데 ‘시크릿 모드에서 서드 파티 쿠키 차단’으로 체크되어 있었다.
그래서 ‘서드 파티 쿠키 차단’에 체크를 하고 다시 테스트를 했다.
테스트 결과 토큰이 만료되었을 때 사파리와 동일하게 로그인 연장에 실패했다. 또한 Application의 쿠키 탭에서 원래는 잘 보이던 refreshToken 값도 안보였다.
사파리에서도 테스트를 했다. 사파리는 ‘설정 → 개인정보 보호 → 크로스 사이트 추적 방지’ 체크 해제를 하면 로그인 연장이 잘 되는 것을 확인할 수 있었다.
모바일 사파리 설정에서도 ‘크로스 사이트 추적 방지’ 토글을 해제하면 로그인 연장이 잘 됨
드디어 원인을 찾았다. 브라우저 설정에서 ‘서드 파티 쿠키 차단’에 체크되어 있으면 쿠키가 제대로 저장되지 않는다. 그래서 새로운 access token 발급 요청을 보내도 쿠키에 refresh token이 없으니 로그인 연장이 되지 않았던 것.
여기서 드는 궁금증…서드 파티 쿠키는 무엇일까?
🤔 서드 파티 쿠키란?
우선 ‘서드 파티’에 대해 알아보자.
서드 파티(Third Party)
사전적 의미: (당사자 이외의) 제 3자
IT 업계에서는 어떠한 분야에서 처음 개발하거나 원천기술을 가지고 있는 게 아닌, 원천기술과 호환되는 상품을 출시하거나 해당 기술을 이용한 파생상품을 생산하는 회사를 말함. 즉, 제 3자로서의 역할을 하는 것
참고(1):네이버 지식백과 - IT 용어사전 / 제3자
참고(2):3분 IT | 많이 들어본 용어인데.. 서드파티가 뭘까?
그럼 ‘서드 파티 쿠키’는 무엇일까?
서드 파티 쿠키(Third Party Cookie)
쿠키 발행 주체에 따라 퍼스트 파티 쿠키, 서드 파티 쿠키 두 가지로 나눌 수 있음
퍼스트 파티 쿠키: 사용자가 방문한 도메인과 동일한 도메인에서 생성된 쿠키
서드 파티 쿠키: 사용자가 방문한 도메인과 다른 도메인에서 생성된 쿠키
🤔 사파리의 서드 파티 쿠키 차단
사파리는 2020년 iOS 및 iPadOS 13.4와 macOS 13.1부터 서드 파티 쿠키 차단을 기본 탑재했다고 한다. 👉 WebKit Full Third-Party Cookie Blocking and More 문서 참고
해당 문서에서 Intelligent Tracking Prevention (ITP)에 대한 몇 가지 개선 사항을 소개함
개인정보 보호를 위해 “약간의 크로스 사이트 추적은 허용한다”는 예외 조항을 없애고 크로스 사이트에 대한 쿠키가 기본적으로 차단됨
서드 파티 쿠키 액세스가 필요한 경우 Storage Access API를 사용하면 된다고 함
Tracking Prevention in WebKit 문서 중 Terminology에서 퍼스트 파티와 서드 파티 도메인에 대해 설명하고 있다.
URL 표시줄에 news.example이 표기되고 adtech.example에서 하위 리소스를 로드하는 경우 news.example은 퍼스트 파티, adtech.example는 서드파티 (서로 다른 웹 사이트)
sub.news.example는 news.example 하위에 로드될 때 동일한 사이트로 간주되므로 퍼스트 파티임
정리
다시 정리해보면 로그인 연장에 실패했던 이유는 브라우저가 서드 파티 쿠키를 차단했기 때문이다. 테스트용 사이트 도메인(samchips-test.netlify.app)과 쿠키 생성 도메인(dev.samchips.com)이 서로 달라 서드 파티 쿠키로 간주 되었고 그래서 쿠키 저장이 되지 않았다.
💡해결 방법
해결 방법은 간단하다. dev 브랜치에서 main 브랜치로 머지하면 된다.
프로덕션 도메인은 samchips.com이고 쿠키 생성 도메인인 dev.samchips.com은 퍼스트 파티로 간주되기 때문에 쿠키가 잘 저장된다.
테스트용 사이트에서는 ‘서드 파티 쿠키 차단’ 또는 ‘크로스 사이트 추적 방지’ 설정이 되어있는 경우 로그인 연장이 되지 않는다. 하지만 테스트용이기 때문에 서드 파티 쿠키에 접근하기 위한 처리를 따로 해주지 않았다.
👋 마무리
main으로 머지 후 다시 테스트한 결과 데스크탑과 모바일 크롬, 사파리 브라우저 모두 로그인 연장에 성공했다. 해결 방법은 정말 쉬웠지만 문제를 파악하는 과정에서 사파리 브라우저의 쿠키 정책과 서드 파티 쿠키에 대해 새로 알게 되었다. 또한 브라우저 설정에 따라 기능이 동일하게 작동하지 않을 수 있으니 꼼꼼한 테스트의 필요성을 체감했다.