이번시간에서는 중고마켓에 적용될 장바구니를 구현하는 법과 쿠키 로컬 세션 스토리지의 상세한 강의를 들었다.
커리큘럼
- 아하! 이제 const {}, const [] 원리를 알겠어!
- 우와 무시무시한 타입이다! => generic
- 그냥 텍스트 말고, 웹 에디터로 꾸며줘 => Web-Editor
- 결제 API를 테스트할 신용 / 체크카드 준비됐지?! => lamport
- 지도를 연동해준다! 너무 쉰운걸?! => Map
목표
- 우와! 무시무시한 타입이 등장했다!! => Generic
- 변수 말고, 브라우저에 저장해봐 => Cookie / LocalStorage / SessionStorage
- 비회원 / 회원 전용 장방구니가 있다?! => Basket
브라우저 저장소
브라우저에는 3가지를 저장해주는 저장소가 존재하는데
- Cookie (쿠키)
- Local Storage (로컬 스토리지)
- Session Storage (세션 스토리지)
여기서 첫번째 쿠키는 만료시간이 존재한다. 그 시간안에는 쿠키가 사라지거나 제거되지 않는다.
그래서 브라우저를 껏다 키더라도 쿠키는 남아있게 되는 것
쿠키를 많이 저장하는 것은 좋지 않은데
브라우저에서 백엔드로 API를 요청하는데 쿠키 안에 있는 것을 같이 요청하게 된다.
API를 보낼때 쿠키에 있는 것을 자동으로 보내준다.
그래서 백엔드에서는 쿠키를 계속해서 뽑아올 수 있는 것이다.
그래서 백엔드 에서는 request라는 객체안에 Header안쪽에 쿠키가 저장되어 있다.
그안에는 저장한 데이터들이 들어가 있다.
내가 직접 쿠키를 넣지않더라도 자동으로 쿠키가 들어간다.
쿠키는 장점과 단점이 있는데
먼저 단점으로는 쿠키를 너무 많이 저장하게 되면 내가 구현하려는 기능에도 쿠키가 딸려들어가는 현상이 발생한다.
그래서 내가 요청을 할때마다 같이 딸려 가기 때문에 성능 저하가 발생할 수 있다.
그러나 LocalStorage는 그렇지 않다.
장점이라 하면 브라우저와 백엔드와 데이터를 공유하고 싶다면 쿠키에다가
넣으면 그대로 전송이된다.
반대로 백엔드에서도 쿠키를 날릴 수 있다.
백엔드에서 cookie 값을 넣으면 브라우저와 벡앤드간에 자동으로 정보를 주고 받을 수 있는 것이다.
쿠키는 어떤 용도로 사용되는가?
쿠키는 보안에 중요한 데이터들을 브라우저와 백엔드와 주고받을 때 주로 사용한다.
쿠키는 LocalStorage에 있는 것은 localStorage.getItem을 사용하면 나오는데
그렇기 때문에 우리도 쿠키를 주고 받을 수 있지만 해커도 동일하게 주고 받을 수 있다.
그러면 accessToken을 빼서 자기 컴퓨터로 빼낼 수 있다.
그럼 쿠키에 넣는다면? 쿠키도 마찬가지로 document.cookie를 사용하면
accessToken을 빼낼 수 있다.
둘다 차이점은 없는데? 쿠키에는 option을 넣어줄 수 있다.
옵션에는 httpOnly & secure 을 사용하는 순간 document.cookie는 불가능하다
그냥 브라우저와 백엔드간에 정보 주고 받는 용도로만 사용가능
그래서 httpOnly를 true로 하면 브라우저와 프론트엔드와의 정보주고 받기 밖에 없다.
그래서 굉장히 안전하게 사용이 가능하다.
secure은 http보다 좀더 안전한 https를 사용할 수 있다.
http-only-option때문에 document로 빼낼 수 없어 백엔드 통신으로만 가능하다.
Typescript 기초 다지기
// any타입(그냥 자바스크립튼)
// 숫자든 뭐든 다 더하는 타입
export const getAny = (args: any) => {
const answer = args + 2;
return answer;
};
const myResult1 = getAny(233);
console.log(myResult1);
타입스크립트에서는 타입을 주는 방식보다 any라는 타입을 주는 방법이 있다.
이타입을 그냥 자바스크립트라고 설명할 수 있다.
any를 사용하면 숫자든 뭐든 더해주는 기능을 만들 수 있다.
// 2. unknown 타입 (개발자에게 안전하게 코딩하도록 유도)
// 타입을 모르니까 안전하게 코딩하라 할때
const getUnknown = (args: unknown) => {
if (typeof args === 'number') {
const answer = args + 2;
return answer;
} else {
return '숫자를 넣어주세요';
}
};
두번째로는 unkown이라는 타입이 있는데 이 타입은 개발자에게 안전하게 코딩하도록 유도하는 타입이라
설명할 수 있다. unkown 말 그대로 타입을 모르니까 안전하게 코딩하고 싶을 때 사용한다.
// 1.문자
// args 는 string
// 가능하기 위해 제네릭에도 string을 해줘야 함
export function getString(args: string): string {
return args;
}
const result1 = getString('철수');
console.log(result1);
문자열 타입을 args에 string 타입으로 넣울 수 있고 이것을 구현하기위해서 제네릭에도 string 타입을 매겨야 한다.
export function getAnyReverse(arg1: any, arg2: any, arg3: any): [any, any, any] {
return [arg3, arg2, arg1];
}
배열타입도 넣어줄 수있는데 서로 다른 arg에 any타입으로 배열에 넣어주고 return으로 배열 값에 순서대로 내보내
주면 된다.
// 6.Generic 응용
// 들어올때는 순서대로 나갈떄는 거꾸로
// prettier-ignore
export function getGenericResver<MyType1, MyType2, MyType3>(arg1: MyType1, arg2: MyType2, arg3: MyType3): [MyType3, MyType2, MyType1] {
return [arg3, arg2, arg1];
}
GenericResver기능은 들어올떄는 순서대로 넣지만 나올때는 꺼구로 내보내주는 기능이다.
// 6.Generic 응용 - 축약1
// 들어올때는 순서대로 나갈떄는 거꾸로
// prettier-ignore
export function getGenericResverT<T1, T2, T3>(arg1: T1, arg2: T2, arg3: T3): [T3, T2, T1] {
return [arg3, arg2, arg1];
}
제네릭은 축약형으로 넣을 수 있는데 T1이라는 짧은 이름으로도 제네릭 선언이 가능하다.
import { useRouter } from 'next/router';
import { ComponentType, useEffect } from 'react';
// @ts-ignore
export const withAuth =
(Component: ComponentType) =>
// P는 뭔지 모르지만 객체
<P extends {}>(props: P) => {
const router = useRouter();
useEffect(() => {
if (!localStorage.getItem('accessToken')) {
alert('로그인');
router.push('/22-05-login-check');
}
}, []);
return <Component {...props}></Component>;
};
로그인을 확인해주는 withAuth 부분에도 Component에 타입을 주기위해 ComponentType을 넣어주면 된다.
P extends {} 로 P라는 것을 모르지만 아무튼 객체라고 설명할 수 있다.
const handleClickBaskt = (el: IBoard) => () => {
console.log(el);
// 없으면 빈배열 psuh
// 처음에 가져오고 psuh 후 저장
const baskets = JSON.parse(localStorage.getItem('basket') || '[]'); // "문자열"
const temp = baskets.filter((basketEl: IBoard) => basketEl._id === el._id);
if (temp.length === 1) {
// 담겨있다면
alert('이미 담으신 물품입니다.');
return;
}
const { __typename, ...newEl } = el;
baskets.push(newEl);
localStorage.setItem('basket', JSON.stringify(baskets));
};
storage를 응용해서 장바구느를 구현해보면 baskets라는 장바구니에 getItem을 이용해 클릭시
브라우저에 저장해주는 기능을 만들어 주면 된다.
장바구니에 넣었는데 이것을 확인하고 다시 눌르때는 저장할 수 없게 만들기 위해 if문을 이용해주면 된다.
import { useEffect, useState } from 'react';
import { IBoard } from '../../src/commons/types/generated/types';
export default function BasketLoggedInPage() {
const [basketItems, setBasketItems] = useState([]);
// 윈도우가 없다면
// if (typeof window !== 'undefined')
// if (process.browser)
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>
);
}
담긴 장바구니 목록을 불러올려면 getItem을 사용해 장바구니 목록을 불러오면 된다.!!
'etc. > TIL' 카테고리의 다른 글
[TIL] 2022년 02월 17일 - refecth 보다 더 좋은 것 (0) | 2022.02.17 |
---|---|
[TIL] 2022년 02월 16일 - 로그인 Validataion (0) | 2022.02.16 |
[TIL] 2022년 02월 15일 - withAuth와 SessionStorage / Cookie (0) | 2022.02.15 |