React의 핵심 개념 이해하기: React Element


react

React는 효율적이고 선언적인 UI 개발을 가능하게 하는 라이브러리입니다. React의 강력한 성능과 유연성은 두 가지 핵심 개념, React Element와 Virtual DOM에 기반하고 있습니다. 이번 포스트에서는 이 두 가지 개념이 무엇인지, 그리고 React가 어떻게 이를 활용해 UI를 효율적으로 업데이트하는지 알아보겠습니다.


React Element란 무엇인가?

React Element는 React에서 UI를 표현하는 가장 기본적인 단위로, 컴포넌트를 통해 UI를 구성하지만 실제로 화면에 렌더링되는 것은 React Element입니다. 또한, React Element는 React의 렌더링 프로세스에서 중요한 역할을 하며, 컴포넌트가 상태나 props를 기반으로 새로운 React Element를 반환하면 React는 이를 Virtual DOM에 반영하고 UI를 업데이트합니다.


React Element의 특징

1. JavaScript 객체

React Element는 화면에 표시될 DOM 노드나 컴포넌트를 나타내는 불변 객체입니다.

JSX로 작성된 코드:

const element = (  
  <div id="container" className="main-container">  
    <h1 style={{ color: 'blue', fontSize: '24px' }}>Hello, React!</h1>  
    <p>  
      React Element는 UI를 표현하는 가장 기본적인 단위입니다.   
      아래는 React Element의 주요 특징입니다:  
    </p>  
    <ul>  
      <li>React Element는 불변 객체입니다.</li>  
      <li>React는 상태나 props가 변경되면 새로운 React Element를 생성합니다.</li>  
      <li>React Element는 Virtual DOM의 기반이 됩니다.</li>  
    </ul>  
    <button onClick={() => alert('React Element 클릭!')}>클릭하세요</button>  
  </div>  
);

위 코드는 React.createElement를 호출하여 다음과 같은 객체를 생성합니다:

const element = {  
  type: 'div',  
  props: {  
    id: 'container',  
    className: 'main-container',  
    children: [  
      {  
        type: 'h1',  
        props: {  
          style: { color: 'blue', fontSize: '24px' },  
          children: 'Hello, React!',  
        },  
      },  
      {  
        type: 'p',  
        props: {  
          children: 'React Element는 UI를 표현하는 가장 기본적인 단위입니다. 아래는 React Element의 주요 특징입니다:',  
        },  
      },  
      {  
        type: 'ul',  
        props: {  
          children: [  
            { type: 'li', props: { children: 'React Element는 불변 객체입니다.' } },  
            { type: 'li', props: { children: 'React는 상태나 props가 변경되면 새로운 React Element를 생성합니다.' } },  
            { type: 'li', props: { children: 'React Element는 Virtual DOM의 기반이 됩니다.' } },  
          ],  
        },  
      },  
      {  
        type: 'button',  
        props: {  
          onClick: () => alert('React Element 클릭!'),  
          children: '클릭하세요',  
        },  
      },  
    ],  
  },  
};

2. 불변성(Immutability)

React Element는 불변 객체(Immutable Object)입니다. 이는 React Element가 한 번 생성되면 변경되지 않는다는 것을 의미합니다. React는 상태(state)나 props가 변경될 때마다 새로운 React Element를 생성하며, 이전 React Element를 직접 수정하지 않습니다. 이러한 불변성은 React의 효율적인 렌더링과 Virtual DOM의 작동 원리를 이해하는 데 중요한 개념입니다.

React Element가 불변인 이유

React Element가 불변으로 설계된 이유는 다음과 같습니다:

  1. 변경 추적의 용이성
    • React는 상태나 props가 변경될 때 새로운 React Element를 생성하고, 이전 React Element와 새로운 React Element를 비교(diffing)하여 변경된 부분만 실제 DOM에 반영합니다.
    • React Element가 불변이기 때문에, React는 이전 상태를 안전하게 참조할 수 있으며, 변경 사항을 효율적으로 추적할 수 있습니다.
  2. Virtual DOM의 효율성
    • Virtual DOM은 React Element를 기반으로 생성됩니다. React Element가 불변이기 때문에, React는 Virtual DOM에서 변경된 부분만 계산(diffing)하고, 최소한의 DOM 업데이트를 수행할 수 있습니다.
    • 만약 React Element가 가변적이었다면, 변경 사항을 추적하기 위해 더 복잡한 로직이 필요했을 것입니다.
  3. 코드의 안정성과 예측 가능성
    • 불변 객체는 코드의 안정성을 높이고, 예측 가능한 동작을 보장합니다.
    • React Element가 불변이기 때문에, 개발자는 React Element를 직접 수정하는 실수를 방지할 수 있습니다.

3. UI의 스냅샷

React Element는 UI의 현재 상태를 나타내는 스냅샷(Snapshot) 역할을 합니다. React에서 UI는 React Element로 표현되며, React Element는 컴포넌트의 상태(state)와 props를 기반으로 생성됩니다. React는 상태나 props가 변경될 때마다 새로운 React Element를 생성하여 UI의 새로운 스냅샷을 만듭니다. 이러한 스냅샷은 React의 렌더링 프로세스와 Virtual DOM 업데이트의 핵심입니다.

UI의 스냅샷이란 무엇인가?

UI의 스냅샷은 특정 시점에서의 UI 상태를 React Element로 표현한 것입니다. React는 컴포넌트의 상태와 props를 기반으로 React Element를 생성하며, 이 React Element는 UI의 현재 상태를 정확히 반영합니다.

스냅샷의 특징
  1. 정적인 UI 상태 표현
    • React Element는 특정 시점에서의 UI 상태를 나타내며, 변경되지 않는 불변 객체입니다.
    • 상태나 props가 변경되면 새로운 React Element가 생성되어 새로운 스냅샷을 제공합니다.
  2. Virtual DOM의 기반
    • React Element는 Virtual DOM을 구성하는 기본 단위입니다.
    • React는 이전 React Element와 새로운 React Element를 비교(diffing)하여 변경된 부분만 실제 DOM에 반영합니다.
  3. 렌더링 프로세스의 시작점
    • React는 컴포넌트가 반환하는 React Element를 기반으로 렌더링을 수행합니다.
    • React Element는 UI의 “무엇을 렌더링할지”를 선언적으로 표현합니다.


JSX와 React의 주요 개념:

JSX, ReactNode, JSX.Element, ReactElement

React를 처음 배우는 초보 개발자들은 종종 JSX를 HTML과 동일하게 생각하는 실수를 합니다. 하지만 JSX는 HTML이 아니며, React에서 UI를 선언적으로 표현하기 위해 사용하는 JavaScript 확장 문법입니다. JSX는 HTML과 비슷한 문법을 사용하지만, 실제로는 JavaScript 코드로 변환됩니다. React는 JSX를 React.createElement 함수 호출로 변환하여 React Element를 생성합니다. 따라서 JSX는 HTML의 대체물이 아니라, React에서 UI를 정의하기 위한 도구로, React Element를 생성하는 데 사용됩니다.

React에서 UI를 구성하는 데 사용되는 주요 개념으로는 ReactNodeJSX.Element, 그리고 ReactElement가 있습니다. 이들은 모두 React에서 UI를 표현하는 데 중요한 역할을 하지만, 각기 다른 범위와 사용 사례를 가지고 있습니다. 아래에서 이 개념들을 비교하고, 차이점과 사용 사례를 명확히 설명하겠습니다.

1. JSX와 React Element

JSX는 React에서 UI를 선언적으로 표현하기 위한 문법적 설탕(Syntactic Sugar)입니다. JSX를 사용하면 HTML과 유사한 문법으로 React Element를 작성할 수 있습니다. 하지만 JSX는 브라우저가 이해할 수 있는 문법이 아니기 때문에, React는 이를 React.createElement 함수 호출로 변환하여 React Element를 생성합니다.

JSX와 React Element의 관계
  • JSX는 React Element를 생성하기 위한 문법입니다.
  • React Element는 React에서 UI를 표현하는 가장 기본적인 단위로, 불변 객체입니다.
  • JSX로 작성된 코드는 내부적으로 React.createElement를 호출하여 React Element를 반환합니다.
// JSX로 작성된 React Element
const element = <h1>Hello, React!</h1>;

// React.createElement로 작성된 동일한 React Element
const element2 = React.createElement("h1", null, "Hello, React!");

위 두 코드는 동일한 React Element를 생성하며, React는 이를 Virtual DOM에 반영하여 UI를 업데이트합니다.

2. ReactNode

ReactNode는 React에서 렌더링할 수 있는 모든 값을 포함하는 가장 포괄적인 타입입니다. React 컴포넌트가 반환할 수 있는 모든 값이 ReactNode에 해당합니다.

ReactNode의 특징
  • ReactNode는 다음과 같은 값들을 포함합니다:
    • string (예: "Hello")
    • number (예: 123)
    • boolean (예: truefalse) → 렌더링되지 않음
    • null 또는 undefined → 렌더링되지 않음
    • ReactElement (JSX로 생성된 React 요소)
    • ReactFragment (여러 요소를 그룹화하는 데 사용)
    • 배열 (ReactNode의 배열)
    • Portal (React Portal로 렌더링된 요소)
ReactNode의 사용 사례
  • 컴포넌트의 children 타입으로 자주 사용됩니다.예를 들어, children이 문자열, JSX, 또는 다른 React 컴포넌트를 포함할 수 있는 경우:
type Props = {
  children: React.ReactNode;
};

const Wrapper: React.FC<Props> = ({ children }) => {
  return <div className="wrapper">{children}</div>;
};

3. JSX.Element

JSX.Element는 JSX 문법으로 생성된 React Element의 타입입니다. JSX를 사용하여 작성된 모든 요소는 JSX.Element 타입을 가집니다.

JSX.Element의 특징
  • JSX를 사용하여 생성된 React Element만 포함합니다.
  • JSX.Element는 ReactElement의 특정 타입으로, 일반적으로 JSX 문법으로 생성된 요소를 나타냅니다.
JSX.Element의 사용 사례
  • 컴포넌트가 JSX를 반환할 때 타입을 명시적으로 지정할 수 있습니다.

const MyComponent = (): JSX.Element => {
  return <div>This is a JSX.Element</div>;
};

4. ReactElement

ReactElement는 React에서 UI를 표현하는 불변 객체로, React Element의 타입을 나타냅니다. ReactElement는 JSX를 사용하거나 React.createElement를 호출하여 생성됩니다.

ReactElement의 특징
  • ReactElement는 React에서 UI를 표현하는 가장 기본적인 단위입니다.
  • ReactElement는 type과 props를 포함하는 객체입니다.
  • JSX로 생성된 요소는 내부적으로 React.createElement를 호출하여 ReactElement를 반환합니다.
  • ReactElement는 JSX.Element보다 더 일반적인 타입으로, JSX 외에도 React.createElement로 생성된 요소를 포함합니다.
ReactElement의 사용 사례
  • 컴포넌트가 반환하는 값이 React Element임을 명시적으로 지정할 때 사용됩니다.
const MyComponent = (): React.ReactElement => {
  return <div>This is a ReactElement</div>;
};

5. React.FC와 JSX의 차이

React.FC는 React Functional Component를 정의하기 위한 타입스크립트 유틸리티 타입입니다. JSX는 UI를 선언적으로 표현하기 위한 문법인 반면, React.FC는 함수형 컴포넌트를 정의할 때 사용됩니다. 이 둘은 역할과 사용 목적이 다릅니다.

React.FC의 특징
  • React.FC는 함수형 컴포넌트의 타입을 정의할 때 사용됩니다.
  • 기본적으로 children을 포함하는 props 타입을 제공합니다.
  • 컴포넌트의 반환값은 ReactElement로 제한됩니다.
React.FC와 JSX의 차이

결론

React Element는 React에서 UI를 표현하는 불변 객체로, React의 렌더링 프로세스와 Virtual DOM의 핵심입니다. React는 상태(state)나 props가 변경될 때마다 새로운 React Element를 생성하여 UI의 스냅샷을 업데이트합니다. 이러한 불변성과 선언형 프로그래밍 방식 덕분에 React는 효율적으로 변경 사항을 추적하고, 최소한의 DOM 업데이트를 수행할 수 있습니다. React Element는 컴포넌트 내부에서 반환되는 값으로, React의 모든 UI 구성 요소의 기본 단위입니다.

React의 주요 개념 요약

  • ReactNode: 렌더링 가능한 모든 값을 포함하는 가장 포괄적인 타입.
  • JSX.Element: JSX 문법으로 생성된 React Element만 포함.
  • ReactElement: React에서 UI를 표현하는 불변 객체로, JSX 또는 React.createElement로 생성된 요소를 포함.
  • React.FC: 함수형 컴포넌트를 정의하기 위한 타입스크립트 유틸리티 타입.

React Element의 중요성

React Element를 이해하는 것은 React의 렌더링 프로세스와 Virtual DOM의 작동 원리를 이해하는 데 필수적입니다. React Element는 UI의 현재 상태를 나타내는 스냅샷 역할을 하며, React는 이를 기반으로 효율적인 업데이트를 수행합니다. React의 선언형 프로그래밍 방식과 불변성 원칙은 React Element를 중심으로 작동하며, 이를 통해 React는 복잡한 UI를 간단하고 예측 가능하게 관리할 수 있습니다.

React의 이러한 핵심 개념들을 이해하면, React 애플리케이션의 성능을 최적화하고 유지보수성을 높이는 데 큰 도움이 됩니다. React를 효과적으로 사용하려면 React Element와 관련된 개념들을 명확히 이해하고, 이를 기반으로 컴포넌트를 설계하는 것이 중요합니다.

jeewoo jung 아바타