|
| 1 | +# 챕터 12 리액트 디자인 패턴 |
| 2 | + |
| 3 | +## 고차 컴포넌트 (HOC) |
| 4 | +- 다른 컴포넌트를 인자로 받아 새로운 컴포넌트를 반환하는 컴포넌트 |
| 5 | + |
| 6 | +### 장점 |
| 7 | +- 재사용하고자 하는 로직을 한 곳에 모아 관리 가능 => DRY 유지, 관심사 분리 가능 |
| 8 | + |
| 9 | +### 단점 |
| 10 | +- prop 이름 충돌 가능성 => 어떤 고차 컴포넌트가 어떤 prop 제공하는지 파악하기 어려워 디버깅이 어려울 수 있음 |
| 11 | + |
| 12 | +> 이것만 단점으로 꼽는다고?! 복잡성과 트리 깊이 문제가 단점이라 생각 |
| 13 | +
|
| 14 | +## 렌더링 Props 패턴 |
| 15 | +- JSX 요소를 반환하는 함수 값을 가지는 컴포넌트 prop |
| 16 | + |
| 17 | +```js |
| 18 | +function Input(props) { |
| 19 | + const [value, setValue] = useState(''); |
| 20 | + return ( |
| 21 | + <> |
| 22 | + <input type="text" value={value} onChange={(e) => setValue(e.target.value)} /> |
| 23 | + {props.render(value)} |
| 24 | + </> |
| 25 | + ); |
| 26 | +} |
| 27 | + |
| 28 | +export default function App() { |
| 29 | + return ( |
| 30 | + <div className="App"> |
| 31 | + <h1>Temperature Converter</h1> |
| 32 | + <Input |
| 33 | + render={(value) => ( |
| 34 | + <> |
| 35 | + <Kelvin value={value} /> |
| 36 | + <Fahrenheit value={value} /> |
| 37 | + </> |
| 38 | + )} |
| 39 | + /> |
| 40 | + </div> |
| 41 | + ); |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +> 상태 끌어 올리기 예제가 아주 적절했음, 컴포넌트 자식으로 함수 전달하는 예제도 굿 |
| 46 | +
|
| 47 | + |
| 48 | +### 장점 |
| 49 | +- 여러 컴포넌트 사이에서 로직과 데이터 쉽게 공유 가능 |
| 50 | +- 재사용성 높이기 |
| 51 | +- 애플리케이션 로직과 렌더링 컴포넌트 분리 가능 |
| 52 | + |
| 53 | +### 단점 |
| 54 | +- 받은 데이터를 변경할 필요가 없는 렌더링에 치중한 컴포넌트에만 사용 가능 |
| 55 | + |
| 56 | +> 개인적으론 코드 가독성 떨어진다 생각, 가끔 유용하게 쓰일 떄 있을 것 같음 |
| 57 | +
|
| 58 | + |
| 59 | +## hook의 장단점 |
| 60 | + |
| 61 | +### 더 적은 코드 라인 수 |
| 62 | +- hook을 사용하면 코드를 라이프사이클 별로 나누지 않고 관심사 및 기능별로 그룹화 가능 |
| 63 | +- 코드 길이도 줄일 수 있음 |
| 64 | + |
| 65 | +### 복잡한 컴포넌트 단순화 |
| 66 | +- 클래스 컴포넌트는 관리 어려움, 핫 리로딩과 함께 사용하기 힘듦, 코드 경량화 어려움 |
| 67 | +- 함수 컴포넌트는 hook이 쉽게 도와줌 |
| 68 | + |
| 69 | +### 상태 관련 로직 재사용 |
| 70 | +- 자바스크립트 클래스는 여러 단게에 걸친 상속 때문에 전체적인 복잡성을 높임 |
| 71 | +- hook은 클래스 작성 안하고 기능 사용 가능 |
| 72 | + |
| 73 | +### UI에서 분리된 로직 공유 |
| 74 | +- 클래스 컴포넌트는 UI와 무관한 로직을 추출하고 공유할 방법이 없었음 => 그래서 고차 컴포넌트, 렌더링 props같은 복잡한 방법 동원함 |
| 75 | +- hook 등장 이후 자바스크립트 함수로 추출할 수 있게 되고 문제 해결 |
| 76 | + |
| 77 | +## 로더블 컴포넌트 |
| 78 | +loadable-components 라이브러리는 SSR 환경에서 Suspense를 대체할 수 있는 좋은 방법 |
| 79 | +> react 18부터 SSR환경에서도 Suspense 사용할 수 있다고 적혀있는데 굉장히 제한적임 |
| 80 | +> Suspense 자체에 데이터 페칭 매커니즘이 없어서 tanstack-query에 의존하지 않으면 사용 못함 ㅋㅋ |
| 81 | +> SSR 환경에서 suspense 사용? => next.js 아니면 못함 ㅅㄱ |
| 82 | +
|
| 83 | +## PRPL 패턴 |
| 84 | +- push: 중요 리소스 푸쉬해서 서버 왕복 횟수 최소화, 로딩 시간 단축 |
| 85 | +- render: 최대한 빠르게 렌더링 (TTI 줄여 초기 사용자 경험 개선하기) e.g SPA 에서 초기에 필요한 js 번들만 로드하기 |
| 86 | +- pre-cache: 초기 화면 렌더링 끝난 후, 사용자가 방문할 가능성 높은 경로와 리소스를 사전에 캐시하기 e.g service worker 사용 |
| 87 | +- lazy-load: 초기 화면에 필요하지 않은 리소스(이미지, 비동기 JS 모듈 등)를 나중에 로드 e.g Intersection Observer API를 사용해 사용자 화면에 나타나는 시점에 이미지 로드, React.lazy와 Suspense로 필요한 컴포넌트를 동적으로 로드 |
| 88 | + |
| 89 | + |
| 90 | +## 리스트 가상화 |
| 91 | +한번에 수천개의 목록 요소를 렌더링하여 초기 렌더링 속도 저하 또는 스코롤 성능 저하를 유발하는 대신 가상화는 사용자에게 보이는 항목만 렌더링 시킴 |
| 92 | + |
| 93 | +> 실제로 무한 스크롤로 이루어진 페이지에서 이미지와 데이터가 DOM에 계속 쌓이다보면 점점 느려지는 경우가 있음 |
| 94 | +> 무신사는 virtuoso, 오늘의집은 예전에는 react-virtualized 쓰다가 최근에 virtuoso로 갈아탄듯함 [오늘의집 무한스크롤 개발기](https://www.bucketplace.com/post/2024-09-11-virtualizedlist-%EB%AC%B4%ED%95%9C%EC%8A%A4%ED%81%AC%EB%A1%A4-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-%EA%B0%9C%EB%B0%9C-%EC%9D%B4%EC%95%BC%EA%B8%B0/) |
| 95 | +
|
0 commit comments