accessToken, state등을 브라우저에 저장시키면 새로고침 or 페이지 이동 시 초기화된다.
➡️ 해결하기 위해 브라우저 내 저장소를 사용
1️⃣ session Storage - 브라우저 종료 시 사라짐
2️⃣ local Storage - 영구 저장, 보안상 좋지 않지만 refreshToken을 배우기 전까지 임시 사용!
3️⃣ Cookie - 영구저장, 만료시간을 정할 수 있고 refreshToken을 저장한다
개발자도구 - 애플리케이션
local Storage
localStorage.setItem(“key”,value) ➡️ 저장 localStorage.getItem(“key”,value) ➡️ 사용
❗️ 페이지를 새로고침하면, app.tsx내 accessToken state가 날아가는데, localStorage는 새로고침 이후에도 사라지지 않는다.
그래서 새로고침 이후에도 localStorage에 저장 시켜 놓은 accessToken을 setAccessToken을 사용해 집어 넣어주면 만료시간까지 유지가 가능하다!
➡️ 그러면 app.tsx에서 setAccessToken으로 받아보자❗️근데 에러발생 : undefined
Next.js의 렌더링
Browser에서 요청이 오면 frontend서버에서 미려 그려본 후(Pre-rendering) Browser에 그려준 뒤, 비교(diffing)하고 변경사항을 적용(hydration)한다. 따라서 frontend 서버에서 그려줄때는 Browser저장소인 localStorage가 없다
➡️ undefined 에러 발생
➡️ 해결방법 : 3가지
1️⃣ process.browser
if( process.browser) {
if (localStorage.getItem("accessToken")) {
setAccessToken(localStorage.getItem("accessToken") || "");
}
}
2️⃣ typeof window !== "undefined"
//윈도우가 있을때(=브라우저) 실행해줘
if( typeof window !== "undefined") {
if (localStorage.getItem("accessToken")) {
setAccessToken(localStorage.getItem("accessToken") || "");
}
3️⃣ useEffect
// 브라우저에서 컴포넌트들이 다 그려지고나서 실행~ 한 번만 그려지기 때문에
useEffect(() => {
if (localStorage.getItem("accessToken")) {
setAccessToken(localStorage.getItem("accessToken") || "");
}
}, []);
❗️ 위 중 useEffect를 사용하는 이유
1번 2번은 매번 새로그려지지만, 3번은 한 번만 그려지기 때문에 가장 안정적 방식인 useEffect를 사용
useEffect에서 accessToken이 없으면 /login 화면으로 페이지를 이동시켜 줬는데, 로그인 권한이 필요한 모든 페이지마다 입력을 해야한다
➡️ 불가능
❗️ 해결방법: HOC(Higher Order Component)
HOC에 앞서 Closure, HOF를 단계적으로 이해하자
큐(queue) 구조
(FIFO) First In First Out : 먼저 들어온게 먼저 나간다
(LILO) Last In Last Out : 마지막에 들어온게 마지막에 나간다
📌 스택(stack)구조
(FILO) First In Last Out : 먼저 들어온게 마지막에 나간다
(LIFO) Last In First Out : 마지막에 들어온게 먼저 나간다
스택 : 먼저 실행되는 순서대로 쌓이는 구조
스코프체인 : Local->Closure(가장 가까운 외부 함수)->Global 순으로 찾아 간다
스코프체인은 아래로 내려가는데 local에 없어서 global로 내려와서 banana를 찾는다
apple이 없어서 스코프체인으로 위로 올라간다
다시말해, 클로저 closure
는 외부 함수에 접근할 수 있는 내부 함수를 말한다
🔥 나중에 이해하자
순서대로 실행한다고 생각하면됨!!
app.tsx ➡️ 권한 컴포넌트(useEffect) ➡️ 접속 컴포넌트
step 02) aaa ➡️ apple ➡️ banana
HOC는 특정 컴포넌트를 실행하기 전에 상위 컴포넌트를 먼저 실행시켜준다.
HOC를 하나 만들어 놓고, 로그인이 필요한 컴포넌트 앞에 HOC만 붙여주면 간단하게 권한처리가 된다
특징
📌 클로저 함수의 특징을 이용해 data를 무손실로 전달할 수 있다
📌 event.target.id 를 쓰지 않는다 ➡️ 코드 간결화, id 남용을 막아 안정성 확보
HOC 작성
1. component와 props 받기
2. 받은거 그대로 props 넘겨주기
3. 내용에서 실행하고 싶은거(useEffect) 쓰기
❗️ 다른 컴포넌트와 함께 실행되므로 with라는 이름을 앞에 붙인다 ex) withAuth, withApllo
❗️ 코드에 With가 붙어있으면 HOC 의심하기!
HOC와 HOF
HOC.omponent - JSX 리턴 ⭕️
HOF.unction - JSX 리턴 ❌
1. withAuth 실행 후
2. LoginSuccessPage 실행
freeboard - boards에 withAuth 적용