React

JSX는 어떻게 자바스크립트에서 변환될까?

ea_jung 2024. 4. 23. 00:29

@babel/plugin-transform-react-jsx 플러그인이 JSX 구문을 JS가 이해할 수 있는 형태로 변환합니다.

 

 

⭐️⭐️  예시. JSX에서 => JS가 이해할 수 있는 형태로 반환합니다.

  // JSX 코드
  const ComponentA = <A required={true}>Hi</A>

  const ComponentB = <>Hi<>

  const ComponentC = (
    <div>
      <span>Hi<span>
    </div>
  )
  // JSX 코드를 @babel/plugin-transform-react-jsx로 변환한 결과
  'use strict'

  var ComponentA = React.createElement(
    A,
    {
      required: true
    },
    'Hi',
  )

  var ComponentB = React.createElement(React.Fragment, null, 'Hi')

  var ComponentC = React.createElement(
    'div',
    null,
    React.createElement('span', null, 'Hi'),
  )

 

리액트 17, 바벨 7.9.0 이후 버전에서 추가된 자동 런타임(automatic runtime)으로 트랜스파일한 결과는 조금 다르지만 결국에는 공통점이 있습니다. 

 

1. JSXElement를 첫 번째 인수로 선언해 요소를 정의합니다. 

2. 옵셔널인 JSXchildren, JSXAttributes, JSXStrings는 이후 인수로 넘겨주어 처리합니다. 

이를 통해서 실제 활용해 볼 수 있는 점은 JSXElement를 렌더링해야 할 떄, 굳이 요소 전체를 감싸지 않더라도 처리할 수 있다는 점입니다. 이는 JSXElement만 다르고, JSXAttributes, JSXChildren이 완전히 동일한 상황에서 중복 코드를 최소화 할 수 있어 유용합니다. 

 

  // props 여부에 따라 children 요소만 달라지는 경우
  // 굳이 번거롭게 전체 내용을 삼항 연산자로 처리할 필요가 없다.
  // 이 경우 불필요한 코드 중복이 일어난다.
  import {createElement, PropsWithChildren} from 'react'

  function TextOrHeading({
    isHeading,
    children,
  }: PropsWithChildren) {
    return isHeading ? (
      <h1 className="text">{children}</h1>
      ) : (
        <span>{children}</span>
      )
  }

  // JSX가 변환되는 특성을 활용한다면 다음과 같이 간결하게 처리 할 수 있다.
  import {createElement} from 'react'

  function TextOrHeading({
    isHeading,
    children
  }: PropsWithChildren<{ isHeading: boolean}>) {
    return createElement(
      isHeading ? 'h1' : 'span',
      { className: 'text' },
      children,
    )
  }

 

JSX 반환값이 결국 React.createElement로 귀결된다는 사실을 파악한다면 이런 식으로 쉽게 리팩토링 할 수 있습니다. 

반응형