카테고리 없음

[React] JSX 파일

불곰자리 2024. 8. 28. 21:32

JSX파일

JSXJavaScript의 확장으로, JavaScript 파일 내에 HTML처럼 마크업을 작성할 수 있습니다. 컴포넌트를 작성할 수단은 그 외에도 존재하지만, 대부분의 React 개발자는 JSX의 간결함을 선호하기 때문에, 대부분 코드에 JSX가 사용된다.

 

JSX: JavaScript에 마크업을 삽입

이때까지는 HTML, CSS, JavaScript만을 사용해 페이지를 만들어왔다. 오랜 기간에 거쳐, 웹 개발자는 콘텐츠는 HTML으로 작성하고, 디자인은 CSS, 로직은 JavaScript 각각의 파일로 분리하여 만들어왔다. 콘텐츠가 HTML 내에 마크업되는 방법으로, 페이지 로직은 다른 파일의 JavaScript에 존재해온 형태였다.

 

그러나 웹이 좀 더 상호작용하는 형태로 변화하자, 로직이 콘텐츠를 결정하게 되었다. 이것이 React가 로직과 마크업을 같은 파일에 작성하는 컴포넌트를 만들게 된 이유이다.

 

로직에 따라 보여지는 화면이 달라지는 컴포넌트 파일

버튼의 렌더링 로직과 마크업을 같은 파일에 작성하면, 코드 수정 시 동기화가 보장된다. 반대로, 버튼 마크업과 사이드바의 마크업은 각각 관계가 없기 때문에 분리되어 작성된다면 안전하고 독립된 파일의 갱신이 가능하다.

 

각각의 React 컴포넌트는 JavaScript의 함수 형태로, React가 브라우저에 표시하기 위한 마크업을 포함할 수 있다. JSX는 HTML과 비슷하게 생겼지만, 구문이 엄밀히 존재하며, 동적인 정보를 표시할 수 있다. 이해하기 위해선, HTML 마크업을 JSX 마크업으로 변환해보는 것이 좋다.

JSX와 React는 엄연히 다르다. 같이 사용되는 경우가 많지만 둘 다 각각 따로 사용하는 것이 가능하다.  JSX는 언어의 확장이며, React는 JavaScript 라이브러리다.

 

HTML을 JSX로 변환하기

이런 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>

 

이것을 컴포넌트 내에 그대로 삽입한다고 생각하면 된다.

export default function TodoList() {
  return (
    // ???
  )
}

 

그러나 그대로 복사해서 붙여넣기하는 것 만으로는 제대로 동작하지 않는다.

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>
  );
}

 

/src/App.js: Adjacent JSX elements must be wrapped in an enclosing tag.
Did you want a JSX fragment <>...</>? (5:4)

3 |        // This doesn't quite work!
4 |        <h1>Hedy Lamarr's Todos</h1> >
5 |        <img |
            ^
6 |             src="https://i.imgur.com/yXOvdOSs.jpg"
7 |             alt="Hedy Lamarr"
8 |             class="photo"

 

이건, JSX을 사용하는 방법이 엄밀하고, HTML보다 규칙이 많기 때문이다. 위의 에러 메시지에도 나와있지만, 다음 안내를 따르면 괜찮다.

대부분의 경우엔 React가 화면 상에 표시하는 에러 메시지가, 문제가 있는 코드 위치를 찾을 수 있는 단서가 된다.

 

JSX의 규칙

1. 단 하나의 루트 요소만을 반환한다.

컴포넌트에서 둘 이상의 요소를 반환하기 위해선, 하나의 태그로 묶어야한다.

예를 들어 <div>를 사용할 수 있다.

<div>
  <h1>Hedy Lamarr's Todos</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</div>

 

마크업에 여유롭게 <div>를 추가할 수 없는 경우엔, 대신 <>과 </>를 사용할 수 있다.

<>
  <h1>Hedy Lamarr's Todos</h1>
  <img 
    src="https://i.imgur.com/yXOvdOSs.jpg" 
    alt="Hedy Lamarr" 
    class="photo"
  >
  <ul>
    ...
  </ul>
</>

 

이 태그는 프래그먼트(Fragment)라고 불린다. 프래그먼트를 사용하면, 브라우저의 HTML 트리에는 존재하지 않지만, 두 개 이상의 요소를 묶을 수 있다.

 

2. 모든 태그에는 닫는 태그가 필요하다.

JSX에선 모든 태그를 명시적으로 닫아줄 필요가있다. <img>와 같은 자동으로 닫히는 태그는 <img />로 되고, <li>oranges와 같은 감싸는 태그는 <li>oranges</li>와 같은 식으로 작성해야한다.

 

Hedy Lamarr의 영상과 리스트 항목은, 닫기 태그를 작성한 상태에선 아래와 같이 변한다.

<>
  <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. 대부분의 경우 카멜 케이스로 작성해야 한다.

JSX는 JavaScript로 변형되어, 안에 작성된 속성은 JavaScript의 객체 키가 된다. 컴포넌트 내에선, 이 속성을 변수로 읽어낼 수 있다. 다만 JavaScript 변수명엔 일정한 제약이 있다. 예를 들어, 이름에 하이픈(-)을 포함하거나 class와 같은 예약어를 사용하는 것은 안된다.

이를 위해, React는 HTML 및 SVG 파일의 속성을 카멜 케이스로 작성한다. 예를 들어 stroke-width 대신 strokeWidth를 사용한다. class는 예약어이기 때문에, React에선 className을 작성한다. (대응하는 DOM 프로퍼티가 유래되어진다.)

<img 
  src="https://i.imgur.com/yXOvdOSs.jpg" 
  alt="Hedy Lamarr" 
  className="photo"
/>

 

모든 항목은 React DOM 컴포넌트에 존재하는 속성 목록에서 확인할 수 있다. 잘못 작성할 경우에도 브라우저 콘솔창에 메시지와 어떻게 수정해야 할지에 대한 정보를 보여주기 때문에 걱정할 필요가 없다.

역사적 이유에 의해, aria-*와 data-* 속성은 HTML 속성과 같이 하이픈이 존재한다.

 

힌트: JSX 변환기를 사용한다.

선점한 마크업의 속성을 모두 바꿔 작성하는 것은 때로 귀찮을 수 있다. 선점한 HTML이나 SVG를 JSX로 변환할 경우 변환기를 사용하는 것을 추천한다. 변환기는 실용상 매우 도움되지만, 스스로 JSX 파일을 편하게 작성할 수 있도록, 무엇이 일어나는지 이해하는 것도 중요하다.

마지막 결과는 아래와 같다.

export default function TodoList() {
  return (
    <>
      <h1>Hedy Lamarr's Todos</h1>
      <img 
        src="https://i.imgur.com/yXOvdOSs.jpg" 
        alt="Hedy Lamarr" 
        className="photo" 
      />
      <ul>
        <li>Invent new traffic lights</li>
        <li>Rehearse a movie scene</li>
        <li>Improve the spectrum technology</li>
      </ul>
    </>
  );
}

 

위 코드의 실행 결과

 

정리

이것으로 JSX가 존재하는 이유와, 컴포넌트 내 사용 방법에 대해 이해할 수 있었다.

  • 렌더링 로직과 마크업은 서로 관련되어있어, React에선 이것을 그룹화한다.
  • JSX는 HTML과 비슷하지만 몇 개의 차이가 있다. 필요하다면 변환기를 사용한다.
  • 에러 메시지를 보면, 대부분의 마크업 수정 방법에 대한 지시사항을 얻을 수 있다.

 

참고글

JSX에서 마크업 작성하기