Removing Effect Dependencies

date
2026-01-28
order
7
link
  • Removing Effect Dependencies โ€“ React

You will learn

  • effect ์˜์กด์„ฑ ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ๋ฒ•
  • effect์— ๋ฐ˜์‘ํ•˜์ง€ ์•Š๊ณ  effect์˜ ๊ฐ’์„ ์ฝ๋Š” ๋ฐฉ๋ฒ•
  • ๊ฐ์ฒด์™€ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ํ”ผํ•ด์•ผ ํ•˜๋Š” ์ด์œ ์™€ ๋ฐฉ๋ฒ•
  • ๋ฆฐํ„ฐ์˜ ์˜์กด์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๋ฌด์‹œํ•˜๋ฉด ์•ˆ๋˜๋Š” ์ด์œ ์™€ ๋Œ€์‹  ํ•ด์•ผ ํ•  ์ผ๋“ค

์˜์กด์„ฑ์€ ์„ ํƒํ•  ์ˆ˜ ์—†๋‹ค.

์ดํŽ™ํŠธ๋Š” ์˜์กด์„ฑ ๋ฐฐ์—ด์— ์žˆ๋Š” ๊ฐ’์ด ๋ณ€ํ•  ๋•Œ ๋งˆ๋‹ค ์‹คํ–‰๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ์„ ๊ฐ€์ง„๋‹ค๋ฉด ์ดํŽ™ํŠธ๊ฐ€ ๋„ˆ๋ฌด ์ž์ฃผ ์‹คํ–‰๋˜๊ฑฐ๋‚˜ ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์งˆ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฌด์—‡์ด ์ง„์งœ ์˜์กด์„ฑ์ธ์ง€, ๋ฌด์—‡์ด ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ์ธ์ง€ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•œ๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ ์ดํŽ™ํŠธ๊ฐ€ ์–ด๋–ค ์˜์กด์„ฑ์„ ๊ฐ€์ง€๋Š”์ง€ ์„ ํƒํ•  ์ˆ˜ ์—†๋‹ค. ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ๋ฐ˜์‘ํ˜• ๊ฐ’ reactive value(state, props, ์ปดํฌ๋„ŒํŠธ์—์„œ ์„ ์–ธ๋œ ๋ณ€์ˆ˜)์€ ๋ฐ˜๋“œ์‹œ ์˜์กด์„ฑ ๋ฐฐ์—ด์— ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์–ด๋–ค ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๊ณ ์‹ถ๋‹ค๋ฉด ํ•ด๋‹น ๊ฐ’์„ ๋น„๋ฐ˜์‘ํ˜• ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜, ํ•ด๋‹น ๊ฐ’์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค.

์˜์กด์„ฑ ์ œ๊ฑฐํ•˜๊ธฐ

์ดํŽ™ํŠธ๊ฐ€ ๋„ˆ๋ฌด ์ž์ฃผ ์‹คํ–‰๋˜๊ฑฐ๋‚˜, ์ผ๋ถ€ ์˜์กด์„ฑ ๊ฐ’์— '๋ฐ˜์‘'ํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ์ตœ์‹  ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๊ฑฐ๋‚˜ ํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฒดํฌ๋ฆฌ์ŠคํŠธ๋ฅผ ํ™•์ธํ•ด๋ณด๋Š”๊ฒƒ์ด ๋„์›€์ด ๋œ๋‹ค.

1. ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ์˜ฎ๊ฒจ์•ผ ํ•˜์ง€ ์•Š์„๊นŒ?

๋งŒ์•ฝ ์ดํŽ™ํŠธ์˜ ์–ด๋–ค ์ฝ”๋“œ๊ฐ€ ํŠน์ • ์œ ์ € ์ด๋ฒคํŠธ์— ์ข…์†์ ์ด๋ผ๋ฉด? " You Might not need an Effect" ํŽ˜์ด์ง€์—์„œ ๋ดค๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ ์ด ๊ฒฝ์šฐ๋Š” ์ดํŽ™ํŠธ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๊ณ  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ํฌํ•จ๋˜์–ด์•ผ ํ•œ๋‹ค.

2. ์ดํŽ™ํŠธ๊ฐ€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ผ์„ ํ•˜๋Š”๊ฒƒ ์•„๋‹๊นŒ?

ํ•˜๋‚˜์˜ ์ดํŽ™ํŠธ์—์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ผ์„ ํ•˜๋Š” ๊ฒฝ์šฐ ์˜์กด์„ฑ์ด ๋Š˜์–ด๋‚˜๊ณ  ๋”ฐ๋ผ์„œ ์„œ๋กœ ๊ด€๋ จ ์—†๋Š” ์ฝ”๋“œ๋ผ๋ฆฌ ์„œ๋กœ์˜ ์˜์กด์„ฑ์— ์˜ํ•ด ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

3. ๋‹ค์Œ state๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด state๋ฅผ ์ฝ๋Š”๊ฐ€?

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);
  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      setMessages([...messages, receivedMessage]);
    });
    return () => connection.disconnect();
  }, [roomId, messages]); // โœ… All dependencies declared
  // ...

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๋ฉด ๋ฉ”์‹œ์ง€๊ฐ€ ๋„์ฐฉํ•  ๋•Œ ๋งˆ๋‹ค ์ดํŽ™ํŠธ๊ฐ€ ์žฌ์‹คํ–‰ ๋œ๋‹ค. message ์ƒํƒœ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๊ณ  ์˜์กด์ค‘์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

function ChatRoom({ roomId }) {
  const [messages, setMessages] = useState([]);
  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      setMessages(msgs => [...msgs, receivedMessage]);
    });
    return () => connection.disconnect();
  }, [roomId]); // โœ… All dependencies declared
  // ...

์ด๋ ‡๊ฒŒ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์—…๋ฐ์ดํ„ฐ ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.

4. ๊ฐ’์˜ ๋ณ€ํ™”์— '๋ฐ˜์‘'ํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ๊ฐ’์„ ์ฝ๊ณ ์‹ถ์€๊ฐ€?

useEffectEventํ›… ๋‚ด์šฉ ์ฐธ๊ณ .

prop์œผ๋กœ ๋ฐ›์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์„๋•Œ์—๋„ ์ ์šฉ๋œ๋‹ค.

function ChatRoom({ roomId, onReceiveMessage }) {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      onReceiveMessage(receivedMessage);
    });
    return () => connection.disconnect();
  }, [roomId, onReceiveMessage]); // โœ… All dependencies declared
  // ...

onReceiveMessage ๋Š” ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๋ Œ๋”๋ง๋งˆ๋‹ค ์ฃผ์†Œ๊ฐ’์ด ๋‹ฌ๋ผ ์ดํŽ™ํŠธ๋Š” ๋งค๋ฒˆ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค๊ณ  ํŒ๋‹จํ•˜๊ณ  ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. (๊ตณ์ด prop์œผ๋กœ ๋ฐ›์€ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ผ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์ •์˜๋œ ํ•จ์ˆ˜๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์—๋Š” ํ•จ์ˆ˜๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์— ์ •์˜ํ•˜๋ฉด ํ•ด๊ฒฐ ๊ฐ€๋Šฅํ•˜๋‹ค. )

  const onMessage = useEffectEvent(receivedMessage => {
    onReceiveMessage(receivedMessage);
  });

  useEffect(() => {
    const connection = createConnection();
    connection.connect();
    connection.on('message', (receivedMessage) => {
      onMessage(receivedMessage);
    });
    return () => connection.disconnect();
  }, [roomId]); // โœ… All dependencies declared

5. ์–ด๋–ค ๋ฐ˜์‘ํ˜• ๊ฐ’์ด ์˜๋„์น˜ ์•Š๊ฒŒ ๋ณ€๊ฒฝ๋˜๋Š”๊ฐ€?

  const options = {
    serverUrl: serverUrl,
    roomId: roomId
  };
  
  useEffect(() => {
    const connection = createConnection(options);
    connection.connect();
    return () => connection.disconnect();
  }, [options]); // โœ… All dependencies declared

์œ„ ์ฝ”๋“œ์˜ ์˜๋„๋Š” serverUrl์ด๋‚˜ roomId๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด option๊ฐ์ฒด๊ฐ€ ์—…๋ฐ์ดํŠธ ๋˜๋ฉด ์ดํŽ™ํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ, ํ•จ์ˆ˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ฐ์ฒด๋„ ๋ชจ๋“  ๋žœ๋”๋ง๋งˆ๋‹ค ๋‹ค๋ฅธ ์ฃผ์†Œ๊ฐ’์„ ๊ฐ€์ง€๋ฉด์„œ ๋ชจ๋“  ๋ฆฌ๋ Œ๋”๋ง๋งˆ๋‹ค ์ฑ„ํŒ…๋ฐฉ ์—ฐ๊ฒฐ์ด ๋ฐ˜๋ณต๋œ๋‹ค.

๋ฌธ์„œ์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€ ์ œ์•ˆํ•œ๋‹ค. ๋งŒ์•ฝ ์˜์กดํ•˜๊ณ ์žˆ๋Š” ๊ฐ์ฒด๊ฐ€ ์ •์ ์ด๋ผ๋ฉด, ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๊ทธ๊ฒƒ์„ ์ปดํฌ๋„ŒํŠธ ๋ฐ–์—์„œ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด ์˜ˆ์‹œ์ฒ˜๋Ÿผ roomId๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด ์ด ๊ฐ์ฒด๋Š” ์ •์ ์ธ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋™์ ์ธ ๊ฐ์ฒด๊ฐ€ ๋œ๋‹ค. ์ด๋Ÿด๋• ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ์ด๋ ‡๊ฒŒ option ๊ฐ์ฒด๋ฅผ ์ดํŽ™ํŠธ ์•ˆ์—์„œ ์ •์˜ํ•˜๋ฉด ๋œ๋‹ค.

  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    return () => connection.disconnect();
  }, [roomId]); // โœ… All dependencies declared

๊ทธ๋Ÿฐ๋ฐ ๊ฐ์ฒด๊ฐ€ prop์ธ ๊ฒฝ์šฐ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? option ๊ฐ์ฒด๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›๋Š”๋‹ค๋ฉด?

function ChatRoom({ options }) {
  const [message, setMessage] = useState('');

  const { roomId, serverUrl } = options;
  useEffect(() => {
    const connection = createConnection({
      roomId: roomId,
      serverUrl: serverUrl
    });
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, serverUrl]); // โœ… All dependencies declared

roomId์™€ serverUrl์„ ์ถ”์ถœํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

์˜ˆ์‹œ ๋ฌธ์ œ

1. ์ธํ„ฐ๋ฒŒ ์ดˆ๊ธฐํ™” ๋ฌธ์ œ

  useEffect(() => {
    console.log('โœ… Creating an interval');
    const id = setInterval(() => {
      console.log('โฐ Interval tick');
      setCount(count + 1);
    }, 1000);
    return () => {
      console.log('โŒ Clearing an interval');
      clearInterval(id);
    };
  }, [count]);

setCount์—์„œ ์ง์ ‘ ๊ฐ’์„ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  ์—…๋ฐ์ดํ„ฐ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

2. ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ด‰๋ฐœ ๋ฌธ์ œ

function Welcome({ duration }) {
  const ref = useRef(null);

  useEffect(() => {
    const animation = new FadeInAnimation(ref.current);
    animation.start(duration);
    return () => {
      animation.stop();
    };
  }, [duration]);

์ตœ์‹ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์ดํŽ™ํŠธ๊ฐ€ ๋ฐ˜์‘ํ•˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋Š” useEffectEventํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

  const onAppear = useEffectEvent(animation => {
    animation.start(duration);
  });

  useEffect(() => {
    const animation = new FadeInAnimation(ref.current);
    onAppear(animation);
    return () => {
      animation.stop();
    };
  }, []);

3. ์žฌ์—ฐ๊ฒฐ ๋˜๋Š” ์ฑ„ํŒ…

export default function ChatRoom({ options }) {
  useEffect(() => {
    const connection = createConnection(options);
    connection.connect();
    return () => connection.disconnect();
  }, [options]);

prop์œผ๋กœ ๋ฐ›์€ option์—์„œ ํ•„์š”ํ•œ ๊ฐ’์„ ์ถ”์ถœํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

export default function ChatRoom({ options }) {
  const { roomId, serverUrl } = options;
  useEffect(() => {
    const connection = createConnection({
      roomId: roomId,
      serverUrl: serverUrl
    });
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, serverUrl]);

4. ์žฌ์—ฐ๊ฒฐ ๋˜๋Š” ์ฑ„ํŒ… 2

export default function ChatRoom({ roomId, createConnection, onMessage }) {
  useEffect(() => {
    const connection = createConnection();
    connection.on('message', (msg) => onMessage(msg));
    connection.connect();
    return () => connection.disconnect();
  }, [createConnection, onMessage]);

์—ฌ๊ธฐ์„œ roomId์™€ isEncrypted๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งŒ ์ƒˆ๋กœ ์—ฐ๊ฒฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด? ์ผ๋‹จ createConnection๊ณผ onMessage๋ฅผ ์˜์กด์„ฑ์—์„œ ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค. onMessage์˜ ๊ฒฝ์šฐ ์ดํŽ™ํŠธ ์ด๋ฒคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

export default function ChatRoom({ roomId, createConnection, onMessage }) {
  const onReceiveMessage = useEffectEvent(onMessage);

  useEffect(() => {
    const connection = createConnection();
    connection.on('message', (msg) => onReceiveMessage(msg));
    // ...

๊ทธ๋Ÿฐ๋ฐ createConnection์˜ ๊ฒฝ์šฐ๋Š” ๋ณต์žกํ•˜๋‹ค. roomId์™€ isEncrypted์— ๋ฐ˜์‘ํ•ด์•ผ ํ•œ๋‹ค. ์ฆ‰ ์œ„์˜ ๋‘ state๋ฅผ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„์™€์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

      <ChatRoom
        roomId={roomId}
        isEncrypted={isEncrypted}
        onMessage={msg => {
          showNotification('New message: ' + msg, isDark ? 'dark' : 'light');
        }}
      />

๊ทธ๋ฆฌ๊ณ  createConnection์ด๋ผ๋Š” ํ•จ์ˆ˜๋Š” ๋ถ€๋ชจ์—์„œ ์ •์˜ํ•˜์ง€ ์•Š๊ณ  Chatroom ์ปดํฌ๋„ŒํŠธ์—์„œ ์ •์˜ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์ •์˜ํ•œ ํ•จ์ˆ˜๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ Œ๋”๋ง๋งˆ๋‹ค ์ฃผ์†Œ๊ฐ’์ด ๋ฐ”๋€๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋‹จ์ˆœํžˆ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ์ •์˜ํ•ด์„œ๋Š” ์•ˆ๋˜๊ณ  ์ดํŽ™ํŠธ ์•ˆ์— ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.

  useEffect(() => {
    function createConnection() {
      const options = {
        serverUrl: 'https://localhost:1234',
        roomId: roomId // Reading a reactive value
      };
      if (isEncrypted) { // Reading a reactive value
        return createEncryptedConnection(options);
      } else {
        return createUnencryptedConnection(options);
      }
    }

    const connection = createConnection();
    connection.on('message', (msg) => onReceiveMessage(msg));
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, isEncrypted]); // โœ… All dependencies declared