[리액트] JSX란? JSX문법 소개

2023. 4. 15. 12:13개발/React

JSX란

리액트 공식 웹사이트에 따르면 JSX란 JavaScript 확장 문법이다. React에서 UI를 만들기 위해 사용되는 문법으로 JSX 코드를 작성하면 웹팩의 로더(babel과 같은)를 통해 번들링되면서 일반적인 JavaScript 코드로 변환된다.

웹팩의 로더는 직접 설치하는 과정이 필요하지만 React 프로젝트 생성을 도와주는 CRA로 번거로운 작업을 대신 할 수 있다.

React 프로젝트 생성 후 기본적으로 설정되어 있는 src/App.js를 살펴보자.

function App(){
    /* 생략 */
return (
    <div className="App">
        <header className="App-header">
            <img src={logo} className="App-logo" alt="logo"/>
            <p>Edit <code>src//App.js</code> and save to reload.</p>
            <a className="App-link" href="https://reactjs.org" target="_black" rel="noopener noreferrer">Learn React</a>
        </header>
    </div>
)
}

src/App.js는 현재 React 프로젝트에 App이란 컴포넌트를 생성하고 있다. 컴포넌트가 리턴하는 내용을 화면에 보여준느 것이 랜더링이다. (React 기본 프로젝트에선 리턴된 JSX구문을 index.js에서 받은 다음 랜더를 통해 HTML과 JS로 변경한 후 index.html에 그려준다.) App 컴포넌트가 리턴하는 내용은 마치 HTML 코드처럼 보인다. 하지만 정확히는 HTML이 아니라 JSX이다.

왜 JSX를 사용해야 하는가

React는 ReactElement를 통해 화면을 나타낸다. ReactElement를 생성하는 자바스크립트 코드는 다음과 같다.

/* React.createElement() 함수를 사용한 예시 코드 */
const element = React.createElement(
  "div",
  { className: "container" },
  React.createElement("h1", null, "Hello, world!"),
  React.createElement("p", null, "Welcome to my website.")
);

..도대체 뭔말이야…?..
반면 동일한 코드를 JSX로 표현하면 다음과 같다.
const element = (
  <div className="container">
    <h1>Hello, world!</h1>
    <p>Welcome to my website.</p>
  </div>
);

HTML을 조금이라도 다뤄본 사람이라면 아래의 JSX문법이 훨씬 직관적으로 이해될 것이다.

JSX 문법

HTML, JavaScritp와 상당히 유사하지만 JSX는 몇가지 특징이 있다. 모든 문법을 정리할 수는 없지만 눈에 띄는 내용만 정리해보겠다. 처음으로 리액트를 다루면서 몰라서 실수한 부분들만 정리 하였다. (거의 다 이긴 할 것.. 왜냐면 하나도 모르고 시작했기 때문에…)

  1. JSX구문에서 여러 요소를 리턴한다면 반드시 부모 요소하나로 감싸야 한다.

    1. 일반

       // src/App.js
       import React from 'react';
       function App(){
           return(
               <h1>제목 요소입니다.</h1>
               <h2>소제목 요소입니다.</h2>
           )
       }

      <h1>태그와, <h2>태그를 JSX요소로 리턴하고자 할 때 이와 같이 작성하면 ‘…JSX elements must be wrapped in an enclosing tag…Did you want a JSX fragment…’오류가 발생한다.

      반드시 하나의 태그로 전체 반환 요소를 감싸야 한다는 것이다. (이는 가상돔에서 변화를 감지할때 효율적으로 비교할 수 있도록 하나의 돔트리로 구성되어야 한다는 규칙이 있기 때문이라고 한다…)

      정상적으로 고쳐보면 다음과 같다.

       // src/App.js
       import React from 'react';
       function App(){
           return(
               <div>
                   <h1>제목 요소입니다.</h1>
                   <h2>소제목 요소입니다.</h2>
               </div>
           )
       }
    2. 리액트 v16부터 도입된 Fragment 태그

      태그로 감싸지지 않았을 때 오류가 발생하면서 오류 메세지는 JSX fragment를 언급한다. 리액트 16부터 도입되었다는 fragment는 빈 태그로 해당 요소로 감싸서 리턴하게 되면 다음과 같이 고칠 수 있다.

       // src/App.js
       import React from 'react';
       function App(){
           return(
               <>
                   <h1>제목 요소입니다.</h1>
                   <h2>소제목 요소입니다.</h2>
               </>
           )
       }

      이 코드 또한 정상적으로 리액트 엘리먼트를 생성한다. 두 방식은 반환하는 HTML결과물이 다르니 참고하자

       <!-- 일반적인 태그로 감싼 뒤 반환한 결과 HTML -->
       <div>
           <h1>제목 요소입니다.</h1>
           <h2>소제목 요소입니다.</h2>
       </div>
      
       <!-- Fragment 태그로 감싼 뒤 반환한 결과 HTML -->
       <h1>제목 요소입니다.</h1>
       <h2>소제목 요소입니다.</h2>
  2. 자바스크립트를 표현할 때는 {} 중괄호로 감싸야 한다.

    1. JSX내에서 자바스크립트를 표현할 때는 {}로 감싼 뒤 표현해야 한다.
    2. JSX 주석 또한 별도의 구문을 사용하는 것이 아니라 {}안에 자바스크립트 주석 구문을 사용한다.
      1. 처음엔 이걸 몰라서 {/* 여기에 JSX 구문을 작성하세요.*/} 라고 적힌걸 보고 {}안에 열심히 태그들을 작성했다.
  3. CSS 스타일 요소를 적용할 때 자바스크립트 객체 {} 형식을 사용해야 하며, 스타일 이름 중 -이 포함된 이름은 카멜식으로 표현해야 한다.

    1. 인라인으로 스타일 요소를 표현하는 예시를 찾아보는데 <p style={{color : red}}>내용</p> 을 보고 반드시 이중으로 겹쳐진 중괄호 안에 스타일을 작성해야 하는 줄 알았는데 그게 아니라 자바스크립트 요소를 표현하는 중괄호 안에 객체 형식으로 스타일을 넣어주는 것이었다.
    2. 백그라운드 컬러를 넣거나 가운데 정렬등을 사용할 때 <div style={{background-color : green}}>내용</div>를 사용하면 정상적으로 동작하지 않는다. 하이픈이 들어간 스타일 요소들은 카멜식으로 표현해야한다. <div style={{backgroundColor : green}}>내용</div>
  4. class 대신 className을 사용해야 한다.

  5. HTML에선 닫지 않아도 묵시적으로 닫은것으로 표현되는 태그들도 닫아주어야 하는 것들이 있다.

    대표적으로 input 태그가 그렇다. HTML 작성시 input 태그는 별도로 </input> 을 하지 않더라도 의도대로 출력되지만 JSX 에서는 <input></input>라고 작성해 주어야 한다.

  6. 반드시 모든 리턴에서 ()로 감쌀 필요는 없다.

    1. 함수 리턴부분에서 JSX구문을 작성할 때 ()로 감싼 것을 살펴볼 수있다. 반드시 ()로 리턴을 감싸야 한다고 생각했는데 한줄로 작성된 JSX구문은 ()로 감싸지 않아도 된다!