React는 웹 프레임워크로, 자바스크립트 라이브러리의 하나로서 사용자 인터페이스를 만들기 위해 사용된다.
React를 많이 사용하는 이유
강력한 커뮤니티
리액트는 국내외로 인기가 많은 프레임워크이기 때문에 매우 큰 커뮤니티를 보유하고 있으며, 이에 따라 풍부한 교육 자료, 튜토리얼, 예제코드, 라이브러리가 존재한다.
광범위한 생태계
리액트는 다양한 서드파티 라이브러리와 도구를 지원합니다. 예를 들어서 상태 관리를 위한 리덕스, MobX, 스타일링을 위한 Styled-Components, CSS Modules, 라우팅을 위한 React Router 등이 있다.
하나를 배우면 모바일 앱까지
리액트를 배우면 React Native를 사용해서 모바일 앱을 만들 수 있다. 물론 아예 똑같은 문법은 아니지만, 같은 결의 언어이기 때문에 러닝 커브가 낮다.
DOM이란?
돔은 Document Object Model을 의미한다. 웹 브라우저에 표시되는 모든 UI 구성 요소는 웹 브라우저 내부적으로 객체 형태로 관리되고 있으며, 이를 이용해서 자바스크립트는 웹 브라우저 구성 요소에 접근할 수 있다. 이러한 DOM은 데이터 자료 구조 중 트리(tree) 구조인데, 그래서 다른 말로 돔 트리(DOM Tree)라고 하기도 한다
가상돔(Virtual Dom)이란?
이러한 기존 DOM을 대비하기 위해서 리액트는 가상 돔이라는 새로운 개념을 만들었다. 가상 돔은 기존의 DOM을 그대로 복사해서 리액트 내부 메모리에 저장한다. 리액트에서 어떤 코드의 변경 사항이 발생하게 되면 이렇게 복사한 DOM을 사용해서 변경 사항을 처리하며, 최종적으로 실제 DOM과 비교하여 변경된 부분만 업데이트하기 때문에 DOM 구성 요소의 변경에 대한 작업 비용이 낮고 효율적이다
특정 페이지에서 데이터가 변했다고 가정했을 때, 리액트를 이용해 돔을 업데이트시키는 절차는 다음과 같다.
1. 변화가 일어났다. 변화된 버전을 가상돔으로 바꾸자.
- 데이터가 업데이트 되면 전체 UI를 가상돔에 리렌더링한다.
2. 가상돔끼리 비교하자.
- 변화 전의 가상돔과 변화된 가상돔을 비교한다.
3. 바뀐 부분만 적용하자.
- 바뀐 부분만 실제 돔에 적용을 함으로서 레이아웃 계산은 한 번만 이행된다.(ex. 네비게이션(컴포넌트)을 열었을 때 특정 영역(컴포넌트)이 빨갛게 변하면서 위치가 변경되는 경우의 레이아웃 계산이 일괄로 단 한 번만 이행)
작은 규모의 레이아웃(리플로우)이 여러번 발생하는 것보다 큰 규모의 레이아웃이 한 번 발생하는 것은 성능상의 큰 차이를 나타낸다. 리액트는 위와 같은 얕은 비교와 일괄 돔 업데이트 방식을 이용해 성능 향상을 이끄는 것이다.
리액트는 Component 기반의 구조라는 특징을 가지고 있다.
리액트는 모든 페이지가 Component로 구성되어 있고 하나의 Component는 또 다른 여러 개의 Component의 조합으로 구성될 수 있다.
이러한 Component들을 마치 레고 블록을 조립하듯 끼워 맞춰 새로운 Component를 만들 수 있다.
Component : 입력(props)을 받아 출력(Element) 하는 역할
CreateElement
:CreateElement는 리액트가 처음 출시될 때 부터 존재했던 컴포넌트 작성 방법
const element = createElement(type, props, ...children)
JSX(Javascript XML)JSX는 Javascript XML의 약자로 자바스크립트를 확장한 문법입니다.
function Greeting() { return ( <div> <h1 className="greeting">Hello, React!</h1> <p>Welcome to React 18!</p> </div> ); }
JSX는 반드시 하나의 루트 태그로 구성되어야 한다.
const app = () => { return( <> <div>bbb</div> <div>aaa</div> </> ) }
Tailwind CSS
Tailwind는 쉽게 말해 엄청나게 많은 유틸리티(utility) 클래스로 이루어진 CSS 프레임워크 Tailwind가 제공하는 유틸리티 클래스들을 다양하게 조합하면 추가적인 CSS 코드 작성없이 단순히 HTML 요소의 class 속성에 설정해주는 것만으로도 스타일링이 가능함
// 설치 npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
// tailwind.config.js 설정 /** @type {import('tailwindcss').Config} */ export default { content: [ "./index.html", "./src/**/*.{js,ts,jsx,tsx}", ], theme: { extend: {}, }, plugins: [], }
// index.css @tailwind base; @tailwind components; @tailwind utilities;
// ex) export default function App() { return ( <h1 className="text-3xl font-bold underline"> Hello world! </h1> ) }
인라인 스타일(Inline Style)
인라인 스타일은 HTML 태그의 style 속성을 사용해서 CSS 스타일을 지정하는 방식
🔔 style 속성에는 객체 형식 값이 할당되어야함, font-size -> fontSize 카멜 케이스형식으로 작성const App = () => { return ( <h1 style={{ fontSize: "30px", color: "#ed4848", textDecoration: "line-through", }} Hello World! </h1> ); }; export default App;
CSS Modules
모듈 방식을 사용해서 특정 컴포넌트에만 종속되는 CSS 코드를 작성하기 위한 방법
// App.moudle.css .title { font-size: 30px; color: #ed4848; text-decoration: line-through; }
// App.tsx import styles from "./App.module.css"; const App = () => { return ( <div> <h1 className={styles.title}>Hello World!</h1> </div> ); }; export default App;
CSS-in-JS
CSS-in-JS는 JavaScript 내에서 CSS 스타일을 작성하고 관리하는 기법
CSS파일과 다르게 JavaScript 코드 내에서 정의하고 컴포넌트와 함께 번들링하는 접근 방식
Styled Components
// npm i styled-components 설치 import styled from "styled-components"; const HelloWorld = styled.h1` font-size: 30px; color: #ed4848; `; const App = () => { return ( <div> <HelloWorld>Hello, World!</HelloWorld> </div> ); }; export default App;
Emotion
// npm i @emotion/css import { css } from "@emotion/css"; const App = () => { return ( <h1 className={css` font-size: 30px; color: #ed4848; `} Hello, World! </h1> ); }; export default App;
vanilla extract
제로 런 타임(Zero Run Time)이라는 개념이 새롭게 등장하게 되면서 최근에 급 부상하고 있는 라이브러리. 제로 런 타임이란, 런 타임 오버헤드가 없는 CSS를 의미함
// npm i @vanilla-extract/css @vanilla-extract/vite-plugin
//styles.css.ts import { style } from "@vanilla-extract/css"; export const h1Style = style({ fontSize: "30px", color: "#ed3838", textDecoration: "line-through", });
// app.tsx import { h1Style } from "./vanila/styles.css.ts"; const App = () => { return ( <div> <h1 className={h1Style}>Hello, World!</h1> </div> ); }; export default App;