카테고리 없음

[오류해결] 머리박고 배운 cookie

kingmusung 2024. 9. 4. 22:25

개요.

프런트엔드에서 사용자인증을 하는 과정에서(JWT사용을 하지 않고, cookie를 이용한 인증 방법 구현임.)

 

서버에서 넘겨준 JSESSIONID 쿠키는 HTTPONLY로 설정이 되어있으므로

 

JS, TS 즉 프런트엔드에서 쿠키의 값, 존재여부를 읽어 올 수 없기 때문에

 

JSESSIONID 쿠키의 생명주기와 일치하는 쿠키를 만들어서 대안으로 사용하는 과정에서, 

 

쿠키의 정체를 잘 알 필요성이 있었고, "쿠키라는 단순한 개념" 으로는 성에 안 차서 이참에 알아보기로 했다!

 

중간중간 어떤 부분에서 어려움을 겪었고 해결했는지도 적어보았다..!

 

개인적으로 오류를 해결하면서 느낀 공통적인 부분에 대한 회고를 해보려고 한다.


쿠키의 기본적인 구조.

name=value; expires=Date; path=Path; domain=Domain; Secure; HttpOnly; SameSite=Strict|Lax|None

 

 

(개발자도구 -> application -> cookie에 들어가면 볼 수 있다.)

 

순차대로 이해해 보자.

 

name: 

  • 쿠키의 값은 Key, Value로 구성이 되었다 즉 이름이 Key 값이 Value이다.
  • 쿠키의 value에 한글을 그대로 집어넣으면 오류가 생긴다. 이것 때문에 엄청난 고생을 했다.
  • 한글도 쓸 일이 있다면 쿠키를 심을 때 encoding, 쿠키값을 읽을 때 decoding을 해서 읽어야 한다.

 

expires

  • Wed, 21 Oct 2024 07:28:00 GMT UTC형식으로 넣어주어야 한다.
  • 쿠키의 만료 기간을 설정하는 부분이다.
  • 이 부분을 생략한다면, 즉 별도의 유효기간을 설정하지 않은 쿠키를 SESSION COOKIE라고 하는데, 사용자가 브라우저를 닫으면 만료가 되는 쿠키이다.
  • 사실 SESSION COOKIE 때문에 애를 먹었다. 탭만 닫으면 안 없어지고 진짜 브라우저를 전부 닫아야 한다.
    (맥북기준이라 윈도는 모르겠음.)

 

path:

  • 쿠키가 사용될 수 있는 경로, ‘/’로 설정 시 모든 경로에서 쿠키사용 가능
  • path = “/calendar” 로 지정을 한다면, path =”/calendar/register” 등 서브 url에서도 접근이 가능하다.
  • 이 부분을 비워 놓거나 명시하지 않을 시 path=/ 값이 기본값이다.

secure

  • 이 속성이 설정된 경우, 쿠키는 HTTPS 연결을 통해서만 전송된다.
  • 로컬 개발환경에서는 http를 쓰니까 true로 하면 쿠키 전송이 안될 수 있다.
  • 이 부분을 비워 놓거나 명시하지 않을 시 false로 설정된다.

 

HttpOnly : JS 혹은 TS 즉 프런트엔드에서는 접근이 안되도록 하는 설정이다. 서버에서만 값을 읽고 쓸 수 있다.

  • JSESSIONID 쿠키 같은 경우가 위 경우에 해당함으로, javascripts 즉 프런트 엔드 코드에서 해당 쿠키를 읽어오려고 하면 읽어올 수 없는 경우가 여기에 해당함.

domain: 쿠키가 유효한 도메인을 지정함. 생략 시 현제 도메인에서만 유효함.

위 쿠키 사진을 보면 domain = localhost로 되어있다.

 

예를 들면 http://localhost:5173 vite를 사용하고 있는데 생략하면 http://localhost:5173 여기서만 유효하고 http://localhost:8080 여기서는 유효하지 않는가? (프런트서버와 백엔드서버 간 쿠키를 어떻게 받는 건지 궁금한 게 포인트임.)

 

답: 아니다, 만약 domain=localhost로 설정하면, 이 쿠키는 localhost라는 도메인에 대해 유효하다. 따라서 http://localhost:5173http://localhost:8080 모두에서 쿠키가 유효함.

 

SameSite: 웹사이트가 다른 웹사이트에서 보내는 요청에 쿠키를 어떻게 처리할지를 결정하는 부분이다.

Strict: 쿠키가 동일한 사이트 즉 위에서 한 domain 내에서만 전송.(타 사이트(domain)에서 쿠키를 이용하지 못함.)

Lax: 일부 다른 도메인의 사이트 요청에서 쿠키가 전송될 수 있음.

None: 모든 사이트 요청에서 쿠키가 전송. 이 경우 Secure 속성을 True로 사용해야 함.

생략 시 기본값은 LAX이다.


path, domain, SameSite 3개다 비슷한 개념인 거 같은데 뭐야

 

 path 

 

메인페이지(http://localhost:5173/main) 우측 상단을 보면 "s@naver.com님"이라고 보이는데 이 부분의 동작원리는

 

로그인 페이지(http://localhost:5173/login)에서 로그인을 하게 되면 name=s@naver.com이라는 value 값을 가진 쿠키가 심어

 

지게 되는데, path=/ 이렇게 되어있으므로, 위 사진에 해당하는 메인페이지(http://localhost:5173/main)에서 쿠키의 값을 읽어서 화

면에 보여준 것이다.

 

http://localhost:5173/main

http://localhost:5173/chatBot

http://localhost:5173/profile

등등에서도 접근이 가능하다.

 

반대로 로그인 후 쿠키를 심어줄때 "path=/login"으로 심어주게 된다면

 

위와 같이 메인페이지(http://localhost:5173/main)에서 쿠키의 값을 읽어 올 수가 없다, 하지만 우측에 쿠키가 있는 건 확인할 수 있다.

 

domain

 

위 주소창을 보면 domain이 localhost로 되어있다, domain을 설정 시에는 http, https 등을 다 빼고 작성을 해야 한다고 한다.

추가로 쿠키를 심을 때 "생략" 혹은 "localhost"를 했을 때는 쿠키가 심어지지만 다른 도메인을 입력했을 때는 심어지지 않아서 찾아본 결과

"브라우저는 보안상 현재 접근하고 있는 도메인과 일치하지 않는 도메인에 대해 쿠키를 설정할 수 없다"라고 진단을 받았다.

 

단!! 현제 테스트 환경은 로컬환경이므로 실 서비스를 지속한다면 테스트해 볼 예정이다. 도메인을 생략 시에는 현제 도메인과 일치하도록 알아서 심어지니 굳이 건들필요는 없는거 같다. 임시로 AWS 베포까지 한 후에도 오류가 없었던걸 보면. 도메인 생략시에는 유동적으로 그 도메인에 맞춰지는 거 같다.

 

 

SameSite

path는 경로, domain인은 도메인, 주소에 관해서 다뤘다면

 

samesite는 정책에 대해서 다루는 부분이다.

 

"자! 네가 설정한 경로 그리고 도메인 ㅇㅋ 알겠어. 그럼 정책을 어떻게 해줄까"

 

라고 생각하면 편할듯하다.


쿠키를 어떻게 심냐 그럼.

일단 TS, JS를 사용하고 있고,

document.cookie = `키값=벨류값; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/login; domain=example.com; Secure;(적으면 true 안적으면 false) SameSite=;`;

 

코딩을 하다 유동적으로 받아야 하는 부분이 있다면 변수로 받아서 처리하면 된다,

 

개인적인 의견으로는 일반적으로 하는 프로젝트에서는 

document.cookie = `키값=벨류값; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/`;

 

쿠키의 키와 그리고 값, 만료일, 경로 정도만 써주면 좋을 듯하다.


쿠키는 한글을 못 읽는다?

예시를 위한 예제이다, 이 부분은 내 정보 페이지인데 메인페이지처럼 쿠키에 있는 이름을 가져온 후 랜더링을 해주게 된다.

 

사실 이름 입력하는 칸에 자동완성으로 이메일주소로 가입해 버려서 이름이 영문으로 되어있다.

 

팀원들은 저 부분이 오류가 생긴다고 하는 것이다.

 

위처럼???로 처리가 된다는 거다. git pull도 다 받았고, 브렌치도 최신인데 왜 그러지? 혹시나 해서 한글로 가입을 하니까 진짜 위처럼 동작이 안 하는 것이다. (??? 처리는 회원정보가 없으면 위처럼 나오도록 설정했음.)

 

에러 로그를 살펴보았는데, 뜬금없이 CORS에러가 뜨는 것이다. 백엔드 서버에서도 CORS설정을 잘했고, api요청 시에도 "withcredential:true" 설정으로 분명 전까지 잘 되었는데 무엇이 문제일까 하고. 찾아본 결과

(CORS 설정 오류랑 무슨 관계가 있는지 혹시 아시는 분은 알려주세요 ㅠㅠㅠㅠ)

 

"쿠키의 값은 일반적으로 ASCII 문자로만 저장되기 때문에 인코딩, 읽을 때 디코딩 작업이 필요하다."라는 정보를 입수해 버렸다.

 

인코딩 후 쿠키저장, Get Cookie 후 디코딩을 하니 오류가 해결이 되었다.

(기존 저장하려는 Value값에 encoding, decoding 하는 방법은 검색하면 너무 많이 나와서 안 다룰 예정!!)