2. JSX 알아보기

최건우·2021년 2월 6일
0

react.js

목록 보기
3/6

0. JSX란

리액트 프로젝트를 갓 생성했을 때, App.js에는 App 컴포넌트가 아래와 같이 작성되어 있을 것입니다.

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>
        .......
        (중략)
        .......
      </header>
    </div>
  )
}

export default App;

뭔가 재밌는 형식이지 않나요? 함수형 컴포넌트인 App 컴포넌트가 return하는 내용을 보세요. 웹 브라우저가 이 App 컴포넌트를 렌더링(렌더링이란 '(브라우저에) 보여준다' 라는 뜻)하면, App 함수에서 return하는 내용을 브라우저에 그려줍니다. 무엇을 return하는지 살펴보니, HTML 코드 같이 태그들이 보입니다. 하지만 이 코드는 HTML이 아닙니다. 문자열도 아닙니다. 이러한 문법을 JSX 라고 부릅니다.

리액트 공식 문서에서는 아래와 같은 용례도 보여주고 있습니다. JSX 코드를 변수를 선언할 때도 쓸 수 있네요.

const element = <h1>Hello, world!</h1>;

JSX란 React 프로젝트에서 요소(Element)를 생성할 때 사용하는 특별한 문법입니다. 즉, 리액트에서는 요소의 생김새를 정의하는데 JSX란 것을 사용한다고 이해하시면 됩니다.

JSX에는 HTML 태그가 사용되어 HTML 같아 보이지만, 사실은 Javascript를 확장한 것입니다. '그럼 JSX를 사용하지 않고 순수 Javascript로 React element를 구성할 수 있다는 말인가??' 라는 생각이 드셨다면, 정답입니다. 리액트에서 JSX의 사용은 필수사항이 아닙니다. 하지만, JSX를 사용하면 Javascript 코드 안에서 UI 작업을 할 때 시각적으로 도움이 된다는 장점이 있습니다. 또한, React 개발 시 도움이 되는 에러 및 경고 메시지를 표시할 수 있다는 점도 장점입니다.

이렇게 JSX 문법으로 코드를 작성하면, Babel이라는 도구를 통해 Javascript 코드로 변환됩니다. JSX 문법과 Javascript로 쓰인 리액트 컴포넌트가 어떻게 다른지 봅시다.

Babel이란, 최신 Javascript 문법으로 작성된 코드를 구버전인 ES5 문법으로 변환해 주는 도구입니다. 최신 버전의 Javascript 코드가 구버전 웹 브라우저에서 실행되지 않는 문제를 해결하기 위한 도구입니다.
이러한 Babel이 언급된 이유는 JSX는 리액트로 개발할 때만 사용되므로 공식적인 Javascript 문법이 아니며, 따라서 일반 Javascript 문법으로 변환해야 하는데 이때 Babel이 사용되기 때문입니다.

왼쪽은 JSX로 쓴 문법입니다. Babel이 JSX를 Javascript로 변환하는 원리는 오른쪽과 같습니다. React.createElement() 호출하여 JSX를 컴파일하는 방식이죠.

여기서 느낄 수 있는 JSX의 장점

1. 보기 쉽고 익숙하다!
위 이미지를 보시면 알겠지만, JSX를 사용한 왼쪽이 더 심플하지요? 그리고 HTML 코드로 작성하는 것과 비슷해서, HTML을 경험한 분들에게는 더 익숙합니다.
2. 활용도가 높다!
컴포넌트도 JSX 안에서 작성할 수 있습니다. src/index.js 파일을 열어 보면, App 컴포넌트가 ReactDOM.render() 안에서 마치 HTML 태그 쓰듯이 작성된 것을 확인할 수 있습니다.

ReactDOM.render(
  <React.StrictMode>
    <App />  <!--☜ 바로 이렇게요!-->
  </React.StrictMode>,
  document.getElementById('root')
);

1. JSX를 사용할 때 기억해야 할 것

JSX가 Javascript로 변환되기 위해서는 몇 가지 규칙이 준수되어야 합니다.

1. 태그는 꼭 닫혀있어야 합니다.

리액트에서는 태그를 반드시 닫아줘야 합니다. <div> ... </div> 처럼요. 아래 코드는 Parsing Error가 납니다.

//옳지 않은 예
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
    <div>
      <div>    <!-- ☜ 요 부분이 에러를 유발합니다. -->
      <HelloWorld />
    </div>
}

export default App;

HTML에서는 <input><br>처럼 태그 사이에 내용이 들어가지 않을 때는 닫는 표시를 해도 되고 안 해도 됩니다. 그러나 리액트에서는 반드시 /> 형식으로 self-closing tag를 사용해야 합니다.

//옳은 예
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
    <div>
      <HelloWorld /> <!-- Self closing 태그를 사용한 HelloWorld 컴포넌트 예시 -->
    </div>
}

export default App;

2. 모든 요소는 반드시 하나의 요소로 감싸져 있어야 한다.

컴포넌트에 여러 요소가 있다면, 반드시 최상위에 하나의 부모 요소 그것들을 감싸야 합니다.

//옳지 않은 예
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
	  <div>React Project</div>
      <HelloWorld />
}

export default App;

2개의 요소가 하나의 요소 안에 감싸져 있지 않은 위 코드는 에러가 발생합니다. 아래처럼 하나의 부모 요소 안에 감싸줘야 합니다.

//옳은 예
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
	<div>
	  <div>React Project</div>
      <HelloWorld />
    </div>
}

export default App;

이렇게 하나의 요소로 감싸 줘야 하는 이유는, Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록, 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문입니다.

하지만, 단순히 감싸기 위해 태그를 만드는 것이 불편할 때도 있습니다. 에를 들면 스타일 관련 설정을 하다가 복잡해질 때가 있을 수 있습니다. 이 때는 Fragment라는 기능을 사용하면 됩니다(React v16 이상부터 도입됨)

//Fragment 를 사용하는 방식 1
import React, {Fragment} from 'react';
import HelloWorld from './HelloWorld';

function App() {
	<Fragment>
	  <div>React Project</div>
      <HelloWorld />
    </Fragment>
}

export default App;
//Fragment 를 사용하는 방식 2
import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
	<>
	  <div>React Project</div>
      <HelloWorld />
    </>
}

export default App;

3. JSX 안에 Javascript 표현을 넣는 법

JSX로 DOM 요소를 렌더링할 수 있을 뿐 아니라, Javascript 표현식을 쓸 수도 있습니다. 다음과 같이 { } 안에 Javascript 변수를 씁니다.

import React from 'react';
import HelloWorld from './HelloWorld';

function App() {
  const name = 'clock509';
  return (
    <>
      <HelloWorld />
      <div>내 이름은 {name}</div>
    </>
  );
}

export default App;

4. style, className, 주석

JSX에서 CSS 스타일을 설정하는 방법은 HTML의 그것과는 다릅니다.

style

인라인 스타일은 객체 형태로 선언해 주어야 합니다. 또한 font-size 처럼 -로 구분된 이름들은 fontSize 처럼 camelCase 형태로 네이밍 해 주어야 합니다.

import logo from './logo.svg';
import HelloWorld from './HelloWorld';

function App() {
  const name = 'react'
  //JSX에서 스타일을 사용할 땐 아래와 같이 객체 형태로 선언
  const style = {
    backgroundColor: 'black',
    color: 'aqua',
    fontSize: 24, //기본 단위는 px
    padding: '1rem',
  }
  return (
    <>
      <div>
        <HelloWorld 
          //컴포넌트 내 주석
        />
        <div style={style}>{name}</div> <!-- 위에서 정의한 style 변수 입력 -->
      </div>
    </>
  );
}

export default App;

className, 주석

CSS class를 설정할 때, HTML에서는 <div class='myclass'></div>와 같이 class라는 속성을 설정합니다. 반면 JSX에서는 className라는 속성으로 설정합니다. App.css 파일에 css를 정의한 후 App.js에서 불러오는 예시를 보겠습니다.
그리고 App.js를 보면 주석을 사용하는 법도 나옵니다. 특별한 점은 JSX 안에서라도 컴포넌트 안에서 주석을 쓸 때(//)와 컴포넌트와 컴포넌트 사이에서 주석을 쓰는 경우({/* */})가 다르다는 점입니다. 후자는 중괄호로 꼭 감싸주어야 합니다.

App.css

.gray-box {
  background: gray;
  width: 64px;
  height: 64px;
}

App.js

import logo from './logo.svg';
import './App.css';
import HelloWorld from './HelloWorld';

function App() {
  const name = 'react'
  //JSX에서 스타일을 사용할 땐 아래와 같이 객체 형태로 선언
  const style = {
    backgroundColor: 'black',
    color: 'aqua',
    fontSize: 24, //기본 단위는 px
    padding: '1rem',
  }
  return (
    <>
      <div>
        <HelloWorld 
          //컴포넌트 내 주석
        />
        <div style={style}>{name}</div>
        <div className="gray-box"></div>
        {/* css 클래스를 사용하려면 class가 아니라 className이라고 해야 Warning이 안 생긴다. */}
      </div>
    </>
  );
}

export default App;

5. if문 대신 조건부 연산자 사용

JSX 내부의 자바스크립트 표현식에서는 if문을 사용할 수 없습니다. 조건에 따라 다른내용을 렌더링해야 할 경우에는 두 가지 방법 중 하나를 사용하여 할 수 있습니다.

  • JSX 밖에서 if문을 사용해 사전에 값을 설정하기
  • { }안에 삼항 연산자를 사용하여 조건부 연산자 표현하기
import React from' react';

function App() {
	const name = "clock509"; //name 값을 바꾸면 rendering되는 내용도 다를 것입니다.
    return (
      <div>
        {name === "clock509:" ? (
          <h1>clock509의 블로그 입니다.</h1>
          ) : (
            <h1>여기는 어디인가....</h1>
          )}
      </div>
    );
}

export default App;

6. AND 연산자를 사용한 조건부 렌더링

특정 조건을 만족할 때 내용을 보여주고, 그렇지 않으면 렌더링하지 않는 상황에서 사용하는 방법입니다.

import React from' react';

function App() {
    const name = "clock509";
    return <div>{name === "clock509" && <h1>clock509의 블로그 입니다.</h1>}</div>
}

export default App;

&& 앞의 name ===가 false이면 && 뒷 내용을 렌더링하지 않습니다. AND 연산자로 조건부 렌더링이 가능한 이유는, 리액트에서 false를 렌더링할 때는 null과 마찬가지로 아무 것도 렌더링하지 않기 때문입니다. 단, falsy한 값인 0은 예외적으로 화면에 나타나니 주의합시다.

7. undefined를 렌더링하지 않기

어떤 컴포넌트(함수)가 undefined만 return한다면, Nothing was returned from render. 라는 에러가 발생합니다.

import React from' react';

function App() {
    const name = undefined;
    return name;   <!-- 에러 발생 -->
}

export default App;

이럴 경우, OR 연산자를 사용하여 return값이 undefined일 때 사용할 값을 지정해 두면 에러를 방지할 수 있습니다.

function App() {
    const name = undefined;
    return name || '값이 undefined 입니다.';
}

하지만, JSX 내부에서 undefined를 rendering하는 것은 에러가 발생하지 않습니다.

import React from' react';

function App() {
    const name = undefined;
    return <div>{name}</div>;   <!-- OK! -->
}

export default App;

undefined는 값이 할당되지 않은 경우를 의미합니다. 변수를 정의할 때 이름만 정의하고 값은 정의하지 않을 경우나, return 값을 명시하지 않은 함수를 호출하는 경우 경우 undefined를 볼 수 있습니다. 또한 정의되지 않은 변수나, 초기화되지 않은 것, 존재하지 않는 객체의 값에 접근하려 할 경우도 undefined를 볼 수 있습니다.

null은 의도적으로 객체나 변수가 비어있는 경우를 말합니다. '아무 것도 참조하고 있지 않다' 라는 의미를 담고 있습니다. 이럴 경우 변수를 정의할 때 그 값을 명확히 null로 초기화 합니다.

const nullVariable = null;

undefined과 null은 비슷한 것 같지만, 분명 다른 타입의 데이터 입니다. 아래 링크를 참고하면 그 차이를 이해하시는데 도움이 될 것입니다.
MDN Web Docs - undefined
null, undefined 타입
Javascript 비교 연산자 - null이나 undefined와 비교하기

정리

이번 장의 내용을 정리하겠습니다. 이번 장에서는 간단한 컴포넌트를 만들어 보았습니다.

  • JSX란 React 프로젝트에서 요소(Element)를 생성할 때 사용하는 특별한 문법입니다.
  • React에서 UI 관련 작업을 할 때 순수 Javascript로 하는 것보다 JSX를 사용하면 더욱 편리합니다.
  • JSX란 엄밀히 말하면 공식 Javascript 문법은 아니어서, 브라우저가 Javascript 코드로 인식할 수 있도록 Babel이라는 도구를 통해 변환합니다.
  • JSX가 Javascript로 변환되기 위해서는 몇 가지 규칙이 준수되어야 합니다.
    • 태그는 꼭 닫혀있어야 합니다.
    • 모든 요소는 반드시 하나의 요소로 감싸져 있어야 한다.
    • JSX 안에 Javascript 표현을 넣을 때는 { } 안에 쓴다.
    • JSX에서 CSS 스타일을 사용할 때는 HTML과는 조금 다른 방법으로 설정해야 한다.
      • style: 객체 형태로 선언하며, -로 구분되는 이름들은 camelCase 형태로 이름을 적어야 한다.
      • className: css 파일에 정의된 클래스명을 명시할 때, class 대신 className을 사용해야 한다
      • 주석: JSX 안에서 사용할 때는 중괄호를 사용해 {/* */} 형태로 쓴다.
    • JSX 안에서는 if문 대신 삼항 연산자를 활용하면 된다.
    • 특정 조건을 만족할 때만 내용을 보여주려면, 삼항 연산자 이외에 AND 연산자도 활용할수 있다.
    • 컴포넌트가 undefined만 return할 경우 에러가 발생한다. 단, JSX 안에 undefined가 있을 경우는 괜찮다.
profile
부족한 경험을 채우기 위한 나만의 기록 공간

0개의 댓글

관련 채용 정보