프론트 입장에서 로그인이 된 것의 여부를 알려면?
이때 로그인 정보를 state에 저장하게되면 한가지 컴포넌트에서만 로그인 여부를 알 수 있게 되므로
여러 컴포넌트에서 로그인된 데이터를 사용해줘야 하므로 리덕스로 관리해줄 필요성이 생긴다.
다만 리덕스를 사용하지 않고,
- Context API
- SWR
를 사용하여 전역적으로 상태 관리를 할 수 있다.
---
리액트로 비동기 통신을 다루기 위해 redux-saga, useSWR, react-query 등이 있는데..
리덕스의 경우 하나의 액션을 작성하는데 많은 부가적 코드가 필요하므로
SWR 설정하기
주로 GET 요청을 저장하기 위해 사용 (POST 도 가능은 함)
다만 로그인은 POST 요청이므로 POST 이후에 GET 요청을 또 보내줄 필요가 있음
npm i swr 로 설치 (next.js와 연동이 잘댐)
import useSWR from 'swr';
const {} = useSWR('주소', fetcher);
주소를 fetcher 함수에 넘겨주는 기능을 해주는 useSWR 훅
fetcher는 새로 만들어줘야 하는데
import axios from 'axios';
const fetcher = (url:string) => {
axios.get(url , {
withCredentials : true,
})
.then((res) => res.data)
.catch((err) =>
err.data
);
}
export default fetcher;
fetcher 함수는 결국 받은 주소로 axios 처리를 하여 then 안의 res.data 를 useSWR 에 리턴해준다.
const {data, error} = useSWR('http://localhost:3095/api/users', fetcher);
그리고 useSWR 의 두번째 비구조화 할당으로는 error 값이 들어가게 된다.
SWR 을 사용하면 컴포넌트는 지속적으로 자동으로 업데이트 스트림을 받게 되어 실시간 업데이트가 되는 것이다.
axios.get 의 두번째 파라미터 / axios.post의 세번째 파라미터에 서로 주소가 다른 백/프론트 사이에서
쿠키를 전달 받기 위해선 { withCredentials : true } 옵션이 추가 되어야 한다.
쿠키는 백에서 생성하지만 프론트에선 쿠키를 보내주는? 개념인 것
로그인 구현하기!!
const onSubmit = useCallback((e) => {
e.preventDefault();
setLogInError(false);
axios.post('/api/users/login', {
email, password
}, {
withCredentials:true,
}).then((res) => {
})
.catch((err) => {
setLogInError(err.response?.data?.statusCode === 401);
});
}, [email, password]);
POST 로 '/api/users/login' 주소에 요청을 보내준다.
정상적으로 로그인이 실행되면, 재 로그인을 시도할 시 당연히 에러가 발생할텐데
로그아웃처리가 안되었기 때문이다.
이때 백엔드 서버를 껐다키는 것이 제일 확실하지만 그러지 못하는 경우,
개발자도구 어플리케이션 탭의 쿠키 중,

connect.sid (세션쿠키명 -> express 의 경우, 다른 이름일 수도 있음) 를 제거해주면 로그아웃처리가 된다.
즉, 세션쿠키를 삭제해주면 로그아웃이 되는 것임!
로그인 완료 후?
채팅 페이지로 넘어가기 위한 SWR 을 호출하기!
내가 원할 때 SWR 호출하려면?
revalidate() 호출하기 ---> mutate() 로 바뀌었음!
const {data, error, mutate} = useSWR('http://localhost:3095/api/users', fetcher, {
dedupingInterval: 100000,
});
const onSubmit = useCallback((e) => {
e.preventDefault();
setLogInError(false);
axios.post('/api/users/login', {
email, password
}, {
withCredentials:true,
}).then(() => {
mutate();
})
.catch((err) => {
setLogInError(err.response?.data?.statusCode === 401);
});
}, [email, password]);
로그인이 성공하면 mutate 에 의해 SWR 의 fetcher가 실행된다.
주기적으로 호출은 되는게 default 지만, 추가해준 옵션 dedupingInterval 기간 내에선 캐시를 불러오게 되는 것이다! (최적화)
즉, dedupingInterval 기간 이후엔 최초 1번에 의해 데이터를 불러오게 되고 기간 안에는 캐시에 의해 저장된 데이터를 불러오게 됨!
revalidate? mutate?
서버 데이터를 변경하고 변경된 데이터를 로컬 캐시에 반영하는 함수
api 요청 후 새로운 데이터를 서버에 보낸 뒤 해당 데이터를 받아와 화면에 반영하는 경우 사용된다.
그러므로 클라이언트 측에서 서버 데이터를 변경해주고 해당 변경 사항을 즉시 반영하기 위해 사용되는 것임
다만 revalidate 의 경우는, 서버에 요청을 다시 보내서 정보를 받아오지만
mutate 는 서버에 요청을 다시 보내는 것이 아닌 캐시로 저장된 정보를 받아올 수 있음
optimistic UI 란? <-> passimistic UI (기본)
mutate 라는 기능으로 2번째 파라미터(shouldRevalidate)에 true 로 지정해주면 서버로부터 요청을 보내기도 전부터 변경 사항을 처리해버려서 사용자 경험을 높여줄 수 있다고 한다. (즉각적 반영)
전역 mutate 의 경우는 key 값(api주소)을 첫번째 파라미터에 꼭 넣어줘야하지만
지역 mutate 의 경우는(함수형 컴포넌트 안에 useSWR로 선언해주는 경우) key 값을 이미 SWR에서 지정해주므로 key를 넣어주지 않아도 되는 것임.
Gravatar
랜덤으로 프로필 이미지를 만들어주는 패키지
npm i gravatar
npm i @types/gravatar
*** 패키지에 타입스크립트를 따로 받아야 하는지 아닌지 확인하는 방법
npm 홈페이지에 들어가서 패키지를 검색한 뒤, 패키지명 옆에 TS 인지 DT 인지 확인해주기
둘다 없다면 직접 패키지용 타입을 만들게 될 수도 있으니...(중략)
TS의 경우는 @types/패키지명 으로 따로 받아줄 필요가 없는 것이며
DT의 경우 @types/패키지명으로 따로 받아줘야 한다. (물론 받아준다고 해도 패키지와 타입스크립트 패키지가 종종 서로 타입이 다르면 만들어줄 수도 있다..)
<ProfileImg src={gravatar.url(data.email, { s: '28px', d: 'retro'})} alt={data.nickname} />
프로필 이미지는 그라바타를 사용하여 src에 gravatar.url(문자열, { 옵션들, s:크기, d :디자인, }) 를 넣어줘서 랜덤 프로필을 줄 수 있다.
리액트에서 레이아웃 가지는 방법
1. App 에서 중첩되는 주소로 Route 처리해주고, layout 관련 컴포넌트로 컨텐츠를 감싸주기 + {children} 으로 써주면 됨
2. 해당 컨텐츠를 감싸주는 layout 컴포넌트를 App에 라우터처리 하고 layout 컴포넌트 안에 Switch-Route 처리 해주기 (중첩 라우터)
-> 주소가 계층적일 때 사용해주면 좋음
<Chats>
<Switch>
<Route path='/workspace/channel' component={Channel} />
<Route path='/workspace/dm' component={DirectMessage} />
</Switch>
</Chats>
'Web Study > Slack 클론 코딩' 카테고리의 다른 글
슬랙 클론 코딩 - 1 (0) | 2023.04.21 |
---|