SPA에서 Cookie를 사용할 때의 주의점
포스트
취소

SPA에서 Cookie를 사용할 때의 주의점

본 문서는 서론이 좀 깁니다. 만약 Cookie에 대해서 잘 알고 계신다면 여기를 눌러서 본론으로 바로 넘어가주세요!

웹에서 데이터 유지하기

웹에서 사용되는 데이터들은 연결이 끊어지면 모두 날아가는 휘발성 데이터가 대부분이기에, 다음 접속 시에도 정보를 유지하기 위한 몇 가지 수단이 있습니다.
대표적으로 Cookie, Session, LocalStorage가 있습니다.

각각이 가진 데이터의 특징이 너무나 명확해서 적재적소에 활용하면 좋은 퍼포먼스를 낼 수 있지만 세 가지 방식 중 SSR 타임에 이용할 수 있는 데이터는 Cookie가 유일하기에 대부분의 개발자들이 로그인 정보 등을 보관하기 위해 Cookie를 사용합니다. 이 문서에서는 Cookie만을 알아볼 예정입니다.

Cookie

Cookie는 사용자의 컴퓨터에 직접적으로 다운로드 되는 텍스트 형태의 데이터입니다.

비휘발성

덕분에 웹과의 연결이 끊겨도 유실 될 일이 없어서 배너 다시 보지 않기자동 로그인 등의 기능에 활용 됩니다.

문자열만 저장

Cookie는 텍스트 형태의 파일이라고 위에서 언급했습니다.
그렇기 때문에 JSON이나 배열과 같은 데이터들이나, Boolean, Number와 같은 자료형을 모두 문자로 변환하여 저장해야 합니다.
기본형의 경우에 문자열로 변환하는 것은 그리 어렵지 않으나, 객체같은 경우 JSON.stringify를 통해 문자열로 변환하고, 추후 데이터를 꺼낼 때 JSON.parse를 이용하여 원복하는 형태로 이용해야 합니다.

저장 된 도메인에서만 이용

Cookie는 로그인 정보를 저장하는데 주로 사용하는 방식인 만큼 보안이 중요합니다.
그렇기 때문에 Javascript로 사용자의 컴퓨터에 저장 된 모든 Cookie를 불러오는 것은 불가능합니다.
Cookie를 만약 www.naver.com에서 token이라는 Key로 저장을 했다면, 이를 www.facebook.com에서 token이라는 Key로 참조했을 때 undefined가 반환되게 됩니다.

데이터 저장 규칙 정의

해당 Cookie를 얼마나 유지 할 것인지, 어떤 Location에서 사용할 것인지 등 다양한 옵션을 정의할 수 있습니다.

expires

Cookie가 만료 될 일자를 Date 형태로 삽입하면 해당 일자가 되었을 때 브라우저에서 사라집니다.

max-age

Cookie의 수명을 초 단위로 삽입할 수 있습니다. 설정한 수명이 끝나면 소멸합니다.

다만 구형 IE 브라우저에서는 해당 옵션을 지원하지 않습니다.

만약 expiresmax-age를 둘 다 설정했다면, max-age를 무시하고 expires에 기준합니다.

path

어떤 페이지에서만 사용할 수 있는 데이터인지 제한할 수 있습니다.
path에는 String 형태로 URI의 Segment 부분이 들어갑니다.

예를 들면, https://www.naver.com/blog 주소 내부에 있는 모든 라우트에서만 token을 유지하고 싶다면, path를 /blog로 설정하면 됩니다.
그러면 해당 토큰은 /blog 혹은 /blog/my-first-blog와 같은 /blog의 하위 페이지에서만 사용할 수 있습니다.

SPA에서 Cookie 사용 시 주의할 점

SPA라고 말은 했지만, 실제로 제가 이 상황을 마주한 케이스는 Nuxt입니다.
다만, SPA의 특징으로 인해 발생되는 이슈이기 때문에 다른 프레임워크도 마찬가지일 것이라 생각하고 작성합니다.

대부분의 경우에서 Cookie를 사용하는 것은 아무런 문제가 되지 않지만, path를 통해 Cookie의 사용 범위에 제약을 두는 순간 예상과는 다른 방식으로 Cookie가 동작합니다.

Test Case

동일한 프로젝트에 관리자부관리자 라는 두 유저가 있습니다.
두 유저는 동일한 CMS를 통해 웹사이트를 관리하는데 관리자는 /admin으로 진입하여 사용하고, 부관리자는 /semi-admin로 진입하여 사용합니다. 관리자가 로그인을 하면 token은 token이라는 Key로 관리되며, path는 /admin으로 지정합니다.
부관리자는 마찬가지로 Key를 token으로 설정하고, path를 /semi-admin으로 지정합니다.

만약 프로젝트에 진입할 때 /로 진입한다면 /admin으로 강제 Redirect를 시킵니다.

문제점

보기에는 아무 문제 없어보입니다. 다만 이 로직을 SPA 프레임워크로 작성한다면 문제가 생깁니다.
최초 진입 시, /admin이나 /semi-admin을 통해 진입하지 않고 /에 접속하여 /admin으로 이동 된 경우, 브라우저는 현재 사용자의 진입 위치를 /admin이 아닌 /로 착각하기 때문에 /admin Path에 지정 된 Cookie의 참조가 불가능합니다.
그렇기 때문에 이후 /admin에서 진행되는 모든 자격 검증에 이슈가 발생하게 됩니다.
SPA에서의 페이지 이동은 실제 페이지 이동이 아닌, History State를 Javascript로 변경하여 페이지가 이동한 것 처럼 보이게 만든 것이기 때문입니다.

해결방법

내키진 않지만 path를 /로 선언하여 전체 페이지에서 통합적으로 관리하게 만들어야 합니다.
그리고 각각의 페이지에서 동시 로그인을 지원해야만 한다면 Token을 저장할 때 Key를 서로 다르게 저장한다면 별 문제 없이 프로그램이 동작하게 됩니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

광택용 천을 샀습니다

새로운 Javascript 생태계, Deno에 대해 핥아보자