
리액트로 개발할 때 우리는 매일 JSX를 사용합니다. 하지만 처음 접하면 HTML과 너무 비슷해 보이기 때문에 "이거 그냥 HTML 아냐?"라고 착각하기 쉽습니다.(😂)
JSX 문법이 HTML과 매우 유사하게 보이지만, 실제로는 중요한 차이점(작동 방식부터 문법 규칙까지)들이 있습니다.
JSX(JavaScript XML)는 React에서 UI를 구성하기 위해 사용하는 JavaScript의 확장 문법입니다. 외관상 HTML과 유사하지만, 실제로는 JavaScript 객체로 변환되어 React 엘리먼트를 생성합니다.
쉽게 말하면, 자바스크립트 안에서 HTML처럼 보이는 코드를 작성할 수 있는 문법입니다.
const element = (
<div className="container">
<h1>안녕하세요!</h1>
</div>
);
이 코드는 겉으로 보기엔 HTML 같지만 브라우저에서 직접 실행되지 않고, Babel과 같은 트랜스파일러를 통해 다음과 같은 JavaScript 코드로 변환됩니다:
const element = React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, '안녕하세요!')
);
→ 즉, JSX는 브라우저가 바로 이해할 수 없고, 컴파일 과정(Babel 등)을 거쳐 자바스크립트 코드로 변환된다는 것이 가장 큰 포인트입니다.
HTML:
속성 이름은 대소문자를 구분하지 않습니다.
케밥 케이스(kebab-case)를 사용합니다.
케밥 케이스(kebab-case)란?
케밥 케이스는 프로그래밍과 웹 개발에서 사용되는 명명 규칙(naming convention) 중 하나입니다.
이름이 재미있게도 "케밥"에서 유래했는데, 단어들이 하이픈(
-) 기호로 연결되어 마치 케밥 꼬치처럼 보이기 때문입니다.케밥 케이스의 특징:
1. 단어 사이에 하이픈(
-) 사용: 모든 단어가 소문자로 작성되고, 단어 사이는 하이픈으로 구분합니다.2. 예시:
background-color,margin-top,user-select,font-family
class, for 같은 키워드를 그대로 사용합니다.
<div class="container" tabindex="-1" data-value="example"></div>
JSX:
속성 이름은 카멜 케이스(camelCase)를 사용합니다.
카멜 케이스(camelCase)란?
카멜 케이스는 프로그래밍에서 흔히 사용되는 명명 규칙(naming convention) 중 하나입니다.
이름이 "낙타(camel)"에서 유래했는데, 단어들이 대소문자로 구분되어 낙타의 등처럼 올라갔다 내려갔다 하는 모양을 연상시키기 때문입니다.
카멜 케이스의 특징:
1. 첫 단어는 소문자로 시작: 첫 번째 단어는 모두 소문자로 작성합니다.
2. 이후 단어는 대문자로 시작: 두 번째 단어부터는 첫 글자만 대문자로 작성합니다.
3. 단어 사이에 공백이나 특수문자 없음: 모든 단어가 붙어있고 대소문자로만 구분됩니다.
4. 예시:
backgroundColor,userName,isLoggedIn,handleSubmit→ JavaScript와 React에서는 카멜 케이스가 변수, 함수, 메서드, 그리고 JSX 속성에 대한 표준 명명 규칙으로 사용됩니다
HTML 속성과 다른 이름을 사용하는 경우가 있습니다(예: class → className).
이유는 간단합니다.
class와 for는 자바스크립트에서 이미 특별한 의미를 가지는 키워드이기 때문에, 이름을 살짝 바꿔야 합니다.
<div className="container" tabIndex="-1" data-value="example"></div>
HTML:
<p>2 + 2</p> <!-- 브라우저에는 "2 + 2"로 표시 -→JSX:
{}를 사용하여 JavaScript 표현식을 직접 삽입할 수 있습니다. const name = "React";
const element = <h1>Hello, {name}!</h1>;
// 조건부 렌더링
const showElement = true;
const conditionalElement = (
<div>
{showElement && <p>이 요소는 조건에 따라 렌더링됩니다.</p>}
</div>
);
<p>{2 + 2}</p> // 결과: 4
HTML:
<div style="color: blue; margin-top: 20px;"></div>JSX:
const divStyle = {
color: 'blue',
marginTop: '20px' // 카멜 케이스 사용
};
const element = <div style={divStyle}></div>;
// 또는
const element = <div style={{ color: 'blue', marginTop: '20px' }}></div>;HTML:
<img>, <input> 태그처럼 일부 태그는 닫을 필요가 없습니다.<input type="text">
<br>
<img src="image.jpg">JSX:
<input type="text" />
<br />
<img src="image.jpg" />HTML:
<!-- 이것은 HTML 주석입니다 -->
JSX:
{/* 이것은 JSX 내부의 주석입니다 */}
HTML:
JSX:
class → classNamefor → htmlFor<label className="form-label" htmlFor="username">사용자 이름:</label>HTML:
JSX:
const items = ['사과', '바나나', '오렌지'];
const element = (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);| 구분 | HTML | JSX |
|---|---|---|
| 사용 대상 | 브라우저 | 리액트 |
| 문법 해석 | 브라우저가 직접 해석 | Babel 등으로 변환 후 JS 실행 |
| 속성 이름 | class, for | className, htmlFor |
| 태그 닫기 | 선택 가능 | 필수 |
| JS 표현식 | 불가 | 중괄호 {} 사용 |