Learn React / Components

user profile img

신현호

React

React Docs

Post Thumbnail

목차

    Components

    Fragment

    Fragment는 래퍼 노드 없이 엘리먼트를 그룹화할 수 있습니다.

    jsx

    <>
      <OneChild />
      <AnotherChild />
    </>
    

    Fragment로 엘리먼트를 그룹화하면 DOM 엘리먼트와 같은 다른 컨테이너로 엘리먼트를 감싸는 경우와 달리 레이아웃이나 스타일에 영향을 주지 않습니다.

    다른 엘리먼트와 마찬가지로 Fragment를 변수에 할당하고 props로 전달하는 등의 작업도 가능합니다.

    jsx

    function CloseDialog() {
      const buttons = (
        <>
          <OKButton />
          <CancelButton />
        </>
      )
      return (
        <AlertDialog buttons={buttons}>
          Are you sure you want to leave this page?
        </AlertDialog>
      )
    }
    

    <></> 문법 대신에 명시적으로 Fragment를 작성해야 하는 상황이 있습니다. 바로 반복을 통해 여러 엘리멘트를 렌더링할 때 입니다.

    이 때는 key속성을 제공하기 위해 일반 JSX 문법을 사용해야 합니다.

    jsx

    function Blog() {
      return posts.map((post) => (
        <Fragment key={post.id}>
          <PostTitle title={post.title} />
          <PostBody body={post.body} />
        </Fragment>
      ))
    }
    

    Profiler

    Profiler는 프로그래밍 방식으로 React 트리의 렌더링 성능을 측정할 수 있습니다.

    jsx

    <Profiler id="App" onRender={onRender}>
      <App />
    </Profiler>
    

    이런식으로 컴포넌트 트리를 Profiler로 감싸주게 되면 렌더링 성능을 측정할 수 있습니다.

    react profiler

    여러 개를 사용하여 애플리케이션을 부분별로 측정할 수 있습니다.

    jsx

    <App>
      <Profiler id="Sidebar" onRender={onRender}>
        <Sidebar />
      </Profiler>
      <Profiler id="Content" onRender={onRender}>
        <Content />
      </Profiler>
    </App>
    

    Profiler를 여러개 중첩 사용 할 수도 있습니다.

    jsx

    <App>
      <Profiler id="Sidebar" onRender={onRender}>
        <Sidebar />
      </Profiler>
      <Profiler id="Content" onRender={onRender}>
        <Content>
          <Profiler id="Editor" onRender={onRender}>
            <Editor />
          </Profiler>
          <Preview />
        </Content>
      </Profiler>
    </App>
    

    StrictMode

    StrictMode는 개발 중에 컴포넌트에서 일반적인 버그를 빠르게 찾을 수 있도록 합니다.

    jsx

    <StrictMode>
      <App />
    </StrictMode>
    

    Strict Mode는 다음과 같은 개발 전용 동작을 활성화합니다.

    • 순수하지 않은 렌더링으로 인해 발생하는 버그를 찾기 위해 컴포넌트가 추가로 다시 렌더링됩니다.
    • Effect 클린업이 누락되어 발생하는 버그를 찾기 위해 컴포넌트가 추가로 Effect를 다시 실행합니다.
    • 더 이상 사용되지 않는 API의 사용여부를 확인하기 위해 컴포넌트를 검사합니다.

    전체 앱에 대한 Strict Mode를 활성화하고싶다면 루트 컴포넌트를 Strict Mode로 래핑하세요.

    jsx

    import { StrictMode } from 'react'
    import { createRoot } from 'react-dom/client'
    
    const root = createRoot(document.getElementById('root'))
    root.render(
      <StrictMode>
        <App />
      </StrictMode>
    )
    

    Strict Mode 검사는 개발 환경에서만 실행됩니다. 이는 코드에 존재하지만 프로덕션에서 제대로 재현하기 어려울 수 있는 버그를 찾는 데 도움이 됩니다.

    Suspense

    Suspense는 자식 요소가 로드되기 전까지 화면에 대체 UI를 보여줍니다.

    jsx

    <Suspense fallback={<Loading />}>
      <SomeComponent />
    </Suspense>
    

    Suspense는 다음과 같이 사용할 수 있습니다.

    콘텐츠가 로드되는 동안 대체 UI 보여주기

    애플리케이션의 모든 곳을 Suspense 경계로 감쌀 수 있습니다.

    아래 코드에서 React는 Albums가 로딩될 때 까지 loading fallback을 보여줍니다. 그리고 로딩이 완료되면 Albums를 표시합니다.

    Suspense가 가능한 데이터만이 Suspense 컴포넌트를 활성화합니다.
    독단적인 프레임워크를 사용하지 않는 Suspense가 가능한 데이터 불러오기 기능은 아직 지원되지 않습니다.

    • Relay, NextJS와 같이 Suspense가 가능한 프레임워크를 사용한 데이터 가져오기
    • lazy를 활용한 지연 로딩 컴포넌트
    • use를 사용해서 Promise 값 읽기

    Suspense는 Effect 또는 이벤트 핸들러 내부에서 가져오는 데이터를 감지하지 않습니다.

    콘텐츠를 한꺼번에 함께 보여주기

    기본적으로 Suspense 내부의 전체 트리는 하나의 단위로 취급됩니다. 예를 들어, 이러한 구성 요소 중 하나라도 어떤 데이터에 의해 지연되더라도 모든 구성 요소가 함께 로딩 표시로 대체됩니다.

    jsx

    <Suspense fallback={<Loading />}>
      <Biography />
      <Panel>
        <Albums />
      </Panel>
    </Suspense>
    

    추가적으로, 데이터를 로드하는 컴포넌트가 Suspense의 직접적인 자식일 필요는 없습니다.

    jsx

    ;<Suspense fallback={<Loading />}>
      <Details artistId={artist.id} />
    </Suspense>
    
    function Details({ artistId }) {
      return (
        <>
          <Biography artistId={artistId} />
          <Panel>
            <Albums artistId={artistId} />
          </Panel>
        </>
      )
    }
    

    중첩된 콘텐츠가 로드될 때 보여 주기

    컴포넌트가 일시 중단되면 가장 가까운 상위 Suspense 컴포넌트가 Fallback을 보여줍니다. 이를 통해 여러 Suspense 컴포넌트를 중첩하여 로딩 순서를 만들 수 있습니다. 각 Suspense의 Fallback은 다음 레벨의 콘텐츠를 사용할 수 있게 되면 채워집니다. 예를 들어 앨범 목록에 자체 Fallback을 지정할 수 있습니다.

    jsx

    <Suspense fallback={<BigSpinner />}>
      <Biography />
      <Suspense fallback={<AlbumsGlimmer />}>
        <Panel>
          <Albums />
        </Panel>
      </Suspense>
    </Suspense>
    

    이 변경을 통해 Biography를 보여줄 때 Albums의 로딩을 기다리지 않아도 됩니다.

    새 콘텐츠가 로드되는 동안 이전 콘텐츠 보여주기

    useDeferredValue의 예시처럼 Suspense를 통해서도 새 콘텐츠가 로드되는 동안 이전 콘텐츠를 보여줄 수 있습니다.

    이미 보인 콘텐츠가 숨겨지지 않도록 방지하기

    컴포넌트가 지연되면 가장 가까운 상위 Suspense가 Fallback을 보여주도록 전환합니다. 이미 일부 콘텐츠가 보이는 경우 사용자 경험이 끊길 수 있습니다. 아래 예제를 확인해봅시다.

    버튼을 눌렀을 때 ArtistPage 내부의 컴포넌트가 지연되어 가장 가까운 Suspense가 Fallback을 보여주기 시작합니다. 가장 가까운 Suspense는 root 근처이기때문에 전체 사이트 레이아웃이 대체됩니다.

    이를 방지하기 위해서 useTransitionstartTransition을 사용하여 이 업데이트를 transition으로 처리할 수 있습니다. 이는 state 전환이 급하지 않으며 이미 공개된 콘텐츠를 숨기기보단 이전 페이지를 계속 표시하는게 좋다는 것을 React에게 알립니다.

    위에 예제에서는 이를 적용하여 버튼을 클릭하면 Biography가 로드될 때까지 대기합니다.

    추가적으로, key를 사용하면 React에서는 서로 다른 컴포넌트로 취급하여 탐색하는동안 Suspense를 재설정하도록 할 수 있습니다.

    jsx

    <ProfilePage key={queryParams.id} />
    
    Profile Image

    신현호

    Frontend Developer

    프론트엔드 개발자를 꿈꾸고 있는 대학생입니다. 끊임없이 배우고 성장하는 개발자가 되기 위해 노력하고 있습니다.

    React Docs

    총 5개의 포스트가 존재합니다.