IT Data 분석

JSX 이해: React UI 렌더링의 핵심에 대해 알아볼까요?

totoro2030 2025. 5. 4. 08:34

지난 블로그에서는 React의 기본적인 개념과 개발 환경 설정 방법에 대해 알아보았습니다. 이제 React 애플리케이션의 UI를 구축하는 데 있어 빼놓을 수 없는 핵심 문법, JSX (JavaScript XML)의 세계로 깊숙이 들어가 보겠습니다. JSX는 React 개발자가 UI를 직관적이고 효율적으로 기술할 수 있도록 해주는 강력한 도구입니다. 이번 글을 통해 JSX의 기본 문법부터 JavaScript와의 차이점, 그리고 실제 UI 렌더링에 어떻게 활용되는지 자세히 살펴보겠습니다.

JSX란 

JSX는 JavaScript의 확장 문법으로, JavaScript 코드 내에서 XML과 유사한 마크업 형태를 사용하여 UI 구조를 선언적으로 기술할 수 있도록 해줍니다. 얼핏 보면 HTML과 비슷해 보이지만, JSX는 JavaScript의 모든 기능을 활용할 수 있도록 설계된 문법입니다. React 컴포넌트 내에서 JSX를 사용하여 UI의 생김새를 정의하면, React는 이 JSX 코드를 이해하고 실제 DOM 요소로 변환하여 화면에 렌더링합니다.

JSX의 장점:

  • 직관적인 UI 구조 표현: HTML과 유사한 문법을 사용하여 UI의 구조를 시각적으로 쉽게 파악하고 작성할 수 있습니다. 복잡한 UI도 계층적인 구조로 명확하게 표현할 수 있어 코드의 가독성을 높여줍니다.
  • JavaScript와의 강력한 통합: JSX 내에서 JavaScript 표현식을 직접 사용할 수 있어 동적인 UI를 쉽게 구현할 수 있습니다. 변수, 함수 호출, 조건부 로직 등을 JSX 코드에 자연스럽게 녹여낼 수 있습니다.
  • 컴포넌트 기반 개발 용이성: React의 핵심인 컴포넌트 기반 아키텍처와 자연스럽게 어울립니다. 각 컴포넌트의 UI 구조를 JSX를 사용하여 명확하게 정의하고, 다른 컴포넌트와 조합하여 복잡한 UI를 구축할 수 있습니다.
  • 보안성 향상: JSX는 사용자 입력을 자동으로 이스케이프 처리하여 잠재적인 XSS (Cross-Site Scripting) 공격을 방지하는 데 도움을 줍니다.

JSX 기본 문법 

이제 JSX의 기본적인 문법 규칙들을 자세히 살펴보겠습니다.

1. 단일 루트 요소:

React 컴포넌트에서 반환되는 JSX는 반드시 하나의 최상위 요소 (root element)로 감싸져야 합니다. 여러 개의 형제 요소를 반환하려면 <>와 </> 또는 <React.Fragment>와 </React.Fragment>로 감싸주어야 합니다.

// 올바른 예
function MyComponent() {
  return (
    <div>
      <h1>Hello</h1>
      <p>World!</p>
    </div>
  );
}

function MyComponentFragment() {
  return (
    <>
      <h1>Hello</h1>
      <p>World!</p>
    </>
  );
}

function MyComponentReactFragment() {
  return (
    <React.Fragment>
      <h1>Hello</h1>
      <p>World!</p>
    </React.Fragment>
  );
}

// 잘못된 예 (두 개의 최상위 요소)
// function MyComponentError() {
//   return (
//     <h1>Hello</h1>
//     <p>World!</p>
//   );
// }

 

2. JavaScript 표현식 사용 ({}) :

JSX 내에서 JavaScript 변수, 함수 호출 결과, 연산 결과 등을 사용하려면 중괄호 {}로 감싸야 합니다. 이를 통해 JSX 코드 안에서 동적인 값을 렌더링할 수 있습니다.

function Greeting(props) {
  const name = "React Developer";
  const age = 3;

  function getGreetingMessage() {
    return `Welcome, ${name}! You are ${age} years into React.`;
  }

  return (
    <div>
      <h1>Hello, {name}!</h1> {/* 변수 사용 */}
      <p>{age * 2} years of React experience in dog years!</p> {/* 연산 결과 사용 */}
      <p>{getGreetingMessage()}</p> {/* 함수 호출 결과 사용 */}
      <p>{props.message}</p> {/* props로 전달된 값 사용 */}
    </div>
  );
}

function App() {
  return <Greeting message="Have a great learning journey!" />;
}

 

3. HTML과 유사한 속성 (Attributes):

JSX 요소는 HTML 요소와 유사하게 속성을 가질 수 있습니다. 하지만 몇 가지 중요한 차이점이 있습니다.

  • class 대신 className: HTML의 class 속성은 JavaScript의 예약어이므로 JSX에서는 className을 사용해야 합니다.
  • for 대신 htmlFor: HTML의 for 속성도 JavaScript의 예약어이므로 JSX에서는 htmlFor를 사용해야 합니다.
  • 카멜 케이스 속성: HTML 속성 이름이 여러 단어로 이루어진 경우 (예: tabindex, aria-label), JSX에서는 카멜 케이스로 작성합니다 (예: tabIndex, ariaLabel).
  • JSX 표현식 속성 값: 속성 값으로 JavaScript 표현식을 사용하려면 중괄호 {}로 감싸야 합니다. 문자열 리터럴은 따옴표로 묶을 수 있습니다.
function MyLink() {
  const url = "https://react.dev/";
  const linkText = "React 공식 웹사이트";

  return (
    <div>
      <a href={url} className="external-link" target="_blank" rel="noopener noreferrer">
        {linkText}
      </a>
      <label htmlFor="name-input">이름:</label>
      <input type="text" id="name-input" tabIndex="0" aria-label="이름 입력 필드" />
    </div>
  );
}

 

4. 이벤트 핸들링:

JSX를 사용하여 DOM 요소에 이벤트 핸들러 함수를 연결할 수 있습니다. HTML과 유사하게 onClick, onChange, onSubmit 등의 속성을 사용하지만, 속성 값으로 JavaScript 함수를 직접 전달합니다. 이벤트 핸들러 함수는 일반적으로 컴포넌트 내에서 정의됩니다.

function MyButton() {
  function handleClick() {
    alert('Button clicked!');
  }

  return (
    <button onClick={handleClick}>Click Me</button>
  );
}

function MyInput() {
  function handleChange(event) {
    console.log('Input value:', event.target.value);
  }

  return (
    <input type="text" onChange={handleChange} />
  );
}

 

5. 주석:

JSX 내에서 주석을 작성하는 방법은 약간 다릅니다. JavaScript 주석 (// 또는 /* ... */)은 중괄호 {} 안에서 사용해야 합니다.

function MyComponentWithComments() {
  return (
    <div>
      {/* This is a JSX comment */}
      <h1>Hello</h1>
      {
        // This is a JavaScript single-line comment
        console.log('Rendering...');
      }
      <p>World!</p>
      {/*
        This is a
        multi-line
        JSX comment
      */}
    </div>
  );
}

JSX는 어떻게 JavaScript로 변환될까

브라우저는 JSX 문법을 직접 이해하지 못합니다. 따라서 React는 JSX 코드를 브라우저가 이해할 수 있는 일반적인 JavaScript 코드로 변환하는 과정을 거칩니다. 이 변환 작업은 주로 Babel이라는 JavaScript 트랜스파일러를 통해 이루어집니다.

Babel은 JSX 코드를 React.createElement() 함수 호출 형태로 변환합니다. React.createElement()는 React 요소를 생성하는 함수이며, 이 요소들은 React의 가상 DOM 트리를 구성하는 데 사용됩니다.

예를 들어, 다음과 같은 JSX 코드는:

<h1>Hello, JSX!</h1>

 

Babel에 의해 다음과 같은 JavaScript 코드로 변환됩니다.

React.createElement("h1", null, "Hello, JSX!");

 

더 복잡한 JSX 구조는 중첩된 React.createElement() 호출로 변환됩니다.

<div>
  <h1>Greeting</h1>
  <p>Welcome!</p>
</div>

 

위 JSX는 다음과 같이 변환될 수 있습니다.

React.createElement(
  "div",
  null,
  React.createElement("h1", null, "Greeting"),
  React.createElement("p", null, "Welcome!")
);

 

Create React App과 같은 도구를 사용하면 Babel 설정이 이미 완료되어 있으므로 개발자는 JSX 코드를 직접 작성하는 데 집중할 수 있습니다.

JSX를 활용한 UI 렌더링

간단한 예제를 통해 JSX를 사용하여 동적인 UI를 렌더링하는 방법을 살펴보겠습니다.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  function incrementCount() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Count: {count}</h1> {/* 현재 count 상태를 JSX 내에서 표시 */}
      <button onClick={incrementCount}>Increment</button> {/* 이벤트 핸들러 연결 */}
    </div>
  );
}

export default Counter;

 

 Counter 컴포넌트는 useState 훅을 사용하여 count라는 상태 변수를 관리합니다. JSX 내에서 중괄호 {count}를 사용하여 현재 count 값을 화면에 표시하고 있습니다. <button> 요소의 onClick 속성에는 incrementCount 함수가 연결되어, 버튼을 클릭할 때마다 count 상태가 업데이트되고 UI가 리렌더링되어 변경된 값을 표시합니다.

이처럼 JSX는 JavaScript의 강력한 기능과 HTML과 유사한 직관적인 문법을 결합하여 동적이고 상호작용적인 UI를 쉽고 효율적으로 구축할 수 있도록 지원합니다.

마무리하며

이번 블로그에서는 React UI 렌더링의 핵심 문법인 JSX에 대해 자세히 알아보았습니다. JSX의 기본 문법 규칙부터 JavaScript와의 차이점, 그리고 Babel을 통한 JavaScript 변환 과정까지 이해함으로써 React 개발의 중요한 토대를 마련하셨으리라 생각합니다.

JSX를 능숙하게 사용하는 것은 React 개발의 효율성과 생산성을 높이는 데 필수적입니다. 앞으로 React 컴포넌트를 만들고 UI를 구성하는 과정에서 JSX를 자연스럽게 활용할 수 있도록 꾸준히 연습하는 것이 중요합니다.

다음 블로그에서는 React의 가장 기본적인 단위이자 UI를 구성하는 핵심 요소인 컴포넌트에 대해 더 깊이 있는 내용을 살펴보도록 하겠습니댜. 그리고 함수형 컴포넌트와 클래스형 컴포넌트의 기본 개념과 작성 방법에 대해 자세히 알아보도록 하겠습니다.