Skip to content

Commit 6833ed3

Browse files
committed
draft: memoization section
1 parent 3183a96 commit 6833ed3

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

posts/web-performance-optimization.mdx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ console.log(multiply(4, 2));
247247
```js
248248
const { multiply } = require('./math.js');
249249

250-
console.dir(require.cache['/Users/jake/blog/math.js'].exports);
250+
console.dir(require.cache['/math.js'].exports);
251251
console.dir(multiply);
252252
```
253253

@@ -274,7 +274,7 @@ Tree Shaking과 Module system에 관한 더 자세한 내용을 알기 쉽게
274274
<ol>
275275
<li>CommonJS로 번들된 라이브러리를 사용하고 있는 경우</li>
276276

277-
라이브러리를 선택할 때 어떠한 모듈 시스템을 사용하는지 확인하고 ESM 문법을 사용하는 라이브러리를 사용하는 것이 좋습니다.
277+
`node_modules` 안에서 라이브러리의 빌드된 소스 코드를 보고 CommonJS 문법으로 번들되어 있는지 확인합니다. CommonJS 문법을 사용한다면 ES 모듈 문법을 지원하는지 확인해보고 지원하지 않는다면 비슷한 기능의 다른 라이브러리로 대체하는 것이 좋습니다.
278278

279279
<li>라이브러리 전체를 import하고 있는 경우</li>
280280

@@ -292,7 +292,7 @@ Tree Shaking과 Module system에 관한 더 자세한 내용을 알기 쉽게
292292
const result = get(obj, 'deeply.nested.property');
293293
```
294294

295-
위 예제처럼 라이브러리 전체를 import하는 것보다 필요한 함수만 import하여서 모듈 번들러에게 사용되지 않는 코드는 제거하도록 만드는 것이 좋습니다.
295+
위 예제처럼 라이브러리 전체를 import 하는 것보다 필요한 함수만 import 하여서 모듈 번들러에게 사용되지 않는 코드는 제거하도록 만드는 것이 좋습니다.
296296
</ol>
297297

298298
## 모노레포 공용모듈 트리쉐이킹
@@ -313,3 +313,45 @@ ES 모듈 문법을 사용해 트리 쉐이킹이 정상적으로 동작되게
313313
또는, 자바스크립트로 컴파일 하지 않고 타입스크립트 파일 자체를 모듈로 사용하는 방법도 있습니다. 이 방법이 IDE에서 타입 참조를 하였을 때 원본 파일로 이동하게 되므로 추천하는 방법입니다.
314314

315315
</ol>
316+
317+
# 메모이제이션
318+
319+
메모이제이션은 이전에 계산한 값을 저장해두고 동일한 입력이 들어왔을 때 재계산하지 않고 저장된 값을 반환하는 최적화 기법입니다. React에서는 불필요한 리렌더링을 방지하기 위해 컴포넌트나 값의 메모이제이션을 제공합니다.
320+
321+
메모이제이션은 리렌더링을 최적화하는데 강력한 기법이긴 하지만 무분별하게 적용한다면 오히려 성능이 저하될 수 있습니다. 메모이제이션 자체 동작으로 인해 메모리 사용량이 증가하고 초기 렌더링 비용이 들기 때문에 대부분의 상황에선 React의 기본 최적화만으로도 충분한 성능을 보장합니다.
322+
323+
리액트 공식문서에선 **컴포넌트가 리렌더링 될 때 인지할 수 있을 만큼의 지연이 없다면 메모이제이션이 필요하지 않습니다.** 라고 말합니다. 이 말인즉슨, 반대로 사람이 인지할 수 있을 만큼 성능상의 문제가 있다면 메모이제이션 기법이 굉장히 효과적일 수 있다는 겁니다. _~~(근데 성능 문제의 대부분은 컴포넌트 로직을 잘못 작성해서 발생합니다.)~~_
324+
325+
들어가기 전에, 프로젝트에서 불필요한 리렌더링이 발생하는 컴포넌트가 있는지 [React 개발자 도구 Profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html)를 통해 먼저 확인해보세요.
326+
327+
## React.memo
328+
329+
React의 기본 동작은 부모 컴포넌트가 리렌더링되면 모든 자식 컴포넌트도 리렌더링하는 것입니다. 하지만 자식 컴포넌트의 props가 변경되지 않았다면 리렌더링이 불필요할 수 있습니다.
330+
331+
`memo`는 아래와 같은 상황에서 적용하는 것을 추천드립니다:
332+
333+
- 컴포넌트가 동일한 props로 자주 렌더링되는 경우
334+
- 컴포넌트의 리렌더링 비용이 큰 경우
335+
336+
```jsx {10}
337+
const TodoItem = ({ title, completed }) => {
338+
return (
339+
<li>
340+
<input type="checkbox" checked={completed} />
341+
<span>{title}</span>
342+
</li>
343+
);
344+
};
345+
346+
export default React.memo(TodoItem);
347+
```
348+
349+
자식 컴포넌트의 props가 원시 타입이 아닌 <b>객체 타입(원시타입 외 전부)</b>일 경우 리렌더링될 때마다 새로운 주소를 참조하게 되므로 항상 다른 prop으로 인식하게 됩니다. 이 경우 `useMemo` 혹은 `useCallback`을 같이 사용해야 합니다. 그렇지 않다면 `memo`를 감싸봤자 비용만 들고 리렌더링 최적화 효과를 아예 얻지 못하게 됩니다.
350+
351+
## useMemo
352+
353+
`useMemo`는 계산 비용이 큰 값을 메모이제이션하는 데 사용됩니다.
354+
355+
## useCallback
356+
357+
`useCallback`은 함수를 메모이제이션하는 데 사용됩니다. 특히 자식 컴포넌트에 콜백 함수를 props로 전달할 때 유용합니다.

0 commit comments

Comments
 (0)