[React] JSX 문법 한 번에 정리하기
리액트를 위해 필요한 지식은 얼마 되지 않는다. JSX, 컴포넌트, 훅, 상태 관리 정도이다. 그중에서 JSX는 가장 간단한 개념 중 하나다.
리액트는 컴포넌트로 앱을 구성하며, 컴포넌트는 마크업을 반환하는 함수라고 했다. 이때 이 마크업이 바로 JSX이며, 리액트에서 사용하기 위해 HTML을 확장해서 만든 언어이다.
기본적으로 HTML 태그들을 지원하지만, 기존 HTML과는 약간 다른 점이 있다. 또한 중괄호({})를 사용하여 자바스크립트 표현식을 사용할 수 있다는 것도 JSX의 특징이다. JSX 문법에 대해 아래와 같이 정리해 보자.
1. 태그와 속성
JSX에서는 기본적으로 HTML 태그를 사용할 수 있다. 그러나 기존 HTML과는 다른 몇 가지 규칙이 있다.
- 소문자로 시작하는 HTML 태그를 사용하며, 속성은 camelCase 형식을 따른다.
- 예를 들어, class는 className, for는 htmlFor로 바뀐다.
- 모든 태그는 닫혀야 하며, 닫히지 않는 태그는 self-closing 태그로 작성해야 한다.
export default function App() {
return (
<div>
<h1>Hello, React!</h1>
<img src="image.png" alt="example" />
</div>
);
}
- JSX에서는 HTML 태그뿐만 아니라 다른 컴포넌트를 태그처럼 사용할 수도 있다. 컴포넌트를 사용할 때는 대문자로 시작하는 이름의 self-closing 태그로 작성한다.
export default function Header() {
return <h1>This is the header</h1>;
}
function App() {
return (
<div>
<Header />
<p>Welcome to React!</p>
</div>
);
}
2. 최상위 엘리먼트
JSX는 반드시 하나의 최상위 엘리먼트만 반환해야 한다. 만약 여러 개의 최상위 엘리먼트를 반환하려면, Fragment(<> </>) 를 사용하여 감싸줘야 한다.
export default function App() {
return (
<>
<h1>Title</h1>
<p>Description</p>
</>
);
}
또한, JSX가 여러 줄로 작성될 경우, 반환문에서 소괄호로 감싸야 한다. 소괄호로 감싸지 않으면 반환문과 JSX 태그 사이의 줄바꿈으로 인해 문법 오류가 발생할 수 있다.
export default function App() {
return (
<div>
<h1>Hello, React!</h1>
<p>JSX를 배우는 중입니다.</p>
</div>
);
}
3. 중괄호({})와 표현식
JSX에서는 중괄호({})를 사용해 자바스크립트 표현식을 삽입할 수 있다. 이를 통해 동적으로 값을 렌더링하거나 로직을 처리할 수 있다.
export default function App() {
const name = "React";
const imageUrl = "https://example.com/image.png";
return (
<div>
<h1>Hello, {name}!</h1>
<img src={imageUrl} alt="example" />
</div>
);
}
4. 조건부 렌더링
JSX는 자바스크립트를 확장한 문법이므로, 자바스크립트의 조건문을 그대로 사용할 수 있다. 조건부 렌더링은 삼항 연산자(? :)나 논리 연산자(&&)를 사용하여 구현한다.
export default function App() {
const isLoggedIn = true;
return (
<div>
{isLoggedIn ? <p>환영합니다!</p> : <p>로그인을 해주세요.</p>}
{isLoggedIn && <p>로그인되었습니다.</p>}
</div>
);
}
- 삼항 연산자: 조건에 따라 다른 JSX를 반환.
- isLoggedIn이 true이면 "환영합니다!"를, false이면 "로그인을 해주세요."를 표시한다.
- 논리 연산자: 조건이 true일 때만 특정 JSX를 반환.
- isLoggedIn이 true일 경우 "로그인되었습니다."를 추가로 표시한다.
null 반환
JSX에서 null을 반환하면 아무것도 렌더링되지 않는다. 이를 활용하여 특정 조건에서 UI를 숨길 수 있다.
export default function App() {
const showMessage = false;
return (
<div>
{showMessage ? <p>메시지를 표시합니다.</p> : null}
</div>
);
}
조건부 렌더링을 위한 다른 방법
조건부 렌더링은 삼항 연산자나 논리 연산자 외에도 if 문을 사용할 수 있다. 단, JSX를 반환하기 전에 조건을 처리해야 한다.
export default function App() {
const isLoggedIn = false;
let message;
if (isLoggedIn) {
message = <p>환영합니다!</p>;
} else {
message = <p>로그인을 해주세요.</p>;
}
return <div>{message}</div>;
}
5. 리스트 렌더링
리스트 렌더링은 배열의 map() 메서드를 사용하여 구현한다. JSX로 배열을 렌더링할 때는 각 요소에 고유한 key 속성을 지정해야 한다.
export default function App() {
const items = ["Apple", "Banana", "Cherry"];
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
6. 스타일링
JSX에서 style 속성을 사용할 때는 자바스크립트 객체로 전달해야 한다. 객체의 속성 이름은 camelCase로 작성한다.
export default function App() {
const style = { color: "blue", fontSize: "20px" };
return <div style={style}>Styled Text</div>;
}
7. 주석
JSX에서 주석을 작성하려면 중괄호와 함께 /* */을 사용한다.
export default function App() {
return (
<div>
{/* 이 부분은 주석입니다 */}
<p>Hello</p>
</div>
);
}
8. XSS 방어
JSX는 기본적으로 XSS(크로스 사이트 스크립팅) 공격을 방어한다. HTML을 포함한 값을 출력할 때도 안전하게 처리된다.
export default function App() {
const userInput = "<script>alert('XSS')</script>";
return <div>{userInput}</div>; // 문자열 그대로 렌더링됨
}
9. JSX의 변환
JSX는 빌드 과정에서 Babel에 의해 React.createElement() 함수로 변환된다. 이는 브라우저에서 HTML로 렌더링된다.
export default function App() {
return <h1>Hello</h1>;
}
// 변환 후:
// const element = React.createElement("h1", null, "Hello");
JSX는 단순히 HTML처럼 보이지만, 자바스크립트와 결합하여 동적인 UI를 쉽게 구현할 수 있는 강력한 문법이다. 리액트의 컴포넌트와 함께 사용하여 효율적으로 앱을 개발할 수 있다. JSX 문법을 잘 이해하고 익숙해지면, 리액트를 더 깊이 활용할 수 있을 것이다.
참고
https://ko.react.dev/learn/writing-markup-with-jsx
JSX로 마크업 작성하기 – React
The library for web and native user interfaces
ko.react.dev
리액트를 학습하기 좋은 점 중 하나는 공식 문서의 번역이 잘 돼있다는 점이다. 리액트 공식 웹사이트의 "JSX로 마크업 작성하기" 섹션에서는 JSX에 대한 내용을 자세히 다루고 있으니 반드시 적어도 한 번은 살펴보자.