ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 3. To-Do 앱 최적화 하기
    React 2023. 5. 2. 17:50

     

     React Hooks란 무엇인가? 
    ReactConf 2018에서 발표된, class없이 state를 사용할 수 있는 새로운 기능.

    - React Hooks의 필요성
    React Component는 Class Component와 Functional Component로 나뉨
    Class Component -> 더 많은 기능 제공, 더 긴 코드 양, 더 복잡한 코드, 더딘 성능
    Functional Component -> 더 적은 기능 제공, 짧은 코드 양, 더 심플한 코드, 더 빠른 성능
    Functional Component를 왜 사용하지 않을까?
    리액트의 생명주기를 사용하지 못하기 때문. (Mounting, Updating, Unmounting)
    => 이런 불편함 때문에 Hooks를 사용한다.
     
    Class Component에서 생명주기를 이용할 때 React Hooks를 이용할 때
    componentDidMount, ComponentDidUpdate, componentWillUnmount
    이렇게 각각의 Class를 만들어야함.
    useEffect 안에서 모두 다 처리 가능

    여러 페이지에 똑같은 기능 사용 필요 -> 똑같은 소스 사용 -> 중복되는 코드 많음
    중복되는 부분은 따로 HOC 컴포넌트를 만들어준다.
    -> 간단해지기는 하나, 너무 많은 Wrapper 발생하여 복잡해짐
    -> Custom React Hooks 이용
    -> Wrapper가 많아지지X (Hooks는 직접 호출해서 사용하기 때문) 
     
    HOC란? (Higher Order Component)
    재사용 가능한 로직 -> component
    재사용 불가능한 부분 -> parameter
    Wrapper 형식으로 사용하는 컴포넌트

     To-Do 앱을 클래스 컴포넌트에서 함수형 컴포넌트로 바꾸기 

    class -> function
    extends (상속) 부분 삭제 -> {component} import 삭제
    render() { return() } -> return() (함수형 컴포넌트는 render 필요X)
    {useState} import 추가 (useState라는 함수로 데이터 선언)

    state = {
        todoData: [],
        value: ""
      }
      
    #데이터 선언 부분 아래와 같이변경 
    
      const [todoData, setTodoData] = useState([]);
      const [value, setValue] = useState("");

     

    정의된 함수 및 메소드 사용 방법 변경
    this. -> 제거
    this.state.todoData -> todoData
    this.state.value -> value

    this.setState({value:""});
    
    #state를 업데이트 해줄 때 아래와 같이 변경
    
    setValue("");

     

    함수 및 변수 정의 방법 변경 

    const let var 등 추가
    handleClick -> const HandleClick


     state와 props 
    State Props
    해당 컴포넌트 내부에서 데이터 전달위해
    State으로 전달

    State가 변하면 re-render된다.
    상속하는 부모 컴포넌트로부터
    자식 컴포넌트에 데이터 등을 전달

    읽기전용으로, 자식 컴포넌트 입장에서는 변하지 않음.
    state = { a: "a" }
    this.state.a
    state = { a: "a" }
    <b컴포넌트 aprops = {this.state.a} >

     할 일 목록 부분을 위한 컴포넌트 생성하기(컴포넌트 분리하기) 

    컴포넌트 분리하는 이유

    : 재사용성 좋아짐, 코드가 짧아져 가독성 좋아짐


    리스트 컴포넌트 생성
    1. components 폴더 -> Lists.js 생성
    2. UI 부분 가져오기 -> return () 안에 List 관련 UI -> btnStyle
    3. 필요한 State, 함수 가져오기
    -> HandleCompleChange
    -> getStyle
    -> HandleClick
    4. List 컴포넌트에 Props 내려주기
    5. Props로 필요한 데이터 함수 가져오기


     구조 분해 할당(Destructuring) 

    구조 분해 할당이란?
    : 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담는 것
    -> 좀 더 깔끔한 코드를 위해 


     Form 부분을 위한 컴포넌트 생성하기 

    Form 컴포넌트 생성
    1. components 폴더 - > Form.js
    2. UI 부분 가져오기 -> 할 일 입력 부분
    3. 필요한 함수 가져오기 -> HandleChange
    4. Form 컴포넌트에 Props 내려주기
    5. Props로 필요한 데이터 함수 가져오기


     TailWindCss소개 

     

    TailWindCSS란?
    : HTML 안에서 CSS 스타일을 만들 수 있게 해주는 CSS 프레임 워크

    CSS 프레임 워크란?
    : 레이아웃 및 여러 컴포넌트 구성, 브라우저 호환성을 보장하는데 소요되는 시간을 최소화하기 위해 여러 웹 개발/디자인 프로젝트에 적용할 수 있는 CSS 파일 모음
    -> 빠르게 애플리케이션을 스타일링 하는데 도움을 준다.

    Tailwind CSS의 장점
    : 부트스트랩과 비슷하게 m-1, flex와 같이 미리 세팅된 Utility Class를 활용하는 방식으로 HTML 에서 스타일링을 할 수 있다.
    -> 빠른 스타일링 작업 가능
    -> class 혹은 id명 작성하기 위한 고생을 안해도 됨
    -> 유틸리티 클래스가 익숙해지는 시간이 필요할 수 있으나, intelliSense 플러그인이 제공돼서 금방 익숙해질 수 있다.

    tailwindcss.com 방문 후 자세히 살펴보기

    npm install -D tailwindcss postcss autoprefixer -> 해당 명령어로 설치
    npx tailwindcss init -> tailwindcss 적용

    tailwind.config.js 파일에
    "./src/**/*.{.js,jsx,ts,txt}" (경로) 추가

    App.css 파일에
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    추가


     TailWindCss로 Todo 앱 스타일링 해주기 

    원래 스타일링 지우기
    -> btnStyle

    -> app.css  

    -> getStyle

    -> Form.js

    -> Inline style


    원래 스타일링 className에 TailwindCSS 적용


     Drag and Drop 기능 추가하기 

     

    Drag and Drop 기능 구현
    -> 사용자가 드래그를 할 때 적절한 애니메이션 주기
    -> 드래그 멈췄는지 확인하고 애니메이션 주기
    -> 목록 재정렬한 경우 항목의 위치 새 항목으로 업데이트

    필요 모듈 설치하기
    npm install react-beautiful-dnd --save -> 해당 명령어로 설치


    DragDropContext : 드래그하고 드랍하기를 원하는 부분 감싸주기
    Droppable : 드랍할 수 있는 공간
    Draggble : 드래그 할 수 있는 부분

    provided object에는 스타일 지정 및 조회를 위한 속성이 포함되어 있다.
    요소를 드래그하면 className 속성을 selected로 변경한다. (드래그시 스타일을 변경하는데 사용)
    placeholder 속성은 목록에 빈 공간을 만든다. (드래그 시 그 부분이 비어있도록. 드래그 작업이 자연스럽게 느껴진다.)


     리액트 불변성 지키기 

    자바스크립트 타입을 통한 불변성 의미 살펴보기
    원시 타입은 불변성을 가지고 있고 참조타입은 그렇지 않다
    원시 타입 -> 고정된 크기로 Call Stack 메모리에 저장, 실제 데이터가 변수에 할당
    참조 타입 -> 데이터 크기가 정해지지 않음, 데이터의 값이 heap에 저장되며 변수에는 heap 메모리의 주소값이 할당
     => 배열에 대한 요소를 추가하거나 객체 속성 값을 변경할 때 Call Stack의 참조ID는 동일하게 유지되고 heap 메모리에서는 변경된다. (즉, 불변성 유지X)

    불변성을 지켜야하는 이유?
    : 참조 타입에서 객체나 배열의 값이 변할 때 원본 데이터가 변경되기에 이 원본 데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있다. (프로그래밍이 복잡해진다)
    => 리액트에서 화면을 업데이트할 때 불변성을 지켜서 값을 이전 값과 비교해서 변경된 사항을 확인한 후 업데이트하기 때문에 불변성을 지켜줘야 한다.

    불변성을 지키는 앙법?
    참조 타입에서는 값을 바꿨을 때 주소 값은 같은데 메모리 값만 바꿔준다
    -> 새로운 배열을 반환하는 메소드를 사용하면 된다.
    -> spread opreator, map, filterm slice, reduce
    -> 원본 데이터를 변경하는 메소드는 splice, push 


     List 컴포넌트 생성하기 

    List 컴포넌트 생성
    1. List.js 파일 생성 -> rafce (함수형 컴포넌트 생성)
    2. UI 부분 List 컴포넌트로 이동
    3. 필요한 함수 이동
    4. Lists 컴포넌트에서 List 컴포넌트 import 및 props 내려주기
    -> data. 제거 (props로 받았기 때문에 이름 그대로 사용하면 됨)


     React.memo 를 이용한 렌더링 최적화 

    현재 Todo 앱의 문제
    : 한 컴포넌트만 렌더링되어야하는데, 한 컴포넌트가 리렌더링되면 다른 컴포넌트들도 렌더링 되고 있음.
    -> 최적화 필요
    -> React.memo 적용
    => List.js 와 Lists.js에 React.memo 적용 (원하는 부분 감싸주기)


     useCallback 을 이용한 함수 최적화 

    똑같은 함수를 컴포넌트가 렌더링된다고 해서 계속 다시 만드는 것은 좋은 현상이 아니다.
    이 함수가 자식 컴포넌트에 props 내려준다면, 이 함수뿐만 아니라 자식 컴포넌트도 새롭게 만들어질 것.
    => React.useCallback 적용으로 문제 해결


    useCallback 안에 콜백함수와 의존성 배열을 순서대로 넣는다.
    함수 내에 참조하는 state, props가 있다면 의존성 배열에 추가한다.
    todoData가 변하지 않는다면, 함수는 새로 생성되지 않는다. (의존성 배열에 의해 Callback 된다.)


    의존성 배열에 아무것도 없다면 컴포넌트가 최초 렌더링 시에만 함수가 생성되며 그 이후에는 동일한 참조 값을 사용하는 함수가 된다. (의존성 배열이 변하지 않기 때문에)


     useMemo를 이용한 결과 값 최적화 

    Memoization 이란?
    : 비용이 많이 드는 함수 호출의 결과를 저장, 동일한 입력이 다시 발생할 때 캐시된 결과를 반환하여 컴퓨터 프로그램의 속도를 높이는데 주로 사용되는 최적화 기술

    컴포넌트 내의 compute 함수가 만약 복잡한 연산을 수행하면 결과값을 리턴하는데 오랜 시간이 걸리게 된다.
    -> 이때 컴포넌트가 리렌더링된다면 오랜시간이 걸릴 것. (성능다운, UI 지연 현상 발생)
    => useMemo 사용. (결과값이 이전과 동일하다면 다시 연산하지 않고 전에 저장해두었던 값을 재사용)


     리액트 확장 프로그램 추가하기 

    크롬 확장프로그램에서 추가 (React Developer Tools)


    components 탭에서 highlight updates 부분 체크
    -> 컴포넌트 렌더링 되는 것 쉽게 확인 가능


     할 일 리스트 모두 지우기 버튼 생성 

    할일 리스트 모두 지우기 버튼 생성
    -> handleRemoveClick


     할 일 목록을 수정하는 기능 추가하기 

    edit이라는 버튼 생성 (할 일 목록 수정하는 버튼)
    1. 다른 UI 제공을 위한 state 생성
    2. edit 버튼 추가, 클릭시 isEditing state 변경
    3. 조건에 따른 UI 렌더링
    4. editing 입력할 때 editedTitle State 변경
    5. editing 입력 후 save


     localStorage에 todoData 값 담기 

    localStorage에 todoData 담기
    : 페이지를 refresh해도 todoData가 계속 남아있을 수 있게 해준다.


    1. setTododata를 이용해서 todoDatastate를 바꿔줄때 localStorage에도 같이 바꿔주기
    2. JSON.stringfy를 이용해 텍스트로 변환해준 후에 저장해준다.
    3. JSON.parse로 가져오기

     

     

     

     

Designed by Tistory.