목차


에러 분석


리액트 컴포넌트를 사용할 때에는 무조건 대문자로 시작해야 한다. <bCompo>라는 소문자 컴포넌트를 이용을 하면 브라우저에 이런 에러가 뜬다.

에러
The tag <bCompo> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

해석
<bCompo>는 이 브라우저에서 인식되지 않습니다. React 구성 요소를 렌더링하려는 경우 이름을 대문자로 시작하세요.

리액트에서도 친절하게 대문자를 사용하라고 한다. 왜 대문자로 사용해야 할까? 그것을 알려면 리액트 JSX문법의 원리를 알아야 한다.

React.createElement()


리액트 공식문서에서 createElement를 살펴볼수 있다. 우리가 흔히 사용하는 JSX문법은 babel에 의해 react가 읽을 수 있는 코드인 createElement()로 변환된다.

babel을 통한 JSX문법 변환


아래의 코드는 우리가 흔히 사용하는 JSX문법을 사용한 리액트 코드이다.

const ACompo = () => {
  return (
    <div>
      <p>ACompo</p>
    </div>
  )
}

const BCompo = () => {
  return (
    <div>
      <p>BCompo</p>
    </div>
  )
}

const CCompo = () => {
  return (
    <>
      <ACompo/>
      <bcompo/>
    </>
  )
}

위의 코드는 babel의 @babel-plugin-transform-react.jsx 플러그인으로 인해 아래와 같은 코드로 변환된다.

변환 후 코드


babel로 변환 후의 코드

위의 코드에서 /*#__PURE__*/_jsxReact.createElement로 생각하면 된다.

babel의 Try it out에서 직접 코드를 입력하여 확인해 볼 수 있다.

번외) JSX없이 엘리먼트 만들기 (createElement만으로 엘리먼트 만들기)

그렇다면 번외로 처음부터 createElement로 작성해도 잘 동작할까?

JSX 없이 작성된 코드 JSX 없이 작성된 코드 결과

위의 그림과 같이 당연히(?) 잘 나오는 것을 볼 수 있다. 그 이유는 위에서 말했듯이 우리가 작성한 JSX문법은 결국 createElement로 변환하여 사용되기 때문이다.

대문자만 가능한 이유


그렇다면 본론으로 돌아와서 리액트 컴포넌트가 대문자만 사용 가능한 이유는 HTML태그와 컴포넌트를 분리하기 위해서 이다. 위의 변환 후 코드를 다시 살펴보자.

/*#__PURE__*/_jsxcreateElement로 바꾸었다.

const ACompo = () => {
  return createElement("div", {
    children: createElement("p", {
      children: "ACompo"
    })
  });
};

const BCompo = () => {
  return createElement("div", {
    children: createElement("p", {
      children: "BCompo"
    })
  });
};

const CCompo = () => {
  return createElements(_Fragment, {
    children: [createElement(ACompo, {}), createElement("bcompo", {})]
  });
};

CCompochildren 내부를 살펴보자.

[createElement(ACompo, {}), createElement("bcompo", {})]

createElement내부를 보면 대문자로 시작된 ACompo는 함수 그대로 들어가 있는데, bCompo는 문자열로 들어가있는 것을 볼 수 있다. 여기서 문자열로 변환된 곳이 또 있다. ACompo, BCompo의 내부도 “div”, 문자열로 들어가 있는 것을 볼 수 있다. 소문자로 시작된 것은 컴포넌트로 보지않고 HTML의 tag로 인지하여 문자열로 들어간다. 그래서 bCompo뿐만 아니라 div도 문자열로 들어가 있는 것이다. 대문자로 해야 우리가 작성한 함수가 그대로 들어가 컴포넌트 그대로를 인지할 수 있다.

결론


babel은 JSX에서 대소문자로 컴포넌트와 HTML 태그를 구분하여 변환한다. 그래서 컴포넌트로 사용할 때에는 대문자로 사용해야 원하는 컴포넌트를 화면에 노출 될 수 있도록 해야한다.