함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우, 해당 함수는 Side Effect가 있다고 이야기한다.
React에서는 컴포넌트 내에서 fetch를 사용하여 API 정보를 가져오거나, 이벤트를 활용해 DOM을 직접 조작할 때 Side Effect가 발생했다고 말한다.
let foo = 'hello''
function bar() {
foo = 'world';
}
bar(); // bar는 함수 외부의 변수인 foo에 영향을 끼치므로 Side Effect를 발생시킨다고 할 수 있다.
순수 함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미한다.
(함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 준다면, 순수 함수가 아님)
순수 함수의 특징
function upper(str) {
return str.toUpperCase(); // toUpperCase 메소드는 원본을 수정하지 않음
}
upper('hello') // 실행 결과: 'HELLO'
Q.
Math.random()
은 순수 함수가 아닙니다. 왜일까요?
- Math.random() 메서드는 항상 같은 값이 리턴되지 않기 때문
Q. 어떤 함수가 fetch API를 이용해 AJAX 요청을 한다고 가정해 봅시다. 이 함수는 순수 함수가 아닙니다. 왜일까요?
- fetch API를 이용해 AJAX 요청을 하는 경우, Side Effect가 발생함
React의 함수 컴포넌트는 props가 입력, JSX Element가 출력으로 나간다. 여기에는 그 어떤 Side Effect도 없으며, 순수 함수로 작동한다.
functio SingleTweet({ writer, body, createdAt }) {
return (
<div>
<div>{writer}</div>
<div>{createdAt}</div>
<div>{body}</div>
</div>
)
}
하지만 보통 React 앱을 작성할 때에는, AJAX 요청이 필요하거나, 로컬스토리지 또는 타이머와 같은 외부 API를 사용하는 경우가 발생할 수 있다. 이는 React 입장에선 전부 Side Effect 이다.
React 컴포넌트에서의 Side Effect
- 타이머 사용 (setTimeout)
- 데이터 가져오기 (fetch API, localStorage)
React는 Side Effect를 다루기 위한 Hook인 Effect Hook(useEffect()
)을 제공한다.
useEffect()
useEffect() 함수는 React 컴포넌트가 렌더링 될 때마다 특정 작업(Side Effect)을 실행할 수 있도록 하는 Hook이다.
여기서 Side effect는 컴포넌트가 렌더링 된 이후에 비동기로 처리되어야 하는 부수적인 효과들을 뜻한다.
useEffect(function, [deps1, deps2, ...])
배열 내에 하나 또는 여러 개의 값이 있다면, 그중의 단 하나만 다르더라도 effect를 재실행한다.
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // count가 바뀔 때만 effect를 재실행합니다.
두 번째 인자를 넣지 않으면 새롭게 컴포넌트가 렌더링 될 때마다 실행된다.
useEffect(function)
컴포넌트가 처음 생성될 때 한 번만 실행되게 하려면 빈 배열을 넣어주면 된다.
useEffect(function, [])
대표적으로 처음 단 한 번, 외부 API를 통해 리소스를 받아오고 더 이상 API 호출이 필요하지 않을 때에 사용한다.
반복문, 조건문 혹은 중첩된 함수 내에서 Hook을 호출하지 마세요.
대신 early return이 실행되기 전에 항상 React 함수의 최상위(at the top level)에서 Hook을 호출해야 합니다. 이 규칙을 따르면 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장됩니다. 이러한 점은 React가useState
와useEffect
가 여러 번 호출되는 중에도 Hook의 상태를 올바르게 유지할 수 있도록 해줍니다.