-
12. 채팅방 프론트. 로그인보완 (서버사이트 상태저장)MERN Stack ChatApp 2024. 8. 6. 22:01
https://www.youtube.com/watch?v=2JNL2JBgruI&t=3066s
를 보며 만들고 있다.
그런데 이번편에서는 틀은 이 동영상처럼 하지만 안의 내용은 좀 많이 다르게 할 것이다.
왜냐면 나는 react가 아니라 nextjs로 앱을 만들고 있기도 하고,
이 동영상이 나온지가 좀 됬다보니 좀 옛날 것들을 많이 사용하기도 했다. 지금은 거의 쓰이지 않는.
그래서 모양이나 틀은 이것과 비슷하게 갈거지만, 안의 내용은 다르게 만들어보겠다.
먼저 로그인 상태관리를 해주기위해 zustand를 인스톨 해준다.
https://docs.pmnd.rs/zustand/getting-started/introduction
npm install zustand
동영상에서는 context api를 사용해 전역 객체 관리를 해주고 있는데, 나는 zustand를 사용하려 한다.
https://dev.to/shubhamtiwari909/react-context-api-vs-zustand-pki
위 글에서 context API와 zustand를 비교해주고 있는데, zustand가 더 좋다는 느낌을 받았다.
설치했으면 frontend/lib/store/user.ts 파일을 만들어준다.
// lib/store/user.ts import { User } from "@/schema/UserShema"; import { create } from "zustand"; import { persist, createJSONStorage } from "zustand/middleware"; interface UserState { user: User | null; setUser: (user: User | null) => void; } export const useUser = create<UserState>()( persist( (set) => ({ user: null, // default state setUser: (newUser) => set((state) => ({ user: newUser })), }), { name: "userStorage" } ) );
여기서 persist라는 거를 사용하고 있는데, 이는 local storage등 web storage에 유저 정보등을 저장하여 새로고침을 하더라도 상태가 지속되게 하기 위함이다.
https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md
잘 안된다면 서버를 껐다가 다시 켜보기 바란다.
User객체는 예전에 zod를 위한 유효성검사를 하기위해 만들어둔 객체를 활용한다. (없으면 깃헙 참조바람)
이제 로그인 하면 유저 정보를 저장해주자.
// frontend/components/Authentication/Login.tsx "use client"; import { useUser } from "@/lib/store/user"; const Login = () => { const router = useRouter(); const [show, setShow] = useState<boolean>(false); const setUser = useUser((state) => state.setUser); // 요기!!!!! // 폼 제출 const onSubmit = async (values: z.infer<typeof SigninSchema>) => { const result = await signin(values); if (result.error) { toast.error(result.error, { richColors: true, position: "top-center" }); } else { // 로그인 성공 console.log("result : ", result); setUser(result); // 요기!!!! router.push("/chats"); } };
위 코드에서 요기라고 한부분.
간단하게 유저의 정보를 저장했다.
그리고 나서 chats 페이지에서 유저정보가 없다면 로그인하는 페이지로 푸시하도록 useEffect를 사용해서 만들어줬다.
if (!user) {router.push("/");}이런식으로 useEffect안에 만들어줬다.
이제 로그인을 하면 따로 storage를 설정해준 부분이 없으니 디폴트인 localStorage에 저장된다.
로그아웃을 만드는 것도 간단한데,
useUser안에 저장된 user객체를 null로 만들어주면 된다.
그러면 자동으로 localStorage안에 저장되어있던 객체도 null로 바뀜.
그리고나서 router로 첫화면으로 보내던지, 알맞은 처리를 해주면 된다.
그런데 이렇게 하면 클라이언트사이드에서는 localStorage로 상태저장이 잘 되어 토큰등을 잘 사용할 수 있지만,
서버사이드에서는 localStorage에 접근이 불가능하기 때문에 token등의 정보가 없다.
그렇다고 매번 클라이언트 사이드에서 받아와 서버액션등을 부를 때 변수로 넘겨주기도 불편한 일이다.
따라서 이 때, 서버사이드에서도 전역적으로 상태를 관리할 수 있는게 있는데 cookies다.
이름에서 유추할 수 있듯이 쿠키에 상태저장해서 쓰는거다.
https://nextjs.org/docs/app/api-reference/functions/cookies
로그인을 할 때 받아온 토큰을 쿠키에 저장해주고, 토큰이 필요한 정보가 있을때마다 여기서 가져와서 넣어주면 된다.
클라이언트와 서버사이드 쿠키의 차이는 거의 없지만, httpOnly쿠키를 만들었을 때, 클라이언트사이드에서는 접근을 못한다.
Client-side vs. server-side cookies
One question a lot of people ask is if there are any differences between client and server-side cookies.
Cookies can be created from both client and server operations. Server-side cookies refer to cookies typically created and accessed via HTTP headers. Regardless of how you create them, cookies are still stored on the user’s browser and can be accessed directly on the client side.
However, there’s an exception for httpOnly cookies. If you create a cookie with the httpOnly attribute enabled, such cookies cannot be directly accessed via client-side operations, reducing the risk of XSS attacks.
https://blog.logrocket.com/guide-cookies-next-js/
그러니깐 서버에서 받아온 token은 httpOnly쿠키로만 만들어 사용하고, localStorage에도 저장하지 말자.
추가로 chat page를 좀 꾸며줬다.
SearchUser를 하기 위해 서버와 통신하고, 현재 있는 모든 내 채팅도 불러오기를 했다.
좀 많이 지저분한데, 우선 진행하고 나중에 다듬어주는 걸로 하겠다. 계속 세세하게 하려다보니 생각보다 시간이 너무 오래걸린다...
여기서 하나 알았던 점이, 현재 서버액션.ts 내에서 getToken이라는 함수를 만들어서 쓰고 있는데, 이걸 익스포트해서 쓰면 안된다.
const getToken = () => { const cookieStore = cookies(); const token = cookieStore.get(TOKEN)?.value; if (!token) { redirect("/"); // 인증에 필요한 토큰이 없을 경우 다시 로그인하도록 } return token; };
클라이언트에서는 당연히 쓰면 안되고 (서버측에서 쿠키를 불러와서 쓰는 함수기 때문에),
프레임워크 상에서 서버컴포넌트에서도 쓰면 못쓰게 막아놓은것같다.
어쩌면 이건 리다이렉트때문일 수도 있지만.
... 계속 진행해보겠다.
github : https://github.com/Wunhyeon/ChatApp-MERNStack/tree/12.ChatFront_1
'MERN Stack ChatApp' 카테고리의 다른 글
14. Message API (0) 2024.08.14 13. 채팅방 프론트 - 그룹챗 만들기 (0) 2024.08.13 11. 1:1 채팅방 API, 모든 내 대화방 가져오기, 그룹채팅방 만들기, 채팅방 이름 바꾸기 (0) 2024.08.05 10. AuthMiddleware (0) 2024.08.05 9. Find Users API (0) 2024.08.05