[항해99] WIL #4

김헤일리·2022년 12월 11일
0

TIL

목록 보기
11/46

WIL Part 1 - 내가 새롭게 알게된 핵심 부분

React Lifecylcle

  • 컴포넌트는 생성(mounting) -> 업데이트(updating) -> 제거(unmounting)의 생명주기를 갖는다.

  • 리액트에서 클래스형 컴포넌트는 라이프 사이클 메서드를 사용하고, 함수형 컴포넌트는 Hook을 사용한다.

    • LifeCycle Method 는 한국어로 "생명주기 메서드" 라고 부른다.
    • 생명주기 메서드는 컴포넌트가 브라우저상에 나타나고, 업데이트되고, 사라지게 될 때 호출되는 메서드를 의미한다.
    • 컴포넌트에서 에러가 났을 때 호출되는 메서드도 있다고 한다.

✅ 클래스형 컴포넌트의 생명주기

  • 컴포넌트가 생성될 때 발생하는 생명주기 메소드를 "마운트(Mount)할 때 발생한다"라고 표현한다.

    1. Constructor는 컴포넌트의 생성자 메서드다.

      • 컴포넌트가 만들어지면 가장 먼저 실행된다.

      • 예시:

          ```javascript
                  constructor(props) {
                    super(props);
                    console.log("constructor");
                  }
          ```

    2. getDerivedStateFromProps 는 props 로 받아온 것을 state 에 넣어주고 싶을 때 사용한다.

      • 다른 생명주기 메서드와는 달리 앞에 static 을 필요로 하고, 이 안에서는 this를 조회 할 수 없다.

      • 여기서 특정 객체를 반환하게 되면 해당 객체 안에 있는 내용들이 컴포넌트의 state 로 설정된다.

      • 하지만 null 을 반환하게 되면 아무 일도 발생하지 않는다.

      • 이 메서드는 컴포넌트가 처음 렌더링 되기 전에도 호출 되고, 그 이후 리렌더링 되기 전에도 매번 실행된다.

        • 예시:
        static getDerivedStateFromProps(nextProps, prevState) {
            console.log("getDerivedStateFromProps");
            if (nextProps.color !== prevState.color) {
              return { color: nextProps.color };
            }
            return null;
        }

    1. componentDidMount는 컴포넌트의 첫번째 렌더링이 마치고 나면 호출되는 메서드다.

      • 이 메서드가 호출되는 시점에는 만들어진 컴포넌트가 화면에 나타난 상태이다.

      • 주로 D3, masonry 처럼 DOM 을 사용해야하는 외부 라이브러리 연동을 하거나, 해당 컴포넌트에서 필요로하는 데이터를 요청하기 위해 axios, fetch 등을 통하여 ajax 요청을 하거나, DOM 의 속성을 읽거나 직접 변경하는 작업을 진행한다.

        • 예시:
        useEffect(()=>{
            console.log("componentDidMount");     
        },[])

  • 컴포넌트가 업데이트되는 시점에 호출되는 생명주기 메소드도 있다.

    1. getDerivedStateFromProps 같은 메소드는 컴포넌트의 props 나 state 가 바뀌었을때도 이 메서드가 호출된다.

    2. shouldComponentUpdate 메서드는 컴포넌트가 리렌더링 할지 말지를 결정하는 메서드다.

      • 주로 최적화 할 때 사용한다

        • 예시:
        shouldComponentUpdate(nextProps, nextState) {
      	 console.log("shouldComponentUpdate", nextProps, nextState);
      	  // 숫자의 마지막 자리가 4면 리렌더링하지 않는다
      	 return nextState.number % 10 !== 4;
        }

    3. getSnapshotBeforeUpdate 는 컴포넌트에 변화가 일어나기 직전의 DOM 상태를 가져와서 특정 값을 반환한 다음 발생하게 되는 componentDidUpdate 함수에서 받아와서 사용을 할 수 있다.

      • 예시:
        getSnapshotBeforeUpdate(prevProps, prevState) {
          console.log("getSnapshotBeforeUpdate");
          if (prevProps.color !== this.props.color) {
            return this.myRef.style.color;
          }
          return null;
        }

    4. componentDidUpdate 는 리렌더링이 마치고, 화면에 변화가 모두 반영되고 난 뒤 호출되는 메서드다.

      • 3번째 파라미터로 getSnapshotBeforeUpdate 에서 반환한 값을 조회 할 수 있다.
        • 예시:
        componentDidUpdate(prevProps, prevState, snapshot) {
            console.log("componentDidUpdate", prevProps, prevState);
            if (snapshot) {
              console.log("업데이트 되기 직전 색상: ", snapshot);
            }
          }

  • 컴포넌트가 사라질 때, 즉 umount될 때 발생하는 생명주기 메소드는 하나만 존재한다.

    1. componentWillUnmount 는 컴포넌트가 화면에서 사라지기 직전에 호출된다.

      • 주로 DOM에 직접 등록했었던 이벤트를 제거하고, 만약에 setTimeout 을 걸은것이 있다면 clearTimeout 을 통하여 제거한다.
      • 추가적으로, 외부 라이브러리를 사용한게 있고 해당 라이브러리에 dispose 기능이 있다면 여기서 호출한다.
      componentWillUnmount() {
          console.log("componentWillUnmount");
        }
      

✅ 함수형 컴포넌트의 생명주기

  • 리액트에서 Hook은 함수형 컴포넌트에서 React state와 생명주기 기능을 연동 할 수 있게 해주는 함수다.

  • Hook은 class 안에서는 동작하지 않고, 함수형 컴포넌트를 class없이 사용할 수 있게 한다.

    • 리액트 훅을 사용하는 이유는 라이프사이클 메소드가 아니라 로직 기반으로 컴포넌트를 잘게 쪼갤 수 있기 때문이다.
    • 라이프사이클 메서드에는 관련 없는 로직이 자주 섞여 들어가는데, 이로인해 버그가 쉽게 발생하고, 무결성을 쉽게 해친다고 한다.
  • 리액트 훅을 사용하는 경우, 지켜야 하는 규칙이 있다.

    • 최상위 에서만 Hook을 호출해야 한다
    • 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다.
    • 리액트 함수 컴포넌트에서만 Hook을 호출해야 하고, 일반 JS함수에서 Hook을 호출해서는 안된다.
  • 이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다고 한다.


  1. 가장 흔하게 사용하는 Hook은 useState다.
    • 상태를 관리할 때 사용하고, state의 이름과 해당 state의 setter 이름 순으로 반환 받는다.
    • 예시:
const [state, setState] = useState(initialState);

  1. useEffect 는 화면에 렌더링이 완료된 후에 수행되며 라이프사이클 메소드 중 componentDidMountcomponentDidUpdate, componentWillUnmount가 합쳐진 것과 같다.

    • 만약 화면을 다 그리기 이전에 동기화 되어야 하는 경우에는, useLayoutEffect를 활용하여:
    • 컴포넌트 렌더링 > useLayoutEffect 실행 > 화면 업데이트 순으로 effect를 실행시킬 수 있다.
    useEffect(() => {}); 
    // 렌더링 결과가 실제 돔에 반영된 후마다 호출
    useEffect(() => {}, []); 
    // 컴포넌트가 처음 나타날때 한 번 호출 (의존성 배열 추가)
    useEffect(() => {}, [의존성1, 의존성2, ..]); 
    // 조건부 effect 발생, 의존성 중 하나가 변경된다면 effect는 항상 재생성된다.
  • useEffect안에서의 return은 정리 함수(clean-up)를 사용하기위해 쓰여진다.
    • 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 전에 수행한다.
    • 컴포넌트가 여러 번 렌더링 된다면 다음 effect가 수행되기 전에 이전 effect가 정리된다.

  1. useContext는 Context API를 통해 만들어진 Context에서 제공하는 Value를 가져올 수 있다.

    const value = useContext(MyContext);
  • 컴포넌트에서 가장 가까운 MyContext.Provider 가 갱신되면 이 Hook은 그 MyContext provider에게 전달된 가장 최신의 context value를 사용하여 렌더러를 트리거 한다.

  1. useReduceruseState의 대체 함수로 컴포넌트 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.

    • 컴포넌트 바깥에 로직을 작성할 수 도 있고, 심지어 다른 파일에 작성한 후 불러와서 사용할 수 있다.
    • reducer란 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수다.
    const [state, dispatch] = useReducer(reducer, initialArg, init);

  1. useRef는 특정 DOM 선택할때 주로 쓰이며 .current 프로퍼티로 전달된 인자로 초기화된 변경 가능한 ref 객체를 반환한다.

    • 반환된 객체는 컴포넌트의 전 생애주기를 통해 유지됩니다.
    const refContainer = useRef(null);

  1. useMemo는 메모이제이션된 값을 반환한다.

    • 이미 연산 된 값을 리렌더링 시 다시 계산하지 않도록 한다.
    • 의존성이 변경되었을 때에만 메모이제이션된 값만 다시 계산한다.
    • 의존성 배열이 없는 경우 매 렌더링 때마다 새 값을 계산한다.
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

  1. useCallback은 메모이제이션 된 콜백을 반환한다.

    • useMemo와 유사하게 이용되며 '함수'에 적용된다.
    • 의존성이 변경되었을때만 변경되기 때문에 특정 함수를 새로 만들지 않고 재사용이 가능하다.
    const memoizedCallback = useCallback(
      () => {
        doSomething(a, b);
      },
      [a, b],
    );


WIL Part 2 - 일주일을 끝내고 쓰는 일기.

이번 주는 리덕스와 리액트를 함께 사용하는 것을 배웠다.
그리고 이번 주가 지나서 고작 3주 동안 리액트를 공부하는게 얼마나 짧은 시간이고, 얼마나 수박 겉핥기 수준으로 얕게 배울 수 있는지 확실히 느껴졌다.

이제 이번 달 말 부터 실전 프로젝트가 시작할텐데, 나는 아직 내가 무언가를 혼자 할 수 있다고 생각되지 않는다.
개발 공부는 재밌지만, 확실히 몇개월은 더 공부해야 내가 뭔가 할 수 있는 사람이 될거라고 생각한다.
더 많은 시간을 공부에 쏟아야 하나 싶기도 하지만, 사람이 기계가 아닌데 어떻게 이걸 다 소화하나...

그래도 항해를 하면서 좋은 건 앞으로 내가 혼자서 공부를 하든, 다른 곳에서 공부를 하든, 어떻게 공부해야할지에 대해서 조금 더 명확해졌다는 것이다.

이제 코드를 배끼는거 같다 어쩐다는 솔직히 아-무 문제가 되지 않는다!
지금은 그렇게 배끼고나서 코드와 흐름을 이해할 수 있다면 그거로도 성과라고 생각하기 때문에!

압박과 스트레스는 당연히 크게 느껴지지만 적어도 공부만 하는 것 보단 뭐라도 만들 수 있는 주차가 더 재밌긴 하다.

내 머릿속에 있는게 그대로 만들어질 것을 생각하니 재밌는건지 모르겠지만!

앞으로 뭐가됐든 개발 공부는 쭉 하고싶다!


한 주 한 주 지날때마다 오,,,, 나 바본가,,, 싶은 마음이 들지만 그래도 재밌는건 재밌는거고! (어려운건 어려운거..)

다른 사람들도 공부하고 있다는 사실이 위안이되고 힘이된다.

아자아자 화이팅... 오늘도 나의 멧돌은 빙글빙글 🫠

출처:

profile
공부하느라 녹는 중... 밖에 안 나가서 버섯 피는 중... 🍄

0개의 댓글