1.useMemo를 이전에 학습할 때는 해당 값이 그대로일 경우
다시 계산을 하지 않고 이전의 값을 사용한다는 부분까지만 이해하고 넘어갔다.

하지만 이제 useState와 useEffect가 어떻게 동작하는지를 이해하고 있기 때문에
useMemo 또한 어떤 원리로 동작하는지에 이해할 수 있었다.

아래와 같은 데이터가 입력되는 경우
people외에도 어떤 state가 변경되더라도 이 컴포넌트의 모든 내용은 리렌더링된다.
즉 countActivePeople함수의 연산 또한 다시 하게 되는데

const [people, setPeople] = useState([{id:1, active: true},{id:2, active: false},{id:3, active: true}])
const count = useMemo(() => countActivePeople(people), [people]);

 

여기에 들어있는 people의 정보가 적을 경우에는 상관없지만
들어간 사람들의 숫자가 늘어나면 늘어날수록 연산에 부담이 생길 수 있다.

이런 문제를 해결하기 위해 useMemo는 useState처럼 의존성배열에 비교할 state를 넣어준 다음
해당 state의 값이 그대로일 경우 추가 연산을 시행하지 않고 저장된 값을 그대로 사용한다.

비교할 부분이 값이 아닌 의존성배열이기 때문에
의존성 배열에 직접적으로 영향을 받는 경우에만 제대로 사용될 수 있어
사용에 주의가 필요하다.

예를 들어 총 지출액을 계산하는 경우
소비 품목들이 변경되지 않았을 경우 다시 계산하지 않지만
소비 품목의 갯수는 다른 state에서 관리하며
그 state의 변경 여부는 의존성배열에 넣지 않았다면
품목 변경에 의한 총 지출액은 증가해야 하지만 반영되지는 않는다.

이 경우 총 지출액이 정상화 되는 경우는 
소비 품목의 종류가 추가 또는 제거되는 경우
함수의 계산을 다시 시행하기 때문에 품목과 갯수의 연산을 진행할 것이다.

이를 통해 왜 순수함수들이 강조되고
하나의 함수가 한가지의 기능을 수행하기를 강조하는지 알 수 있었다.

함수가 여러개의 기능을 하는 경우 
의존성배열에 해당하는 값을 모두 추가하기 어렵고
모두 추가한다고 해도 sideEffect의 문제가 생길 수 있다.


2.React DevTools의 Highlight Updates 기능을 사용할 경우
컴포넌트의 업데이트가 시각화되어 어떤 컴포넌트가 리렌더링되는지를 알 수 있다.
이를 통해 현재 state의 변경 또는 동작을 통해 불필요한 부분까지 리렌더링되는지를 보고
어떤 방식으로 최적화해야 하는지에 대한 정보를 알 수 있다.


3.setState를 사용할 때 setState(newState)를 하는 것과
setState((state) => state + 1)을 하는 것은 중요한 차이를 가지고 있다.

현재 state가 0일 때 아래와 같은 동작을 하면 number는 1이 증가한다.

const [number, setNumber] = useState(0);
  const addNumber = () => {
    setNumber(number + 1); //0 + 1 = 1
    setNumber(number + 1); //0 + 1 = 1
  };
  console.log(number);  //1

 

 

하지만 setState에 Functional Update를 사용하면 결과는 달라지는데
이전에 사용된 state의 비동기적 값이 반영되는 모습을 볼 수 있다.

const [number, setNumber] = useState(0);

const addNumber = () => {
setNumber((number) => number + 1); //0 + 1 = 1
setNumber(number + 1); //0 + 1 = 1
};
console.log(number);  //1

 

const [number, setNumber] = useState(0);

const addNumber = () => {
setNumber(number + 1); //0 + 1 = 1
setNumber((number) => number + 1); //1 + 1 = 2
};
console.log(number);  //2


또한 state의 number값의 변경 여부와 관계없이
setNumber는 현재 값의 증가만 바라보고 있기 때문에
아무리 많은 setNumber에 number+1을 넣어주더라도
최종적으로 number는 1이 될 뿐이기 때문에
함수형 갱신을 통해 2가 되는 모습을 볼 수 있고

const [number, setNumber] = useState(0);

const addNumber = () => {
setNumber(number + 1); //0 + 1 = 1
setNumber(number + 1); //0 + 1 = 1
setNumber(number + 1); //0 + 1 = 1
setNumber(number + 1); //0 + 1 = 1
setNumber((number) => number + 1); //1 + 1 = 2
};
console.log(number);  //2


함수형 갱신을 통해 3이 된 상태라고 하더라도
number+1의 일반적 비동기 처리는 number를 0으로 인식하고 있기 때문에
결과는 1이 출력된다.

const [number, setNumber] = useState(0);

const addNumber = () => {
setNumber((number) => number + 1); //0 + 1 = 1
setNumber((number) => number + 1); //1 + 1 = 2
setNumber((number) => number + 1); //2 + 1 = 3
setNumber(number + 1); //0 + 1 = 1
};
console.log(number);  //1

 

여기서 응용해보면 아래와 같이 state를 아무리 갱신하더라도

setState의 일반적 사용으로는 값이 초기화되기 때문에 2씩 증가되는 것 또한 볼 수 있다.

const addNumber = () => {
setNumber(number + 1);               //0 + 1 = 1
setNumber(number + 1);               //0 + 1 = 1
setNumber(number + 1);               //0 + 1 = 1
setNumber(number + 1);               //0 + 1 = 1
setNumber((number) => number + 1);   //1 + 1 = 2
setNumber((number) => number + 1);   //2 + 1 = 3
setNumber(number + 1);               //0 + 1 = 1
setNumber(number + 1);               //0 + 1 = 1
setNumber((number) => number + 1);   //1 + 1 = 2
setNumber((number) => number + 1);   //2 + 1 = 3
setNumber((number) => number + 1);   //3 + 1 = 4
setNumber((number) => number + 1);   //4 + 1 = 5
setNumber(number + 1);               //0 + 1 = 1
setNumber((number) => number + 1);   //1 + 1 = 2
};
console.log(number);  //2

 

정리하자면 useState로 사용한 state값을 원하는 방식으로 사용하기 위해서는
useEffect에 의존성배열을 추가한 다음 상태변화를 인지해야 하지만
함수형 갱신을 사용한다면 현재 state의 정확한 값을 가져올 수 있기 때문에
최적화를 할 때 의존성배열 제거에 이용할 수 있다.





(1).백준 10828 스택은 push x, pop, size, empty, top의 기능을 구현한 다음
해당 기능의 결과를 출력하는 문제였다.

push는 스택에 값을 추가하기만 하고
pop은 스택에서 값을 제거(pop)하고 그 값을 출력하며 비어있으면 -1을 출력한다.
size는 stack의 길이를 출력하고
empty는 비어있는지 여부를 1,0으로 출력하고
top은 pop과 유사하게 마지막 값을 출력 및 빈 경우 -1을 출력하지만
 pop과는 다르게 값을 제거하지는 않아 스택이 유지된다.

여기서 여러가지 입력이 들어왔을 때 처리를 하는 문제였는데
출력할 결과물들을 저장할 result와 실제 stack의 기능을 수행할 배열 stack을 만든 다음
기능에 맞춰 길이체크, pop, push, empty체크, top체크 등을 수행했다.

스택에 대해 이해하고 분기만 에러없이 처리할 수 있으면
무리없이 풀 수 있는 문제였다.

const input = `14
push 1
push 2
top
size
empty
pop
pop
pop
size
empty
pop
push 3
empty
top`.split('\n')

const result = []
const stack = []

for(let i = 1 ; i < input.length ; i++){
    if(input[i] === "pop"){
        const popNow = stack.pop()
        if(popNow !== undefined){
            result.push(popNow)
        }
        else{
            result.push(-1)
        }
        
    }
    else if(input[i] === "size"){
        result.push(stack.length)
    }
    else if(input[i] === "empty"){
        result.push(stack.length ? 0 : 1)
    }
    else if(input[i] === "top"){
        const topNow = stack.pop()
        if(topNow !== undefined){
            stack.push(topNow)
            result.push(topNow)
        }
        else{
            result.push(-1)
        }
    }
    else{
        const pushNum = input[i].split(' ').map(Number)[1]
        stack.push(pushNum)
    }
}

console.log(result.join('\n'))
 

'회고' 카테고리의 다른 글

[취업준비일지] - 114  (0) 2023.02.11
[취업준비일지] - 113  (0) 2023.02.10
[취업준비일지] - 111  (0) 2023.02.08
[취업준비일지] - 110  (0) 2023.02.07
[취업준비일지] - 109  (0) 2023.02.06

+ Recent posts