240614 TIL_개인 프로젝트4 (인증 서비스가 들어간 개인 가계부 제작) 종료, React 강의 ( zustand | debouncing | throttling| tailwind | 반응형 웹)

미밍·2024년 6월 13일
2

우당탕탕 개발 일기

목록 보기
57/108

240610 ~ 240614 프로젝트 종료!

회고록은 어제 썼다~!

React

zustand

전역 상태 관리

zustand 특징

  1. 간결함
  2. 성능 최적화

zustand 설치 방법

yarn add zustand

zustand 사용 방법

  1. store 세팅
    1-1. bearsStore.js 파일 생성
//beatsStore.js create 임포트 필요
//화살표 함수 예제

const @@BeatsStore = create((set) => ({
    bears: 0,
    increase: () => set((state) => ({
        bears: state.bears + 1
    })),
    init: () => set({
        bears: 0
    })
}));
//beatsStore.js create 임포트 필요
//함수 표현식 예제

const @@BeatsStore = create(function(set) {
    return {
        bears: 0,
        increase: function() {
            set(function(state) {
                return {
                    bears: state.bears + 1
                };
            });
        },
        init: function() {
            set({
                bears: 0
            });
        }
    };
});
  1. 필요한 곳에 쓰기

const {bears} = useBearsStore((state)=>state)
const increase = useBearsStore((state)=>state.increase)

const {bears, increase, init} = useBearsStore((state)=>state)

이렇게도 쓸 수 있다~

zustand 사용시 주의점

immer 라이브러리가 안 깔려있다.

불변성

불변성을 어기는 행위 (= 직접 객체나 배열을 수정하여 값이 "변하는" 행위)
1. 배열에 그대로 푸시
2. 객체를 그대로 수정

인간 관점으로는 객체, 배열이 변했지만 쥬스탠드(=컴퓨터)는 이와 같은 행동은 값 변경을 인지하지 못한다. 컴퓨터는 얘가 변하든지 말든지 똑같은 주소에 참조되어있으니까 상관하지 않는다~!

+) 리액트에서 불변성 (= 변하지 않음) 을 유지
불변성을 유지한다. 화면이 바뀐다.
이 사이에는 연결 고리가 있다.
컴퓨터에게 얘 달라졌어요 하고 신호를 줘야 한다.

변하지 않음을 유지하되, 화면을 바뀌게 하기 위해서는 주소값을 다르게 할 필요가 있다. => 그래서 새로운 객체 배열을 복사 (=주소 값 다르게) 해서 사용하는 것.

불변성 유지라고는 하지만 실제로는 복사하고 주소값 바뀌고 한다...

zustand 에서 불변성 유지하는 법

  1. 이머 라이브러리 설치

yarn add immer

  1. immer로 감싸기
//@@store.js
import create from 'zustand'
import { immer } from 'zustand/middleware/immer';

const @@BeatsStore = create(immer((set) => ({
    bears: 0,
    increase: () => set((state) => ({
        //불변성 어기는 예시 어쩌고 직접 푸쉬
    })),
    init: () => set({
        //불변성 어기는 예시 어쩌고 객체 속성 직접 수정
    })
})));

zustand vs RTK

zustand?
장점 빠르고 설정이 쉽다
단점 상태가 커지면 관리하기 어렵다

RTK?
장점 대규모 어플 관리 가능
단점 설정이 복잡하다.

persist

새로고침하면 사라짐!
그래서, 로컬 스토리지, 세션 스토리지 이용하여 저장해야 할 경우

//@@store.js
import create from 'zustand'
import { immer } from 'zustand/middleware/immer';
import {persist } from 'zustand/middleware'

const @@BeatsStore = create(persist(immer((set) => ({
    bears: 0,
    increase: () => set((state) => ({
        //불변성 어기는 예시 어쩌고 직접 푸쉬
    })),
    init: () => set({
        //불변성 어기는 예시 어쩌고 객체 속성 직접 수정
    })),
    {
    name : "어쩌고이름"
    // getStorage: () => sesstionStorage 세션에서 저장하고 싶을시
    }
})));

UX 향상 기법

Throttling

? 연속해서 발생한 이벤트를 일정 시간 단위로 그룹하여 처음 혹은 마지막 이벤트 핸들러만 호출 (*10초에 12903109328119번 눌러도 시간에 따라 몇 번만 되게 한다.)
주로 무한 스크롤에서 사용됨

Throttling 타입

  • Leading Edge
    ? 이벤트가 처음 발생한 후 주어진 시간 동안은 이벤트가 무시된다.
    e.g.스크롤을 시작할 때 API 호출, 일정 시간동안 추가 호출을 무시

    		↕️ 반대 개념! ↕️
  • Trailing Edge
    ? 이벤트가 반복적으로 실행될 때, 주어진 시간이 지나면 마지막 이벤트를 처리한다.
    e.g. 입력 필드에 타이핑을 멈춘 후 일정 시간이 지나야 서버에 검색 요청이 전송

    		= 합친 개념!
  • Leading & Trailing Edge
    ? 주어진 시간에 대해 이벤트가 처음 발생할 때 핸들러 실행, 주어진 시간이 지나면 마지막 이벤트도 처리
    e.g. 버튼을 여러번 클릭했을 때, 최초에 api 호출 + 주어진 시간의 마지막 이벤트에도 api 호출

Debouncing

? 짧은 시간 간격으로 연속해서 이벤트가 발생하면 이벤트 핸들러를 호출하지 않다가, 마지막 이벤트로부터 일정 시간이 경과한 후 한 번만 호출
e.g 입력값 실시간 검색, 화면 resize 이벤트

  • useState로 인풋창 제어하고 있을 경우 useCallback 사용해서 한 번에 완료되게 하기

메모리 누수

throttling, debouncing은 setTimeout을 주로 사용한다. 이 함수로 인하여 메모리 누수 가능성이 있긴 하다!
함수가 끝나기 전에 다른 페이지로 이동한다면 메모리 누수 관련 처리를 해줘야 한다!
useEffect + 클린업 함수를 사용하기

e.g.

useEffect(()=> {
	return () => {
    	if (@@) {
        	clearTimeout(@@)
        }
    }
})

lodash 활용

? 유틸리티 라이브러리로, 배열, 객체, 문자열 등 데이터 조작을 쉽게 할 수 있는 다양한 함수를 제공!
=> throttle, debounce 함수도 포함

yarn add lodash

import _ form "lodash"

_.throttle(()=> 로직, 시간)
_.debounce(()=> 로직, 시간)

tailwind

classname= "여기서 바로 쓰는 거"
마음에 든다 짱이다!!

tailwind 사용법

  1. 패키지 다운

yarn add tailwindcss postcss autoprefixer

npx tailwindcss init -p

  1. tailwind.config 파일이 생겼을 텐데, 거기서 컨텐츠 부분 설정
//tailwind.config

module.exports = {
  content: [
    './index.html',
    './src/**/*.{js,jsx,ts,tsx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  1. index.css 에 아래 세 줄 추가
//index.css

@tailwind base;
@tailwind components;
@tailwind utilities;

이제 한 번 껐다 키고, (*config 설정 했으므로)
이제 스타일 주고 싶은 곳에 가서!!

  1. className= " 여기에 직접 적용~! "
    안의 값은 공식문서 뒤지면서 알아 보면 된다.

테일윈드공식문서

e.g.
<div className="flex justify-between items-center"> 안녕</div>

얼른 익숙해지기로 한다.

반응형 웹

? 다양한 기기에서 인터넷을 할 때 화면이 자동으로 편안하게 바뀌는 것

반응형 웹 장점

사이트를 만들 때 모든 디바이스에 대응하는 사이트를 따로 만들지 않아도 된다.

반응형 웹 사용방법

미디어쿼리 사용

e.g.

.container {
	padding : 20px;
}

@media (max-width:768px) {
	.container {
    	padding : 10px;
    }
}

=> 너비 768px 까지는 패딩은 10px만...

styled-components 사용

e.g.

const container = styled.div`
	padding :20px;
    
    @media (max-width:768px) {
    	padding : 10px;
    }
`

react-responsive 라이브러리 사용

e.g
// SampleComponent.jsx

import React from 'react';
import { useMediaQuery } from 'react-responsive';

const SampleComponent = () => {
  const isMobile = useMediaQuery({ query: '(max-width: 768px)' });

  return (
    <div style={{ padding: isMobile ? '10px' : '20px' }}>
      반응형 웹
    </div>
  );
}

export default SampleComponent;

Tailwind 사용

테일윈드공식문서_반응형디자인

테일윈드공식문서_테마활용

테일윈드공식문서_스크린사이즈지정

e.g 예제 
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      'sm': '640px',
      // => @media (min-width: 640px) { ... }

      'md': '768px',
      // => @media (min-width: 768px) { ... }

      'lg': '1024px',
      // => @media (min-width: 1024px) { ... }

      'xl': '1280px',
      // => @media (min-width: 1280px) { ... }

      '2xl': '1536px',
      // => @media (min-width: 1536px) { ... }
    }
  }
}

하단의 주석과 같은 뜻임!

실제 적용

e.g.

<div>
	<span className="block md:hidden lg:hidden">모바일 환경</span>
    <span className="hidden md:block lg:hidden">테블릿 환경</span>
    <span className="hidden lg:block">데스크탑 환경</span>
</div>

적응형 웹

? 미리 정해진 화면 크기에 맞게 웹사이트를 만드는 것

적응형 웹 장점

각 기기마다 디자인을 다르게 만들 수 있음


개인 과제

오늘 잡은 버그에 대해서 몇 가지

  1. user 정보 관리
    마이페이지에서 프로필 사진 수정 안 하고 닉네임만 수정했을 때 프로필 사진이 날라가고 디폴트 이미지로 업데이트
    => 리덕스 세팅 다시 해줌

  2. 글리치 서버 오류
    무한 로딩에 걸림
    패치에도 안 뜸
    이유? 테스트용으로 몇 개 넣어놨는데 삭제하다가 ] 와 , 등등 빼먹었다! 서버 로그도 잘 확인하기~!

  3. 마이페이지에서 새로 고침 시 오류
    초기 유저 세팅이 null일 경우 불러오지 못하는 거라 useEffect로 다시 초기 세팅

useEffect(() => {
    if (!isAuthenticated) {
      Swal.fire({
        title: "로그인 후에 이용해주세요.",
        text: "로그인 페이지로 이동합니다.",
      });
      navigate("/login");
    } else {
      if (user) {
        dispatch(setUser(user));
      }
    }
  }, [isAuthenticated, dispatch]);

+)
TODO 하고 싶은 거

1. 버셀 배포 페이지에서 새로 고침 하면 안 되는 오류
2. 페이지 나가면 자동으로 로그아웃되는 기능
3. 토큰 만료 되면 로그아웃 되게 설정
4. 랜더링 늦어서 user 정보 안 나오는 거 이유 찾기
5. 마이페이지에서 사진 안 바꾸면 기본 이미지 됐다가 -> 새로 고침하면 다시 원래 이미지로 바뀌는 이유 ?

빈 배열이다가 갑자기 됨... 후...^^ 느리잖아요

+ 이전 유저 정보 남아있음~~

근데 굉장히 힘들었나보다! 😂

수정 후

 useEffect(() => {
    const getUserInfo = async () => {
      const token = localStorage.getItem("accessToken");
      if (token) {
        try {
          const { data } = await axios.get(
            "https://moneyfulpublicpolicy.co.kr/user",
            {
              headers: {
                Authorization: `Bearer ${token}`,
              },
            }
          );
          dispatch(setUser(data));
        } catch (error) {
          console.log(error);
        }
      }
    };

    getUserInfo();
  }, [dispatch, token]);

유저 정보 담는 부분에 의존성 배열에 token 추가 하니까 됐다~!

새벽 1시 50분.......... 오류 고치기 좋은 시간^-^~! 뭔가뭔가 하나만 고치고 가려다가 시간이 생각보다 더 흘러가버렸다. 허리가 뽀개질 거 같다


(과제 제출 후)

  1. 쥬스탠드, 테일윈드, 반응형 강의 보기
  2. 해설 영상 보기

배포하고 문제 생겨서 와다다다다 커밋 푸쉬했다. 근데 잡고 나니 즐겁다^-^ 그래서 룰루랄라 기능 하나 더 넣었다. 오류... 🥹 는 안 났다... 다행...

profile
프론트앤드; Frontend

0개의 댓글