⬇️ Main Note
https://docs.google.com/document/d/18aytI_bQKBKqEMolbcuUG-w5hMBh_Um_QRT2Ojfb2E4/edit
//1. anyType
export const getAny = (args: any) => {
  const answer = args + 2; //result => J2
  return answer;
};
const myResult1 = getAny("J");
console.log(myResult1);
//Same to js when used 'any'
//for any type, it doesn't matter what kind of arguments are put in. 
//2. unknown type
const getUnknown = (args: unknown) => {
  //When argument is unknown type
  if (typeof args === "number") {
    const answer = args + 2;
  } else {
    return "Enter the number";
  }
  const answer = args + 2;
  return answer;
};
const myResult2 = getUnknown("철수"); 
// Whether number+2 comes out or "Enter the number" comes out.
console.log(myResult2);
unknown type is warning the developer to make sure the coding is done safely.export function getAny(arg: any): any {
  return arg;
}
const myResult31 = getAny("철수");
const myResult32 = getAny(123);
const myResult33 = getAny(true);
console.log(myResult31);
console.log(myResult32);
console.log(myResult33);
export function getGeneric<MyType>(arg: MyType): MyType {
  return arg;
}
const aaa: string = "JJ"; 
//--> saved as string and executed as string
const bbb: number = 8;
const ccc: boolean = true;
const result41 = getGeneric(aaa);
const result41 = getGeneric(bbb);
const result41 = getGeneric(ccc);
//Checking
console.log(result41);
console.log(result41);
console.log(result41);
Session Storage: When the user exits the browser and comes back to the browser, the data gets re-set.
Local Storage: The data is still activated even the user exits and comes back to the browser.
Cookie: Same as local storage, but expiration time exists. 
It's a bad idea to save heavy data inside cookies.
export default function BrowserStoragePage() {
  const onClickSaveCookie = () => {
    document.cookie = "aaa=철수";
    document.cookie = "zzz=맹구";
  };
  const onClickSaveLocal = () => {
    localStorage.setItem("bbb", "영희");
  };
  const onClickSaveSession = () => {
    sessionStorage.setItem("ccc", "훈이");
  };
  const onClickGetCookie = () => {
    // const aaa = document.cookie;
    // console.log(aaa); //aaa=철수; zzz=맹구 => 세미콜론이 붙어서 나옴 ;
    const aaa = document.cookie //
      .split("; ") //["aaa=철수" , "zzz=맹구"]
      .filter((el) => el.startsWith("aaa="))[0]; // ["aaa=철수"][0] 필터는 배열이기에 철수가 배열에 담겨서 출력
    const result = aaa.replace("aaa=", "");
    console.log(result);
  };
  const onClickGetLocal = () => {
    const bbb = localStorage.getItem("bbb");
    console.log(bbb);
  };
  const onClickGetSession = () => {
    const ccc = sessionStorage.getItem("ccc");
    console.log(ccc);
  };
  return (
    <div>
      <button onClick={onClickSaveCookie}>쿠키 저장</button>
      <button onClick={onClickSaveLocal}>로컬 저장</button>
      <button onClick={onClickSaveSession}>세션 저장</button>
      <br />
      <button onClick={onClickGetCookie}>쿠키 조회</button>
      <button onClick={onClickGetLocal}>로컬 조회</button>
      <button onClick={onClickGetSession}>세션 조회</button>
    </div>
  );
}
localStorage.getItem("accessToken")
--> This can also be approached by the hacker.
document.cookie
--> Functions the same as localStorage, but it has secure, httpOnly, etc.
--> When httlpOnly is set ture, it is safely sent and received. 
//게시글 장바구니에 담기
import { gql, useQuery } from "@apollo/client";
import { IBoard } from "../../src/commons/types/generated/types";
const FETCH_BOARDS = gql`
  query fetchBoards {
    fetchBoards {
      _id
      writer
      title
    }
  }
`;
export default function BasketPage() {
  const { data } = useQuery(FETCH_BOARDS);
  const onClickBasket = (el) => () => {
    console.log(el);
    // localStorage.getItem("Basket") //문자열임 "{}" 그래서 객체로 돌려놔야함
    const baskets = JSON.parse(localStorage.getItem("basket") || "[]");
    //데이터가 있으면 basket에 더해나가고 없으면 빈객체에 더해나가고
    const temp = baskets.filter((basketEl: IBoard) => basketEl._id === el._id);
    //basketEl은 장바구니에 담겨있는 element
    //같은게 있다면 필터링해줘
    //temp에 아이디가 담겨있다는건 이미 기존에 한번 담겨있었다는거
    //temp의 길이가 0인지 1인지에 따라서 구분할 수 있는거임
    if (temp.length === 1) {
      //temp.length ===1 이라는건 내가 선택한게 이미 장바구니에 있다는거 (중복된 아이디 걸러내기)
      alert("이미 장바구니에 담겨있습니다");
      return;
    }
    //Board 인자 제거하고싶음
    // delete el.__typename //원본 건드리는거 좋은 방법이 아님
    const { __typename, ...newEl } = el;
    baskets.push(newEl);
    localStorage.setItem("basket", JSON.stringify(baskets));
  };
  return (
    <div>
      {data?.fetchBoards.map((el: IBoard) => (
        <div key={el._id}>
          <span>{el.writer}</span>
          <span>{el.title}</span>
          <button onClick={onClickBasket(el)}>장바구니 담기</button>
        </div>
      ))}
    </div>
  );
}
//비회원 장바구니 조회
import { useEffect, useState } from "react";
import { IBoard } from "../../src/commons/types/generated/types";
export default function BasketLoggedInPage() {
  const [basketItems, setBasketItems] = useState([]);
  useEffect(() => {
    const baskets = JSON.parse(localStorage.getItem("basket") || "[]");
    setBasketItems(baskets);
  }, []);
  return (
    <div>
      <h1>비회원 장바구니</h1>
      {basketItems.map((el: IBoard) => (
        <div key={el._id}>
          <span>{el.writer}</span>
          <span>{el.title}</span>
        </div>
      ))}
    </div>
  );
}