CEOS 2주차

·2024년 9월 19일
post-thumbnail

🌞 1. Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요?

☀️ 라이브러리 VS 프레임워크

라이브러리와 프레임워크의 가장 큰 차이점은 애플리케이션의 제어 흐름을
누가 가지고 있는가에 있다

🌝 라이브러리

제어권이 개발자에게 있다
👉 애플리케이션 개발에서 단순 활용이 가능한 도구들의 집합으로, 자주 사용되는 기능들을 객체나 함수 등의 라이브러리 형태로 만들어 놓아, 나중에 필요할 때마다 해당 기능을 호출하여 사용한다. 목적을 위한 하나의 도구를 제공받는 것으로 우리가 원하는 내용을 선택할 수 있지만, 다른 도구들은 스스로 선택해서 조합해야 한다.

🌝 프레임워크

제어권이 프레임워크에 있다
👉 만들어진 뼈대에 비즈니스 로직만 넣어줌으로써 원하는 기능 구현에만 집중할 수 있도록 필요한 기본 구조와 구성을 모두 포함하고 있다. 따라서 모든 환경과 도구를 제공해주는 대신 그것들만 사용해야 한다.

☀️ SPA

Single Page Application
👉 단 한 개의 페이지만으로 구성되며, 모든 정적 리소스를 최초 단 한번만 다운로드하여 렌더링, 페이지 갱신에 필요한 데이터만을 내려받아 리렌더링한다.

🌝 SPA 특징

  1. 초기 구동 속도가 느리다.
  2. 리로딩이 발생하지 않아 플래시 현상이 나타나지 않는다. (전체적인 트래픽 감소 및 렌더링에서 효율, 빠른 화면 이동)
  3. 어플리케이션을 로드할 때 빈 HTML을 로드 -> Component에 작성한 React HTML을 밀어 넣어준다.
  4. 검색엔진 최적화 (SEO)에 불리하다.
  5. 데이터 처리를 클라이언트에서 하는 경우가 많아, 코드가 외부에 노출되어 보안적인 문제가 생길 수 있다.

🌝 초기 렌더링

맨 처음 사용자에게 어떻게 보일지를 정하는 것으로, 컴포넌트가 어떻게 생겼는지를 정의하는 역할로 render() 함수가 역할을 한다.
즉, 뷰가 어떻게 생겼고 어떻게 작동하는지에 대한 정보를 지닌 객체를 반환하는 것

🌝 조화 과정

React에서 View를 업데이트 한다 ===> Reconcilitaion(조화) 과정을 거친다
즉, 컴포넌트에서 데이터 변화가 있을 때 View가 변경되는 것이 아닌 새로운 요소로 갈아끼우는 과정이기 때문이다
이때 과정은
1. 데이터 업데이트
2. 새로운 데이터로 render 재호출
3. 해당 데이터 지닌 뷰를 새로 생성
4. 이전의 render함수가 만들었던 컴포넌트 정보와 비교
5. 두 가지 뷰의 차이를 최소한의 연산으로 DOM 트리 업데이트

☀️ Virtual DOM

브라우저에 실제로 보여주는 DOM이 아닌 메모리에 가상으로 존재하는 DOM
Javascript 객체 👉 작동 성능이 실제 DOM을 보여주는 것보다 빠르다
업데이트가 되면 필요한 곳의 UI를 Virtual DOM을 통해 렌더링한다 👉 차이가 있는 곳 감지하여 실제 DOM에 패치

🌝 DOM의 문제점

동적 UI에 최적화되어 있지 않다
👉 각 데이터를 표현하는 요소의 수가 많아질수록 DOM에 직접 접근하여 변화를 주게 되면 웹페이지 속도가 점차 느려질 것

DOM 자체를 읽고 쓸 때의 성능은 빠르다
👉 단, 웹 브라우저 단에서 변화가 일어나면 CSS 재연산 + 레이아웃 구성 + 페이지 리페인트 과정의 시간이 추가

🌝 리렌더링 방식

  1. 상태(state) 업데이트
  2. 변경 사항이 모두 적용된 전체 UI를 새로운 Virtual DOM에 렌더링
  3. 이전 버전의 Virtual DOM과 새로 생성된 Virtual DOM 비교
  4. 차이점이 있는 부분을 실제 Browser DOM에 적용

🌞 2. React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 리액트 렌더링 최적화에 대해 설명해주세요. 다른 방식이 있다면 이에 대한 소개도 좋습니다.

☀️ Rerendering

변경된 부분을 업데이트하여 화면을 보여준다

🌝 리렌더링 조건

  1. 자신이 전달받은 props가 변경될 때
  2. 자신의 state가 바뀔 때
  3. 부모 컴포넌트가 리렌더링 될 때
  4. forceUpdate 함수가 실행될 때 (강제 리렌더링)

🌝 state

변화를 감지하여 화면에 영향을 주기 위해서 사용
state를 직접 조작하는 것이 아닌 setter 함수를 이용하여 state를 변경해야 한다.

🌝 React.memo()

Memoization 기법으로 동작하며, 고차 컴포넌트(HOC)이다.
컴포넌트가 props로 동일한 결과를 렌더링하면, React.memo를 호출하고 결과를 메모이징(Memoization) 하도록 래핑하여 경우에 따라 성능 향상을 할 수 있다.
즉, 마지막으로 렌더링된 결과를 재사용하는 것.

props 변화에만 영향을 주므로 함수 컴포넌트 안에서 구현한 state, context가 변할 때에는 재렌더링된다.
따라서, props가 갖는 복잡한 객체에 대하여 얕은 비교만을 수행하는 것이 기본적인 동작이다.

☀️ Hooks

함수 컴포넌트에서 React state와 생명주기 기능을 연동할 수 있게 해주는 함수로 class 없이 상태 관리가 가능하다.

☀️ 최적화 관련 Hooks

🌝 useMemo

특정 값이 바뀌었을 때만 연산을 실행하고, 원하는 값이 바뀌지 않았다면 이전에 연산했던 겨로가를 다시 사용하는 방식
-> memo는 memoization으로, 메모리에 넣기라는 의미를 가지고 있다.

const value = useMemo(() => {
  ...
}, [deps])

🌈 연산 최적화

컴퓨터 프로그램이 동일한 계산을 반복해야 할 때 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술

🌝 useCallback

리렌더링될 때마다 새로 만들어진 함수를 사용하지 않도록 최초 렌더링 또는 이후 특정값 업데이트가 있을 때에만 함수를 새로 생성

const value = useCallback(() => {
  ...
}, [deps])

🌞 3. React 컴포넌트 생명주기에 대해서 설명해주세요.

☀️ 라이프 사이클 (생명주기)

마운트: DOM이 생성되고 웹 브라우저 상에 나타나는 것
업데이트: 아래의 네 가지 경우에 업데이트가 일어남
=> props변화, state 변화, 부모 컴포넌트 리렌더링, 강제 리렌더링 트리거
언마운트: 컴포넌트를 DOM에서 제거하는 것

🌝 라이프 사이클 메서드

render(), constructor, getDerivedStateFromProps, componentDidMount, shouldComponentUpdate, getSnapshotBeforeUpdate, componentDidUpdate, componentWillUnmount, componentDidCatch

will 접두사: 어떤 작업을 작동하기 전에 실행
Did 접두사: 어떤 작업을 작동한 후에 실행

componentDidMount: 컴포넌트가 첫 렌더링을 다 마친 후 실행
componentDidUpdate: 리렌더링(업데이트)을 완료한 후 실행
componentWillUnmount : 컴포넌트가 웹 브라우저상에서 사라지기 전에 실행

☀️ 생태 주기 관련 Hooks

🌝 useEffect

리액트 컴포넌트가 렌더링되고 난 직후 특정 작업을 수행할 수 있도록 설정하는 hook (componentDidMount + componentDidUpdate)

useEffect(() => {
  ...effect함수
}, [deps])

effect 함수: 실행하고자 하는 콜백함수
deps: 의존성 배열, function을 실행시킬 조건,
=> 빈 배열: 처음 컴포넌트가 mount될 때만 수행,
=> deps가 있을 때: 특정 state, 컴포넌트가 리렌더링(update) + mount될 때

🌈 useEffect -> cleanUp

parameter로 넣은 effect 함수의 return 함수
unMount 전이나 업데이트 되기 직전에 어떠한 작업을 수행

useEffect(() => {
    // mount 시점, deps update 시점에 실행할 작업
    return () => {
      //unmount 시점, deps update 직전에 실행할 작업
    };
  }, [deps]);

4. 과제 코드 issue log

localStorage

localStorage 관련

처음에 zustand를 활용해서 localStorage에 저장하도록 했는데, persist 만 쓰면 되어서 매우 쉬웠으나,,,, zustand를 쓰면 안된다는 걸 제출 직전에 알아버려서 부랴부랴 바꾸었습니다.

  const [todoList, setTodoList] = useState(() => {
    const savedList = localStorage.getItem("todoList");
    return savedList ? JSON.parse(savedList) : [];
  });

  useEffect(() => {
    localStorage.setItem("todoList", JSON.stringify(todoList));
  }, [todoList]);
  1. local에 저장해야 하는 todoList를 state로 관리합니다.
  2. 이미 저장된 todoList가 있으면 불러옵니다.
  3. useEffect를 사용해 localStorage에 todoList가 바뀔 때에 update를 하도록 합니다.

props drilling vs 상태 관리

zustand

상태 관리 라이브러리 중 하나로, 작은 패키지가 특징입니다.
사용은 다음과 같은 코드를 이용합니다.

import { create } from 'zustand'

export const useStore = create((set) => ({
  weekStart: startOfWeek(newDate),
  startDay: format(weekStart, "d"),
  headerDay: `${format(weekStart, "yyyy")}${format(weekStart, "MM")}`,

  increaseWeek: () =>
    set((state) => {
      const oneWeekLater = addDays(state.weekStart, 7);
      return {
        weekStart: oneWeekLater,
        startDay: format(oneWeekLater, "d"),
        headerDay: `${format(oneWeekLater, "yyyy")}${format(oneWeekLater, "MM")}`,
      };
    }),

  decreaseWeek: () =>
    set((state) => {
      const oneWeekAgo = subDays(state.weekStart, 7);
      return {
        weekStart: oneWeekAgo,
        startDay: format(oneWeekAgo, "d"),
        headerDay: `${format(oneWeekAgo, "yyyy")}${format(oneWeekAgo, "MM")}`,
      };
    }),
}));

props drilling

React의 데이터 흐름은 단방향 바인딩으로 (부모 컴포넌트 -> 자식 컴포넌트)로 이어집니다. 따라서, 단방향 데이터 바인딩은 상태를 예측하고 디버깅하기 쉽게 만들기 위함 입니다.
따라서, React에서 단방향 데이터 바인딩이 되는 이유로는,
1. 예측 가능한 데이터 흐름
2. 디버깅 용이성 ( 특정 컴포넌트에서 데이터의 변경이 발생하면, 변경이 일어난 부모 컴포넌트에서부터 디버깅을 시작할 수 있음)
3. 컴포넌트의 독립성
4. 유지보수의 용이성

props drilling의 장, 단점

장점

  • 명시적인 값의 사용
  • 값 추적 용이성
  • 코드 변경 파악 용이성

단점

  • 프로퍼티 데이터 형식 변경의 불편함
  • 중간 컴포넌트에 불필요한 프로퍼티 전달
  • 누락된 프로퍼티 인지의 어려움
  • 프로퍼티 이름 변경 추적의 어려움

context API

custom hook

profile
new blog: https://hae0-02ni.tistory.com/

0개의 댓글