1. 순수 함수(pure function)란?
: 같은 입력 값을 받으면 항상 같은 출력 값을 반환하는 함수 (순수 함수는 입력으로 전달된 값을 수정하지 않는다.)
순수 함수의 특징:
- side effect가 없다.
- 예측가능하고, 신뢰할 수 있고, 테스트하기 쉽다.
2. side effect(부수 효과)란?
: 함수 내에서 어떤 구현이 함수 외부의 상태에 의존하거나 외부의 상태를 변경하는 경우, 해당 함수는 side effect가 있다고 이야기한다.
1) 외부 상태에 의존: 외부에 있는 변수의 값에 따라 함수의 결과가 달라진다.
2) 외부 상태를 변경: 힘수가 외부에 있는 변수의 값을 변화시킨다.
순수 함수의 예시: React의 컴포넌트
리액트의 컴포넌트는 props가 입력으로, JSX Element가 출력으로 나가는 순수함수이다. 그렇기 때문에 아래의 경우들을 side effect라고 생각한다.
1) 예측할 수 없는 타이머 사용: setTimeout, setInterval
2) 네트워크 요청, 데이터 가져오기: fetch API, localStorage
3) 이벤트를 활용해 DOM 직접 조작: document, window 직접 사용 (브라우저 API와 상호 작용)
예를 들어 fetch API를 사용해 Ajax 요청을 하는 경우를 조금 상세히 들여다보면 Ajax 요청은 네트워크 통신이 이루어지는 것이기 때문에 네트워크 상황, 서버 상태에 따라 응답 코드가 달라진다. 이처럼 반환되는 결괏값을 예측할 수 없기 때문에 fetch API는 순수함수가 아니다. 또한 POST 메소드 등으로 외부 상태를 바꿀 수 있기 때문에 순수함수가 아니다.
결국 side effect는 '외부 세계'와 함께 수행되기 때문에 예측할 수 없다. 무언가를 하기 위해 React 컴포넌트 외부에 도달하는 경우 side effect가 발생하는 건데, 이러한 side effect를 수행한 결과는 예측할 수가 없다. 그렇기 때문에 컴포넌트 내에서 side effect를 수행하고 싶을 경우 effect hook(useEffect)을 사용해야 한다.
3. 순수함수와 불변성의 관계
위에서 리액트 컴포넌트 예시를 든 것처럼 프로그래밍에서는 무언가를 저장하고 변경하고 불러올 수 있는 '상태'라는 개념이 존재한다. 프로그래밍에서 불변성(immutable)이란 '상태를 변경하지 않는 것'이라고 간단하게 정의할 수 있겠다. 순수함수는 함수 외부의 무언가에 절대 영향을 받지도 않고 끼치지도 않는다는 점에서 불변성을 유지하는 함수라고 할 수 있다.
상태를 변경한다는 것이 대체 무슨 뜻일까? 단순히 '함수 외부의 변수에 접근하거나 재할당해서는 안 된다'(리액트에서 useState 함수를 써서 state 값을 관리하는 것이 아닌 state 변수를 직접 재할당하는 것을 금지하는 것), '함수의 인자를 변경하면 안 된다'는 것에 그치지 않는다. 불변성이 이야기하는 상태의 변경이라는 것은 메모리에 저장된 값을 변경하는 모든 행위를 의미하며, 여기에 변수의 재할당 같은 행위도 포함되는 것이다.
4. 불변성을 지킬 때의 장점
1) 무분별한 상태의 변경을 막는다
전역 변수의 남용을 주의해야 하는 이유이다. 불변성을 유지하며 순수함수를 사용한다는 것은 함수 외부의 상태에 접근하여 이미 메모리에 할당되어 있는 값을 변경하지 않는다는 의미이므로, 예측하지 못한 상태의 변경을 방어할 수 있다.
2) 상태의 변경을 추적하기 쉽다
JavaScript에서 객체의 프로퍼티나 배열의 원소를 변경해야 하는 경우, 불변성이 깨질 수 밖에 없다. 애초에 배열이나 객체 같은 참조자료형를 사용하는 이유가 어딘가에 구조화된 데이터를 저장해 놓고 상태를 유지하고 변경해가며 쓰고자 함이기 때문이다.
그래서 리액트에서 상태를 변경하고 싶을 때 setState 메소드를 사용하는데, 해당 메소드를 사용하여 상태를 변경했을 때 Object.is 메소드를 사용해 이전 상태와 다음 상태를 비교하고, 두 객체가 같지 않다고 평가되면 상태가 바뀌었다고 판단하고 컴포넌트를 다시 렌더링한다. (상태 관리 라이브러리인 Redux도 동일한 원리로 상태의 변화를 판단한다.)
📚 참고자료:
'배워서 남 주자' 카테고리의 다른 글
[React] 이벤트 핸들러에 argument 전달하는 방법 (0) | 2022.12.26 |
---|---|
[React] 모달창 영역 바깥 클릭시 모달 닫기 구현 (2) | 2022.12.24 |
바닐라JS로 fetch API를 사용해 서버에 요청한 데이터 받아오는 방법 (0) | 2022.12.13 |
[JavaScript] 문자열(string)을 날짜로 바꾸는 방법 (0) | 2022.12.13 |
컴퓨터는 어떻게 덧셈을 할까? (0) | 2022.12.10 |