서론
JSX는 React와 밀접하게 사용되지만, 사실 JSX와 React는 서로 다른 개념이다. JSX는 문법 확장(syntax extension)이고, React는 JavaScript 라이브러리다. 많은 개발자들이 두 개념을 혼동하지만, JSX는 React와 독립적으로 사용할 수 있다. 이 글에서는 JSX의 정의, 왜 JSX를 사용하는지, 그리고 새로운 JSX 변환 방식이 등장한 이유에 대해 알아보겠다.
JSX의 규칙
JSX는 HTML과 비슷해 보이지만, 좀 더 엄격하다. 또한 동적인 정보를 표시할 수 있는 기능이 있다. 이 점이 JSX를 단순한 HTML 대체물이 아니라 특별한 문법 확장으로 만들어준다. 반면 React는 상태 관리, 컴포넌트 기반 구조 등 다양한 기능을 제공하는 라이브러리다.
1. 하나의 루트 요소 반환
JSX는 하나의 루트 요소만 반환할 수 있다. 여러 개의 요소를 반환하려면 <Fragment>나 빈 JSX 태그 <>...</>로 감싸야 한다. 이 방법을 사용하면 불필요한 DOM 노드를 추가하지 않고도 여러 요소를 하나로 그룹화할 수 있다.
return (
<>
<h1>Title</h1>
<p>Description</p>
</>
);
2. 모든 태그를 닫아야 한다
HTML에서는 일부 태그를 닫지 않아도 오류가 발생하지 않지만, JSX에서는 모든 태그를 명시적으로 닫아야 한다. 예를 들어 <img>는 <img />로, <li>는 <li>내용</li>로 작성해야 한다.
3. camelCase로 작성해야 한다
JSX에서 HTML 속성은 JavaScript 객체의 키로 변환되기 때문에 camelCase로 작성해야 한다. 예를 들어 class는 className으로, for는 htmlFor로 작성해야 한다.
JSX는 React에 종속적이지 않다.
JSX는 주로 React와 함께 쓰이지만, React와 독립적으로도 존재할 수 있다. 그러나 브라우저는 JSX를 해석할 수 없다. 따라서 JSX 코드를 일반 JavaScript로 변환하기 위해 컴파일러(예: Babel 또는 TypeScript)를 사용해야 한다. JSX를 사용하는 이유는 가독성을 높이고 코드 작성을 더 직관적으로 만들기 위함이지만, 결국 브라우저가 이해할 수 있는 JavaScript로 변환되어야 한다는 점은 변하지 않는다.
JSX 변환
React 17부터 새로운 JSX 변환 방식이 도입되었다. 기존에는 JSX가 React.createElement(...)로 변환되었다. 예를 들어, 아래 JSX 코드를 살펴보자.
import React from 'react';
function App() {
return <h1>Hello World</h1>;
}
위 코드는 기존 변환 방식에서는 아래와 같이 변환되었다.
import React from 'react';
function App() {
return React.createElement('h1', null, 'Hello world');
}
하지만 이 방식은 몇 가지 문제를 야기했다. JSX를 사용할 때마다 React를 반드시 import해야 했고, key나 ref 같은 특수 props가 자동으로 처리되었지만 그 과정이 비효율적이었다.
새로운 변환 방식
React 17부터는 JSX가 React.createElement 대신 react/jsx-runtime 모듈에서 제공하는 특별한 함수들로 변환된다.
기존 JSX 변환 방식에는 몇 가지 단점이 있었다.
- 첫째, .defaultProps가 React.lazy와 함께 제대로 작동하지 않아, 렌더링 단계에서 defaultProps를 따로 확인해야 하는 문제가 있었다.
- 둘째, 자식 요소들이 가변 인수(var args)로 전달되기 때문에 호출 시점에서 props의 구조를 정적으로 알 수 없었고, 이를 동적으로 처리해야 했는데, 이는 성능 저하를 초래할 수 있었다.
- 셋째, JSX가 React의 기본 import에 의존해 JSX를 사용할 때마다 React를 import해야 했다는 점도 불편함을 야기했다.
- 마지막으로, key와 ref가 JSX props에서 자동으로 추출되면서 객체를 복제하거나 삭제할 때 객체가 map-like 형태로 변해 성능 저하가 발생할 가능성이 있었다.
이러한 문제들은 새로운 JSX 변환 방식에서 크게 개선되었다. 예를 들어, 아래 코드를 보면
function App() {
return <h1>Hello World</h1>;
}
새로운 변환 방식에서는 다음과 같이 변환된다.
// babel 혹은 typescript에 의해 자동으로 import 된다
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('h1', { children: 'Hello world' });
}
이 새로운 변환 방식 덕분에 JSX는 더 가볍고 효율적으로 변환될 수 있다. 또한, React를 반드시 import하지 않아도 된다는 점에서 코드가 더 간결해졌다. 더 나은 방식으로 key와 ref가 처리되어 성능이 향상된다. 이제 자식 요소들은 항상 props.children으로 전달되어 코드의 일관성이 높아진다.
결론
JSX는 HTML과 비슷해 보이지만, 엄격한 규칙과 동적 기능을 제공한다는 점에서 더 발전된 문법이다. React 17의 새로운 JSX 변환은 기존의 문제를 해결하고, 더 간결하고 효율적인 코드를 작성할 수 있게 해준다.
'React' 카테고리의 다른 글
React Hook 이해하기 (1): useState (0) | 2024.09.10 |
---|---|
React에서의 Event Handler (0) | 2024.09.10 |
React에서 조건부 렌더링 (0) | 2024.09.02 |
React 컴포넌트 이해하기: UI의 기본 단위 (0) | 2024.09.02 |
React로 UI 구성: 단계별 접근 가이드 (0) | 2024.08.23 |