[React] 컴포넌트

sikkzz·2023년 8월 15일
0

React

목록 보기
4/12
post-thumbnail

엘리먼트

엘리먼트(element)는 View에 렌더링 할 내용을 React에 알려주기 위한 수단으로, React 애플리케이션을 구성하는 가장 작은 블록입니다.

const element = <p className="greeting">Hello, World</p>

React 엘리먼트는 HTML 태그의 이름을 값으로 가지는 type 필드와 그 외 속성들을 값으로 전달받는 props 필드로 구성된 객체(object) 형태로 정의되며, React는 이 객체를 읽어들여 DOM을 구성하고 최신 상태로 업데이트하는데 사용합니다.

React 엘리먼트는 일반 객체(plain object)로 손쉽게 생성할 수 있지만, 불변 객체(immutable object)이기 때문에 일단 생성된 후에는 상태나 속성을 변경할 수 없습니다. 따라서 React에서 UI를 업데이트하는 방법은 새로운 엘리먼트를 생성하고, 이를 render() 메서드에 전달하는 것입니다.

루트 DOM 노드

React 애플리케이션에는 id 속성값이 root인 "div" 요소가 하나 존재합니다. 이를 루트 DOM 노드(Root DOM Node)라고 부르며, 이 내부에 들어가는 모든 요소들은 React DOM에서 관리하게 됩니다.

React 프로젝트 파일 중 public 폴더의 index.html 파일을 열어보면, "body" 요소 안에 아래와 같은 루트 DOM 노드가 존재함을 확인할 수 있습니다.

<div id="root"></div>

React 애플리케이션은 일반적으로 하나의 루트 DOM 노드를 가지지만, 기존 애플리케이션에 React를 순차적으로 도입하려는 경우에는 원하는 만큼의 독립된 루트 DOM 노드를 포함할 수도 있습니다.

엘리먼트의 렌더링

React 애플리케이션에서 index.js 파일은 애플리케이션의 진입점입니다. 초기 코드는 아래와 같습니다.

import React from 'react';
import ReactDom from 'react-dom/client';
import App from './App';

const root = ReactDom.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

우선 루트 DOM 요소를 createRoot() 함수에 전달하여 새로운 루트 DOM 노드를 생성하여 반환합니다. 이렇게 반환된 루트 DOM 노드의 render() 메서드에 화면에 나타내길 원하는 엘리먼트들을 전달하여 View를 렌더링하게 됩니다.

index.js 파일의 코드를 아래와 같이 수정하면 새롭게 생성한 element라는 React 엘리먼트를 화면에 렌더링 할 수 있습니다.

import React from 'react';
import ReactDom from 'react-dim/client';
import App from './App';

const root = ReactDom.createRoot(document.getElementById('root'));
const element = <h1>새로운 React 엘리먼트</h1>;
root.render(element);

컴포넌트

React에서 컴포넌트란 자바스크립트 함수의 개념과 비슷하게 이해할 수 있습니다. React에서는 애플리케이션의 UI를 설계할 때 사용자가 볼 수 있는 화면을 여러 개의 컴포넌트로 나누어 구성함으로써 각각의 컴포넌트를 개별적으로 관리할 수 있습니다.

이러한 컴포넌트는 단순히 재사용이 가능한 템플릿의 역할 뿐만 아니라, 데이터(props)를 입력 받아 View의 상태에 따라 화면에 어떻게 표시되는지를 정의하는 React 엘리먼트를 반환합니다.

React 컴포넌트는 선언하는 방식에 따라 클래스 기반의 컴포넌트와 함수 기반의 컴포넌트로 구분할 수 있습니다.

클래스 컴포넌트와 함수 컴포넌트

컴포넌트를 정의하는 가장 간단한 방법은 자바스크립트 함수를 작성하는 것입니다.

export default function App() {
  return (
    <div>
      <h1>Hello, World!</h1>
    </div>
  );
}

또한 class 키워드를 사용하여 클래스 기반의 컴포넌트를 정의할 수도 있습니다.

클래스 컴포넌트는 Component 클래스를 상속해야 하며, render() 메서드를 반드시 구현해야 합니다. 그리고 render() 메서드를 통해 화면에 보여주어야 할 JSX 표현식(expression)을 반환하면 됩니다.

import React from 'react';
export default class App extends React.component {
  render() {
    return <h1>Hello, World!</h1>;
  }
}

React에서 이 두 가지 유형의 컴포넌트는 기능적으로 완전히 동일하게 동작합니다. 단지 클래스 컴포넌트는 state 기능과 생명 주기 메소드를 사용할 수 있지만, 함수 컴포넌트에서는 해당 기능들을 사용할 수 없다는 차이점만 있었습니다.

하지만 함수 컴포넌트는 클래스 컴포넌트보다 선언하는 방법이 훨씬 간결하고, 메모리의 소비 또한 적다는 장점을 가집니다. 그리고 state 기능과 생명 주기 메소드의 사용이 불가능하다는 단점 또한 Reactv16.8부터 새롭게 추가된 Hook을 사용함으로써 더 이상 문제가 되지 않게 되었습니다.

React 공식 문서에서는 클래스 컴포넌트보다는 함수 컴포넌트와 Hook의 사용을 권장하고 있습니다.

컴포넌트의 생성

React에서 컴포넌트를 생성할 때는 반드시 컴포넌트의 이름을 대문자로 시작하도록 작성해야 합니다. React는 소문자로 시작하는 이름의 컴포넌트를 "h1", "div"와 같은 정규 HTML 태그로 취급하기 때문입니다.

소문자로 시작하는 내장 컴포넌트는 'h1'이나 'div'같은 문자열 형태로 React.createElement() 메서드에 전달되지만, "Greeting"과 같이 대문자로 시작되는 사용자 정의 컴포넌트는 React.createElement(Greeting)의 형태로 컴파일되어 자바스크립트 파일에서 사용자가 직접 정의했거나 import를 통해 가져온 컴포넌트를 가리키게 됩니다.

Greeting 컴포넌트를 작성해보겠습니다.

function Greeting() {
  return (
    <>
      <h1>React Component</h1>
      <p>나의 첫 React 컴포넌트!</p>
    </>
  );
}

export default Greeting;

그 후 App.js 파일에 작성한 Greeting 컴포넌트를 import해서 렌더링 시킵니다.

import Greeting from './Greeting';

function App() {
  return <Greeting />;
}

export default App;

이렇게 사용자 정의 컴포넌트를 사용하는 이유는 React.createElement() 메서드의 호출이나 JSX 구문으로 생성하는 Virtual DOM의 생성 코드를 사용자 정의 컴포넌트 쪽으로 이동시킴으로써 코드를 간결하게 만들고 재사용의 목적을 둡니다.

profile
FE Developer

0개의 댓글