본문 바로가기
웹개발/ReactJS

[React] JSX 알아보기

by 김무스비 2025. 1. 29.
728x90
반응형

JSX란?

JSX(JavaScript XML)는 JavaScript의 확장 문법입니다.

XML과 매우 비슷하게 생겼으며, 이런 형식으로 작성한 코드는 브라우저에서 실행되기 전에 코드가 번들링되는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환되어 적용됩니다.

React 라이브러리를 사용해서 웹 개발을 할 때, JSX 문법을 사용하면 더 직관적이고 편하게 작업을 할 수 있는데요.

설명만 해서는 어떤 구조인지 왜 쓰는지 잘 이해가 안되죠?

어떻게 편한지 한번 간단한 예시로 살펴봅시다.

반응형

 

JSX를 왜 쓸까?

JSX 없이 순수하게 JavaScript로만 React 컴퍼넌트를 만드려면 다음과 같이 만들 수 있습니다.

function Greeting({ name }) {
return React.createElement(
'h1',
{ className: 'greeting' },
'Hello ',
React.createElement('i', null, name),
'. Welcome!'
);
}

먼저, 이 컴퍼넌트는 name이라는 prop을 받습니다.

그 다음으로, React.createElement는 첫 번째 인자로 type, 두 번째 인자로 속성, 세 번째 인자 이후로 자식들을 넣어줘야하는데요.

우선,

1)className이 greeting이고 텍스트가 'Hello'인 h1태그를 만들고,

2)그 하위에 'Hello ' 텍스트 + input으로 받은 name을 가지고 만든 이탤릭 텍스트(i태그) + ' . Welcome!' 텍스트를 렌더링 해줍니다.

input으로 name='musubi'라는 값을 넣어줬다면, 'Hello musubi'(이탤릭) . Welcome' 이라는 결과가 나오겠죠.

 

근데 이렇게 코드를 짜게 되면 계속 자식들을 만들어야 하는 경우 코드가 계속 중첩되고 복잡하겠죠. 그리고 html에서 작업하던 것처럼 트리 구조를 쌓아가는 느낌으로 작업할 수도 없겠죠. 

 

그런데, JSX를 쓰면 다음과 같이 직관적으로 표현이 가능합니다.

function Greeting({ name }) {
  return (
    <h1 className="greeting">
      Hello <i>{name}</i>. Welcome!
    </h1>
  );
}

들여쓰기도 딱 들어가고 직관적이고 보기 좋죠?

 

 

JSX의 특징

그러면 JSX의 특징과 사용할 때 지켜야 할 부분들에 대해 간단히 살펴봅시다.

1)JavaScript 표현식 사용 가능 

JSX를 쓰면 중괄호({}) 안에 JavaScript 표현식을 삽입할 수 있습니다. 예를 들어, 변수 값이나 함수 호출 결과를 넣을 수 있습니다.

const name = "John";
const element = <h1>Hello, {name}!</h1>;

요렇게 말이죠.

 

하지만, 문자열을 직접 넣을 때는 {}가 필요 없습니다.

// ✅ 올바른 예제
<img src="logo.png" alt="Logo" />

// ✅ 변수 사용 시 중괄호 필요
const imageUrl = "logo.png";
<img src={imageUrl} alt="Logo" />

이렇게요.

 

2)JSX에서 컴퍼넌트는 단일 루트 요소로 감싸져야한다.

React는 JSX를 변환할 때 하나의 단일 요소 트리로 처리하기 떄문에 하나의 태그 안에 여러 태그를 자식으로 갖는 건 되지만, 여러 태그를 독립적으로 나열하는 건 안됩니다.

이게 무슨말이냐면, 

function App() {
  return (
    <h1>Title</h1>
    <p>Paragraph</p>
  );
}

이렇게 최상위에 있는 태그가 2개(h1과 p)이상이면 안된다는 겁니다.

 

대신, 

function App() {
  return (
    <>
      <h1>Title</h1>
      <p>Paragraph</p>
    </>
  );
}
function App() {
  return (
    <div>
      <h1>Title</h1>
      <p>Paragraph</p>
    </div>
  );
}

요렇게 최상위에는 <> 나 <div> 하나만 남기고, 그 안에 자식 태그를 여러 개 병렬적으로 넣는다는 건 가능합니다.

 

3)속성 다룰 때 camelCase로 작성해야하거나 다른 이름으로 써줘야 경우가 많다

JSX를 쓰게 되면 javascript 예약어, 이벤트 핸들러 등은 그대로 쓰면 안되고 camelCase로 써주거나 다른 이름으로 써줘야 하는 경우가 있습니다.

예를 들면, 

 class, for가 javascript 예약어이기 때문에 JSX에서는 HTML의 class 속성을 className이나 htmlFor으로 써야합니다.

// ❌ 오류 발생
<div class="container"></div>

// ✅ 올바른 코드
<div className="container"></div>

// ❌ HTML 방식 (오류 발생)
<label for="username">Username</label>

// ✅ JSX 방식
<label htmlFor="username">Username</label>

요렇게 말이죠

 

또한, 아래의 예시에서처럼 HTML에서는 이벤트 핸들러를 소문자로 작성하지만, JSX에서는 camelCase로 작성해야합니다.

// ❌ HTML 방식 (오류 발생)
<button onclick="handleClick()">Click me</button>

// ✅ JSX 방식 (camelCase)
<button onClick={handleClick}>Click me</button>

 

4)인라인 스타일 작성 시 객체로 camelCase 문법으로 작성

JSX에서 style 속성은 객체 형태로 작성해야 하며, CSS 속성은 camelCase로 변환해야 합니다. 

// ❌ 오류 발생
<div style="color: red; background-color: blue;"></div>

// ✅ 올바른 코드
<div style={{ color: "red", backgroundColor: "blue" }}></div>

요렇게요.

 

5)IF문 대신 조건부 렌더링 구현

JSX 문법 하에서는 직접적으로 if문을 쓸 수 없어서 &&또는 삼항 연산자를 이용해야 합니다.
function Greeting({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome back!</h1>
      ) : (
        <h1>Please sign up.</h1>
      )}
    </div>
  );
}

이렇게 말이죠.

 

6)Self closing tag는 닫아주자

JSX에서는 <img>, <input> 같은 태그를 반드시 self-closing 형태로 작성해야 합니다.

// ❌ 오류 발생
<img src="logo.png">

// ✅ 올바른 코드
<img src="logo.png" />

요렇게요.

 

7)배열 렌더링 시 key 속성을 가급적 써줍시다.

map() 함수를 이용해 리스트를 렌더링 해 줄 때, 각 항목에 key 속성을 부여하는 것이 권장됩니다.(특정 상황에서는 필수일 수 있음)

React는 기본적으로 이전과 새로운 리스트를 비교하여 변경된 부분만 업데이트하려고 하는데, key가 없으면 React가 어떤 항목이 변경되었는지 알기 어렵기 때문에, 전체 리스트를 다시 렌더링할 수 있습니다.

 

 

그렇기 때문에, key를 설정하지 않으면 React 콘솔에 아래와 같은 경고를 띄웁니다.

Warning: Each child in a list should have a unique "key" prop.

 

 

따라서, 

function FruitList() {
  return (
    <ul>
      {fruits.map((fruit) => (
        <li>{fruit}</li> // ❌ key가 없어서 React가 경고를 띄움!
      ))}
    </ul>
  );
}

이렇게 하는 것 보단, 

 

const fruits = ["🍎 사과", "🍌 바나나", "🍊 오렌지"];

function FruitList() {
  return (
    <ul>
      {fruits.map((fruit, index) => (
        <li key={index}>{fruit}</li>
      ))}
    </ul>
  );
}

이렇게 하는 게 권장된다는 것입니다.

 

그리고, 항목들이 변경될 가능성이 있다면, 위의 경우에서처럼 그냥 index를 쓰는 것보단, unique한 id를 써주는게 좋을 수 있습니다.

 

예를 들어, 

const [items, setItems] = useState(["🍎 사과", "🍌 바나나", "🍊 오렌지"]);

function removeItem(indexToRemove) {
  setItems(items.filter((_, index) => index !== indexToRemove));
}

function ItemList() {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>
          {item} <button onClick={() => removeItem(index)}>삭제</button>
        </li>
      ))}
    </ul>
  );
}

위 코드에서 중간 항목이 삭제되면, React가 key를 index로 사용하기 때문에 예상치 못한 UI 버그가 발생할 수 있습니다.

0: 🍎 사과 1: 🍌 바나나 2: 🍊 오렌지 인 경우에 🍎 사과"를 삭제하면, React는 "🍌 바나나"의 index가 1에서 0으로 변경되었다고 인식할 수 있고, 잘못된 UI 업데이트가 발생할 수 있습니다.

 

그렇기 떄문에, 

const items = [
  { id: 1, name: "🍎 사과" },
  { id: 2, name: "🍌 바나나" },
  { id: 3, name: "🍊 오렌지" },
];

function ItemList() {
  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

이렇게 해주는 게 좀 더 안전하다는 의미입니다. 


이상으로, 오늘은 React를 이용해 웹 개발을 할 때 많이 쓰는 JSX 문법에 대해서 알아봤는데요.

도움이 되었으면 좋겠습니다~!

728x90

 

728x90
반응형