JSX(JavaScript XML)는 JavaScript 파일 안에서 HTML과 유사한 문법으로 UI를 표현할 수 있게 해주는 문법 확장입니다. 브라우저가 직접 이해하는 문법이 아니며, 빌드 과정에서 순수한 JavaScript 함수 호출로 변환됩니다.
// 개발자가 작성하는 JSX
const element = <h1 className="title">안녕하세요</h1>;
JSX 없이도 React를 사용할 수 있지만, 중첩된 UI 구조를 표현할 때 JSX가 훨씬 가독성이 높습니다.
JSX는 Babel이 컴파일 타임에 React.createElement 호출로 변환합니다.
// 입력 (JSX)
const element = (
<button className="btn" onClick={handleClick}>
클릭
</button>
);
// Babel 변환 결과 (React 17 이전)
const element = React.createElement(
'button',
{ className: 'btn', onClick: handleClick },
'클릭'
);
React 17부터는 새로운 JSX Transform이 도입되어 파일 상단에 import React from 'react'를 명시하지 않아도 됩니다. Babel이 자동으로 react/jsx-runtime에서 필요한 함수를 import합니다.
// React 17+ 변환 결과
import { jsx as _jsx } from 'react/jsx-runtime';
const element = _jsx('button', {
className: 'btn',
onClick: handleClick,
children: '클릭'
});
React.createElement(type, props, ...children)는 React 엘리먼트 객체를 반환합니다.
React 엘리먼트: 화면에 그릴 내용을 담은 순수한 JavaScript 객체. 실제 DOM 노드가 아닙니다.
// createElement가 반환하는 객체 (단순화)
{
type: 'button',
props: {
className: 'btn',
onClick: handleClick,
children: '클릭'
}
}
이 객체는 불변(immutable)이며, React가 이를 읽어서 실제 DOM을 구성합니다.
JSX에서 중괄호 {}를 사용하면 JavaScript 표현식을 삽입할 수 있습니다. 표현식(값을 반환하는 코드)만 사용 가능하며, if, for 같은 문(statement)은 직접 사용할 수 없습니다.
const name = '홍길동';
const isAdmin = true;
return (
<div>
<p>{name}님 환영합니다</p>
<p>{isAdmin ? '관리자' : '일반 사용자'}</p>
<p>{2 + 3}</p>
</div>
);
조건 렌더링은 삼항 연산자(? :) 또는 논리 AND(&&)를 주로 사용합니다.
{isLoggedIn && <LogoutButton />}
{isLoggedIn ? <LogoutButton /> : <LoginButton />}
하나의 루트 엘리먼트: JSX는 반드시 하나의 루트 엘리먼트로 감싸야 합니다. 불필요한 <div> 추가를 피하려면 <>...</> 프래그먼트를 사용합니다.
// 오류
return <h1>제목</h1><p>내용</p>;
// 올바른 방법
return (
<>
<h1>제목</h1>
<p>내용</p>
</>
);
className: HTML의 class 속성은 JSX에서 className으로 씁니다. class는 JavaScript 예약어이기 때문입니다.
camelCase 속성: HTML 속성은 JSX에서 camelCase로 씁니다. onclick → onClick, tabindex → tabIndex.
자기 닫힘 태그: <input>, <img> 같이 자식이 없는 태그는 반드시 자기 닫힘 형식으로 써야 합니다: <input />, <img />.
주석: JSX 안에서 주석은 {/* 주석 내용 */} 형식으로 작성합니다.
JSX는 JavaScript와 UI 선언을 같은 파일에서 관리할 수 있게 해주는 문법 설탕(syntactic sugar)입니다. 브라우저가 직접 처리하는 것이 아니라 Babel을 통해 createElement 호출로 변환되므로, JSX를 이해하려면 그 변환 결과를 함께 이해하는 것이 중요합니다.