본문 바로가기
부트캠프

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 70 (리액트 라이브러리 API, 리액트 컴포넌트, 컴포넌트 렌더링)

by 나른한_꼬리_ 2025. 8. 12.
반응형

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 70 (리액트 라이브러리 API, 리액트 컴포넌트, 컴포넌트 렌더링)

 

목차

 

리액트 라이브러리 API

리액트 라이브러리를 사용하면 정적 마크업을 동적으로 구현할 수 있다. React.createElement는 리액트 앱 UI를 구성하는 요소(Element)를 생성하는 API(함수)다. ReactDOM.createRoot는 리액트로 구현된 요소 트리(Element Tree)를 실제 DOM에 렌더링하는 API(함수)다.

// React.createElement(type, props, ...children)
const divElement = React.createElement('div', { className: 'container' })

// ReactDOM.createRoot(element)
const root = ReactDOM.createRoot(document.querySelector('main'))
root.render(divElement)

 

접근성 문제

자바스크립트를 지원하지 않는 환경에서는 자바스크립트(또는 리액트)로 구현하여 렌더링하는 경우 정상적으로 작동하지 않기 때문에 접근성에 문제가 생긴다. 자바스크립트 미지원 환경에서 아무런 정보를 제공하지 않기 때문이다. 일부 검색 엔진 봇은 자바스크립트를 실행하지 않고 HTML만 읽기도 한다. 자바스크립트를 지원하지 않는 환경에 대한 고려가 필요하다. 자바스크립트 없이도 접근할 수 있도록 만드는 것이 웹 접근성검색 최적화에 중요하다.

 

최소한의 정보를 제공해 모든 사용자의 접근성을 높이는 방법으로 <noscript> 요소를 사용하여 자바스크립트 미지원 환경에 대응할 수 있다.

<noscript>
  이 사이트를 이용하려면?<br />
  사용 중인 웹 브라우저에서 JavaScript를 활성화해야 합니다.
</noscript>

 

 

리액트 컴포넌트

리액트 컴포넌트는 UI를 구성하는 독립적이고 재사용 가능한 코드 조각(piece)으로, 각 컴포넌트는 자체적으로 상태와 UI를 관리하며, 컴포넌트를 조합하여 복잡한 화면을 효율적으로 만들 수 있다. 컴포넌트는 독립적으로 분리되어 재사용되는 것을 목적으로 한다. 리액트 앱에서 컴포넌트는 개별적인 파일로 분리해서 관리한다.

컴포넌트 트리

컴포넌트는 다른 컴포넌트를 내부에 포함할 수 있다. 포함된 컴포넌트는 하위 컴포넌트, 포함하는 컴포넌트는 상위 컴포넌트가 된다. 그리고 이렇게 구성된 구조를 컴포넌트 트리라고 부른다.

 

 

컴포넌트 타입

컴포넌트는 재사용을 목적으로 설계한다. 자바스크립트에서는 재사용할 수 있는 설계 구현을 위해 함수나 클래스를 사용한다. 함수와 클래스 타입이 재사용을 위한 리액트 컴포넌트의 타입이다.

 

 

함수 컴포넌트

리액트 컴포넌트는 개념상 자바스크립트 함수와 유사하다. 컴포넌트 외부러부터 속성을 전달 받아 어떻게 UI를 구성해야 할지 설정하여 리액트 엘리먼트를 반환한다. 이런 구문을 사용하는 컴포넌트를 리액트 함수형(functional)으로 분류한다.

function AppButton(props) {
  return React.createElement(
    'button',
    {
      type: 'button',
      className: 'normal-button'
    },
    props.children
  )
}

 

클래스 컴포넌트

클래스 문법을 사용해 컴포넌트를 정의할 수도 있다. 함수 컴포넌트와 다르게 리액트의 컴포넌트를 확장해서 사용해야 한다. 일반 클래스를 사용하면 리액트에서 제대로 렌더링하지 못하기 때문이다.

class AppButton extends React.Component {
  constructor(props) {
    super(props)
  }

  render() {
    return React.createElement(
      'button',
      {
        type: 'button',
        className: 'normal-button'
      },
      props.children
    )
  }
}

오늘날 클래스 컴포넌트 구문은 리액트에서 잘 사용되지 않는다.

 

 

컴포넌트 추출

컴포넌트 구조가 복잡할 때는 요청사항에 따라 변경이 까다로울 수도 있고 재사용하기도 어렵다. 이럴 때 컴포넌트를 작게 나눠 재사용하는 용도로 구분해 개발하는 것이 좋다. 함수를 작게 구성해 단일 책임 원칙에 맞게 구성해 재사용하는 것과 같다. 컴포넌트를 분리하면 앱 규모가 커질수록 효율적으로 관리하기 좋아진다.

컴포넌트를 내보낼 때는 다음과 같이 작성한다.

// components/app.js
export default function App(props) {
  return React.createElement(
    // ...
  )
}

 

추출된 컴포넌트는 다음과 같이 불러와 사용한다.

// main.js
import App from './components/app.js'

// ...

 

 

컴포넌트 렌더링

컴포넌트는 리액트 엘리먼트로 렌더링(rendering)된다. 클래스의 인스턴스를 만드는 것과 같다. React API를 사용할 때는 아래처럼 컴포넌트 참조를 type으로 설정하고 props 객체를 전달한다.

React.createElement(AppButton, { type: 'button' }, '메뉴 펼치기')

 

컴포넌트 이름은 항상 대문자로 시작하는 PascalCase 방식을 사용해야 한다. 실제 HTML 표준 요소 이름은 대소문자 모두 사용할 수 있지만, 일반적으로 소문자만 사용한다. HTML 표준 컴포넌트의 인스턴스와 리액트 엘리먼트를 구분짓기 위해서 리액트 엘리먼트는 항상 대문자로 시작한다.

 

리액트 컴포넌트에 전달되는 속성(properties)은 항상 객체로 props라고 줄여 부른다.

 

조건부 렌더링

전달된 컴포넌트 속성(props)에 따라 렌더링 결과가 달라지는 것을 조건부 렌더링이라고 한다. 조건문값을 제공하지 않기 때문에 함수 컴포넌트 몸체에서는 사용할 수 있지만, createElemet() 함수 내부에서는 사용할 수 없다. 조건문 대신 표현식을 사용하면 값을 제공하기 때문에 함수 컴포넌트 몸체와 createElement() 함수 내부 모두 사용할 수 있다.

 

 

리스트 렌더링

동일한 컴포넌트를 여러 번 렌더링해야 할 때 반복문을 활용해 컴포넌트 배열을 만들거나 배열 객체의 map() 메서드를 사용할 수 있다. 배열의 map() 메서드나 filter() 메서드와 같이 새로운 배열을 반환하는 메서드는 createElement() 함수 내부에 넣을 수도 있다.

 

오늘 하루를 돌아보며

리액트에서는 컴포넌트라는 개념을 잘 이해하는 것이 중요하다는 생각이 들었다. 일상에서도 웹사이트에 들어갔을 때나, 앱을 사용할 때, 혹은 다양한 상황에서 컴포넌트로 분리해보는 훈련을 해봐야겠다.

 

예를 들어, 메시지 앱에 들어가면 사용자 아바타 아이콘, 사용자 이름, 보낸 날짜, 보내는 말풍선, 보낸 시간, 답장 말풍선 등으로 나눠볼 수 있겠다.

 

반응형