ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • useEffect와 side Effect
    프론트엔드 개발자가 될거야./react 2022. 7. 13. 22:50

    react Hook 중에 하나인 useEffect.

    useEffect는 무엇일까?

    useEffect를 알기 전에 먼저 side Effect를 알아야 한다.

    side Effect

    side Effect는 우리말로 부작용, 부수효과로 해석된다.

    근본적인 역할 대신에 부수적인 효과가 있거나 특정 목적 대신에 다른 행위가 발생할 때 

    부작용이 있다. 부수효과가 있다.라고 말할 수 있다.

    이 개념을 React에 적용해보자.

     

    React의 함수 컴포넌트 자체는 input(인자)로 state, props를 받아 output으로 UI를 그려내는 것이다.

    그런데 UI를 그려내지 않고 그 이외의 행위를 하면 side Effect가 일어났다고 할 수 있다.

     

    let count = 0
    
    function greetWithSideEffect(name) { // Input
      count = count + 1 // Side Effect!
    
      return `${name}님 안녕하세요!` // Output
    }

    이 코드는 side Effect가 일어났다. 

    왜냐하면 이 함수의 특정 목표는 name을 인자로 받아 String을 리턴하는 것인데

    뜬금없이 count라는 외부 변수의 개입이 있다.

     

    function printNum(num){
    console.log(num); //side Effect
    
    return num;
    }
    
    printNum(3)

    이 코드도 side Effect가 일어났다.

    왜냐하면 콘솔이라는 자체가 외부 요소를 쓰는 거기 때문이다.

     

    let number = 3;
    
    function printNum(num){
     const result = num + 3;
        
     return result;
    }
    
    printNum(3)

    이 코드는 side Effect가 일어나지 않았다.

    외부 변수의 개입이 없고 오직 함수 내부 로직으로만 작동하기 때문이다.

     

    정리해보자면

    react에서의 side Effect는

    state, props 이외의 다른 값을 작성하는 것

    즉, 렌더링이 아니고 외부 세계에 영향을 주는 어떤 행위라고 할 수 있다.

     

    주된 side Effect로

    fata fetching, Dom접근(Event Listener 등록), 구독(setInterval)이 있다.

    그런데 함수에서의 side Effect는 부정적인 의미가 아니다.

    우리는 side Effect를 잘 활용해야 한다.

     

    그런데 side Effect에는 두 가지 문제점이 있다. 이것을 해결해주는 것이 useEffect이다!

    문제점 1. block rendering

    js는 위에서부터 한줄한줄 읽는 동기적인 언어이다.

    만약에 렌더링이 다 되지 않았는데 중간에 엄청나게 무거운 데이터가 있어서

    받는데 30초가 걸리는 데이터가 있다면

    30초 동안 렌더링이 되지 않아서 유저는 사이트가 이상한 줄 알고 이 사이트를 나가버릴 수 도 있다.

    이것이 첫 번째 문제다.

     

    문제점 2. always trigger

    state는 useState로 인해 값이 바뀔 때마다 렌더링 된다는 것을 알 것이다.

    그런데 이것을 인스타그램으로 예를 들었을 때

    수백 수천만 명의 유저가 댓글을 추가하고 삭제할 때마다 렌더링 되는 문제가 생긴다.

    이것은 서버가 터지는 문제점이 생긴다. 렌더링이 수 없이 많이 되기 때문이다.

    여기에 block도 계속 발생하고 있다면 정말 큰 문제가 된다.

     

    이 두 문제점을 useEffect가 어떻게 해결하는 것일까?

     

    useEffect 구성요소

    useEffect(()=> {}, [])

    위와 같이 useEffect는 인자를 두 개 가지고 있는데

    콜백 함수와 의존성 배열이다.

    useEffect(function, dependency array)

    인자가 각각 어떠한 역할을 하는지 알아야 한다.

    그래야 useEffect의 기본 동작을 이해할 수 있다.

     

    첫 번째 인자, 콜백 함수!

    useEffect로 감싸인 console.log("effect!")가 있고

    그냥 console.log("render")가 있다.

    원래 js라면 위에서부터 차례차례 읽혀서

    콘솔에 effect! -> render 순으로 찍힐 것이다.

    그런데 콘솔 로그를 봐보자.

    render가 먼저 찍히고 effect가 그다음에 찍혔다.

    왜냐하면 useEffect는 일단 렌더가 먼저 진행되고 그 다음에 실행되기 때문이다.

    이 말을 즉, 중간에 block이 있어도 일단 렌더가 먼저 진행되니 block rendering문제가 해결되는 것이다.

     

    두 번째 인자, 의존성 배열

    useEffect(() => {

     console.log("count");

    }, [count]);

    를 보면 의존성 배열에서 count를 구독하고 있다.

     

    useEffect(() => {

     console.log("toggle");

    }, [isToggled]);

    는 의존성 배열에서 isToggled를 구독하고 있다.

     

    이것이 무슨 뜻일까?

    count를 의미하는 up를 누르면 

    console.log("render")와

    console.log("count")만 실행되고

    console.log("toggle")는 실행되지 않는다.

     

    또한

    isToggled를 의미하는 toggle을 누르면

    console.log("render")와

    console.log("toggle")만 실행되고

    console.log("count")는 실행되지 않는다.

     

    이것이 의존성 배열의 뜻이다.

    이러한 의존성 배열의 특성을 이용하면

    특정 부분만 렌더링 할 수 있으니 always trigger도 해결할 수 있는 것이다.

     

    useEffect(() => {
     console.log("quiz!");
    }, [count, isToggled]);

    의존성 배열도 배열이므로

    여러 개의 데이터를 동시에 구독할 수 있는데

    이렇게 하면 뭘 누르든 quiz가 찍히게 된다.

    그 데이터 중 하나라도 변하면 로직을 실행시키는 것이다.

     

    useEffect(() => {
     console.log("quiz!");
    }, []);

    이렇게 한다면

    mount로 최초 한 번만 실행된다.

    이것은 API 불러올 때 많이 사용되는 방법이다.

     

    댓글

Designed by Tistory.