[React] 리액트 발상, JSX
리액트의 발상
[상황] 인터랙션이 많고 동적 UI 표현이 필요합 웹 애플리케이션
↓
[문제] DOM을 직접 건드리면서 작업하면 코드가 난잡해지기 쉬움
↓
[해결] Ember, Backbone, AngularJS 등의 프레임워크 등장
자바스크립트의 특정 값이 바뀌면 특정 DOM의 속성이 바뀌도록 연결 = 업데이트 작업 간소화
↓
[문제] 애플리케이션의 규모가 크면 상당히 복잡해지고 제대로 관리하지 않을시 성능 저하 발생
↓
[해결] React 라이브러리 등장
데이터에 변화가 있으면 기존에 있던 뷰를 날려버리고 새로 렌더링하는 방식
렌더링
사용자 화면에 뷰를 보여주는 것
↓
[문제] 모든 것을 새로 만들면 속도와 성능 저하
↓
[해결] Virtual DOM 사용
DOM (Document Object Model)
- 객체로 문서 구조를 표현하는 방법
- 웹 브라우저는 DOM을 활용하여 객체에 자바스크립트와 CSS를 적용
- 동적 UI에 최적화 되어 있지 않음
- 규모가 큰 웹 애플리케이션에서 DOM에 직접 접근하여 변화를 주다 보면 성능 이슈가 조금씩 발생 (느려짐)
- DOM 자체는 빠름. 단, 웹 브라우저 단에서 DOM 변화가 일어나면 웹 브라우저가 CSS 재연산, 레이아웃 구성, 페이지 리페인트를 하며 시간이 허비되는 것
메모리에 가상으로 존재하는 DOM으로서 그냥 DOM을 추상화한 JavaScript 객체 = 작동 성능 빠름
- 데이터를 업데이트하면 업데이트가 필요한 곳의 UI를 Virtual DOM에 리렌더링
- 이전 Virtual DOM에 있던 내용과 현재 내용 비교
- 바뀐 부분만 실제 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 형식이지만 실제로는 자바스크립트 객체
📌 아래 문서와 서적의 내용을 정리한 글입니다.