이번 시간에는
이 함수에 있는 onConfirm 속성을 살펴보겠습니다
이전 강의에서 언급했듯이
Effect 함수에 속성이나
상태값을 사용한다면
dependency (의존성)으로서 추가해야 합니다
그래서 여기에 onConfirm 속성을
의존성으로 추가하고 나서, 실행하는 대신
값으로 가리켜야 합니다
만약 다수의 의존성을 가지고 있다면
쉼표로 구분할 수 있습니다
일단 여기에서 필요한 의존성은 하나입니다
이 onConfirm 속성입니다
여기에서 짚고 넘어가야 할 문제점이 있습니다
의존성으로 함수를 추가하는 작업입니다
onConfirm은 결국 함수입니다
이 속성이 값으로서 함수를 받기 때문입니다
onConfirm은 함수입니다
그리고 종속성으로서 함수를 추가할 때는
무한 루프를 생성하게 될 위험이 있습니다
그 이유는 open과 같은 의존성을
이 배열에 추가할 때, 이 Modal 컴포넌트에서
리액트가 이 Effect 함수를
다시 실행해야 하기 때문입니다
이는 이 Modal 컴포넌트 함수가 실행될 때
그리고 open 값이 변경될 경우에 해당됩니다
그래서 open인 경우, 만일 False에서 True가 되었거나
True에서 False가 되었다면
의존성이 숫자이거나 문자열이라면
Effect 함수는 그 의존성 값이 변경될 때 다시 작동합니다
이 때 의존성이 함수라면 좀 더 까다롭습니다
왜냐하면 여기서 사용하는 이 함수, 즉
onConfirm함수는 앱 컴포넌트 안에서
정의되고 있기 때문입니다
이 onConfirm 속성은 여기 handleRemovePlace 함수와
동일하도록 설정되어 있습니다
이 함수를 살펴보면
절대 변하지 않는다고 생각하기 쉽습니다
코드와 함수는 항상 같다고 생각할 수 있지만
자바스크립트의 함수는 값이기 때문에
이는 틀린 말입니다
엄밀히 말하면 함수는 객체입니다
그리고 이 함수 객체는
이 handleRomovePlace 함수 객체로
앱 컴포넌트 함수가 실행될 때마다 재생성됩니다
그 이유는 이 함수의 전체가
다시 실행되기 때문입니다
이 앱 컴포넌트 함수에
정의된 모든값들은
앱 컴포넌트 함수가 다시 실행될 때마다
재실행됩니다
예를 들어 hello라는 변수를 정의하겠습니다
이것을 1과 같게 하면
이 부분은 앱 컴포넌트 함수가 재실행될 때 재생성됩니다
이제 이 함수 안에 정의된 함수는
handleRemovePlace의 경우이기에
이 또한 재생성됩니다
그리고 자바에서 함수는 객체이기 때문에
새로운 객체가 생성됩니다
아시다시피 자바스크립트에서는
만약 두 개의 다른 객체를 생성할 때
그 둘이 같은 모양 또는 같은 코드를 가졌더라도
즉 여기 함수와 같이 동일하더라도
그 두 객체는 같지 않습니다
이 부분을 보여드리겠습니다
브라우저 내 관리자 도구로 가 보겠습니다
여기에서 콘솔을 열면
새로운 함수인 hello를 생성해서
Hello에 대해 console.log를 만들겠습니다
그리고 또다른 함수인 hello2를 만들겠습니다
완전히 같은 함수 구성으로 만들겠습니다
console.log에도 같은 내용을 쓰겠습니다
그렇게 하고서 hello와 hello2를 비교하면
False가 나오게 됩니다
즉 둘은 같지 않습니다
자바에서는 두 함수가 같은 코드를 가진다고 해도
동일하게 보지 않습니다
이는 대부분 자바의 객체에 적용됩니다
만일 Max라는 이름의 객체 A를 만들고
객체 B를 만들어서
같은 모양과 같은 값을 줘도
이 두 객체는 동일하게 여겨지지 않습니다
같은 이유로 객체와
함수 또한 동일하다고 여겨지지 않기 때문에
deleteConfirmation 컴포넌트에 있는 Effect 함수의
onConfirmed 의존성은 렌더링 중에
다르게 여겨집니다
그 이유는 앱 컴포넌트가 다시 렌더링될 때
함수가 다시 실행되면
완전히 새로운 handleRemovePlace 함수가 생성되기 때문입니다
이 함수를 DeleteConfirmation에서
받은 후에는
리액트는 이 새로운 값, 새로운 함수를 보고
이전의 값 또는 함수와 비교하게 됩니다
그리고는 이 둘이 다르다고 판단을 내립니다
이에 대한 이유를 설명드렸습니다
그러므로 리액트는 이 컴포넌트 함수를
다시 실행하게 됩니다
해당 의존성이 바뀌지 않았음에도 그렇습니다
그리고 이는 문제 발생으로 이어질 수 있습니다
만일 여기 Effect 함수 내부에서 실행되는
그 함수에서
상태를 다시 업데이트하게 된다면
여기의 경우에 나오듯
무한 루프를 발생시킬 수 있기 때문입니다
여기서 상태를 업데이트 할 것이고
이러면 앱 컴포넌트 함수가 다시 작동하도록 하게 되고
그렇게 해서 완전히 새로운 handleRemovePlace 함수가
생성되어 DeleteConfirmation으로 보내지게 됩니다
그렇게 하면 Effect 함수가 다시 작동합니다
그러고 나면 다시 onConfrim을 작동시키고 반복합니다
이제 이 앱에서는 이 특유의 작동 방식 때문에
무한 루프 문제가 생기지 않습니다
그 이유는 이 앱에서는
onConfirm이 호출될 때 상태 업데이트가 작동되면서
무한 루프를 맞닥뜨릴 수도 있지만
실행되는 상태 업데이트가
modalIsOpen을 False로 설정하고
이는 DeleteConfirmation이 DOM으로부터
삭제되게 함으로써
Modal 컴포넌트가 DOM으로부터 자식을 삭제하도록 유도합니다
그리고 Modal 컴포넌트의 자식 속성은
해당 DeleteConfirmation 컴포넌트를 지니게 되어
여기서 무한 루프에 빠지지 않는 것입니다
이 컴포넌트가 사라지기 때문에 그렇습니다
그렇긴 하지만 위험은 여전히 존재합니다
즉 무한 루프가 야기될 수 있는 위험이며 이는
앱 컴포넌트에서 확인 가능합니다
일시적으로 setModalisopen을 비활성화해서
DeleteConfirmation이 DOM에서 삭제되지 않도록 하겠습니다
아직 다른 몇 가지 상태를 업데이트 하는 중입니다
그러므로 앱 컴포넌트는 다시 렌더링될 것이며
이제 무한 루프를 볼 수 있게 됩니다
이 부분을 앱에서 확인해 보기 위해
새로고침 후 모달을 열어서
타이머 만료되기를 기다리면 새로운 타이머가 보입니다
또 새로운 타이머가 생성되고 또다른 타이머가 생성됩니다
그리고 이는 계속 반복됩니다
여기 모달을 끄기 전까지는
이 무한 루프가 반복됩니다
이 무한 루프를 피하기 위해선
상태 업데이트에 적용한 것처럼 해당 요소를
꼭 DOM으로부터 삭제하도록 해야 합니다
이것보다 더 안전한 방법은
요소가 삭제되는 것과 관련 없이
또 다른 특별한 리액트 훅을 사용하는 것입니다.
이 훅에 대해서는
다음 강의에서 보여드리겠습니다