1.useEffect에는 마운트, 언마운트가 존재한다.
이전까지는 마운트와 의존성배열까지만 정확하게 알고
언마운트(clean up)를 제대로 알지 못했기 때문에
내부에서 setState등을 반복하는 callBack등을 시행할 때 문제가 생겼었다.

useEffect를 처음 실행(마운트 / 페이지 로딩)할 때는
useEffect에 들어있는 함수가 작동하며
페이지가 종료될 경우 또는 의존성 배열이 변경될 경우에만 디마운트되고
의존성배열에 포함되지 않은 리렌더링은 무시된다.

또한 내용이 없다고 의존성배열자체를 생략할 경우
useEffect를 사용하는 의미가 전혀 없게
리렌더링할 때 마다 새로 호출된다.

즉 의존성배열 내부에 들어있는 값들을 리액트 저장소에 저장하고 
해당 값의 변경을 현재 저장소의 값과 비교해 감지한 다음
변경되었을 경우 진행하기 때문에

빈 배열을 설정할 경우 비교될 값이 없어서 변경이 되지 않고
마운트 된 1회 시점 이후 변화가 없지만

빈 배열조차 넣지 않은 경우 비교연산을 할 인자 자체가 없기 때문에
계속해서 변경되는 것 같다.

그렇기 때문에
디마운트를 제대로 사용하지 않을 경우
state의 변경을 감지하지 않는다면
내부에 작동하는 함수는 처음 세팅된 state를 그대로 인식하고 있기 때문에
현재 useState에서 관리하는 state의 값은 변경되었지만
useEffect 내부의 state 값은 변경되지 않았기 때문에
초기 state의 작동 루프가 계속해서 돌아가는 것이었다.

또한 디마운트를 통한 제거를 하지 않고
단순히 의존성배열에만 값을 추가해 state를 변경한다면
기존에 작동하던 콜백함수(예를 들어 setInterval)이 무한반복되며
새로 변경된 state로 콜백함수가 추가될 뿐이다.


예를 들어 console.log(state)를 1초마다 진행할 경우
의존성배열에 state를 넣고 setState(state+1)로 변경한다면
기존에는 1, 1, 1, 1, 1 순서로 출력된다면
state를 +1로 변경할 경우 작동하다가 2가 추가될 뿐이다.
1, 1, 1, 2, 1, 2, 1, 2, 1, 2 

최종적으로 타이머를 제대로 작동하게 구현하기 위해서는 아래와 같이 cleanup 함수가 필요하다.

(왜 "/"하나로 갑자기 주석처리가 되는지는 모르겠지만 "나누기로 "/"를 대체했다.. 원래는 newTimeCount/60이다)

useEffect(() => {
    if(time.isStart && time.timeCount){
        const countDown = setInterval(()=>{
          const newTimeCount = time.timeCount-1
          const newTimeLeft = `${String(Math.floor(newTimeCount"나누기"60)).padStart(2,'0')}:${String(newTimeCount%60).padStart(2,'0')}`
          console.log(newTimeCount,newTimeLeft)
          setTime({...time, timeCount: newTimeCount, timeLeft:newTimeLeft})
      },1000);
      //의존성배열에 들어있는 값이 변경되면 clear를 통한 초기화 후 재실행된다.
      return () => clearInterval(countDown)
    }
  },[time.isStart, time.timeCount])






(1).백준 1874 스택 수열은 순서대로 스택에 숫자를 집어넣고
pop은 원하는 시점에 마음대로 할 수 있다는 규칙을 가지고
특정 배열을 만드는 문제였다.
예를 들어 stack에는 1,2,3,4 순으로 들어가고
요구하는 배열은 [4,3,2,1]인 경우 
1,2,3,4를 넣어 + + + +(+는 push, -는 pop이라는 설정)가 먼저 되고
4,3,2,1순으로 pop을 해 ----처리를 하면
결과값은 ++++----가 되고
4,1,3,2를 요구할 경우 4 다음 1이 나올 수 없는 구조기 때문에
NO를 출력하면 되는 문제였다.

문제를 해결하기 위해 수도코드를 작성해보니 아래와 같았다.

1. 값을 빼서 stack에 집어넣고 result에 +를 추가
2. 현재 스택의 마지막 값을 pop으로 꺼내 비교 후 출력해야 하는 값이 아닐 경우 다시 push
3. 위 처리 전 pop이 undefined가 아니어야 하며 
     targetIndex가 처리될 때 마다 1씩 증가시키고 
     while은 현재 pop과 target이 일치하지 않을 때 까지 진행
4. 최종적으로 들어있는 스택의 길이에 따른 출력

 

 

처리 과정의 흐름을 숫자 입력을 기준으로 진행했는데
1이 들어간 다음 현재 목표가 1이 아니라면 while문을 종료한다.
현재 목표가 2라면 타겟을 다음 순서로 넘기고 while문이 다시 돌아간다.
while문이 종료될 경우 numberStack에 값을 추가한 다음 while을 실행한다.

const input = `8
4
3
6
8
7
5
2
1`.split('\n').map(Number)

const range = input[0]
const numberStack = []
const result = []
let targetIndex = 1

for(let i = 1 ; i <= range ; i++){
    numberStack.push(i)
    result.push('+')
    while(targetIndex <= range){
        const popedNumber = numberStack.pop()
        if(popedNumber === undefined){
            break
        }
        if(popedNumber === input[targetIndex]){
            targetIndex++
            result.push('-')
        }
        else{
            numberStack.push(popedNumber)
            break
        }
    }
}

if(numberStack.length){
    console.log("NO")
}
else{
    console.log(result.join('\n'))
}

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

[취업준비일지] - 106  (0) 2023.02.03
[취업준비일지] - 105  (0) 2023.02.02
[취업준비일지] - 103  (0) 2023.01.31
[취업준비일지] - 102  (0) 2023.01.30
[취업준비일지] - 101  (0) 2023.01.29

+ Recent posts