본문 바로가기
항해99/실전 WIL | TIL

[TIL-019] React Lv4 과제(1) - 중복되는 컴포넌트를 App이 아닌 Router 컴포넌트에서 렌더링하는 이유

by junvely 2023. 5. 1.

Today목표 : 4/30일 React Lv4 과제(1)


중복되는 컴포넌트를 App이 아닌 Router 컴포넌트에서 렌더링하는 이유

중복되는 Layout, header, footer 등의 컴포넌트를 왜 App 컴포넌트에서 렌더링하지 않고, 하위의 Router 컴포넌트에서 렌더링 할까?

function App() {
  return (
    <div className="App">
      <Header></Header> // 새 페이지 마다 렌더링
      <BrowserRouter>
        <Routes>
const Router = () => {
  return (
    <BrowserRouter>
      <Header />
      <Routes>
        <Route path="/" element={<Main />} />
        <Route path="/:id" element={<Detail />} />
      </Routes>
      <Footer />
    </BrowserRouter>
  );
App 컴포넌트에서 모든 라우트를 처리하면, 모든 페이지에서 공통으로 사용되는 Header와 Footer를 중복으로 렌더링해야 합니다. 반면에 Router를 사용하면, 각각의 라우트마다 별도의 컴포넌트를 렌더링하며, 공통으로 사용되는 Header와 Footer를 중복으로 렌더링하지 않아도 됩니다. 이는 코드의 양을 줄이고, 유지보수를 용이하게 할 수 있습니다. 따라서, Router에서 공통으로 사용되는 Header와 Footer를 렌더링하는 것이 더 효율적이며, 중복 코드를 방지할 수 있습니다.

Router가 중복 렌더링을 하지 않는 이유는 React의 Virtual DOM에서 각각의 컴포넌트가 고유한 식별자를 가지기 때문입니다. 이를 통해 React는 각 컴포넌트가 서로 다르다는 것을 인식하고, 컴포넌트의 업데이트를 최적화합니다. router를 사용하지 않으면 모든 라우트를 처리하는 컴포넌트에서 공통으로 사용되는 Header와 Footer를 중복으로 렌더링해야 하기 때문에 중복 렌더링이 발생합니다.

App 컴포넌트에서 라우트를 처리하면, 각각의 페이지에서 Header와 Footer를 계속 렌더링 해줘야 한다. 하지만 Router를 사용하여 내부에서 중복되는 코드를 작성할 경우, 중복 렌더링을 방지하여 각각 컴포넌트 내에서 중복되는 경우 렌더링하지 않기 때문에 더 효율적이다.

 

❗그럼 중복 rendering을 방지하는 것은 react VDOM의 역할일까 router의 역할일까? 둘 다 인가?

중복 렌더링 방지는 React의 Virtual DOM의 기능입니다. React는 Virtual DOM에서 각 컴포넌트가 고유한 식별자를 가지기 때문에, 중복된 컴포넌트를 렌더링할 때에도 식별자를 통해 각각을 구분하고, 변경된 부분만 업데이트합니다.
하지만 Router는 중복 렌더링을 방지하는 것이 아니라, React의 Virtual DOM이 제공하는 이점을 최대한 활용하여 중복 렌더링을 방지할 수 있는 방법을 제공합니다. Router는 각각의 라우트에 대한 컴포넌트를 개별적으로 렌더링하고, 이를 통해 중복 렌더링을 최소화합니다.
따라서 중복 렌더링 방지는 React의 Virtual DOM의 기능이며, Router는 이를 활용하여 중복 렌더링을 방지하는 방법을 제공하는 것입니다.

따라서 앱 전체에 같은 레이아웃 골격을 잡고 싶다면 다음과 같이 styled-components로 사용한다. 

=> ❗처음에는 AppLayout 컴포넌트를 만들어 감싸주었더니, 감싸준 하위 컴포넌트들은 렌더링 하지 않았다. 그 내부에 MainPage가 나오게 하려면 다시 AppLayout 컴포넌트에서 MainPage를 import해야한다... 이렇게 되면 각각 페이지를 다 렌더해줘야 하기 때문에 말도 안되는 일이다. 그냥 골격 스타일만 감싸 주기 위해 때문에 styled-components로 만들어 감싸주었다.

function Router() {
  return (
    <>
      <BrowserRouter>
        <StFlexWrap bgColor={Colors.lightBlue}>
          <StLayout>
            <Header></Header>
            <Routes>
              <Route path="/" element={<MainPage />}></Route>
              <Route path="/intro" element={<IntroPage />}></Route>
              <Route path="/posts" element={<PostsPage />}></Route>
              <Route path="/posts:id" element={<PostPage />}></Route>
              <Route path="/form" element={<FormPage />}></Route>
            </Routes>
          </StLayout>
        </StFlexWrap>
      </BrowserRouter>
    </>
  );
}

그럼 만약 SCSS를 사용한다면 어떻게 해야 할까?

function MyComponent() {
  return (
    <div className={styles.container}>
      <h1>Hello, World!</h1>
      <p>This is a paragraph.</p>
    </div>
  );
}

다음과 같이 스타일로 감싸주면 된다. 다시 되새기자면 컴포넌트화 해버리면 다시 내부에서 페이지를 각각 렌더링해줘야 한다.