React์—์„œ iframe ์ „์ฒดํ™”๋ฉด ์ „ํ™˜ํ•˜๊ธฐ(์†์„ฑ ์ฒดํฌ ํฌํ•จ)

allowfullscreen ๊ทธ๋ฆฌ๊ณ  document.fullscreenEnabled

ํ™”๋ฉด ๋‚ด๋ถ€์— ์‚ฝ์ž…๋œ iframe์—์„œ ์ „์ฒด ํ™”๋ฉด ์„ค์ •, ํ•ด์ œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.
๊ตฌํ˜„์€ ์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๋‹ค.

๋จผ์ € iframe ํƒœ๊ทธ์— allowfullscreen ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
allowfullscreen ์†์„ฑ์„ ๊ฐ–๋Š” iframe์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ „์ฒดํ™”๋ฉด ์„ค์ •, ํ•ด์ œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฉฐ ESC๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

<iframe src=”https://choonse.com” allowfullscreen />

์ „์ฒด ํ™”๋ฉด ์„ค์ • ๋ฉ”์„œ๋“œ document.documentElement.requestFullscreen()
์ „์ฒด ํ™”๋ฉด ํ•ด์ œ ๋ฉ”์„œ๋“œ document.exitFullscreen()

์ „์ฒดํ™”๋ฉด ์„ค์ •/ํ•ด์ œ ๋ฒ„ํŠผ์— ์ด๋ฒคํŠธ๋ฅผ ๊ฑธ์–ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐ˜ํ™˜ํ˜•์€ Promise์ด๋‹ค.

๋งŒ์•ฝ allowfullscreen ์†์„ฑ์ด ์—†๋Š” iframe์—์„œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?disallowed by permissions policy ์—๋Ÿฌ๋กœ ์‚ฌ๋žŒ์„ ๋‹นํ™ฉ์‹œํ‚จ๋‹ค.

์ด ๋•Œ๋Š” allowfullscreen ์†์„ฑ์˜ ์กด์žฌ ์—ฌ๋ถ€(true)๋ฅผ ์ฒดํฌํ•ด์ฃผ๋ฉด ๋˜๋Š”๋ฐ, ํ•ด๋‹น ์†์„ฑ์€
document.fullscreenEnabled ์†์„ฑ์„ ์‚ฌ์šฉํ•ด true/false๋กœ ํ™•์ธํ•œ๋‹ค.

๋งŒ์•ฝ iframe์— allowfullscreen ์†์„ฑ์ด ์—†์„ ๋•Œ ์ „์ฒด ํ™”๋ฉด ๋ฒ„ํŠผ์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

document.fullscreenEnabled๋ฅผ ์ฒดํฌํ•ด์„œ ํ™œ์„ฑ/๋น„ํ™œ์„ฑ์„ ๊ฒฐ์ •ํ•˜๋ฉด ๋˜๋Š”๋ฐ document is not defined์™€ ๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” useEffect ๋‚ด๋ถ€์—์„œ ํ•ด๋‹น ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋œ ์‹œ์ ์— document์— ์ ‘๊ทผํ•˜๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

Next.js + Leaflet(OSM) Marker ํ‘œ์‹œํ•˜๊ธฐ

Next.js์—์„œ Leaflet Marker ์ด๋ฏธ์ง€ ๋กœ๋”ฉํ•˜๊ธฐ

React-leaflet์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ ์„ค์ • ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ leaflet ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ๋„ ๋งต์€ ํ‘œ์‹œ๋˜์ง€๋งŒ Marker ์ด๋ฏธ์ง€๋Š” ๊นจ์ ธ์„œ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Next.js์—์„œ ์ด๋ฏธ์ง€๋Š” Next/image์™€ ์ด๋ฏธ์ง€ ์ƒ๋Œ€ ์ฃผ์†Œ๋ฅผ importํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ์ž˜ ๋กœ๋”ฉ์ด ๋˜์ง€๋งŒ ์ƒ๋Œ€ ๊ฒฝ๋กœ url์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋ฉด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

import Image from "next/image";
import logo from "../../styles/images/logo.png";

//์ž‘๋™ํ•จ
<Image src={logo} alt="logo />

//์ž‘๋™ํ•˜์ง€ ์•Š์Œ
<Image src={"../../styles/images/logo.png"} alt="logo" width="100px" height="100px" />

์ด๋Š” Next.js์— ์ •ํ•ด์ง„ ํด๋” ๊ทœ์น™์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ์š”. ๋งŒ์•ฝ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋ฏธ์ง€๋‚˜ ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๊ณ  ์‹ถ๋‹ค๋ฉด public ํด๋”๋ฅผ ์ด์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋นŒ๋“œ ํ›„ ๊ธฐ๋ณธ ํด๋”๋Š” public์ด๋ฏ€๋กœ public ํด๋” ๋‚ด logo.png ํŒŒ์ผ์„ ๋„ฃ๋Š” ๊ฒฝ์šฐ /logo.png๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

import Image from "next/image";

<Image src={"/logo.png"} alt="logo" width={"100px"} height={"100px"} />

Marker ์ด๋ฏธ์ง€ ํ‘œ์‹œํ•˜๊ธฐ

์ด๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด Marker ์ด๋ฏธ์ง€ ๋ถ€๋ถ„๋„ icon์„ ์‚ฌ์šฉํ•ด์„œ ์‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

public ํด๋” ๋‚ด images ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  logo.png ํŒŒ์ผ์„ ๋„ฃ์€ ๋’ค ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

import { MapContainer, TileLayer, useMap, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import { icon } from "leaflet";

const Icon = icon({
  iconUrl: "images/logo.png",
  iconSize: [24, 24],
  iconAnchor: [12, 24],
});

const MyMap = () => {
  return (
    <MapContainer
      center={[37.56675, 126.97842]}
      zoom={10}
      scrollWheelZoom={true}
      style={{ width: "500px", height: "500px" }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <Marker position={[37.56675, 126.97842]} icon={Icon} >
        <Popup>์„œ์šธ ์‹œ์ฒญ</Popup>
      </Marker>
    </MapContainer>
  );
};

export default MyMap;

Next.js + Leaflet(OpenStreetMap) ์ดˆ๊ธฐ ์„ค์ •ํ•˜๊ธฐ

Next.js์™€ leaflet์ด ๋งŒ๋‚˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ฐธ๊ณ ํ•ด์•ผ ํ•  ์‚ฌ์ดํŠธ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

leafletjs.com
react-leaflet.js.org
openstreetmap.org

๊ฐ„๋žตํ•˜๊ฒŒ ์ •๋ฆฌํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


1. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

Next.js + Typescript๋Š” ์„ค์น˜๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.(๊ด€๋ จ ํฌ์ŠคํŒ… ํด๋ฆญ)

npm i leaflet react-leaflet

Typescript ์ง€์›์„ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

npm i -D @types/leaflet

2. ์ฝ”๋“œ ๊ตฌํ˜„ํ•˜๊ธฐ

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

import “leaflet/dist/leaflet.css”; ๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋งต์ด ๊นจ์ ธ์„œ ํ‘œ์‹œ๊ฐ€ ๋˜๊ณ  style์— ์‚ฌ์ด์ฆˆ๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ํ•˜์–€ ํ™”๋ฉด๋งŒ ๋‚˜์˜ค๋‹ˆ ๋‘ ๋ถ€๋ถ„ ๋ชจ๋‘ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

scrollWheelZoom์€ ์Šคํฌ๋กค ํ™•๋Œ€/์ถ•์†Œ ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

import { MapContainer, TileLayer, useMap, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";

const MyMap = () => {
  return (
    <MapContainer
      center={[37.56675, 126.97842]}
      zoom={10}
      scrollWheelZoom={true}
      style={{ width: "500px", height: "500px" }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      <Marker position={[37.56675, 126.97842]}>
        <Popup>์„œ์šธ ์‹œ์ฒญ</Popup>
      </Marker>
    </MapContainer>
  );
};

export default MyMap;

๋ณ„๋„์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ด์œ ๋Š” ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ๋ถ„๋ฆฌ๋„ ์žˆ์ง€๋งŒ Next.js์˜ ํŠน์„ฑ์ƒ ์„œ๋ฒ„ ๋ Œ๋”๋ง ์‹œ window ์ „์—ญ ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋ฌธ์ œ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.

DOM์ด ์ƒ์„ฑ๋œ ๋’ค ์‹คํ–‰๋˜๋Š” useEffect๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๋ ˆ์ด์ง€ ๋กœ๋”ฉ ๊ธฐ๋Šฅ์ธ dynamic์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—ฌ๊ธฐ์„œ๋Š” dynamic ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ™์€ ์œ„์น˜์— ๋‹ค์Œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

import dynamic from "next/dynamic";

const MyMap = dynamic(() => import("./MyMap"), { ssr: false });

const ShowMap = () => {
  return <MyMap />;
};

export default ShowMap;

์ด๊ฒƒ์œผ๋กœ ๊ธฐ๋ณธ ๊ตฌํ˜„์€ ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งต์„ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

<ShowMap />

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์œผ๋กœ Next.js์—์„œ Leaflet์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •์ด ์™„๋ฃŒ๋˜์—ˆ์ง€๋งŒ Marker ์ด๋ฏธ์ง€๊ฐ€ ๊นจ์ง€๋Š” ํ˜„์ƒ์ด๋‚˜ ์–ธ์–ด ์„ค์ • ๋“ฑ ์ถ”๊ฐ€ํ•  ๋ถ€๋ถ„์ด ๋งŽ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋‚ด์šฉ์€ ๋‹ค๋ฅธ ํฌ์ŠคํŠธ์—์„œ ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ, ๋ฆฌ๋ Œ๋”๋ง ์‹œ CSS๋„ ํ•จ๊ป˜ ๋ฆฌ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•(feat.animation)

์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง ์‹œ CSS๋„ ํ•จ๊ป˜ ๋ฆฌ๋ Œ๋”๋งํ•˜๋„๋ก ๋งŒ๋“ค๊ธฐ

๋ฆฌ์•กํŠธ๋Š” ๋‚ด๋ถ€ ๋กœ์ง์— ๋”ฐ๋ผ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•˜๋„๋ก ๋˜์–ด์žˆ์ง€๋งŒ ๋•Œ๋กœ๋Š” ์ด ๋กœ์ง์ด ์˜๋„ํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค„ ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๊ณ  ๋งˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํด๋ฆญ ์‹œ๋งˆ๋‹ค ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค๊ณ ์ž ํ•  ๋•Œ ๋‹ค์Œ ๋ฐฉ๋ฒ•์„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์›๋ฆฌ๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ฆฌ๋ Œ๋”๋ง์„ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ํด๋ฆญ ์‹œ๋งˆ๋‹ค state ๊ฐ’์— ๋ณ€๊ฒฝ์„ ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฏธ์ง€๋ฅผ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const ColorChange = ({ color }) => {
  const DisplayBox = styled.div`
    width: 300px;
    height: 300px;
    display: flex;
    background: ${color};
    animation: change 3s;

    @keyframes change {
      0% {
        transition-timing-function: cubic-bezier(1, 0, 0.2, 0.5);
      }
      0% {
        width: 0;
      }
    }
  `;

  return <DisplayBox></DisplayBox>;
};

export default ColorChange;

---------------------------------------------------------------
์ปดํฌ๋„ŒํŠธ ํ˜ธ์ถœ
<ColorChange color={color} /> 

red, green์„ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ๋ˆ„๋ฅด๋ฉด ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ๋˜๋Š” state๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฏ€๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋ฉด์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ red์ธ ์ƒํƒœ์—์„œ ๋‹ค์‹œ red๋ฅผ ํ•œ๋ฒˆ ๋” ๋ˆ„๋ฅด๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ํด๋ฆญ๋งˆ๋‹ค CSS๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์–ด ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

๋‹จ์ˆœํ•˜๊ฒŒ ํด๋ฆญ๋งˆ๋‹ค ์ „๋‹ฌ๋˜๋Š” state์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋„๋ก ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปดํฌ๋„ŒํŠธ key ์†์„ฑ์œผ๋กœ ์ž„์˜์˜ ๊ฐ’์„ ์ƒ์„ฑํ•˜์—ฌ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

const [randomData, setRandomData] = useState(Math.random());

//๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ˜ธ์ถœ ํ•จ์ˆ˜
const changeColor = () => {
     // ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์ž‘์—…
     .......
     // ์ž„์˜์˜ ๊ฐ’ ์ƒ์„ฑ
     setRandomData(Math.random());
}

<ColorChange color={color} key={randomData} /> 

์ „๋‹ฌ๋˜๋Š” color ๊ฐ’์˜ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๊ณ  ๊ทธ์— ๋”ฐ๋ผ CSS animation๋„ ๋ฆฌ๋กœ๋“œ๋˜์ง€๋งŒ ๊ณ„์† ๊ฐ™์€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋™์ผํ•œ color ๊ฐ’์ด ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•ด ๋ฆฌ๋ Œ๋”๋ง์ด ๋˜์ง€ ์•Š๋Š” ์›๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํด๋ฆญ ์‹œ color ๊ฐ’์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋”๋ผ๋„ key ๊ฐ’์„ ๊ณ„์† ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๋ณ€๊ฒฝ์„ ์ธ์‹ํ•˜์—ฌ ๊ณ„์† ์ปดํฌ๋„ŒํŠธ์™€ CSS๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


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

Next.js + Typescript + Emotion + Tailwind ํ™˜๊ฒฝ ๊ตฌ์ถ•ํ•˜๊ธฐ

Next.js์—์„œ Emotion๊ณผ TailwindCSS๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •

1. Next.js ์„ค์น˜

๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด Next.js์˜ ์ตœ์‹  ๋ฒ„์ „ + typescript๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

npx create-next-app@latest --ts

์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ์„ค์น˜ ๋ฐ ๋ฒ„์ „์„ ํ™•์ธํ•œ๋‹ค.

npx next -v

2. emotion ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

emotion ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

npm i @emotion/react @emotion/styled @emotion/css @emotion/server

3. tailwind, twin.macro ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

tailwind, twin.macro ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๊ณ  devDependencies์— ์ถ”๊ฐ€ํ•œ๋‹ค.

npm i twin.macro tailwindcss postcss@latest autoprefixer@latest @emotion/babel-plugin babel-plugin-macros --save-dev

config ํŒŒ์ผ ์ƒ์„ฑ์„ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

tailwind.config.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ž…๋ง›์— ๋งž๊ฒŒ ์‚ฌ์šฉ์ž ์ง€์ • ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

npx tailwindcss init -p
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

styles/globals.css์˜ ์ƒ๋‹จ์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. (HTML ํƒœ๊ทธ ๋‚ด์—์„œ ์ธ๋ผ์ธ์œผ๋กœ tailwind๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ)

@tailwind base;
@tailwind components;
@tailwind utilities;

4. .babelrc ์ƒ์„ฑ

twin.macro์˜ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก plugin ์„ค์ •์„ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ .babelrc ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.

๋‚ด๋ถ€ ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

{
  "presets": ["next/babel"],
  "plugins": ["babel-plugin-macros"]
}

5. ์ž‘๋™ ํ…Œ์ŠคํŠธ

emotion ๋ฐ emotion +tw(tailwind) ์ž‘๋™์„ ํ…Œ์ŠคํŠธํ•œ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ pages/index.tsx์— ์ž‘์„ฑํ•˜๊ณ  npm run dev๋กœ ์‹คํ–‰ํ•œ๋‹ค.

import type { NextPage } from "next";
import styles from "../styles/Home.module.css";
import styled from "@emotion/styled/macro";
import tw from "twin.macro";

const Input = tw.input`
    text-center border h-28
`;

const MyDiv = styled.div`
  background: gold;
  font-size: 5rem;
  margin-top: 10px;
`;

const Home: NextPage = () => {
  return (
    <div className={styles.container}>
      <main className={styles.main}>
        <h1 className={styles.title}>
          <Input placeholder="box" />
          <MyDiv>Test Text</MyDiv>
        </h1>
      </main>
    </div>
  );
};

export default Home;

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.


๊ด€๋ จ ๋งํฌ

nextJS https://nextjs.org/

tailwindCSS https://tailwindcss.com/

emotion https://emotion.sh/docs/introduction

twin.macro https://github.com/ben-rogerson/twin.macro#readme

OnKeyPress๋Š” ์™œ ESC๊ฐ€ ์ธ์‹์ด ์•ˆ๋ ๊นŒ?(React.ํ‚ค ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ)

Key ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์†์„ฑ

๋ฆฌ์•กํŠธ input์—์„œ ํ‚ค ์ž…๋ ฅ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ onKeyPress, onKeyDown, onKeyUp ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์™€ ๊ฐ™์€ ๋ช…์นญ์˜ ์†์„ฑ๋“ค์„ ๋ฆฌ์•กํŠธ๋Š” camel case๋กœ ํ‘œ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

const onKeyPress= e => {
    if(e.key==='Enter'){    
        findExecute();
    }   
}

........

<div onKeyPress={onKeyPress}>click</div>

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์‹œ์ ์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅผ ๋ฟ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ ์ด๋ฒคํŠธ ๋ณ„ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

onKeyDown ๐Ÿ‘‰ ์ด๋ฒคํŠธ๊ฐ€ ๋จผ์ € ์‹คํ–‰
onKeyUp ๐Ÿ‘‰ text๊ฐ€ ์ž…๋ ฅ๋˜๋ฉด ์‹คํ–‰
onKeyPress ๐Ÿ‘‰ text ์ž…๋ ฅ์ด ์™„๋ฃŒ๋˜๋ฉด ์‹คํ–‰ (Deprecated)

MDN์˜ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด ์ด์ œ onKeyPress๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•˜๋‹ˆ ๊ฑฐ์˜ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋Š” onKeyDown์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

MDN – keypress event


์™œ onKeyPress์—์„œ ESC๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์„๊นŒ?

onKeyPress๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ESC๊ฐ€ ๋ˆŒ๋ ค์กŒ์„ ๋•Œ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

onKeyPress๋Š” ESC, CTRL, ALT ๋“ฑ function ๊ธฐ๋Šฅ์„ ๊ฐ–๋Š” ํ‚ค๋ฅผ ์ œ์™ธํ•˜๊ณ  ์•ŒํŒŒ๋ฒณ๊ณผ ์ˆซ์ž ํ‚ค์—์„œ๋งŒ ์ด๋ฒคํŠธ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ onKeyDown, onKeyUp์€ onKeyPress์—์„œ ์ธ์‹๋˜์ง€ ๊ธฐ๋Šฅ ํ‚ค๋“ค๋„ ์ธ์‹์ด ๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ onKeyPress๋Š” ์ด์ œ ๋” ์ด์ƒ ์ง€์›๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•˜๋‹ˆ ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” onKeyDown์„ ์‚ฌ์šฉํ•˜๊ณ  ์ƒํ™ฉ์— ๋”ฐ๋ผ onKeyUp์„ ์‚ฌ์šฉํ•˜๋ฉด ํฐ ๋ฌธ์ œ ์—†์ด ์›ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ ํ‚ค ๊ฐ’๊ณผ ์ด์Šˆ ๊ด€๋ จ ํŽ˜์ด์ง€๋ฅผ ๋งํฌ๋กœ ๋‚จ๊ธฐ๊ฒ ์Šต๋‹ˆ๋‹ค.


ํ‚ค ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•ด๋ณด๋ฉด์„œ ์•Œ ์ˆ˜ ์žˆ๋Š” ์‚ฌ์ดํŠธ -> https://keycode.info/

๊ด€๋ จ ์ด์Šˆ -> https://github.com/Leaflet/Leaflet/issues/5234

setState & useState, ์™œ ๋น„๋™๊ธฐ์ผ๊นŒ?(ํƒ๊ตฌ์ผ๊ธฐ, ๋ฆฌ์•กํŠธReact)

setState, useState๋ฅผ ๋™๊ธฐ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

๋ฆฌ์•กํŠธ(React)์˜ state๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๊ฐ’์ž…๋‹ˆ๋‹ค.

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋Š” state๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋Š” useState ํ›…(ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ๋Š” ๋™์ž‘ X)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ ๋‘๊ณ  ์™œ state๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ’์„ ๊ด€๋ฆฌํ• ๊นŒ์š”?

์ด๋Š” state๊ฐ€ ๊ฐ–๋Š” ํŠน์„ฑ ๋•Œ๋ฌธ์ธ๋ฐ์š”. ๋ฐ”๋กœ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฆฌ๋ Œ๋”๋ง(Re-rendering)์ด ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๊ฐ’์ด ๋ณ€ํ™”ํ•จ์— ๋”ฐ๋ผ ์‹ค์‹œ๊ฐ„(!!!)์œผ๋กœ ํ™”๋ฉด์ด ๋ Œ๋”๋ง๋˜๊ณ  ๋ณ€ํ™”๋œ ๊ฐ’์ด ํ™”๋ฉด์— ๋ฐ”๋กœ ๋ฐ˜์˜๋ฉ๋‹ˆ๋‹ค.

๊ฐ’์˜ ๋ณ€ํ™”๋ฅผ ๋ฆฌ์•กํŠธ๋„ ์•Œ์•„์ฐจ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์–ด์•ผ ํ•˜๋ฏ€๋กœ ๊ฐ’์˜ ๋ณ€๊ฒฝ์€ ๋ฆฌ์•กํŠธ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

//ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ
class MyClass extends React.Component {
  constructor(props) {
    super(props);
    //state
    this.state = {
      cnt: 0  //์ดˆ๊ธฐํ™” 0
    };
  }

updateState = () => {
  this.setState({ cnt: this.state.cnt + 1 });
}

render() {
    return (
      <div>
        <p>๊ฐ’:{this.state.cnt}</p> 
        <button onClick={this.updateState}>plus</button>
      </div>
    );
  }
}
//ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ
import React, { useState } from 'react';

const MyFunc = () => {
  //useState ํ›…์„ ํ†ตํ•ด state ์‚ฌ์šฉ
  const [cnt, setCnt] = useState(0); //์ดˆ๊ธฐํ™” 0

const plusNum = () => {
   setCnt( cnt+1 );
}

return(
    <div>
       <p>๊ฐ’:{cnt}</p>
       {/* ํ›…์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•จ */}
       <button onClick={plusNum}>plus</button>
    </div>
  )
}

ํด๋ž˜์Šคํ˜• ๋˜๋Š” ํ•จ์ˆ˜ํ˜•์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์นœ๊ตฌ๊ฐ€ ๋œน๋‹ˆ๋‹ค.

plus๋ฅผ ๋ˆ„๋ฅด๋ฉด ๊ฐ’์ด 1์”ฉ ํ”Œ๋Ÿฌ์Šค ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ์–ด๋–จ๊นŒ์š”?

const plusNum = () => {
   setCnt(cnt+1);
   console.log('result:'+cnt);
}

์˜๋„ํ•œ ๊ฒƒ์€ state์— cnt+1์˜ ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ  ์ƒˆ๋กœ ์„ค์ •๋œ ๊ฐ’์„ ๋ฐ”๋กœ ์ฝ˜์†”์ฐฝ์— ์ถœ๋ ฅํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์ธ๋ฐ์š”. ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ฝ˜์†”์ฐฝ์˜ ๊ฒฐ๊ณผ๋Š” ํ•œ ๊ฑธ์Œ ๋Šฆ์Šต๋‹ˆ๋‹ค.

์™œ ์ด๋Ÿฐ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ผ๊นŒ์š”?

๋ฐ”๋กœ ๋น„๋™๊ธฐ(Asynchronous)์˜ ํŠน์„ฑ ๋•Œ๋ฌธ์ธ๋ฐ์š”.


1. ๋™๊ธฐ์™€ ๋น„๋™๊ธฐ

๋™๊ธฐ(Synchronous) – ์ˆœ์„œ๋Œ€๋กœ ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌ.

๋น„๋™๊ธฐ(Asynchronous) – ์ˆœ์„œ๊ฐ€ ์•„๋‹Œ ์ด๋ฒคํŠธ์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ.

์งฑ๊ตฌ์˜ ์ผ์ƒ์„ ํ†ตํ•ด ๋™๊ธฐ ์ž‘์—…์„ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์—„๋งˆ : “์งฑ๊ตฌ์•ผ! ์•ก์…˜๋ถ„์‹ ๊ฐ€์„œ ๋–ก๋ณถ์ด 3์ธ๋ถ„๋งŒ ํฌ์žฅํ•ด ์˜ค๊ฒ ๋‹ˆ? ์ง‘์— ๊ฐ€์ ธ์™€์„œ ๊ทธ๋ฆ‡์— ์˜ฎ๊ฒจ ๋‹ด๊ณ  ์—„๋งˆ๋ฅผ ๋ถˆ๋Ÿฌ!”

์งฑ๊ตฌ ํ”„๋กœ์„ธ์Šค๋Š” 1.๋–ก๋ณถ์ด๋ฅผ ์‚ฌ๋Ÿฌ ๋‚˜๊ฐ€์„œ 2.์ฃผ๋ฌธ์„ ํ•˜๊ณ  3.์ง‘์— ๋“ค๊ณ  ์™€์„œ 4.๋‹ค์‹œ ๊ทธ๋ฆ‡์— ๋‹ด๊ณ  5.์—„๋งˆ๋ฅผ ๋ถ€๋ฅด๋Š” ๊ณผ์ •์ด ๋ชจ๋‘ ์ˆœ์„œ๋Œ€๋กœ ๋™๊ธฐ๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

ํ˜ธ๊ธฐ์‹ฌ ๋งŽ์€ ์งฑ๊ตฌ๋Š” ์—„๋งˆ ๋ง์„ ์ž˜ ๋“ค์„๋ฆฌ๊ฐ€ ์—†๊ฒ ์ง€๋งŒ์š”..

๊ทธ๋ ‡๋‹ค๋ฉด ๋น„๋™๊ธฐ ์ž‘์—…์„ ์‹œํ‚ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ• ๊นŒ์š”?

๋น„๋™๊ธฐ ์—„๋งˆ : “์งฑ๊ตฌ์•ผ! ์•ก์…˜๋ถ„์‹ ๋–ก๋ณถ์ด 2์ธ๋ถ„์ด๋ž‘ ์ตธ์ฝ”๋น„๋ฐ˜์  ์งฌ๋ฝ• ๋‘๊ฐœ๋ฅผ ๋ฐฐ๋‹ฌ ์‹œ์ผœ์„œ ๋„์ฐฉํ•˜๋ฉด ๊ฐ์ž ๊ทธ๋ฆ‡์— ์˜ฎ๊ฒจ ๋‹ด์•„์ค˜! ๋ฐฐ๋‹ฌ์ด ์˜ค๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฐฉ์— ์žฅ๋‚œ๊ฐ ์ข€ ์น˜์›Œ์ฃผ๋ฉด ์ดˆ์ฝ”๋น„๋ฅผ ์ค„์ง€๋„ ๋ชฐ๋ผ~!”

์ž‘์—…์„ ๊ฐ๊ฐ ์š”์ฒญํ•˜๊ณ , ์š”์ฒญํ•œ ์ž‘์—…์ด ๊ฐ€๊ฒŒ์—์„œ ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ ์งฑ๊ตฌ๋Š” ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์งฑ๊ตฌ๊ฐ€ ๋ฐฐ๋‹ฌ ์ฃผ๋ฌธ(์ž‘์—… ์š”์ฒญ)์„ ํ•˜๊ณ  ๋„์ฐฉํ•˜๊ธฐ ์ „๊นŒ์ง€(์š”์ฒญ ์ฒ˜๋ฆฌ์ค‘)๋Š” ์žฅ๋‚œ๊ฐ ์น˜์šฐ๊ธฐ(๋‹ค๋ฅธ ์ž‘์—…)๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๊ฐ€ ๋ฐฐ๋‹ฌ์ด ์™„๋ฃŒ(์š”์ฒญ ์ž‘์—… ์™„๋ฃŒ)๋˜๋ฉด ๋‹ค์‹œ ๊ทธ๋ฆ‡์— ์˜ฎ๊ฒจ ๋‹ด๋Š”(์š”์ฒญ ๊ด€๋ จ ์ž‘์—… ์ง„ํ–‰) ์‹์ž…๋‹ˆ๋‹ค.


2. ๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„ ์ƒ˜ํ”Œ์—์„œ ์ฝ˜์†” ์ถœ๋ ฅ์ด ์—…๋ฐ์ดํŠธ๋œ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”?

์—ฌ๋Ÿฌ ๊ธ€๊ณผ ๋ฌธ๋‹ต์„ ์ฐธ๊ณ ํ•˜์—ฌ ๋‚ด๋ฆฐ ๊ฒฐ๋ก ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ํŠน์„ฑ์„ ๊ฐ–๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„์— ์˜ํ•ด setCnt ์ž‘์—…์€ ๋’ค๋กœ ๋ฐ€๋ฆฌ๊ณ  console.log์ž‘์—…์ด ๋จผ์ € ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const printSequence = () => {
    console.log('first Call');
    setTimeout(()=>{secondCall()},0)
    console.log('third Call');
}

const secondCall = () => {
    console.log('second Call');
}

์ฝ˜์†”์ฐฝ์˜ ๊ฒฐ๊ณผ๋Š”์š”.

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ํ•จ์ˆ˜๋“ค์ด ์žˆ์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค์ด๋ฏ€๋กœ ๋™๊ธฐ๋กœ ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์œ„์™€ ๊ฐ™์ด ์ž‘์—… ์ˆœ์„œ๊ฐ€ ๋’ค๋ฐ”๋€Œ๋Š” ์ด์œ ๋Š” ์ด๋ฒคํŠธ ๋ฃจํ”„๋ผ๋Š” ๋ณด์ด์ง€ ์•Š๋Š” ์†์— ์˜ํ•ด ๋น„๋™๊ธฐ๋กœ ์—…๋ฌด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด setTimeout์„ ํ†ตํ•ด console.log ์ž‘์—… ์‹œ๊ฐ„์„ ๋’ค๋กœ ์—ฐ๊ธฐํ•˜๋ฉด ์ž‘์—…์ด ๋๋‚œ ๋’ค ๋กœ๊ทธ๋ฅผ ์ฐ์„ ํ…Œ๋‹ˆ ๊ฐ’์ด ์ œ๋Œ€๋กœ ํ‘œ์‹œ๋˜์ง€ ์•Š์„๊นŒ์š”?

  const showAlert = () => {
    setCnt(cnt+1);
    setTimeout(()=>{
      console.log('result(3sec):'+cnt)}
    ,3000);
 }

plus๋ฅผ ๋‹ค์„ฏ๋ฒˆ ๋ˆ„๋ฅธ ๊ฐ๊ฐ์˜ ๊ฒฐ๊ณผ๋Š”์š”.

๊ฐ’์„ 5๊นŒ์ง€ ์ฐ์—ˆ์œผ๋‹ˆ ์ฝ˜์†”๋„ 5๊นŒ์ง€ ์ฐํ˜€์•ผ ํ•˜์ง€๋งŒ ์œ„์™€ ๊ฐ™์ด ์—…๋ฐ์ดํŠธ ๋˜๊ธฐ ์ „์˜ ๊ฐ’์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.

์ด์œ ๊ฐ€ ๋ฌด์—‡์ผ๊นŒ์š”?

๋ฐ”๋กœ setTimeout ํ•จ์ˆ˜์˜ ํŠน์„ฑ ๋•Œ๋ฌธ์ธ๋ฐ์š”.

setTimeout ํ•จ์ˆ˜๋Š” ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉฐ ์ „๋‹ฌ๋˜๋Š” ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ๊ฐ’์€ ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹Œ ์ „๋‹ฌํ•˜๋Š” ์‹œ์ ์˜ ๋ณ€์ˆ˜์˜ ๊ฐ’(์ƒ์ˆ˜)์ด ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ 3์ดˆ๊ฐ€ ์•„๋‹Œ 1000์ดˆ ๋’ค์— ์‹คํ–‰ํ•˜๋”๋ผ๋„ ์‹คํ–‰๋˜๋Š” ๊ฐ’์€ ์ „๋‹ฌํ•˜๋Š” ์‹œ์ ์˜ ๋ณ€์ˆ˜์˜ ๊ฐ’์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์œ„ ์ฝ”๋“œ๋ฅผ ๋™๊ธฐ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ผ๊นŒ์š”?

state ์„ค์ • ์‹œ ํด๋ž˜์Šคํ˜•์€ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ํ•จ์ˆ˜ํ˜•์€ useEffect๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 //ํด๋ž˜์Šคํ˜•
 updateState = () => {
    this.setState(
      { cnt: this.state.cnt + 1 },
      ()=>{ console.log(this.state.cnt) }
    )
 }


 //ํ•จ์ˆ˜ํ˜•
 const plusNum = () => {
    setCnt(cnt+1);
 }

 useEffect(()=>{
  console.log(cnt);
 },[cnt])

์ด์ œ ์˜๋„ํ•œ ๋Œ€๋กœ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.


3. ๋น„๋™๊ธฐ๋กœ ์ž‘๋™ํ•˜๋Š” ์ด์œ 

๊ทธ๋ ‡๋‹ค๋ฉด state ์„ค์ •์€ ์™œ ๋น„๋™๊ธฐ๋กœ ์ž‘๋™ํ• ๊นŒ์š”?

์œ„์—์„œ ์„ค๋ช…ํ•œ๋Œ€๋กœ state๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๋Š”๋ฐ์š”.

๋ณ€๊ฒฝ์ด ํ•˜๋‚˜๋ผ๋ฉด ๋ฆฌ๋ Œ๋”๋ง์ด ํ•œ๋ฒˆ๋งŒ ๋ฐœ์ƒํ•˜์ง€๋งŒ ์ˆ˜์‹ญ ๊ฐœ, ์ˆ˜๋ฐฑ ๊ฐœ์˜ ๊ฐ’์ด ๊ณ„์† ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด ๋ฆฌ์•กํŠธ๋Š” ๋งค๋ฒˆ ๋ Œ๋”๋ง๋งŒ ํ•˜๋‹ค๊ฐ€ ์ƒ์„ ๋งˆ๊ฐํ•˜๊ณ  ๋ง ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์†๋„๋Š” ๋งํ•  ๊ฒƒ๋„ ์—†๊ตฌ์š”.

๋”ฐ๋ผ์„œ ๋ณ€๊ฒฝ๋œ ๊ฐ’๋“ค์„ ๋ชจ์•„ ํ•œ๋ฒˆ์— ์—…๋ฐ์ดํŠธ๋ฅผ ์ง„ํ–‰ํ•˜์—ฌ ๋ Œ๋”๋ง์„ ์ค„์ด๊ณ ์ž ๋ฐฐ์น˜(Batch) ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ๋น„๋™๊ธฐ๋กœ ์ž‘๋™ํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ๋ฐฐ์น˜ ์—…๋ฐ์ดํŠธ๋Š” 16ms ์ฃผ๊ธฐ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค!


18 ๋ฒ„์ „์—์„œ ์ถ”๊ฐ€๋  ์ž๋™๋ฐฐ์น˜(Automatic Batching)๋Š” ๊ธฐ์กด์— ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ๋งŒ ์‹คํ–‰๋˜๋˜ ๋ฐฐ์น˜๊ฐ€ ์ด์ œ๋Š” setTimeout, Promise ๋“ฑ์˜ ์ด๋ฒคํŠธ์—์„œ๋„ ๋™์ž‘๋  ์˜ˆ์ •์ด๋ฉฐ, flushSync() ๋“ฑ์„ ์‚ฌ์šฉํ•ด ์˜ˆ์™ธ๋ฅผ ๋‘˜ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ํ•˜์—ฌ ๋งŽ์€ ๊ธฐ๋Œ€๋ฅผ ๋ฐ›๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„ ๋ฏธ๋ฆฌ ์•Œ์•„๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ž๋™๋ฐฐ์น˜ ๊ด€๋ จํ•œ ์ƒ์„ธ ์„ค๋ช…(์˜์–ด)

๋ฆฌ์•กํŠธ(React) ์ปดํฌ๋„ŒํŠธ, ๋ผ์ดํ”„์‚ฌ์ดํด์˜ ๊ณผ๊ฑฐ์™€ ํ˜„์žฌ(useEffect)

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด๊ณผ ์ด๋ฒคํŠธ

1. ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ๋ผ์ดํ”„์‚ฌ์ดํด(Life-cycle)

๋ผ์ดํ”„์‚ฌ์ดํด ์ด๋ฒคํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ๋ Œ๋”๋ง๊ณผ DOM ์ด๋ฒคํŠธ ๋“ฑ์„ ์˜๋„๋Œ€๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ธ ๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜ํ•˜๋ฉฐ, ๊ฐ ๋ฉ”์†Œ๋“œ๋Š” ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์œ ์˜ํ•  ๋ถ€๋ถ„๋งŒ ์ •๋ฆฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


  • ๋งˆ์šดํŒ…(Mounting) – ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰(์•„๋ž˜ ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰)

– constructor()

UNSAFE_componentWillMount() -> version 17๋ถ€ํ„ฐ ๊ณต์‹์ ์œผ๋กœ ๊ถŒ์žฅX

render()

– componentDidMount()

  • ์—…๋ฐ์ดํŠธ(Update) – props ๋˜๋Š” state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰

UNSAFE_componentWillReceiveProps() -> ๊ถŒ์žฅX

UNSAFE_componentWillUpdate() -> ๊ถŒ์žฅX

render()

– componentDidUpdate(prevProps, prevState, snapshot)

  • ์–ธ๋งˆ์šดํŒ…(Unmounting) – ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ œ๊ฑฐ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰

– componentWillUnmount()


์œ„์™€ ๊ฐ™์ด ๊ฐ๊ฐ์˜ ์ปดํฌ๋„ŒํŠธ๋Š” [ ๋งˆ์šดํŒ… -> ์—…๋ฐ์ดํŠธ(๋ฐ˜๋ณต) -> ์–ธ๋งˆ์šดํŒ… ]์˜ ๋ผ์ดํ”„์‚ฌ์ดํด์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.

์ด์ „์—๋Š” ์ง๊ด€์ ์ธ ์ด๋ฆ„์„ ๊ฐ–๋Š” ๋‹ค์–‘ํ•œ ๋ฉ”์†Œ๋“œ(componentWillMount, componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate)๋ฅผ ํ†ตํ•ด ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ์ ๋งˆ๋‹ค ์„ธ์„ธํ•œ ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ–ˆ์œผ๋‚˜ ํ˜„์žฌ๋Š” ๋ฒ„๊ทธ๋‚˜ ์•ˆ์ „์„ฑ์˜ ์ด์œ ๋กœ ์ ์  ๋” ๋‹จ์ˆœํ•ด์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ๋Œ€์ฒดํ•˜๋Š” ํ›…(Hook)์ด ๋„ˆ๋ฌด ํŽธํ•ด์„œ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ์•„๋‹ˆ๋ผ๋ฉด ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ๊ป˜ useEffect๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๊ถŒ์žฅ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ผ์ดํ”„์‚ฌ์ดํด ๋ณ„๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

class TestList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter:0
    }
  }

  // ๋งˆ์šดํŒ… ์งํ›„ ์‹คํ–‰
  // ๋งˆ์šดํŒ… ์ „ ์‹คํ–‰์€ constructor() ์‚ฌ์šฉ
  componentDidMount(){
     console.log('component Mounted');
  }

  // ์—…๋ฐ์ดํŠธ ํ›„ ์ด์ „ ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ฐ€์ ธ์˜ด
  componentDidUpdate(prevProps) {
     if(prevProps !== this.props) {
            this.setState({counter:++this.state.counter})
     }
  }

  // ์–ธ๋งˆ์šดํŒ… ์ง์ „ ์‹คํ–‰
  componentWillUnmount(){
     console.log('component Unmounted');
  }

  render() {
    return (
      <div>{this.state.counter}</div>
    );
  }
}

๋งˆ์šดํŒ… ์ด๋ฒคํŠธ๋Š” ์‹ค์ œ DOM์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.

๋งˆ์šดํŒ… ์ด๋ฒคํŠธ๋Š” ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋˜๋Š” ๋ฐ์ดํ„ฐ์™€ ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…์— ์ ์ ˆํ•ฉ๋‹ˆ๋‹ค.

์—…๋ฐ์ดํŠธ ์ด๋ฒคํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์—…๋ฐ์ดํŠธ์™€ ๊ด€๋ จ์ด ์žˆ์œผ๋ฉฐ, props, state ๋“ฑ์˜ ๋ณ€๊ฒฝ์ด ์žˆ์„ ๋•Œ ๋ Œ๋”๋ง ๊ด€๋ จํ•œ ์ž‘์—…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์–ธ๋งˆ์šดํŒ…์€ DOM์—์„œ ์š”์†Œ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.

์–ธ๋งˆ์šดํŒ… ์ด๋ฒคํŠธ๋Š” ํƒ€์ด๋จธ ์ œ๊ฑฐ, ์š”์†Œ ์ œ๊ฑฐ, ์ด๋ฒคํŠธ ์ œ๊ฑฐ ๋“ฑ ์„ค์ •ํ•œ ์š”์†Œ์˜ ์ •๋ฆฌ, ์ œ๊ฑฐ์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.


2. ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์™€ useEffect(Hook)

๋ฆฌ์•กํŠธ 16.8๋ถ€ํ„ฐ ์ถ”๊ฐ€๋œ ํ›…(Hook)์€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ state ๋˜๋Š” ๋ฆฌ์•กํŠธ์˜ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ์„ ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์ด ์ค‘ useEffect ํ›…์€ ๋ผ์ดํ”„์‚ฌ์ดํด๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š”๋ฐ์š”.

๋ฆฌ์•กํŠธ ๊ณต์‹ ๋ฌธ์„œ์—์„œ useEffect๋ฅผ ์œ„์™€ ๊ฐ™์ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰ componentDidMount, componentDidUpdate, componentWillUnmount๋ฅผ ๋ชจ๋‘ ํ•ฉ์ณ ๋†“์€ ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ๊ฒƒ์ด useEffect์ž…๋‹ˆ๋‹ค.

๋ชจ๋‘ ํ•ฉ์ณ ๋†“์•˜์ง€๋งŒ ์ž‘์„ฑ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ๊ฐ๊ฐ์˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ํ•จ์ˆ˜์˜ ์‹œ๊ทธ๋‹ˆ์ณ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชจ์Šต์ด๋ฉฐ, ์ฒซ ๋ฒˆ์งธ๋Š” ์‹คํ–‰ํ•  ํ•จ์ˆ˜, ๋‘ ๋ฒˆ์งธ๋Š” ์กฐ๊ฑด์„ ๋ฐฐ์—ด๋กœ ์ „๋‹ฌํ•˜๋ฉฐ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์ƒ๋žต์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

useEffect(ํ•จ์ˆ˜, ๋ฐฐ์—ด);

  useEffect(() => {
      console.log('useEffect is working');
  });

– ๋งˆ์šดํŒ…๋งŒ ์„ค์ •(=componentDidMount)

๋งˆ์šดํŒ… ์‹œ์—๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์—๋Š” ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋นˆ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function testStatus(props) {

  useEffect(() => {
      console.log('useEffect on mounting');
  },[]);

  return <div>test</div>;
}

– ์–ธ๋งˆ์šดํŒ…๋งŒ ์„ค์ •(=componentWillUnmount)

์–ธ๋งˆ์šดํŒ… ์‹œ์—๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ์—๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉด์„œ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋นˆ ๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function testStatus(props) {

  useEffect(() => {
      
      console.log('useEffect on mounting');

      return () => {
        console.log('useEffect on unmounting');
      }

  },[]);

  return <div>test</div>;
}

– ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ๋งˆ๋‹ค ์„ค์ •(=componentDidUpdate)

useEffect์—์„œ ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์œผ๋ฉด ๋ Œ๋”๋ง๋งˆ๋‹ค ํ•ด๋‹น ํ›…์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ด€๋ จ ์—†๋Š” ๋ฐ์ดํ„ฐ๋กœ ์ธํ•œ ๋ฆฌ๋ Œ๋”๋ง์—๋„ ํ›…์ด ์‹คํ–‰๋˜๋ฉด ์˜๋„์น˜ ์•Š์€ ๊ฒฐ๊ณผ๋ฅผ ๋‚ณ๊ฑฐ๋‚˜ ์„ฑ๋Šฅ์˜ ์ €ํ•˜๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‹คํ–‰์˜ ๊ธฐ์ค€์ด ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์ •ํ•˜๊ณ  ์‹คํ–‰ ์‹œ์ ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์ธ ๋ฐฐ์—ด์— ์ฒดํฌํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function testEffect(props) {

  useEffect(() => {
      console.log('re-rendering');
  });

  useEffect(() => {     
      console.log('props is changed');
  },[props.data]);

  return <div>test</div>;
}


useEffect๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ช‡ ๋ฒˆ์˜ ์‹œํ–‰์ฐฉ์˜ค๋งŒ ๊ฑฐ์น˜๋ฉด ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์–ด๋Š ์ •๋„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ผ์ดํ”„์‚ฌ์ดํด์— ๋Œ€ํ•œ ์ดํ•ด ์—†์ด ๊ณ„์† ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์–ด๋Š ์ˆœ๊ฐ„ ‘์‹œ๊ฐ„์„ ๊ฐˆ์•„ ๋„ฃ์–ด ์ง  ์ฝ”๋“œ’๋Š” ์‹œ๊ฐ„ ์•ž์— ๋ฌด๋ฆŽ์„ ๊ฟ‡๊ฒŒ ๋  ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.