프로그래밍/React

[React] 리액트 발상, JSX

라다디 2022. 3. 7. 16:20

 

리액트의 발상

[상황] 인터랙션이 많고 동적 UI 표현이 필요합 웹 애플리케이션

[문제] DOM을 직접 건드리면서 작업하면 코드가 난잡해지기 쉬움

[해결] Ember, Backbone, AngularJS 등의 프레임워크 등장

자바스크립트의 특정 값이 바뀌면 특정 DOM의 속성이 바뀌도록 연결 = 업데이트 작업 간소화

[문제] 애플리케이션의 규모가 크면 상당히 복잡해지고 제대로 관리하지 않을시 성능 저하 발생

[해결] React 라이브러리 등장

데이터에 변화가 있으면 기존에 있던 뷰를 날려버리고 새로 렌더링하는 방식

더보기

렌더링

사용자 화면에 뷰를 보여주는 것

[문제] 모든 것을 새로 만들면 속도와 성능 저하

[해결] Virtual DOM 사용

더보기

DOM (Document Object Model)

  • 객체로 문서 구조를 표현하는 방법
  • 웹 브라우저는 DOM을 활용하여 객체에 자바스크립트와 CSS를 적용
  • 동적 UI에 최적화 되어 있지 않음 
  • 규모가 큰 웹 애플리케이션에서 DOM에 직접 접근하여 변화를 주다 보면 성능 이슈가 조금씩 발생 (느려짐)
  • DOM 자체는 빠름. 단, 웹 브라우저 단에서 DOM 변화가 일어나면 웹 브라우저가 CSS 재연산, 레이아웃 구성, 페이지 리페인트를 하며 시간이 허비되는 것

메모리에 가상으로 존재하는 DOM으로서 그냥 DOM을 추상화한 JavaScript 객체 = 작동 성능 빠름

  1. 데이터를 업데이트하면 업데이트가 필요한 곳의 UI를 Virtual DOM에 리렌더링
  2. 이전 Virtual DOM에 있던 내용과 현재 내용 비교
  3. 바뀐 부분만 실제 DOM에 적용

리액트와 Virtual DOM이 제공하는 것은 바로 업데이트 처리 간결성

 


Node.js

  • 자바스크립트 런타임 (자바스크립트가 구동되는 환경)
  • 이것으로 웹 브라우저가 환경이 아닌 곳에서도 자바스크립트를 사용하여 연산할 수 있음

설치 이유: 프로젝트 개발에 필요한 주요 도구들이 Node.js를 사용하기 때문 (babel, webpack 등)

 

리액트 프로젝트

  • 컴포넌트를 여러가지 파일로 분리해서 저장
  • 컴포넌트는 일반 자바스크립트가 아닌 JSX 라는 문법으로 작성

웹팩 (Webpack)

  • 여러가지의 파일을 한개로 결합하기 위한 도구

바벨 (Babel)

  • JSX 를 비롯한 새로운 자바스크립트 문법들을 사용하기 위한 도구
  • JSX 코드는 브라우저 실행 전 코드가 번들링되는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환 됨

 

npm

  • Node.js를 설치하면 패키지 매니저 도구인 npm이 설치 
  • npm은 프로젝트에서 사용되는 패키지를 설치하고 해당 패키지들의 버전 관리를 할 때 사용

npm = Package Manager (관리)
npx = Package Runner (실행)

npx
npm 5.2.0 버전부터 따라오는 프로그램으로, 패키지를 설치하지않고, 1회성으로 실행해 볼수 있게 해줌

npx create-react-app [프로젝트명]
create-react-app을 임시로 설치해서 딱 한 번만 실행하고 지워버리라는 뜻

  • 공간 낭비 x
  • 실행할 때마다 다운 받기 때문에 늘 최신 상태

 


웹팩 (Webpack)

import React from 'react';

리액트를 불러와서 사용할 수 있게 해주는 코드

 

리액트 프로젝트를 만들 때 node_modules라는 디렉토리 생성되는데 이 디렉토리에 react 모듈이 설치

 import 구문을 통해 리액트를 불러와서 사용

 

이런식으로 모듈을 불러와서 사용하는 것은 사실 원래 브라우저에 없던 기능

이 기능을 브라우저에서도 사용하기 위해 번들러 사용 (대표적인 번들러: 웹팩)

더보기

번들러 (Bundler)

파일을 묶어 관리

번들러 도구 사용시 import로 모듈을 불러왔을 때 불러온 모듈을 모두 합쳐서 하나의 파일 생성

 

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

웹팩을 사용하면 SVG 파일과 CSS 파일도 불러와서 사용 가능

→ 이렇게 파일들을 불러오는 것은 웹팩의 로더(loader)라는 기능이 담당

  • css-loader: CSS 파일을 불러올 수 있음
  • file-loader: 웹 폰트나 미디어 파일을 불러올 수 있음
  • babel-loader: 자바스크립트 파일을 불러오며 최신 JS문법으로 작성된 코드를 바벨을 이용해서 ES5 문법으로 변환
더보기

ES5 문법으로 변환하는 이유

  • 구버전 웹 브라우저와 호환하기 위해
  • JSX도 정식 자바스크립트 문법이 아니므로 변환해야 함

 


JSX (Javascript XML)

  • 자바스크립트의 확장 문법
  • JSX로 작성된 코드는 브라우저에서 실행되기 전 코드가 번들링되는 과정에서 바벨을 사용하여 일반 자바스크립트 형태의 코드로 변환
function App() {
  return (
    <div>
      Hello <b>react</b>
    </div>
  );
}

해당 JSX 코드는 아래와 같이 변환

function App() {
  return React.createElement("div", null, "Hello ", React.createElement("b", null, "react"));
}

컴포넌트를 렌더링할 때마다 위 코드처럼 React.createElement 함수를 사용해야 한다면 매우 불편

JSX를 사용하면 매우 편하게 UI 렌더링 가능

 

JSX의 장점

  • 가독성이 높고 작성하기 쉬움
  • 높은 활용도 (HTML 태그 뿐만 아니라 컴포넌트도 마치 HTML 태그를 쓰듯이 작성)
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

💡 ReactDOM.render?

  • react-dom 모듈을 불러와 사용
  • 컴포넌트를 페이지에 렌더링하는 역할
  • 첫 번째 파라미터: 렌더링할 내용을 JSX 형태로 작성
  • 두 번째 파라미터: 해당 JSX를 렌더링할 document 내부 요소 설정

 

JSX 작성 규칙

1. 컴포넌트 (일종의 UI 조각)에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 함

→ Virtual DOM에서 컴포넌트 변화를 감지할 때 효율적으로 비교하도록 컴포넌트 내부는 하나의 DOM 트리 구조로 이루어져야 한다는 규칙이 있기 때문

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

↓요소 여러 개가 부모 요소 하나에 의하여 감싸져 있지 않아서 오류 발생

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

 꼭 div 요소를 사용하고 싶지 않다면? Fragment 기능 사용

import { Fragment } from "react";

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

 Fragment는 다음과 같은 형태로도 표현 가능

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

 

2. 자바스크립트 표현식

JSX는 { }로 감싸서 자바스크립트 표현식을 쓸 수 있음

 

3. if문 대신 삼항 연산자

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

JSX 밖에서 if문을 사용하여 사전에 값 설정

→ { } 안에서 삼항 연산자 사용

 

4. AND 연산자(&&)을 사용한 조건부 렌더링

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

false를 렌더링하면 null과 마찬가지로 아무것도 나타나지 않기 때문에 가능

📍 예외

falsy한 값인 0은 예외적으로 화면에 나타남

function App() {
  const num = 0;
  return num && <div>내용</div>;
}

 

5. undefined는 렌더링하지 않기

함수에서 undefined만 반환하여 렌더링하는 상황을 만들면 안 됨

OR 연산자(||)를 이용해 undefined일 때 사용할 값 지정하여 오류 방지

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

📍 JSX 내부에서 undefined를 렌더링하는 것은 괜찮음

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

 

6. 태그는 꼭 닫아야 함

HTML에서 input은 닫지 않아도 작동하지만 JSX에서는 오류 발생

다음과 같이 작성 <input></input>

self-closing 태그: <input />

 

7. 주석

{/* 주석 내용 */}

📍 // 이나 /* 주석 내용 */와 같이 작성하면 페이지에 그대로 나타남

 

 

정리

JSX는 HTML과 비슷하지만 완전히 똑같지 않음

코드로 보면 XML 형식이지만 실제로는 자바스크립트 객체 

 


📌 아래 문서와 서적의 내용을 정리한 글입니다.