[React] 렌더링 방식

yeni·2022년 12월 1일
0

로그인을 위한 accessToken을 변수에 넣고 global State로 사용했다.
하지만 새로고침을 하게 되면 로그인 정보가 모두 날아가서 매번 다시 로그인을 해야한다.
(⇢ 새로고침을 할 때, 새로운 html, css, js를 다시 받아오기 때문. 이전에 그려준 state변수들이 날아가게 되서 accessToken도 날아간 것)

accessToken을 브라우저에 저장해야 새로고침을 해도 정보가 날아가지 않는다!

브라우저에 accessToken 저장하기

localStroage.setItem을 통해서 브라우저 저장소에 저장하기!

import { gql, useMutation } from "@apollo/client";
import { Modal } from "antd";
import { useRouter } from "next/router";
import { ChangeEvent, useState } from "react";
import { useRecoilState } from "recoil";
import { accessTokenState } from "../../src/commons/stores";
import {
  IMutation,
  IMutationLoginUserArgs,
} from "../../src/commons/types/generated/types";

const LOGIN_USER = gql`
  mutation loginUser($email: String!, $password: String!) {
    loginUser(email: $email, password: $password) {
      accessToken
    }
  }
`;

export default function LoginPage() {
  // 1. 뮤테이션
  const [loginUser] = useMutation<
    Pick<IMutation, "loginUser">,
    IMutationLoginUserArgs
  >(LOGIN_USER);

  // 2. 글로벌스테이트
  const [, setAccessToken] = useRecoilState(accessTokenState);
  // 사용을 안하면 지워줄 수 있다. 단, 콤마는 지우면 안된다!

  // 3. 페이지이동
  const router = useRouter();

  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const onChangeEmail = (event: ChangeEvent<HTMLInputElement>) => {
    setEmail(event.currentTarget.value);
  };

  const onChangePassword = (event: ChangeEvent<HTMLInputElement>) => {
    setPassword(event.currentTarget.value);
  };

  const onClickLogin = async () => {
    try {
      // 1. 로그인 뮤테이션 날려서 accessToken 받아오기
      const result = await loginUser({
        variables: { email, password },
      });

      const accessToken = result?.data?.loginUser?.accessToken;
      console.log(accessToken);

      // 2. 받아온 accessToken을 globalState에 저장하기
      if (accessToken === undefined) {
        Modal.error({ content: "로그인에 실패했습니다" });
        return;
      }
      setAccessToken(accessToken);
      localStorage.setItem("accessToken", accessToken); // 임시 사용(refresh Token 배운 후에 지울 예정)

      // 3. 로그인 성공 페이지로 이동
      void router.push("/23-02-login-localstorage-success");
    } catch (error) {
      console.log(error);
    }
  };

  return (
    <>
      이메일 : <input type="text" onChange={onChangeEmail} />
      비밀번호 : <input type="password" onChange={onChangePassword} />
      <button onClick={onClickLogin}>로그인</button>
    </>
  );
}

이후, 브라우저에 저장해둔 accessToken을 getItem을 통해 가지고 와서, setAccessToken에 다시 넣어주어 브라우저에 저장된 토큰으로 바꾸어 줘야 하는데,
이때!! localstorage is not defined이라는 에러를 만나게 된다.

next.js의 렌더링 방식

next.js의 렌더링 방식 : 두번 실행하게 된다??

브라우저에서 url로 접속하면 Frontend에서 html, css, js를 다운받아와서 화면에 뿌려주게 되는데 이때 화면에 그려주기 전에, Frontend서버에서는 프로그램 자체에서 내부적으로 가상으로 미리 그려보게 된다.(pre-rendering)
이후, 가상으로 보여준 결과물과 실제 브라우저에 그려진 두개화면의 차이를 비교해서 업데이트 해주게되는데 이 작업을 hydration이라고하고, 비교해주는 과정diffing이라고 한다.
Frontend서버에서 가상으로 그려보는 곳에는 localStorage, alert 등을 가지고 있지 않기 때문에 실행하지 못하는 것.

Frontend에서 preRendering하는 것은 html, css와 같은 그림만 그려보는 것이지 함수 내부가 실행되거나 기능이 작동하는 것은 아니다.
브라우저까지 와서 실제로 작동을 눌렀을 때 동작하는 것이다!

profile
차곡차곡 쌓는 몌으니 개발노트

0개의 댓글