1.1 자바스크립트 동등 비교
🔖 리액트 가상DOM과 실제DOM의 비교, 컴포넌트 렌더링 여부, 변수나 함수의 메모이제이션은 모두 동등 비교를 기반으로 한다.
1.1.1 자바스크립트의 데이터 타입
🔖 원시타입 : 간단하게 객체가 아닌 모든 타입을 지칭한다고 해도 무방
- undefined : 선언 후 값을 할당하지 않을 시 자동으로 할당되는 값, undefined 하나만 할당 가능
- null : 값이 없거나 빈 값을 표현할 때 사용, null 하나만 할당 가능
- Boolean : true, false만 가질 수 있는 값, 주로 조건문에서 많이 사용(true나 false는 여러가지 값들로 암시적으로 표현 가능)
- Number : 숫자를 할당하는 값, 무조건 10진수로 해석되어 표현
- BigInt : ES2020에서 추가된 값, Number가 표현하지 못하는 큰 값들을 표현
- String : 텍스트 타입 데이터를 저장하기 위한 값, 작은(''), 큰 따옴표("") 혹은 백틱(``)으로 표현된 모든 값(문자열 각각의 값은 변경 불가능)
- Symbol : ES6 이후로 추가된 값, 중복되지 않는 고유한 값을 직접 작성하고 싶을 때 사용
🔖 객체타입 : 원시 타입을 제외한 모든 것, 배열, 함수, 정규식, 클래스 등(참조 타입이라고도 지칭)
1.1.2 값을 저장하는 방식의 차이
🔖 원시타입
- 불변 형태의 값으로 저장되며 메모리 영역 차지
- 값 자체를 복사하기 때문에, 비교하면 true 출력
const hello = "hello";
const hi = hello;
console.log(hello === hi); // true
🔖 객체타입
- 변경 가능한 상태의 값으로 저장
- 얕은 복사를 이용한 참조 전달이므로, 비교하면 false 출력
const hello = {
a: "hello",
};
const hi = {
a: "hello",
};
console.log(hello === hi); // false
1.1.3자바스크립트의 또 다른 비교 공식, Object.is
🔖 두개의 인수를 제공받아 동일한지 체크(타입까지 체크)
사용 이유 : ==, ===가 체크하지 못하는 경우도 전부 체크하기 위함
동등 비교가 가지는 한계를 극복하기 위해 제작, 하지만 객체 간 비교에선 ===와 차이X
1.1.4리액트에서의 동등 비교
- 리액트에서 사용하는 비교가 바로 Object.is
- 이를 기반으로 하는 shallowEquall이라는 함수를 만들어 사용
- 기존 JS와 다르게 객체와의 얕은 비교를 한번더 수행
// 기존 Object.is
Object.is({ hello: "world" }, { hello: "world" }); // false
// shallowEquall : 객체의 비교를 한번 더 수행
shallowEqual({ hello: "world" }, { hello: "world" }); // true
// 객체의 깊이가 1 초과인 경우: 비교 불가
shallowEqual({ hello: { hi: "world" } }, { hello: { hi: "world" } }); // false
🔖 왜 얕은 비교를 한번만 수행하는가?
- 리액트가 사용하는 JSX Props는 객체고, 이 Prop은 한번만 수행되기 때문에 상관X
🔖 props의 비교 예시 : React.memo (어렵다...)
- 리액트의 memo는 props의 변경 여부만 확인하여 동일할 시 재사용하는 로직
- 아래 로직에서 count나 text 둘 중 하나만 변경될 시, 그에 맞는 컴포넌트만 리렌더링
import { useEffect, useState } from "react";
const CounterB = React.memo(({ object }) => {
useEffect(() => {
console.log(`CounterB Update = count: ${object.count}`);
});
return <div>{object.count}</div>;
});
const OptimizeTest = () => {
const [object, setObject] = useState({ count: 1 });
return (
<div>
<h2>Counter B</h2>
<CounterB object={object} />
<button onClick={() => setObject({ count: object.count })}>B Button</button>
</div>
);
};
❗여기서 문제! memo는 props를 얕은 비교를 이용하여 비교하므로, props로 object가 들어오는 경우 리렌더링 시 새로운 주소를 가지게 된다.
😢 따라서 memo가 의미가 없어져 props 값이 바뀌지 않아도 리렌더링이 발생한다.
✅ 이를 위해 깊은 비교를 해주는 함수를 지정하여 따로 두번째 인수로 넣어주면 해결~
1.1.5 정리 + 주관적인 정리
🔖 책 정리
- 객체 비교의 불완전성은 JS의 고유 개념이므로, JS 개발자는 이를 충분히 인지하여야 한다. 또 이 원리를 이용한 의존성 배열 비교나 useMemo, Callback의 필요성, 렌더링 최적화를 위한 React.memo 등을 위해 이 개념을 잘 숙지해야한다.
🏷️ 주관적 정리
- 자바스크립트에 존재하는 데이터타입과 그 비교의 원리를 되짚어보고, 리액트에서 이를 어떻게 활용하는지 알 수 있었다.
- 기존에 관심을 가지고있던 최적화를 위해 꼭 필요한 중요한 개념임을 인지할 수 있었다.
1.2 함수
🔖 JS와 리액트의 중요한 개념 중 하나. 함수형 컴포넌트를 작성 시 화살표 함수와 일반 함수의 차이도 알아보자
1.2.1 함수란 무엇인가?
🔖 작업을 수행하거나 값을 계산하는 과정을 하나의 블록으로 감싸 표현
function sum(a, b) {
// 함수의 시작
return a + b; // a와 b는 매개변수, return으로 결과 반환
} // 함수의 끝
sum(10, 24); // 34
🔖 리액트의 컴포넌트도 이와 같은 개념
function Compo(props) {
// 함수의 시작
return <div>{props.hello}</div>; // props는 매개변수, return으로 결과 반환
} // 함수의 끝
1.2.2 함수를 정의하는 4가지 방법
🔖 함수 선언문
- 가장 일반적인 방식(표현식이 아닌 '문')
function add(a, b) {
return a + b;
}
sum(10, 24);
- ❗그러나 함수 선언문임에도 불구하고 변수에 할당 가능하며, 이는 JS엔진이 함수 선언문을 유도리있게 해석하기 때문에 가능한 일
🔖 함수 표현식
- 자바스크립트에서 함수는 일급 객체(일반적으로 적용 가능한 연산을 모두 지원)이므로, 변수에 할당 하는 등의 표현식으로 작성하는 것이 가능
const sum = function (a, b) {
return a + b;
};
sum(10, 24);
- ❗일반적으로 익명 함수로 작성(혼란 방지)
🏷️ 표현식과 선언식의 차이
- 가장 큰 차이는 호이스팅 (함수를 끌어올려 실행하는 것처럼 작동)
- 선언식은 함수 그 자체이기 때문에, 호이스팅에 의해 가장 먼저 실행되는 것과 동일한 효과(선언 위치의 자유로움)
- 표현식은 변수에 할당하기 때문에, var에 경우 런타임 이전에 초기화(명확한 선언)
🔖 Function 생성자
- 별로 사용하지도 않고 이쁘지도 않음
const add = new Function("a", "b", "return a+b");
add(10, 24);
🔖 화살표 함수
- ES6에서 새롭게 추가된 방식(간편)
❗기존 함수 생성 방식과의 차이
- constructor(생성자)를 사용불가
- argument 존재X
- this 바인딩 객체가 상위 스코프의 this 객체를 가리킴
// 전역 스코프
const arrowFunc = () => {
console.log(this); // window
};
1.2.3 다양한 함수 살펴보기
🔖 즉시 실행 함수
- 함수의 정의와 실행이 동시에 이뤄지는 함수(일회용)
(function (a, b) {
return a + b;
});
🔖 고차 함수
- 일급 객체라는 특성을 활용해 함수를 인수로 받거나 이를 이용해 새 결과를 도출하는 함수
// 대표적 고차 함수 map
const doubleArr = [1, 2, 3].map((item) => item * 2);
console.log(doubleArr); // [2, 4, 6]
- ❗이를 이용해 다른 컴포넌트를 인수로 받는 고차 컴포넌트 제작 가능
1.2.4 함수를 만들 때 주의사항
🔖 함수의 부수효과를 억제하라~
- 함수 내 작동으로 인해 외부에 영향을 끼치는 효과를 지칭
- 항상 기본에 충실한 함수 만들기
🔖 가능한 함수를 작게 만들어라~
- 함수는 길어질 수록 에러 발생 확률이 증가하고 가독성이 감소
- ESLint는 함수가 50줄이 넘어가면 과도한 함수로 판단
🔖 누구나 이해할 수 있는 이름을 붙여라~
- 코드가 길어지고 많아질 수록 함수 이름이 명확하지 않으면 한눈에 파악하기 힘듦
- 항상 간결하고 명확한 함수 네이밍을 할 수 있도록 주의
1.2.5 정리 + 주관적인 정리
🔖 책 정리
- 함수를 위해 알아두어야 할 것과 예외적인 것들에 대한 것들을 항상 숙지해야 하며, 자신의 함수 설계를 되돌아보는 습관을 가지는 것이 좋다.
🏷️ 주관적 정리
- 기존에 모르던 함수 생성자에 대해 알 수 있었고, 표현식과 선언식의 명확한 차이를 확실히 알 수 있었다.
- 내가 지금까지 작성했던 함수 로직에 대해 조금 생각해보는 시간이 되었다.
'Front-End Study > 모던 리액트 딥다이브 스터디' 카테고리의 다른 글
모던 리액트 딥다이브 - 7회차 [3-1, 3-2, 3-3] (2) | 2024.06.19 |
---|---|
모던 리액트 딥다이브 6회차 [2-3, 2-4, 2-5] (0) | 2024.06.17 |
모던 리액트 딥다이브 - 5회차 [2-1, 2-2] (1) | 2024.06.10 |
모던 리액트 딥다이브 - 4회차 [1-6, 1-7] (1) | 2024.06.08 |
모던 리액트 딥다이브 - 3회차 [1-3, 1-4, 1-5] (1) | 2024.06.03 |