React 개발을 하다보면, `.jsx(.tsx)`라는 파일을 생성하여 코드를 작성한다.
그렇다면, jsx가 무엇인지 파헤쳐보자.
본 글을 React.js의 공식문서만을 토대로 작성되었습니다. 확인되지 않은 정보는 참고하지 않았으니, 안심하고 읽어주세요.
다음과 같이 줄여서 작성했습니다. JS: Javascript, 공식문서 : 공문
1. JSX 정의 및 등장배경
공식문서 언급
JSX is a syntax extension for JavaScript that lets you write HTML-like markup inside a JavaScript file.
번역: JSX는 JS안에 HTML처럼 보이는 문법을 작성하는 확장자입니다.
React 이전의 개발을 해보신분이라면, HTML, CSS, Javascript 3개의 파일을 분리하여 작성한 경험이 있으실 겁니다. 그럴 경우, 보이는 화면인 View와 화면의 구성요소를 관리하는 Logic이 완전히 분리되어 있습니다. 하지만, 시간이 지남에 따라 웹 사이트는 복잡해졌고 JS 로직은 늘어만 갔습니다.
이에 따라, 대응하는 로직(JS)과 View(HTML)을 매핑하는데 어려움이 있었고, 이를 해결하기 위해 둘을 같이 두자는 방향아래 JSX가 등장합니다.
JSX를 활용한 React는 특정 부분에 대한 렌더링 로직(JS)과 마크업(HTML)을 하나의 파일에 같이 두어, 둘 간의 연결이 되게끔 코드를 작성합니다. 이러한 부분하나를 여러분이 익히 아는 “컴포넌트”입니다.
주의: JSX는 HTML처럼 보이지만, HTML보다 엄격한 규칙을 지니며 동적으로 데이터를 관리할 수 있습니다.
그렇다면, JSX의 특징은 무엇인지 알아보겠습니다.
2. JSX와 HTML의 차이점
1. JSX는 Single Root ELement만 가질 수 있습니다.
유효한 HTML 코드가 다음과 같이 존재한다고 가정해봅시다.
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
<li>Invent new traffic lights
<li>Rehearse a movie scene
<li>Improve the spectrum technology
</ul>
해당 코드를 `.jsx`의 반환값으로 넣어주면 에러가 발생합니다.
export default function TodoList() {
return (
// This doesn't quite work!
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
>
<ul>
<li>Invent new traffic lights
<li>Rehearse a movie scene
<li>Improve the spectrum technology
</ul>
);
}
“JSX elements must be wrapped in an enclosing tag” 즉, JSX가 하나의 Root로 감싸져야 함을 언급하고 있습니다.
🤔왜 그러는 걸까요?
JSX looks like HTML, but under the hood it is transformed into plain JavaScript objects. You can’t return two objects from a function without wrapping them into an array. This explains why you also can’t return two JSX tags without wrapping them into another tag or a Fragment.
React.js는 JSX를 JS 객체로 변환합니다. 이 과정에서 태그 관계를 토대로 Element를 생성합니다. 자세히 살펴봅시다.
하나의 태그는 `React.createElement`를 토대로 객체를 생성합니다. 하나의 return에 두 개의 객체를 반환할 수 없으므로, 에러가 발생합니다.
// JSX Code
return (
<h2>Let's get started!</h2>
<Expenses expenses={expenses} />
);
// React Code (❌ Two Return values??)
return (
React.createElement("h2", {}, "Let 's get started!"),
React.createElement(Expenses, {expenses: expenses})
);
이를 해결하기 위해 다음과 같은 방법 중 하나로 Root 요소를 만들어줘야 합니다.
- `div` 태그로 감싸준다.
- `<> </>` (Fragment)로 감싸준다. (Fragment는 DOM에 영향을 미치지 않고 그룹화해 주는 특별한 태그입니다)
[사용방법 1]
React에서 제공하는 Fragment를 import 하여 사용.
import { Fragment } from 'react'; const posts = [ { id: 1, title: 'An update', body: "It's been a while since I posted..." }, { id: 2, title: 'My new blog', body: 'I am starting a new blog!' } ]; export default function Blog() { return posts.map(post => <Fragment key={post.id}> <PostTitle title={post.title} /> <PostBody body={post.body} /> </Fragment> ); }
[사용방법 2]
React에서 제공하는 Fragment를 import 하지 않고 그대로 사용.
const posts = [ { id: 1, title: 'An update', body: "It's been a while since I posted..." }, { id: 2, title: 'My new blog', body: 'I am starting a new blog!' } ]; export default function Blog() { return posts.map(post => <React.Fragment key={post.id}> <PostTitle title={post.title} /> <PostBody body={post.body} /> </React.Fragment> ); }
2. 모든 태그는 닫혀있어야 합니다.
기존 HTML 코드를 살펴보면 `img` `ul` 태그가 닫히지 않았고 이는 오류를 발생시킵니다.
따라서, 모든 태그를 닫아야 합니다.
<h1>Hedy Lamarr's Todos</h1>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
> -> 닫혀 있지 않음
<ul>
<li>Invent new traffic lights -> 닫혀 있지 않음
<li>Rehearse a movie scene -> 닫혀 있지 않음
<li>Improve the spectrum technology -> 닫혀 있지 않음
</ul>
<img
src="https://i.imgur.com/yXOvdOSs.jpg"
alt="Hedy Lamarr"
class="photo"
/>
<ul>
<li>Invent new traffic lights</li>
<li>Rehearse a movie scene</li>
<li>Improve the spectrum technology</li>
</ul>
3. 속성을 CamelCase로 작성해야 합니다.
언급했듯이, JSX는 JS 객체로 변환됩니다. 이때, 속성은 key가 되는데 JS에서 key의 제한사항에 따라 CamelCase로 작성해야 하며, reserved name는 사용이 제한됩니다.
참고 문헌
https://react.dev/learn/writing-markup-with-jsx
Writing Markup with JSX – React
The library for web and native user interfaces
react.dev
'웹 프로그래밍 > React' 카테고리의 다른 글
NPM 패키지 개발 1편 [타 라이브러리 사용 트러블 슈팅 과정] (0) | 2025.01.09 |
---|---|
[Tanstack Query] setMutationDefaults로 key 모듈화하여 관리하기 (0) | 2024.12.12 |
[Tanstack Query] queryFc의 인자 FunctionContext에 대해 알아보자 (1) | 2024.11.26 |
[React] 제어 컴포넌트 vs 비제어 컴포넌트 (0) | 2024.07.29 |
[Zustand] 상태관리 방법 및 Little Bit Deep Dive (0) | 2024.07.22 |