
JSX는 흔히 개발자들이 알고 있는 XML과 유사한 내장형 구문이다. JSX가 포함된 구문을 아무런 처리 없이 그대로 실행하면 에러가 발생하며, 반드시 트랜스파일러를 거쳐야 비로소 자바스크립트 런타임이 이해할 수 있는 의미 있는 자바스크립트 코드로 변환된다. JSX의 설계 목적은 다양한 트랜스파일러에서 다양한 속성을 가진 트리 구조를 토큰화 해 ECMAScript로 변환하는데 초점을 두고 있다.
요약하자면 JSX는 자바스크립트 내부에서 표현하기 까다로웠던 XML 스타일의 트리 구문을 작성하는 데 많은 도움을 주는 새로운 문법이라고 볼 수 있다.
JSX는 기본적으로 JSXElement, JSXAttributes, JSXChildren, JSXStrings라는 4가지 컴포넌트를 기반으로 구성되어 있다.
JSX를 구성하는 가장 기본 요소로, HTML의 element와 비슷한 역할을 한다. JSXElement가 되기 위해서는 다음과 같은 형태 중 하나여야 한다.
JSXOpeningElementJSXOpeningElement로 시작했다면 후술할 JSXClosingElement가 동일한 요소로 같은 단계에서 선언되어 있어야 올바른 JSX 문법으로 간주된다.<JSXElemnt JSXAttributes(optional)>JSXClosingElementJSXOpeningElement가 종료됐음을 알리는 요소JSXOpeningElement와 쌍으로 사용되어야 한다.</JSXElemnt>JSXSelfClosingElement<JSXElement JSXAttributes(optional) />JSXFragmentJSXSelfClosingElement 형태를 띨 수는 없다.<>JSXChildren(optional)</>JSXElement의 요소 이름으로 쓸 수 있는 것을 의미
JSXIdentifierJSXNamespacedNameJSXIdentifier:JSXIdentifier의 조합JSXMemberExpressionJSXIdentifier.JSXIdentifier의 조합JSXElement에 부여할 수 있는 속성을 의미한다.
모든 경우에서 필수값이 아니고, 존재하지 않아도 에러가 나지 않는다.
function Example() {
return (
<Component attribute="hello"></Component>
<Component attribute=<div>hello</div>></Component>
);
}
JSXElement의 자식 값을 나타낸다.
JSXChildren을 이루는 기본 단위
JSXChildren은 JSXChild를 0개 이상 가질 수 있다.
function Example() {
return (
<>{'{}'}</>
<>{(() => 'foo')()}</>
);
}
HTML에서 사용 가능한 모든 문자열은 JSXStrings에서도 사용 가능하다.
자바스크립트와는 한가지 중요한 차이점이 있다.
\로 시작하는 이스케이프 문자 형태소 또한 제약없이 사용할 수 있다.
\는 자바스크립트에서 특수문자를 처리할 때 사용되므로 제약사항이 있지만, HTML에서는 아무런 제약 없이 사용할 수 있다.
@babel/plugin-transform-react-jsx 플러그인은 JSX 구문을 자바스크립트가 이해할 수 있는 형태로 변환한다.
const ComponentA = <A required={true}>Hello World</A>
const ComponentB = <>Hello World</>
const ComponentC= (
<div>
<span>Hello World</span>
</div>
)
@babel/plugin-transform-react-jsx 로 변환한 결과'use strict’
var ComponentA =React.createElement(
A,
{
required: true,
},
'Hello World',
)
var ComponentB = React.createElement(React.Fragment, null, ’Hello World’)
var ComponentC = React.createElement(
’div’,
null,
React.createElement(’span’, null, ’Hello World'),
)
'use strict’
var _jsxRuntime = require (’custom-jsx-library/jsx-runtime')
var ComponentA = (0, _jsxRuntime.jsx)(A,
{
required: true,
children : 'Hello World' ,
})
var ComponentB = (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
children : 'Hello World’,
})
var ComponentC = (0, _jsxRuntime.jsx)('div’, {
children: (0, _jsxRuntime.jsx)(’span’, {
children: ’Hello World’
}),
})
JSX 반환값이 결국 React.createElement로 귀결된다는 사실을 활용해 리팩터링할 수 있다.
JSX는 대부분의 경우 편리하고 간결하게 컴포넌트를 작성하는데 많은 도움을 주지만, 때에 따라서는 직접 createElement를 사용해 컴포넌트를 구성하는 편이 더 효율적일 수 있다.
JSX는 HTML과 아주 유사한 문법을 사용하지만 몇 가지 중요한 차이점이 존재한다. 이러한 차이점은 JSX가 자바스크립트로 변환되는 과정에서 발생하며, React에서 컴포넌트를 효율적으로 작성하기 위한 특수한 규칙을 따른다.
HTML에서는 요소의 클래스를 지정할 때 class 속성을 사용하지만 JSX에서는 자바스크립트 키워드인 class와의 충돌을 피하기 위해 className을 사용한다.
// HTML
<div class="container"></div>
// JSX
<div className="container"></div>
for은 자바스크립트에서 예약어이기 때문에 JSX에서는 htmlFor를 사용해야 한다.
// HTML
<label for="input">Input</label>
// JSX
<label htmlFor="input">Input</label>
JSX에서는 HTML 속성명 대신 자바스크립트에서 일반적으로 사용하는 CamelCase 스타일을 사용한다.
// HTML
<button onclick="handleClick()">Click Me</button>
// JSX
<button onClick={handleClick}>Click Me</button>
HTML에서는 태그명이 대소문자를 구분하지 않지만, JSX에서는 대문자로 시작하는 태그를 컴포넌트로 인식한다.
소문자로 시작하는 태그는 HTML 기본 태그로 처리되고 대문자로 시작하는 태그는 React 컴포넌트로 인식한다.
// HTML 태그
<div></div>
// React 컴포넌트
<MyComponent />
JSX에서는 모든 태그가 반드시 닫혀야 한다. HTML에서는 닫히지 않는 태그를 사용할 수 있지만 JSX에서는 모든 태그가 스스로 닫히거나 종료 태그가 있어야 한다.
// HTML
<img src="image.png">
// JSX (self-closing)
<img src="image.png" />
HTML에서는 <!-- -->를 사용해 주석을 작성하지만 JSX에서는 자바스크립트 문법과 동일하게 {/* */}를 사용해 주석을 작성한다.
// HTML
<!-- This is a comment -->
// JSX
{/* This is a comment */}
HTML에서 checked, disabled와 같은 Boolean 속성은 속성명만 작성해도 적용되지만 JSX에서는 true 값을 명시적으로 지정해야 한다.
// HTML
<input type="checkbox" checked>
// JSX
<input type="checkbox" checked={true} />