Development/ReactJs

[React] 리액트 JSX - 정의, 모듈, 문법, DOM 속성

재은초 2024. 11. 18. 17:03
반응형

JSX란?

  • JSX는 자바스크립트를 확장한 문법으로, React에서는 UI를 어떻게 표현해야 하는지를 설명하기 위해 React와 함께 사용할 것을 권장한다.
  • JSX를 사용하면 자바스크립트 코드 내에서도 HTML 코드처럼 UI를 바로 표현할 수 있기 때문에 UI 관련 작업을 할 때 좀 더 직관적이고 용이한 개발이 가능하게 한다.
  • 하지만 JSX는 표준 자바스크립트 문법이 아니기 때문에, 웹 브라우저는 JSX 코드를 그대로 이해하지는 못한다. 따라서 JSX 코드는 웹 브라우저에서 실행되기 전 Babel과 같은 도구를 사용하여 표준 자바스크립트 문법으로 변환되어야만 한다.
  • JSX를 사용하면 아래와 같이 복잡하고 중첩된 React.createElement() 호출 코드를 여러 번 작성할 필요가 없어지므로, UI 개발이 매우 편해지고 작성된 코드의 가독성도 높아진다.
// JSX 코드 예시

function App() {
  return (
    <div>
      <h1>Hello, World!</h1>
    </div>
  );
}
// Babel에 의해 표준 자바스크립트 문법(ES5)으로 변환된 JSX 코드

"use strict";

function App() {
  return React.createElement("div", null, React.createElement("h1", null, "Hello World!"));
}

 

모듈(Module)

  • 애플리케이션의 기능이 많아질수록 작성해야 하는 코드의 양은 많아지고 복잡해진다. 이때 모든 코드를 하나의 소스 파일에 작성하게 되면 코드의 가독성이 나빠질 뿐만 아니라 유지보수 또한 어려워진다.
  • 따라서 기능에 따라 관련된 데이터와 함수들을 별도의 모듈(module)로 나누어 관리하는 것이 보다 일반적이며, 이러한 방식을 모듈화 프로그래밍이라고 한다. 이렇게 모듈을 만들어 사용함으로써 기능에 따른 코드들을 체계적으로 관리할 수 있게 되며, 유지보수도 쉬워진다.
  • 자바스크립트에서는 현재 모듈을 다른 모듈에서 접근할 수 있도록 export 키워드를 제공하고 있으며, 반대로 내보내진 다른 모듈을 불러와 사용할 수 있도록 import 키워드를 제공하고 있다.

모듈 번들러(Module Bundler)

  • 모듈화 프로그래밍을 통해 만들어진 웹 앱이 정상적으로 동작하기 위해서는 필요한 모듈들이 전부 네트워크를 통해 웹 브라우저에 전달되어야 한다. 하지만 웹 브라우저에 전달되는 파일 단위의 모듈 개수가 늘어나게 되면 네트워크 자원의 낭비가 심해질 수 있다. 이러한 문제점을 해결하기 위해 웹 앱을 구성하는 수십, 수백 개의 리소스를 하나의 결과물로 만들어서 전송하는 방법이 사용되고 있으며, 이 과정에서 사용되는 도구가 바로 모듈 번들러(module bundler)이다.

https://webpack.js.org/

  • 많은 수의 모듈을 하나로 병합하는 과정에는 변수와 함수 이름의 중복 문제부터 모듈 간의 의존성 문제까지 수많은 문제가 발생할 수 있으며, 이러한 문제들을 해결하는데 상당한 자원과 시간이 소모된다. 모듈 번들러는 이러한 모든 문제들을 짧은 시간 안에 해결해 줌으로써 웹 앱이 최상의 성능을 낼 수 있도록 도와준다. 즉, 모듈 번들러를 사용하면 소스 코드를 모듈 별로 작성해도 성능 상의 문제가 발생하지 않고, 모듈이나 라이브러리 간의 의존성 문제도 손쉽게 관리할 수 있다.
  • 모듈 번들러는 자바스크립트 파일 뿐만 아니라 이미지나 스타일시트 파일, 폰트 파일 등을 모두 하나의 모듈로 인식하고, 이를 조합해서 병합함으로써 압축된 하나의 결과물(bundle)로 만들어 준다. 또한 최적화를 위해 하나의 파일을 여러 개의 파일로 분리하는 경우도 생길 수 있다.
  • 대표적인 모듈 번들러로는 Browserify, Rollup, Parcel, Webpack 등이 있으며, 이들의 동작 방식은 도구마다 각각 다르다. React에서는 편의성과 확장성이 좋은 Webpack을 주로 사용하고 있다.

Webpack

  • Webpack(https://webpack.kr/)은 자바스크립트 애플리케이션을 위한 번들링과 컴파일을 결합한 정적 모듈 번들러다. Webpack에서는 자바스크립트 모듈 뿐만 아니라 웹 앱을 구성하는 모든 리소스(html, stylesheet, img, font 등)를 모듈로 취급한다.
  • React에서는 주로 Webpack을 번들러로 많이 사용하는데 그 이유는 다음과 같다.
    • 사용하지 않는 리소스의 제거와 같은 최적화 작업을 수행하여 웹 앱의 성능을 향상시킨다.
    • 번들링을 통해 웹 브라우저의 HTTP 요청 횟수의 제약을 피할 수 있도록 해 준다.
    • Webpack의 Code Splitting 기능을 사용하면, 웹 앱의 로딩 속도를 개선할 수 있다.
  • 애플리케이션의 규모가 커질수록 번들러를 통해 만들어지는 결과물(번들) 또한 그 용량이 커지게 된다. 따라서 이렇게 커진 번들로 인해 애플리케이션의 로딩 시간이 길어질 수 있다. 따라서 Code Splitting 기능을 통해 코드를 분할하고, 사용자가 당장 필요로 하지 않는 리소스는 지연 로딩(Lazy Loading)함으로써 애플리케이션의 성능을 향상 시킬 수 있다.
  • CRA(Create-React-App)을 사용하여 React 개발 환경을 설정하면 Webpack은 자동으로 설치된다.

Babel

  • Babel(https://babeljs.io/docs/en/)은 일종의 자바스크립트 컴파일러로, 최신 자바스크립트 문법(ES6)이나 실험적인 자바스크립트 문법으로 작성된 코드를 이전 버전인 ES5 문법의 자바스크립트 코드로 변환해 주는 툴 체인이다.
  • 다른 프로그래밍 언어와 달리 자바스크립트는 정말 다양한 종류와 버전의 웹 브라우저에서 실행된다. 대부분의 최신 웹 브라우저에서는 최신 자바스크립트 문법을 바로 실행시킬 수 있지만, 구 버전의 웹 브라우저에서는 특정 코드가 실행되지 않을 수도 있고 특정 브라우저에서만 실행되지 않는 코드들도 있을 수 있다. 따라서 Babel과 같은 트랜스파일러(transpiler)을 사용하여 작성한 자바스크립트 코드가 어떤 환경에서도 정상적으로 동작할 수 있도록 이전 버전의 자바스크립트 문법(ES5)으로 변환해 주는 것이다.
  • React에서 사용하는 JSX 문법도 표준 자바스크립트 문법이 아니므로, Babel을 통해 ES5 문법의 자바스크립트 코드로 변환되어야만 웹 브라우저가 정상적으로 인식할 수 있다.

 

JSX 문법

JSX과 XML

  • 웹 브라우저에 내장된 HTML 파서(parser)는 HTML 문서의 구문을 분석하는 과정에서 HTML 표준에 맞지 않는 경미한 오류라면 자체적으로 보정하여 렌더링하기 때문에 큰 문제가 발생하지 않는다. 하지만 XML 문서는 매우 규칙적이고 엄격하다. JSX는 XML 구문에 자바스크립트 코드를 결합한 구문을 사용하기 때문에 JSX 구문을 작성할 때도 XML과 마찬가지로 XML 표준을 엄격하게 준수해야 한다.
  • 따라서 JSX 구문이 Babel을 통해 자바스크립트 구문으로 제대로 변환되기 위해서는 다음과 같은 규칙들을 반드시 준수해야 한다.

요소는 반드시 닫혀야 한다.

  • HTML에서는 제대로 종료 태그를 사용하여 요소를 닫지 않아도 대부분 문제 없이 동작한다. 하지만 JSX에서는 반드시 요소를 닫아야만 오류가 발생하지 않는다.
  • <img>나 <br>요소와 같은 빈 요소(void elements)도 반드시 슬래시(/)를 사용하여 self-closing을 해 줘야만 오류가 발생하지 않는다. Self-closing에서 슬래시(/) 기호 앞의 띄어쓰기는 선택사항이다.
export default function App() {
  return (
    <div>
      <h1>Void Elements</h1>
      <hr />
      <input type="text" name="name" />
    </div>
  );
}

컴포넌트에는 최상위 요소가 단 하나만 존재해야 한다.

  • 컴포넌트(component)가 여러 개의 요소를 한 번에 반환할 수 있도록 React에서는 반드시 컴포넌트의 최상위 요소가 하나만 존재하도록 강제하고 있다.
  • React v15 까지는 <div>요소를 최상위 요소로 사용하여 나머지 요소들을 감싸주는 방식을 주로 사용했다. 하지만 이러한 방식은 단순히 JSX 문법을 맞추기 위해서 불필요한 <div>요소를 추가해야만 하기에 권장할 만한 방법은 아니다.
  • React v16부터는 이러한 불필요한 <div>요소의 사용을 재고할 수 있도록 Fragment라는 기능을 추가하였다. 아래 코드처럼 <fragment>요소를 최상위 요소로 사용하면 별도의 요소를 추가하지 않고도 여러 자식 요소들을 그룹화 할 수 있다. 이러한 <fragment>요소는 HTML 페이지에는 실제 렌더링되지 않기 때문에 최종 결과물에 불필요한 요소가 추가되지 않는다.
export default function App() {
  return (
    <fragment>
      <h1>Hello, World!</h1>
      <p>React도 안녕!</p>
    </fragment>
  );
}
// 최종 렌더링된 HTML 코드
// React DOM에 의해 관리되는 모든 요소들은 최종적으로 id 속성값이 root인 <div>요소 안에 렌더링된다.
// 이 <div>요소를 루트 DOM 노드라고 부른다.

<div id="root">
  <h1>Hello, World!</h1>
  <p>React도 안녕!</p>
</div>
  • 만약 <fragment>요소를 선언하는 것이 복잡하게 느껴진다면, 아래 코드처럼 축약형 문법으로도 Fragment 기능을 사용할 수 있다. 단, Fragment의 축약형 문법에서는 키(key)와 속성(attribute)을 사용할 수 없다.
export default function App() {
  return (
    <>
      <h1>Hello, World!</h1>
      <p>React도 안녕!</p>
    </>
  );
}

자바스크립트 표현식은 중괄호({ })로 감싸져야 한다.

  • JSX 구문에는 자바스크립트 표현식을 그대로 사용할 수 있다. 단, 자바스크립트 표현식을 사용할 때는 반드시 중괄호({})로 감싸줘야만 정상적으로 컴파일될 수 있다.
export default function App() {
  const name = "홍길동";
  return <h1>Hello, {name}</h1>;
}

JSX 주석

  • JSX 구문에는 중괄호({})로 감싸기만 하면 자바스크립트 주석(comment)도 그대로 사용할 수 있다.
export default function App() {
  return (
    <>
      {/* 주석의 내용은 렌더링되지 않습니다! */}
      /* 중괄호로 감싸지 않으면 주석의 내용이 그대로 렌더링됩니다. */
      <h1>Hello, World!</h1>
      {
        // 한 줄 주석
      }
      <p>React도 안녕!</p>
      {/* 여러 줄
        주석 */}
    </>
  );
}
  • 한 줄 주석에 사용되는 ‘//’ 키워드는 자신의 오른쪽에 위치한 모든 코드를 주석으로 인식하기 때문에, JSX 구문에서 필수적인 오른쪽 중괄호(})를 찾지 못했기에 오류가 발생하게 된다.
// 잘못된 코드

export default function App() {
  return (
    <>
      <h1>Hello, World!</h1>
      {// 한 줄 주석}
    </>
  );
}
// 올바른 예

export default function App() {
  return (
    <>
      <h1>Hello, World!</h1>
      {
        // 이렇게 주석을 작성하던지,
      }
      {/*이렇게 주석을 작성해야만 합니다.*/}
    </>
  );
}

 

DOM 속성

DOM 속성(attribute)

  • React에서는 모든 DOM 속성(attribute)을 카멜 표기법(camelCase)으로 표현한다.
  • 예외적으로 aria-* 와 data-* 속성은 소문자로 표기하며, 사용자 지정 속성도 소문자로만 표기한다.

className

  • HTML 요소에 CSS 클래스를 사용하기 위해서 HTML에서는 아래 코드와 같이 class라는 속성을 사용하면 된다.
<div class="container"></div>
  • 하지만 JSX에서는 class 대신 className이라는 속성을 사용해야 한다. 이것은 class라는 단어가 자바스크립트 문법에서 클래스(class)를 생성하기 위한 키워드로 이미 예약되어 있기 때문에 중복을 피하기 위해 className을 사용해야 한다.
<div className="container"></div>
  • React v15까지는 className을 사용하는 대신 실수로 class를 잘못 사용하게 되면 오류가 발생했었지만, React v16부터는 JSX 코드에 잘못 사용된 class 속성을 자동으로 className으로 변환해 준다.

htmlFor

  • HTML의 for 속성도 자바스크립트에서 반복문을 정의하는 for 키워드와 중복되므로, JSX에서는 htmlFor 속성으로 바꿔 사용해야 한다.
export default function App() {
  return (
    <>
      <label htmlFor="name">이름 : </label>
      <input id="name" type="text"></input>
    </>
  );
}

 

Reference

반응형