๐Ÿ™„ React ์™œ ์จ์š”?

11187 ๋‹จ์–ด frontendfrontend

๋‚˜๋Š” ๋ฆฌ์•กํŠธ๋ฅผ ๋ฐฐ์šฐ๊ณ  ์žˆ๋‹ค. ๋ณ„๋‹ค๋ฅธ ์ด์œ ๋Š” ์—†๋‹ค. ์ œ์ผ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ํŠธ๋ Œ๋””ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ณ  ๊ทธ๋Ÿผ ๋‚˜๋„ ๋ฐฐ์›Œ์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด๊ฒŒ ๋‚ด ์†”์งํ•œ ์‹ฌ๊ฒฝ์ด์ง€๋งŒ ๋‚จ๋“ค์ด ๋ฌผ์–ด๋ดค์„ ๋•Œ ์ด๋Ÿฐ ์‹์œผ๋กœ ๋Œ€๋‹ต์ด ๋‚˜์˜จ๋‹ค๋ฉด ๊ทธ๊ฑด ์ƒ๋Œ€๋„, ์ž์‹ ๋„ ์ฐธ ๊ณค๋ž€ํ•œ ์ƒํ™ฉ์ผ ๊ฒƒ ๊ฐ™๋‹ค.

๊ทธ๋Ÿฐ ๋ถˆ์ƒ์‚ฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜ํ•˜๋‚˜ ์‚ดํŽด๋ณด์ž.

JS ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ ์‚ฌ์šฉ๋Ÿ‰(์ถœ์ฒ˜: StateOfJS(2021))

๋ฆฌ์•กํŠธ?

๋ฆฌ์•กํŠธ๊ฐ€ ๋ญ์•ผ?

์ถœ์ฒ˜: ๋ฆฌ์•กํŠธ ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€

๋ฆฌ์•กํŠธ๋Š” UI๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ ๋งŒํผ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋“ค๋ณด๋‹ค ๊ธฐ๋Šฅ์ด ์กฐ๊ธˆ ์ ์ง€๋งŒ ํ™•์žฅ์„ฑ์ด ๋›ฐ์–ด๋‚˜๋‹ค๊ณ  ํ•œ๋‹ค.

์˜ˆ์‹œ๋กœ ๋ฆฌ์•กํŠธ๋Š” SPA(Single Page Application) ๊ฐœ๋ฐœ ์ค‘์ ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ผ์šฐํŒ…์„ ์œ„ํ•ด react-router ํŒจํ‚ค์ง€๋ฅผ ์ด์šฉํ•œ๋‹ค.

์žฅ์ ?

์„ธ๊ณ„์—์„œ ์ œ์ผ ์ž˜ ๋‚˜๊ฐ€๋Š” ๋„๊ตฌ๋ผ๋ฉด ๋šœ๋ ทํ•œ ์žฅ์ ์ด ์žˆ๊ฒ ์ง€?

๋ฆฌ์•กํŠธ ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€์— ๋“ค์–ด๊ฐ€๋ฉด ์„ ์–ธํ˜•๊ณผ ์ปดํฌ๋„ŒํŠธ๋ผ๋Š” ๋‹จ์–ด๊ฐ€ ๋ณด์ธ๋‹ค. ๋‹ค์–‘ํ•œ ์žฅ์ ๋“ค์ด ์žˆ๊ฒ ์ง€๋งŒ ์„ ์–ธํ˜•, ์ปดํฌ๋„ŒํŠธ, ๊ทธ๋ฆฌ๊ณ  Virtual DOM์— ๋Œ€ํ•ด ์–˜๊ธฐํ•ด๋ณด๊ฒ ๋‹ค.

์„ ์–ธํ˜•

  • ์„ ์–ธํ˜•(declarative) vs ๋ช…๋ นํ˜•(imperative)
const arr = [1, 2, 3, 4, 5];

const imperative = (function getDoubledArr() {
  const result = [];

  for (let i = 0; i < arr.length; i++) {
    result[i] = arr[i] * 2;
  }

  return result;
})(); // ๋ช…๋ นํ˜•
const declarative = arr.map((data) => data * 2); // ์„ ์–ธํ˜•

console.log(declarative); // [2, 4, 6, 8, 10]
console.log(imperative); // [2, 4, 6, 8, 10]

๋ช…๋ นํ˜•์€ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌ๋ ์ง€, ์„ ์—ฐํ˜•์€ ๋ฌด์—‡์„ ํ• ์ง€์— ๋Œ€ํ•ด ๊ฐ๊ฐ ์ค‘์ ์„ ๋งž์ถ˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์ด๋‹ค.

๋ฆฌ์•กํŠธ๋Š” ๊ณต์‹ ๋ฌธ์„œ์— ๋‹น๋‹นํ•˜๊ฒŒ ์„ ์–ธํ˜•์ด๋ผ๊ณ  ์ ์–ด ๋†“์•˜๋‹ค. ๋ฌด์Šจ ์˜๋ฏธ์ธ์ง€ ์‚ดํŽด๋ณด์ž.

// Without React
const root = document.querySelector(".root");
const container = document.createElement("div");
const counter = 9;

if (counter > 10) {
  container.classList.add(".container");
} else {
  container.classList.add(".box");
}

container.innerText = "Hello";
root.appendChild(container);
// With React
import React, { useState } from "react";
import ReactDOM from "react-dom/client";

const Container = () => {
  const [counter, setCounter] = useState(9);
  
  return <div className={counter > 10 ? 'container' : 'box'}>Hello</div>
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Container />);

์œ„์™€ ๊ฐ™์ด ํ›จ์”ฌ ๊ฐ„ํŽธํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฌธ์„œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ

๋ฆฌ์•กํŠธ ์•ฑ์€ ์ปดํฌ๋„ŒํŠธ๋ผ๋Š” ๋‹จ์œ„๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ๋Š” ๋ถ€๋ชจ์—๊ฒŒ์„œ ๋ฐ›์€ Props์™€ ์ž์‹ ์ด ๊ด€๋ฆฌํ•˜๋Š” State๋ฅผ ๊ฐ€์ง€๋Š”๋ฐ, ์ด ๊ฐ’๋“ค์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋ง์‹œํ‚จ๋‹ค.

์ปดํฌ๋„ŒํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ๋‚˜๋ˆ„๊ณ  ๋˜ ์–ด๋–ป๊ฒŒ ์ปดํฌ๋„ŒํŠธ์˜ State๋ฅผ ๊ด€๋ฆฌํ•˜๋ƒ์— ๋”ฐ๋ผ ๋ฆฌ์•กํŠธ ์•ฑ์˜ ์„ฑ๋Šฅ์ด ์ขŒ์šฐ๋œ๋‹ค.

Virtual DOM

Virtual DOM ์ด์ „์— DOM์— ๋Œ€ํ•ด ๋งํ•ด๋ณด์ž. DOM์€ HTML ๋ฌธ์„œ๋ฅผ ์ด๋ฃจ๋Š” ์š”์†Œ๋ฅผ ๊ตฌ์กฐํ™”ํ•ด์„œ ๋‚˜ํƒ€๋‚ธ ๊ฐ์ฒด๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” DOM์— ์ ‘๊ทผํ•˜์—ฌ ๋ฌธ์„œ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ DOM์„ ์กฐ์ž‘ํ•˜๋Š” ํ–‰์œ„๋Š” ๋น„์šฉ์ด ํฌ๋‹ค. Virtual DOM์€ ์ด ๋น„์šฉ์„ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๋Š”๋ฐ ๋ชฉ์ ์ด ์žˆ๋‹ค.

Virtual DOM์€ ์‹ค์ œ DOM์„ ์ถ”์ƒํ™”ํ•œ ๊ฐ์ฒด์ด๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ๋ณ€๊ฒฝ๋  ๋‚ด์šฉ๋“ค์„ Virtual DOM์— ๋ฐ˜์˜ํ•˜๊ณ  ์‹ค์ œ DOM๊ณผ ๊ฐ’์„ ๋น„๊ตํ•˜๋ฉฐ ๋ฐ”๊ฟ”์•ผ ํ•  ๋ถ€๋ถ„๋งŒ ๋ฐ”๊ฟ”์ค€๋‹ค.

๋ผ๊ณ  ์„ค๋ช…์€ ๋˜์–ด์žˆ๋Š”๋ฐ ๊ฐ€์Šด์— ์™€๋‹ฟ์ง€๋Š” ์•Š๋Š”๋‹ค. ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์ฐพ์•„๋ณด๋‹ˆ key์™€ value ํ˜•ํƒœ๋กœ ๋งค์นญ์‹œ์ผœ diffing ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋”ฐ๋ผ ์žฌ์กฐ์ • ๊ณผ์ •์„ ๊ฑฐ์นœ๋‹ค๊ณ  ํ•œ๋‹ค... (๋‚˜์ค‘์— ์ƒ์„ธํ•œ ๋‚ด์šฉ์„ ๋” ์•Œ์•„๋ด์•ผ๊ฒ ๋‹ค.)

Virtual DOM์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋งŒํผ ๋‹จ์ ๋„ ์กด์žฌํ•˜์ง€๋งŒ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉ๋œ๋‹ค๋ฉด ์„ฑ๋Šฅ ์ธก๋ฉด์—์„œ ํฐ ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

๋‹จ์ ์€?

SPA ๋‹จ์ 

SPA๋Š” ๋กœ๋”ฉ ์ดˆ๊ธฐ์— ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฐ›์•„์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋Š๋ฆฌ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  HTML ๋ฌธ์„œ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๊ทธ๋ฆฌ๋Š” ๊ฒŒ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฒ€์ƒ‰ ์—”์ง„์— ์ตœ์ ํ™”๋˜์ง€ ์•Š๋Š”๋‹ค.(์š”์ฆ˜์€ ์—”์ง„์ด ์ž˜ ๋‚˜์™€์„œ ๊ดœ์ฐฎ๋‹ค๊ณ  ํ•˜๊ธด ํ•จ)

SPA๋ฅผ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ ๋ฆฌ์•กํŠธ๋„ ์ด๋Ÿฐ ๋‹จ์ ์„ ๊ทธ๋Œ€๋กœ ๊ฐ–๊ณ  ์žˆ๋‹ค.

์˜ค๋ฒ„ํ—ค๋“œ

๋ฆฌ์•กํŠธ๋Š” ์•„์ฃผ ํ›Œ๋ฅญํ•œ ๋„๊ตฌ๋‹ค. ์žฆ์€ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๋ฉฐ ๊ทธ์— ๋”ฐ๋ผ ๋‹ค์‹œ ๋ Œ๋”๋ง์„ ํ•ด์•ผํ•˜๋Š” ์•ฑ์ด ์žˆ๋‹ค๋ฉด ๋ฆฌ์•กํŠธ๋Š” ๊ทธ ์—ญํ• ์„ ์ถฉ๋ถ„ํžˆ ์ž˜ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํ•œ ์•ฑ์ด๋ผ๋ฉด? ์˜คํžˆ๋ ค ๋ฆฌ์•กํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๋ฆฌ์•กํŠธ ์ž์ฒด๊ฐ€ ์ง€๋‹Œ ์˜ค๋ฒ„ํ—ค๋“œ ๋˜ํ•œ ํ”„๋กœ์ ํŠธ์— ๊ณ ๋ คํ•ด์•ผํ•œ๋‹ค.


์žฅ๋‹จ์ ์€ ์•Œ๊ฒ ์ง€๋งŒ...

์•„์ง ๋ฆฌ์•กํŠธ์— ๋Œ€ํ•ด ์ƒ์„ธํ•˜๊ฒŒ ๊ธ€์„ ์ ๊ธฐ์—๋Š” ๊ทธ๋งŒํผ ๊นŠ๊ฒŒ ์‚ฌ์šฉํ•ด๋ณด์ง€ ์•Š์•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๊ธ€๋กœ๋งŒ ์ ๋Š”๋‹ค๊ณ  ์•Œ๊ฒŒ ๋˜๋Š” ๊ฒƒ๋„ ์•„๋‹ˆ๊ณ  ์ง์ ‘ ๊ฒช์–ด์•ผ ๊ฐ€์Šด์— ๋‚จ์ง€ ์•Š์„๊นŒ?

ํ”„๋ก ํŠธ์—”๋“œ ์‹œ์žฅ์ด ๊ธ‰์†๋„๋กœ ๋ณ€ํ™”ํ•œ๋‹ค๊ณ ๋Š” ํ•˜์ง€๋งŒ ํ˜„์žฌ ๋ฆฌ์•กํŠธ๊ฐ€ ๋Œ€์„ธ๋ผ๋Š” ์‚ฌ์‹ค์„ ๋ถ€์ •ํ•  ์ˆ˜๋Š” ์—†๋‹ค. ์ผ๋‹จ ๋ฆฌ์•กํŠธ๋ฅผ ์ถฉ๋ถ„ํžˆ ๊ณต๋ถ€ํ•˜๊ณ , ํ”„๋ก ํŠธ์—”๋“œ ์ž์ฒด์— ๋Œ€ํ•œ ์ง€์‹๋„ ํ’๋ถ€ํ•˜๊ฒŒ ์Œ“์•„๋ณด์ž.

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ