📖 리액트/리액트를 다루는 기술

2장 JSX

놀러와요 버그의 숲 2022. 1. 18. 06:06
728x90
반응형

이 글은 『리액트를 다루는 기술』(개정판/ 김민준 저 / 길벗 출판사)이라는 책을 참고하여 썼습니다.

 

음 2장을 통해서 알아야하는 것은 무엇일까? 나는 어떤 대답을 할 수 있어야할까?

 

한마디로 2장 JSX 단원의 목표가 무엇일까? 

 

목표: 1. WHY? => JSX를쓰고, 어떤 문제를 해결해주는지 명확하게 대답을 할 수 있어야 한다.

         2. HOW? => JSX를 어떻게 쓰는지 알아야 한다. (규칙)

 

 

2.1 코드 이해하기

 

 

Create-React-App을 통해서 프로젝트를 만들고 index.js에 들어가보자.

 

import React from 'react';

이 코드는 리액트를 불러와서 사용할 수 있게 해 줍니다.

리액트 프로젝트를 만들 때 node_modules라는 디렉터리도 함께 생성되는데요.

프로젝트 생성 과정에서 node_modules 디렉터리에 react 모듈이 설치됩니다.

그리고 이렇게 import 구문을 통해 리액트를 불러와서 사용할 수 있는 것이죠.

여기서 한 가지 알아 둘 점이 있습니다. 이렇게 모듈을 불러와서 사용하는 것은 사실 원래 브라우저에는 없던 기능입니다.

브라우저가 아닌 환경에서 자바스크립트를 실행할 수 있게 해 주는 환경인 Node.js에서 지원하는 기능입니다.

 

이러한 기능(모듈을 불러와서 사용)브라우저에서도 사용하기 위해 번들러(bundler)를 사용합니다.

번들(bundle)은 묶는다는 뜻입니다. 즉, 파일을 묶듯이 연결하는 것이죠.

 

 

번들러

번들러(Bundler)는 분리된 JavaScript와 CSS 모듈 코드를 브라우저에 최적화된 여러 개의 파일로 결합합니다.

React 애플리케이션에서 널리 사용되는 번들러에는 Webpack Browserify가 있습니다.

 

 

리액트 프로젝트에서는 주로 웹팩을 사용하는 추세입니다. 편의성과 확장성이 다른 도구보다 뛰어나기 때문입니다.

번들러 도구를 사용하면 import(또는 require)로 모듈을 불러왔을 때 불러온 모듈을 모두 합쳐서 하나의 파일을 생성해 줍니다.

 src/index.js를 시작으로 필요한 파일을 다 불러와서 번들링하게 됩니다.

 

import logo from ‘./logo.svg‘;
import ‘./App.css‘;

 

웹팩을 사용하면 SVG 파일과 CSS 파일도 불러와서 사용할 수 있습니다.

이렇게 파일들을 불러오는 것은 웹팩의 로더(loader)라는 기능이 담당합니다. 로더는 여러 가지 종류가 있습니다.

예를 들어 css-loader는 CSS 파일을 불러올 수 있게 해 주고, file-loader는 웹 폰트나 미디어 파일 등을 불러올 수 있게 해 줍니다.

그리고 babel-loader는 자바스크립트 파일들을 불러오면서 최신 자바스크립트 문법으로 작성된 코드를 바벨이라는 도구를 사용하여 ES5 문법으로 변환해 줍니다.

(우리가 앞으로 배우게 될 리액트 컴포넌트에서 사용하는 JSX라는 문법도 정식 자바스크립트 문법이 아니므로 ES5 형태의 코드로 변환해야 합니다.)

 

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="_blank"
        rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
);
}

이 코드는 App이라는 컴포넌트를 만들어 줍니다. function 키워드를 사용하여 컴포넌트를 만들었지요?

이러한 컴포넌트를 함수형 컴포넌트라고 부릅니다.

프로젝트에서 컴포넌트를 렌더링하면(렌더링이란 ‘보여 준다’는 것을 의미합니다) 함수에서 반환하고 있는 내용을 나타냅니다.

함수에서 반환하는 내용을 보면 마치 HTML을 작성한 것 같지요? 하지만 이 코드는 HTML이 아닙니다.

그렇다고 문자열 템플릿도 아닙니다. 이런 코드는 JSX라고 부릅니다.

 

2.2 JSX란?

 

JSX는 자바스크립트 확장 문법이다.

 

이런 형식으로 작성한 코드는 브라우저에서 실행되기 전에 코드가 번들링되는 과정에서 바벨을 사용하여

일반 자바스크립트 형태의 코드로 변환됩니다. JSX 코드가 어떻게 변환되는지 확인해 볼까요?

 

//JSX 문법

function App() {
  return (
    <div>
      Hello <b>react</b>
    </div>
  );
}
function App() {
return React.createElement(“div“, null, “Hello “, React.createElement(“b“, null, “react“));
}

만약 컴포넌트를 렌더링할 때마다 JSX 코드를 작성하는 것이 아니라 위 코드처럼

매번 React.createElement 함수를 사용해야 한다면 매우 불편하겠지요?

JSX를 사용하면 매우 편하게 UI를 렌더링할 수 있습니다.

 

 

추가 예시 (리액트 공식문서)

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);

 

const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

 

 

2.3 JSX의 장점

 

1. 가독성이 좋다

JSX를 사용하는 편이 더 가독성이 높고 작성하기도 쉽다고 느껴진다. (왜냐하면 HTML 코드를 작성하는 것과 비슷하니까) 

 

2. 컴포넌트도 포함시킬 수 있다. (=활용도가 높다)

JSX에서는 우리가 알고 있는 div span 같은 HTML 태그를 사용할 수 있을 뿐만 아니라,

앞으로 만들 컴포넌트도 JSX 안에서 작성할 수 있습니다.

 

예시 ) src/index.js 파일을 열어 보면 이 App 컴포넌트를 마치 HTML 태그 쓰듯이 그냥 작성합니다.

ReactDOM.render(<App />, document.getElementById(‘root‘));

 

cf) ReactDom.render는 무엇인가? 

 

이 코드는 컴포넌트를 페이지에 렌더링하는 역할을 하며, react-dom 모듈을 불러와 사용할 수 있습니다.

이 함수의 첫 번째 파라미터에는 페이지에 렌더링할 내용을 JSX 형태로 작성하고,

두 번째 파라미터에는 해당 JSX를 렌더링할 document 내부 요소를 설정합니다.

여기서는 id가 root인 요소 안에 렌더링을 하도록 설정했는데요. 이 요소는 public/index.html 파일을 열어 보면 있답니다.

 

 

2.4 JSX 문법 규칙

 

1. 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 한다. 

 

//오작동 코드

import React from 'react';

function App() {
  return (
    <h1>리액트 안녕!</h1>
    <h2>잘 작동하니?</h2>
  )
}

export default App;
import React from 'react';
 
function App() {
  return (
    <div>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </div>
  );
}
 
export default App;

 

왜 감싸야 할까?

 

리액트 컴포넌트에서 요소 여러 개를 왜 하나의 요소로 꼭 감싸 주어야 할까요?

그것은 Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록

컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문입니다.

 

 

그런데 여기서 꼭 div 요소를 사용하고 싶지 않을 수도 있습니다.

그런 경우에는 리액트 v16 이상 부터 도입된 Fragment라는 기능을 사용하면 됩니다.

 

import React, { Fragment } from 'react';
 
function App() {
  return (
    <Fragment>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </Fragment>
  );
}
 
export default App;

 

 

Fragment는 다음과 같은 형태로도 표현할 수 있습니다.

 

import React from 'react';
 
function App() {
  return (
    <>
      <h1>리액트 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </>
  );
}
 
export default App;

 

 

2. 자바스크립트 표현식을 작성하려면 JSX 내부에서 코드를 { }로 감싸면 된다.

 

import React from 'react';
 
function App() {
  const name = '리액트';
  return (
    <>
      <h1>{name} 안녕!</h1>
      <h2>잘 작동하니?</h2>
    </>
  );
}
 
export default App;

 

 

3. if문 대신 조건부 연산자를 사용한다. 

 

JSX 내부의 자바스크립트 표현식에서 if 문을 사용할 수는 없습니다.

하지만 조건에 따라 다른 내용을 렌더링해야 할 때는 JSX 밖에서 if 문을 사용하여 사전에 값을 설정하거나, 

{ } 안에 조건부 연산자를 사용하면 됩니다. 조건부 연산자의 또 다른 이름은 삼항 연산자입니다.

 

import React from ‘react‘;


function App() {
  const name = ‘리액트‘;
  return (
    <div>
      {name === ‘리액트‘ ? (
        <h1>리액트입니다.</h1>
      ) : (
        <h2>리액트가 아닙니다.</h2>
      )}
    </div>
  );
}



export default App;

 

4. null을 렌더링하면 아무것도 보여 주지 않는다.

 

개발하다 보면 특정 조건을 만족할 때 내용을 보여 주고,

만족하지 않을 때 아예 아무것도 렌더링하지 않아야 하는 상황이 올 수 있습니다. 

 

import React from 'react';
 
function App() {
  const name = '뤼왝트';
  return <div>{name === '리액트' ? <h1>리액트입니다.</h1> : null}</div>;
}
 
export default App;

 

cf) 이를 더 짧게 && 연산자를 이용하여 나타낼수도 있다. 

 

 

import React from ‘react‘;


function App() {
  const name = ‘뤼왝트‘;
  return <div>{name === ‘리액트‘ && <h1>리액트입니다.</h1>}</div>;
}

export default App;

&& 연산자로 조건부 렌더링을 할 수 있는 이유는

리액트에서 false를 렌더링할 때는 null과 마찬가지로 아무것도 나타나지 않기 때문입니다. 

 

 

 

5. 리액트에서 DOM 요소에 스타일을 적용할 때는 문자열 형태로 넣는 것이 아니라 객체 형태로 넣어 주어야 한다.

    카멜 표기법(camelCase)으로 작성해야 한다.

 

import React from ‘react‘;


function App() {
  const name = ‘리액트‘;
  const style = {
    // background-color는 backgroundColor와 같이 -가 사라지고 카멜 표기법으로 작성됩니다.
    backgroundColor: ‘black‘,
    color: ‘aqua‘,
    fontSize: ‘48px‘, // font-size -> fontSize
    fontWeight: ‘bold‘, // font-weight -> fontWeight
    padding: 16 // 단위를 생략하면 px로 지정됩니다.
  };
  return <div style={style}>{name} </div>;
}



export default App;

 

지금은 style 객체를 미리 선언하고 div style 값으로 지정해 주었는데요.

미리 선언하지 않고 바로 style 값을 지정하고 싶다면 다음과 같이 작성하면 됩니다.

 

import React from 'react';
 
function App() {
  const name = '리액트';
  return (
    <div
      style={{
        // background-color는 backgroundColor와 같이 -가 사라지고 카멜 표기법으로 작성됩니다.
        backgroundColor: 'black',
        color: 'aqua',
        fontSize: '48px', // font-size -> fontSize
        fontWeight: 'bold', // font-weight -> fontWeight
        padding: 16 // 단위를 생략하면 px로 지정됩니다.
      }}
    >
      {name}
    </div>
  );
}
 
export default App;

 

6. JSX에서는 class가 아닌 className으로 설정해 주어야 한다.

 

.react {
  background: aqua;
  color: black;
  font-size: 48px;
  font-weight: bold;
  padding: 16px;
}

 

import React from 'react';
import './App.css';
 
function App() {
  const name = '리액트';
  return <div className="react">{name}</div>;
}
 
export default App;

 

7. 주석

 

JSX 내부에서 주석을 작성할 때는 {/* … */}와 같은 형식으로 작성합니다.

 

return 문안에서는 {/*  /}  안에다가 작성한다. 

 

import React from ‘react‘;
import ‘./App.css‘;


function App() {
  const name = ‘리액트‘;
  return (
    <>
      {/* 주석은 이렇게 작성합니다. /}
      <div
        className=“react“ // 시작 태그를 여러 줄로 작성하게 된다면 여기에 주석을 작성할 수 있습니다.
      >
        {name}
      </div>
      // 하지만 이런 주석이나
      / 이런 주석은 페이지에 그대로 나타나게 됩니다. */
      <input />
    </>
  );
}



export default App;

 

 

정리 및 요약

 

목표에 대해 대답해보기

 

 

JSX를 왜 쓰는가?

 

=> HTML코드와 유사하기에 가독성이 좋고 쉽게 느껴진다.

     HTML 태그 뿐만 아니라, 컴포넌트도 JSX안에서 쓸 수 있기에 활용도가 높다.

 

 

JSX는 어떤 문제를 해결해주는가?

 

=> React.createElement() 함수를 사용한다면 매우 불편하다. JSX를 사용하면 편하게 UI렌더링이 가능하다.

 

 

JSX는 어떻게 사용하는가?

 

1. 최상위 요소로 감싸야한다.

2. 자바스크립트를 사용하려면 {}로 감싼다

3. JSX 내부에서 조건문은 삼항 연산자로 사용한다. if문은 바깥에서 사용하거나 해야한다.

4. 인라인 스타일을 적용하고 싶다면, 객체 형태로 작성해주어야한다. 

5. class는 className으로 사용한다.

6. JSX 내부에서 주석을 작성할 때는 {/* … */}와 같은 형식으로 작성한다.

 

 

 

내가 새로 알게된 사실

 

1. 웹팩 같은 번들러는 브라우저에서도 모듈 불러오는 기능 같은 것들을 사용하기 위해서 사용된다.

 

2. 파일들을 불러오는건 웹팩의 로더라는 기능이 담당한다.

 

3. 렌더링은 '보여준다' 는 것을 의미한다.

 

4. JSX의 장점 중에서 컴포넌트를 JSX안에서 쓸 수 있다는 점이 있다는 것을 인지하게 되었다.

 

5. 컴포넌트 안에서 return안에 최상위 요소로 감싸야하는 이유에 대해서 알게되었다.

     virtual DOM에서 컴포넌트 변화를 감지할 때 효과적으로 비교할 수 있기 때문이다.

     컴포넌트 내부는 하나의 돔 트리 구조로 이루어지는 것이 좋다.

 

6. 객체 형태로 인라인 스타일을 적용할 수 있다는 것을 알게 되었다.

'📖 리액트 > 리액트를 다루는 기술' 카테고리의 다른 글

7장 컴포넌트의 라이프사이클 메서드  (0) 2022.01.25
6강 컴포넌트 반복  (0) 2022.01.24
4장 이벤트 헨들링  (0) 2022.01.21
3장 컴포넌트  (0) 2022.01.19
리액트 스터디 시작!!  (0) 2022.01.17