들어가기
곰곰 다이어리는 자신과 관련한 질문을 담은 다이어리를 만들어 공유하면 다른 사람들이 이에 대해 답장하는 문답 공유 웹 사이트다.
곰곰 다이어리에서는 로그인 기능을 별도로 구현하지 않고, 쿠키로 유저를 인식하고자 한다.
로그인을 해야만 이용할 수 있는 신생 웹 페이지에 유저들이 순순히 회원가입과 로그인을 해줄까?
우리의 생각은 아니다였다.
OAuth도 로그인은 해야 하니 같은 맥락에서 제외했다.
또 단순 다이어리 생성/답장 하는 기능에서만 사용되니, 당장은 로그인 없이 유저를 인식해도 되겠다고 백엔드와 논의를 했다.
다만 이때는 몰랐다. 우리가 곰곰 다이어리에 더 많은 기능을 붙이게 될 줄은... 현재는 로그인의 필요성을 매우 느끼고 있다.
그래서 먼저 쿠키에 대해 좀 더 자세히 알아보았다.
(내가 만든) 쿠키
특징
- 클라이언트 기반 저장소로 유저의 브라우저에 저장된다.
- 키/값의 형태로 구성되어 문자열 형식만 저장할 수 있다.
- 최대 4KB의 작은 데이터를 저장할 수 있다.
- 세션 쿠키(만료 기간 없음)와 영구 쿠키(만료 기간 있음)으로 나뉜다.
사용법
- 백엔드와 통신 시, Set-Cookie 헤더에 쿠키 정보가 담겨 온다.
- 클라이언트 단에서 이를 브라우저 공간에 저장한다.
- 이후 서버로 보내는 모든 요청에 해당 쿠키를 담아 전달한다.
단점
- 유저의 브라우저에 쉽게 접근할 수 있기 때문에 탈취 및 변조될 위험이 있다.
- 서버로 보내는 모든 요청에 쿠키를 담아야 해서 용량이 증가하고 웹 성능 저하의 위험이 있다.
- 개인 정보 침해 이슈가 있다. (퍼스트 파티 쿠키/서드 파티 쿠키)
- 퍼스트 파티 쿠키: 유저가 접속한 웹사이트 === 쿠키를 발행한 웹사이트 일 때 해당 도메인에서 발행한 쿠키 (곰곰의 경우)
- 서드 파티 쿠키: 제 3자 도메인에 의해 발행된 쿠키
⚽️ HttpOnly
문제
곰곰 다이어리에서는 diaryId라는 이름의 쿠키로 백엔드의 기능, 프론트의 접근을 한다.
보안 측면을 개선하기 위해 HttpOnly 옵션을 추가하였는데, 이로 인해 프론트에서 해당 쿠키에 접근할 수 없게 되었다.
프론트에서는 해당 쿠키에 따라 라우팅을 시키고 특정 동작을 인지하게끔 구현해둔 터라 보안과 기능 구현 2가지 중 하나를 택해야 했다.
해결
백엔드 단에서 diaryId, diaryAddress 2개의 쿠키를 세팅해 전달해준다.
diaryId는 보안과 직결되어 HttpOnly 및 암호화를 해두고, diaryAddress에서는 프론트가 접근할 수 있게 해두었다.
이로서 보안과 기능 구현 2가지 중 하나를 포기하지 않고 각자의 기능을 할 수 있게끔 분리했다.
🍪 react-cookie
이 라이브러리는 React에서 쿠키를 쉽게 관리할 수 있게 해준다. (출처: npm react-cookie)
곰곰 다이어리에서는 백엔드 단에서 쿠키 발급 및 설정을 한 후에 보내주는 것이라 실질적으로는 많이 사용하지 않았다.
npm install react-cookie
yarn add react-cookie
라이브러리를 설치한 뒤 App.js에 <CookiesProvider> 로 랩핑해준다.
<CookiesProvider>
<RecoilRoot>
<BrowserRouter>
<Routes>
<Route path="/history" element={<History />} />
<Route path="/history/:historyItemId" element={<HistoryItem />} />
<Route path="/answerers/:diaryId" element={<Main />} />
<Route path="/answer/:diaryId/:answerId" element={<Main />} />
<Route path="/diary/:diaryId" element={<Main />} />
<Route path="/chat/enter_room" element={<Chat />} />
<Route path="*" element={<NotFound />} />
<Route path="/" element={<Main />} />
</Routes>
</BrowserRouter>
</RecoilRoot>
</CookiesProvider>
import { Cookies } from 'react-cookie';
const cookies = new Cookies();
export const setCookie = (name, value, options) => {
return cookies.set(name, value, { ...options });
};
export const getCookie = (name) => {
return cookies.get(name);
};
export const removeCookie = (name) => {
return cookies.remove(name);
};
주로 get, set, remove 3가지를 많이 쓰는 것 같아 먼저 훅으로 분리해두었다.
setCookie로는 쿠키를 세팅할 수 있다.
이름, 쿠키값, 옵션인데 옵션에는 path, expires, maxAge, httpOnly 등을 설정할 수 있다.
getCookie로는 쿠키를 가져올 수 있다.
이름에 해당하는 쿠키를 가져오면 된다.
removeCookie로는 쿠키를 지울 수 있다.
위에서 말한 것처럼 곰곰 다이어리에서는 프론트 단에서 직접 쿠키를 세팅하지 않았고, 주어진 쿠키를 사용해 기능을 구현했기 때문에 실제로는 getCookie만 사용했다.
쿠키에 대해 머리로만 알았는데 실제로 개발을 해보니 훨씬 잘 이해할 수 있었다. (특히 httpOnly...)
내가 많이 부족해서 백단에서 쿠키를 다 구워주셨는데 다음에는 프론트 단에서 쿠키 세팅도 해보고 싶다.