기술 포스트

JSX — HTML인 듯 HTML이 아닌 그 문법


Article

React를 처음 접하면 가장 먼저 눈에 들어오는 게 있습니다. 자바스크립트 파일 안에 HTML처럼 생긴 코드가 들어있는 것입니다.

function Welcome() {
  return <h1>안녕하세요!</h1>;
}

이게 JSX입니다. JavaScript XML의 약자인데, 이름보다 중요한 건 HTML과 뭐가 다른지 아는 것입니다.

JSX는 JavaScript 안에서 쓰는 마크업입니다

퍼블리셔가 만드는 HTML은 .html 파일에 들어갑니다. JSX는 .jsx 또는 .tsx 파일, 즉 자바스크립트 파일 안에 들어갑니다.

이게 가능한 이유는, JSX가 실제로 자바스크립트 코드로 변환되기 때문입니다.

// 우리가 쓰는 JSX
<h1 className="title">안녕하세요</h1>
// 브라우저가 실행하는 실제 코드
React.createElement("h1", { className: "title" }, "안녕하세요")

JSX는 React.createElement()보기 좋게 쓰기 위한 문법입니다. 빌드 과정에서 자동으로 변환되니까 개발자는 편하게 HTML과 비슷한 형태로 쓰면 됩니다.

HTML과 다른 점 — 이것만 기억하세요

퍼블리셔에게는 좋은 소식이 있습니다. JSX는 HTML과 거의 같습니다. 다른 점 몇 가지만 기억하면 됩니다.

1. class 대신 className

HTML에서 가장 많이 쓰는 class 속성이 JSX에서는 className으로 바뀝니다.

// HTML
<div class="container">...</div>

// JSX
<div className="container">...</div>

이유는 간단합니다. class가 자바스크립트에서 예약어이기 때문입니다. 자바스크립트에서 class는 클래스를 선언할 때 쓰는 키워드라서 충돌을 피하기 위해 className을 씁니다.

2. for 대신 htmlFor

<label> 태그에서 쓰는 for 속성도 마찬가지입니다.

// HTML
<label for="email">이메일</label>

// JSX
<label htmlFor="email">이메일</label>

for도 자바스크립트 예약어(반복문)라서 htmlFor로 바꿔 씁니다.

3. 닫는 태그가 필수입니다

HTML에서는 <img>, <br>, <input> 같은 태그를 닫지 않아도 됩니다. JSX에서는 모든 태그를 반드시 닫아야 합니다.

// HTML — 닫지 않아도 OK
<img src="photo.jpg" alt="사진">
<br>
<input type="text">

// JSX — 반드시 닫아야 함
<img src="photo.jpg" alt="사진" />
<br />
<input type="text" />

슬래시(/)를 빼먹으면 에러가 납니다. 처음에는 귀찮지만 금방 습관이 됩니다.

4. 중괄호로 자바스크립트를 쓸 수 있습니다

이게 JSX의 가장 강력한 기능입니다. 중괄호 {} 안에 자바스크립트 표현식을 넣을 수 있습니다.

const name = "민초리";
const today = new Date().toLocaleDateString();

return (
  <div>
    <h1>{name}님, 환영합니다!</h1>
    <p>오늘은 {today}입니다.</p>
    <p>1 + 1 = {1 + 1}</p>
  </div>
);

HTML에서는 불가능한 일입니다. HTML은 정적인 텍스트일 뿐이니까요. JSX에서는 변수 값을 직접 넣고, 계산도 하고, 함수도 호출할 수 있습니다.

5. 스타일은 객체로 씁니다

HTML의 인라인 스타일은 문자열입니다. JSX에서는 객체로 씁니다.

// HTML
<div style="background-color: red; font-size: 16px;">...</div>

// JSX
<div style={{ backgroundColor: "red", fontSize: "16px" }}>...</div>

중괄호가 두 겹인 이유는, 바깥 중괄호는 "자바스크립트 쓸 거야"라는 의미이고, 안쪽 중괄호는 자바스크립트 객체를 나타내기 때문입니다. CSS 속성명은 케밥 케이스(background-color) 대신 카멜 케이스(backgroundColor)로 씁니다.

하나 더 — 최상위 요소는 하나여야 합니다

JSX에서 여러 요소를 반환할 때는 하나의 부모 요소로 감싸야 합니다.

// 에러 — 최상위 요소가 2개
return (
  <h1>제목</h1>
  <p>내용</p>
);

// OK — div로 감쌈
return (
  <div>
    <h1>제목</h1>
    <p>내용</p>
  </div>
);

// OK — Fragment로 감쌈 (불필요한 div를 피할 수 있음)
return (
  <>
    <h1>제목</h1>
    <p>내용</p>
  </>
);

<>...</>Fragment라고 부르는데, 실제 DOM에는 아무 요소도 추가하지 않으면서 여러 요소를 묶어주는 역할을 합니다. 불필요한 div가 생기는 걸 피할 수 있어서 자주 쓰입니다.

차이점 한눈에 보기

HTML JSX
class className
for htmlFor
<img> (닫기 선택) <img /> (닫기 필수)
정적 텍스트만 {변수}, {표현식} 사용 가능
style="color: red" style={{ color: "red" }}
최상위 요소 제한 없음 최상위 요소 하나 필수

퍼블리셔에게 JSX는 어렵지 않습니다

솔직히 말하면, JSX는 HTML을 이미 아는 사람에게 가장 쉬운 React 개념입니다. 차이점이 몇 가지 안 되고, 그마저도 규칙이 명확합니다.

처음에는 className 쓰는 게 어색하고, 닫는 태그에 슬래시 넣는 게 귀찮게 느껴질 수 있습니다. 하지만 며칠만 써보면 완전히 자연스러워집니다.

다음 글에서는 React의 핵심 단위인 컴포넌트에 대해 알아보겠습니다. HTML의 include나 partial과 비슷하지만, 훨씬 더 강력한 개념입니다.