๐Ÿ’ก 05. useEffect ํŒŒ๊ดดํ•˜๊ธฐ (1): ์ง„์‹ค โ€” ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ์•„๋‹ˆ๋ผ ๋™๊ธฐํ™”๋‹ค

๐Ÿ“‹ ๊ฐœ์š”

useEffect๋ฅผ ๋‹จ์ˆœํžˆ ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ/์–ธ๋งˆ์šดํŠธ ์‹œ์ ์— ์‹คํ–‰๋˜๋Š” ์ƒ๋ช…์ฃผ๊ธฐ API๋กœ ์˜คํ•ดํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์™€ ๊ทธ ์ง„์ •ํ•œ ์—ญํ• (๋™๊ธฐํ™”)์„ ๋ฐฐ์›๋‹ˆ๋‹ค.

๐ŸŽฏ ์ด ์„น์…˜์„ ์ฝ๊ณ  ๋‚˜๋ฉด:

  • useEffect๋ฅผ componentDidMount ๊ฐ™์€ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๋กœ ์ƒ๊ฐํ•˜๋Š” ๋‚ก์€ ๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.
  • "๋ฆฌ์•กํŠธ์˜ ์ƒํƒœ(State)์™€ ์™ธ๋ถ€ ์‹œ์Šคํ…œ(Network, DOM)์˜ ์ƒํƒœ๋ฅผ ์–ธ์ œ๋‚˜ ๊ฐ™๊ฒŒ ๋งž์ถ˜๋‹ค(๋™๊ธฐํ™”)"๋Š” ๊ฐœ๋…์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ useEffect ์‚ฌ์šฉ์„ ์ฆ‰๊ฐ ์ฐพ์•„๋‚ด์–ด ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ


๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 15๋ถ„ / ํ•ต์‹ฌ ํŒŒํŠธ: 10๋ถ„

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ์˜์ฒ (์‹ ์ž…): "์ฑ„ํŒ…๋ฐฉ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ๋œฐ ๋•Œ(mount) ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•˜๊ณ , ์‚ฌ๋ผ์งˆ ๋•Œ(unmount) ๋Š์–ด์•ผ ํ•˜๋‹ˆ๊นŒ ๋ฌด์กฐ๊ฑด useEffect๋ฅผ ์จ์•ผ์ฃ !"
  • ์˜ํ˜ธ(๋ฆฌ๋“œ): "์˜์ฒ  ๋‹˜... useEffect๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ '์‹คํ–‰'ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋ฆฌ์•กํŠธ ๋ฐ”๊นฅ ์„ธ์ƒ๊ณผ '๋™๊ธฐํ™”'ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ƒ๋ช…์ฃผ๊ธฐ๋ผ๋Š” ํ™˜์ƒ์—์„œ ๊นจ์–ด๋‚˜์„ธ์š”."

๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€: ๋‚ก์€ ์ƒ๋ช…์ฃผ๊ธฐ์˜ ๋ง๋ น

๊ณผ๊ฑฐ ๋ฆฌ์•กํŠธ๋ฅผ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋กœ ์งœ๋˜ ์‹œ์ ˆ์—๋Š” componentDidMount (ํ™”๋ฉด์— ์ฒ˜์Œ ๋œฐ ๋•Œ), componentDidUpdate (์—…๋ฐ์ดํŠธ๋  ๋•Œ) ๊ฐ™์€ ๋šœ๋ ทํ•œ ์‹œ์ (Lifecycle, ์ƒ๋ช…์ฃผ๊ธฐ) API๋“ค์ด ์žˆ์—ˆ์–ด.
ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ(Hooks)๊ฐ€ ๋„์ž…๋œ ์ดํ›„, ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด useEffect๋ฅผ ๊ทธ์ € "์˜›๋‚  ์ƒ๋ช…์ฃผ๊ธฐ API๋“ค์„ ํ•˜๋‚˜๋กœ ํ•ฉ์นœ ๋งŒ๋Šฅ ํˆด"์ด๋ผ๊ณ  ์ฐฉ๊ฐํ–ˆ์ง€.

๐Ÿค” ์ž ๊น, ๋จผ์ € ์ƒ๊ฐํ•ด๋ด
"์ด ์ฝ”๋“œ๋Š” ํ™”๋ฉด์— ์ฒ˜์Œ ๋œฐ ๋•Œ๋งŒ ํ•œ ๋ฒˆ ์‹คํ–‰๋˜์–ด์•ผ ํ•˜๋‹ˆ๊นŒ useEffect(..., []) ์•ˆ์— ์“ฐ๋ฉด ์™„๋ฒฝํ•ด!" ๋ผ๊ณ  ์ƒ๊ฐํ•œ ์  ์žˆ์ง€?

// โŒ ์ƒ๋ช…์ฃผ๊ธฐ ๋งˆ์ธ๋“œ๋กœ ์ง  ์˜์ฒ ์ด์˜ ์ฝ”๋“œ
function ChatRoom({ roomId }) {
  useEffect(() => {
    // "์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋งˆ์šดํŠธ๋  ๋•Œ ๋ฌด์กฐ๊ฑด ํ•œ ๋ฒˆ ์‹คํ–‰ํ•ด!" (์˜คํ•ด)
    const connection = createConnection();
    connection.connect(roomId);
    
    return () => {
      // "์–ธ๋งˆ์šดํŠธ๋  ๋•Œ ๋Š์–ด!"
      connection.disconnect();
    };
  }, []); // ๐Ÿšจ ์น˜๋ช…์  ๋ฒ„๊ทธ: ์˜์กด์„ฑ ๋ฐฐ์—ด์„ ์˜๋„์ ์œผ๋กœ ๋น„์› ์Œ
  
  return <h1>{roomId}๋ฒˆ ์ฑ„ํŒ…๋ฐฉ</h1>;
}

์œ„ ์ฝ”๋“œ๋Š” ๋”์ฐํ•œ ๋ฒ„๊ทธ๋ฅผ ๋‚ณ์•„. ์‚ฌ์šฉ์ž๊ฐ€ '1๋ฒˆ ๋ฐฉ'์—์„œ '2๋ฒˆ ๋ฐฉ'์œผ๋กœ ๋„˜์–ด๊ฐ”์–ด(roomId prop์ด 2๋กœ ๋ฐ”๋€œ).
ํ•˜์ง€๋งŒ ์˜์ฒ ์ด๋Š” useEffect๋ฅผ "์ฒ˜์Œ ๋œฐ ๋•Œ ํ•œ ๋ฒˆ๋งŒ([]) ์‹คํ–‰ํ•˜๋Š” ๋†ˆ"์ด๋ผ๊ณ  ๊ตณ๊ฒŒ ๋ฏฟ์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ™”๋ฉด์—๋Š” "2๋ฒˆ ์ฑ„ํŒ…๋ฐฉ"์ด๋ผ๊ณ  ๋œจ์ง€๋งŒ ์‹ค์ œ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ์€ ์—ฌ์ „ํžˆ ์˜›๋‚  1๋ฒˆ ๋ฐฉ์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” ๋Œ€์ฐธ์‚ฌ๊ฐ€ ๋ฐœ์ƒํ•ด.


๐Ÿ—๏ธ ๋น„์œ ๋กœ ๋จผ์ € ์ดํ•ดํ•˜๊ธฐ

๐Ÿง’ 5์‚ด์—๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค๋ฉด?
โŒ ์˜์ฒ ์ด์˜ ์ƒ๊ฐ (์ƒ๋ช…์ฃผ๊ธฐ ํŒจ๋Ÿฌ๋‹ค์ž„ - ๋ช…๋ นํ˜•):
"๋น„์„œ์•ผ, ๋‚ด๊ฐ€ ์•„์นจ์— ์ถœ๊ทผํ•  ๋•Œ(Mount)๋งŒ ๋”ฑ ํ•œ ๋ฒˆ ์—์–ด์ปจ์„ 24๋„๋กœ ํ‹€์–ด๋ผ! ๊ทธ๋ฆฌ๊ณ  ํ‡ด๊ทผํ•  ๋•Œ(Unmount) ๊บผ๋ผ!"
(๋งŒ์•ฝ ๋‚ฎ์— ๋„ˆ๋ฌด ๋”์›Œ์„œ ์‚ฌ์žฅ๋‹˜์ด ์‚ฌ๋‚ด ๊ทœ์ •์„ '์—์–ด์ปจ 20๋„'๋กœ ๋‚ด๋ ค๋„, ๋น„์„œ๋Š” ์ถœ๊ทผํ•  ๋•Œ ์ด๋ฏธ ์ผ์„ ๋๋ƒˆ์œผ๋ฏ€๋กœ ํ‡ด๊ทผํ•  ๋•Œ๊นŒ์ง€ ์˜จ๋„ ์กฐ์ ˆ๊ธฐ๋ฅผ ์ณ๋‹ค๋ณด์ง€๋„ ์•Š๋Š”๋‹ค.)

โœ… ์˜ํ˜ธ์˜ ์ƒ๊ฐ (๋™๊ธฐํ™” ํŒจ๋Ÿฌ๋‹ค์ž„ - ์„ ์–ธํ˜•):
"๋น„์„œ์•ผ, ์‚ฌ๋ฌด์‹ค ์˜จ๋„(์™ธ๋ถ€ ์‹œ์Šคํ…œ)๋ฅผ ํ•ญ์ƒ ํ˜„์žฌ ์šฐ๋ฆฌ ํšŒ์‚ฌ ์‚ฌ๋‚ด ๊ทœ์ • ๋ฌธ์„œ(๋ฆฌ์•กํŠธ State/Props)์™€ ์ผ์น˜์‹œ์ผœ ๋†”๋ผ(Synchronize)."
(๊ทœ์ • ๋ฌธ์„œ์— ์ ํžŒ ์˜จ๋„๊ฐ€ 24๋„์—์„œ 20๋„๋กœ ๋ฐ”๋€Œ๋Š” ์ˆœ๊ฐ„, ๋น„์„œ๋Š” ์ฆ‰์‹œ ์—์–ด์ปจ ๋ฆฌ๋ชจ์ปจ์„ ์กฐ์ž‘ํ•ด ์‚ฌ๋ฌด์‹ค ์˜จ๋„๋ฅผ ๊ทœ์ •๊ณผ ๋™๊ธฐํ™”์‹œํ‚จ๋‹ค.)

โœ… ํ•ต์‹ฌ ์›๋ฆฌ:
React์˜ ์ฐฝ์‹œ์ž ์ค‘ ํ•œ ๋ช…์ธ Dan Abramov๊ฐ€ ๋งํ–ˆ์–ด. "useEffect๋Š” ์ปดํฌ๋„ŒํŠธ ์ƒ๋ช…์ฃผ๊ธฐ์™€๋Š” ์•„๋ฌด ์ƒ๊ด€์ด ์—†๋‹ค."
useEffect์˜ ์œ ์ผํ•œ ๋ชฉ์ ์€ ๋ฆฌ์•กํŠธ๊ฐ€ ๋ชจ๋ฅด๋Š” ์™ธ๋ถ€ ์„ธ๊ณ„(์„œ๋ฒ„ ์—ฐ๊ฒฐ, ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€, ์Œฉ DOM ์กฐ์ž‘ ๋“ฑ)๋ฅผ ํ˜„์žฌ ๋ฆฌ์•กํŠธ์˜ ์ƒํƒœ(State/Props)์™€ ๋งž์ถ”์–ด ๋™๊ธฐํ™”(Synchronize)์‹œํ‚ค๋Š” ๊ฒƒ์ด์•ผ.


๐Ÿงฉ ๋™๊ธฐํ™”(Synchronization)์˜ ์™„๋ฒฝํ•œ ์ ์šฉ

โœ… ์˜ํ˜ธ์˜ ๋ฆฌํŒฉํ† ๋ง: ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ๋™์กฐ

์˜์ฒ ์ด์˜ ์ฝ”๋“œ๋ฅผ '๋™๊ธฐํ™”' ํŒจ๋Ÿฌ๋‹ค์ž„์— ๋งž๊ฒŒ ๊ณ ์ณ๋ณผ๊นŒ?
"์ฑ„ํŒ… ์„œ๋ฒ„์™€์˜ ์—ฐ๊ฒฐ ์ƒํƒœ(์™ธ๋ถ€ ์‹œ์Šคํ…œ)๋ฅผ ํ•ญ์ƒ ํ˜„์žฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ›์€ roomId prop๊ณผ ๋™๊ธฐํ™”์‹œ์ผœ๋ผ!"

// โœ… ๋™๊ธฐํ™” ๋งˆ์ธ๋“œ๋กœ ์ง  ์šฐ์•„ํ•œ ์ฝ”๋“œ
function ChatRoom({ roomId }) {
  
  // "๋‚œ ์ด Effect ๋ฉ์–ด๋ฆฌ๊ฐ€ ์–ธ์ œ(mount/update) ์‹คํ–‰๋ ์ง€ ๊ด€์‹ฌ ์—†์–ด."
  // "๋‹ค๋งŒ, roomId๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๋ฌด์กฐ๊ฑด ์˜›๋‚  ์—ฐ๊ฒฐ์„ ๋ถ€์ˆ˜๊ณ  ์ƒˆ ๋ฐฉ์— ๋™๊ธฐํ™”์‹œ์ผœ ์ค˜!"
  useEffect(() => {
    const connection = createConnection();
    connection.connect(roomId); // roomId(ํ˜„์žฌ ์ƒํƒœ)๋กœ ์„œ๋ฒ„์— ์—ฐ๊ฒฐ
    
    return () => {
      // ๋‹ค์Œ ๋™๊ธฐํ™”๊ฐ€ ์ผ์–ด๋‚˜๊ธฐ ์ „, ํ˜น์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฃฝ๊ธฐ ์ „์— ์ž”์žฌ๋ฅผ ์น˜์šด๋‹ค(Cleanup)
      connection.disconnect(); 
    };
  }, [roomId]); // ๐ŸŽฏ ์˜์กด์„ฑ ๋ฐฐ์—ด์— '๋™๊ธฐํ™”ํ•  ๊ธฐ์ค€'์„ ๋ช…์‹œ
 
  return <h1>{roomId}๋ฒˆ ์ฑ„ํŒ…๋ฐฉ</h1>;
}

์ด์ œ ๋ฆฌ์•กํŠธ๋Š” ์ด๋ ‡๊ฒŒ ์ž‘๋™ํ•ด:

  1. roomId = 1 ๋กœ ๋ Œ๋”๋ง โ†’ 1๋ฒˆ ๋ฐฉ ์—ฐ๊ฒฐ!
  2. ์œ ์ €๊ฐ€ ๋ฐฉ์„ 2๋กœ ๋ฐ”๊ฟˆ (roomId = 2 ๋ Œ๋”๋ง ์Šค๋ƒ…์ƒท ์ƒ์„ฑ)
  3. ๋ฆฌ์•กํŠธ: "์–ด? ๊ทœ์น™([roomId])์ด ๋ฐ”๋€Œ์—ˆ๋„ค? ๋‹ค์‹œ ๋™๊ธฐํ™”ํ•ด์•ผ๊ฒ ๋‹ค."
  4. ๋ฆฌ์•กํŠธ: ๋จผ์ € 1๋ฒˆ ๋ฐฉ ์—ฐ๊ฒฐ์„ ์ฒญ์†Œ(disconnect)ํ•˜๊ณ , ์ƒˆ๋กœ 2๋ฒˆ ๋ฐฉ ์—ฐ๊ฒฐ์„ ์‹œ์ž‘(connect)!

์ด๊ฒƒ์ด useEffect์˜ ์ง„์งœ ์กด์žฌ ์ด์œ ์•ผ.


๐Ÿ’ฅ ์—๋Ÿฌ ํ•ด๊ฒฐ ์นดํƒˆ๋กœ๊ทธ

โŒ ๋ฌด์˜๋ฏธํ•œ ์ƒํƒœ ํŒŒ์ƒ(Derived State)์— Effect ๋‚จ์šฉํ•˜๊ธฐ

์ƒํ™ฉ:

function SearchBox({ users }) {
  const [query, setQuery] = useState('');
  const [filtered, setFiltered] = useState([]); // ๐Ÿšจ ๋ƒ„์ƒˆ๊ฐ€ ๋‚œ๋‹ค
 
  // ์‚ฌ์šฉ์ž๊ฐ€ ํƒ€์ดํ•‘(query ๋ณ€๊ฒฝ)ํ•  ๋•Œ๋งˆ๋‹ค ํ•„ํ„ฐ๋ง๋œ ๋ฐฐ์—ด์„ ๋‹ค์‹œ ๋งŒ๋“ค๊ณ  ์‹ถ์–ด!
  useEffect(() => {
    const result = users.filter(u => u.name.includes(query));
    setFiltered(result);
  }, [query, users]); 
  
  // ...

์›์ธ: ๋ฆฌ์•กํŠธ ๊ณต์‹ ๋ฌธ์„œ ("You Might Not Need an Effect") ์—์„œ ๊ฐ€์žฅ ๊ฒฝ๊ณ„ํ•˜๋Š” "๊ฐ€์žฅ ๋ฉ์ฒญํ•œ ํ˜•ํƒœ์˜ Effect ๋‚จ์šฉ" ์ด์•ผ.
users์™€ query๋Š” ๋ฌด์–ธ๊ฐ€ ํ™”๋ฉด ๋ฐ”๊นฅ์˜ ์™ธ๋ถ€ ์‹œ์Šคํ…œ(API ๋“ฑ)์ธ๊ฐ€์š”? โŒ ์•„๋‹™๋‹ˆ๋‹ค.
๋‹จ์ˆœํžˆ ๋ฆฌ์•กํŠธ ๋‚ด๋ถ€์˜ props์™€ state์ผ ๋ฟ์ด์ฃ . ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ๋ฐ useEffect๋ฅผ ์“ฐ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ํƒ€์ดํ•‘ํ•  ๋•Œ๋งˆ๋‹ค ๋ถˆํ•„์š”ํ•˜๊ฒŒ ํ•„ํ„ฐ๋ง์„ ํ•˜๊ณ , setFiltered ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ํ†ตํ•ด ์žฌ์•™ ๊ฐ™์€ ์ถ”๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง(๋ฆฌ๋ Œ๋”๋ง์ด 2๋ฒˆ์”ฉ ๋ฐœ์ƒ) ์„ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…:
Effect๋ฅผ ๊ณผ๊ฐํ•˜๊ฒŒ ๋„๋ ค๋‚ด์„ธ์š”!

function SearchBox({ users }) {
  const [query, setQuery] = useState('');
  
  // โœ… ๋ Œ๋”๋ง ์Šค๋ƒ…์ƒท ๋„์ค‘์— ๊ทธ๋ƒฅ ๊ณ„์‚ฐํ•ด๋ฒ„๋ฆฌ์„ธ์š”! (ํŒŒ์ƒ ์ƒํƒœ)
  // ์–ด์ฐจํ”ผ query๊ฐ€ ๋ฐ”๋€Œ๋ฉด ๋ฆฌ๋”๋ง์ด ๋„๋‹ˆ๊นŒ ๊ทธ๋•Œ ํ•œ ๋ฒˆ ๊ณ„์‚ฐํ•˜๋ฉด ๋.
  const filtered = users.filter(u => u.name.includes(query));
  // ...

๐Ÿ ์ด๋ฒˆ์— ๋ฐฐ์šด ๋‚ด์šฉ ์ด์ •๋ฆฌ

์ƒํ™ฉโŒ ์ƒ๋ช…์ฃผ๊ธฐ ๋งˆ์ธ๋“œ (๋ช…๋ นํ˜•)โœ… ๋™๊ธฐํ™” ๋งˆ์ธ๋“œ (์„ ์–ธํ˜•)
์˜์กด์„ฑ ๋ฐฐ์—ด"์ด๊ฑด ์ฒ˜์Œ ๋งˆ์šดํŠธ ๋  ๋•Œ๋งŒ ํ•œ ๋ฒˆ ์‹คํ–‰ํ•ด!" ([] ๊ฐ•์ œ๋กœ ๋น„์›€)"์ด ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•ด!" ([value] ์ •์งํ•˜๊ฒŒ ํˆฌ์ž…)
๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ ๊ณ„์‚ฐ"์ž…๋ ฅ๊ฐ’์ด ๋ณ€ํ•˜๋ฉด useEffect๋กœ ์ƒˆ ๋ฐฐ์—ด์„ setState์— ๋„ฃ์ž!""๋ Œ๋”๋งํ•  ๋•Œ ๋ฐ”๋กœ const newArr = ... ์„ ์–ธํ•ด์„œ ์“ฐ์ž!"

๐Ÿ’ก ํ•œ ์ค„๋กœ ๊ธฐ์–ตํ•˜๊ธฐ
useEffect๋Š” ์ฝœ๋ฐฑ(ํ•จ์ˆ˜)์„ ํŠน์ • ์‹œ์ ์— ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•œ ๋ฐœ์‚ฌ ๋ฒ„ํŠผ์ด ์•„๋‹ˆ๋‹ค. ํ™”๋ฉด ๋ฐ”๊นฅ์˜ ๋ฌด๋ฒ•์ง€๋Œ€(์™ธ๋ถ€ ์‹œ์Šคํ…œ)๋ฅผ ๋‚ด๋ถ€์˜ ๋ฆฌ์•กํŠธ ๊ตญ๋ฒ• ("State/Props") ์ฒด์ œ๋กœ ๋งž์ถ”์–ด ๊ฐ•์ œ๋กœ ๋™๊ธฐํ™”์‹œํ‚ค๋Š” '๊ตญ๊ฒฝ ๊ฒฝ์ฐฐ' ์ด๋‹ค.


๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

์—ฌํƒœ๊ป useEffect๋ฅผ ๊ทธ๋ƒฅ ๋ถ€ํŒ…ํ•  ๋•Œ ๋”ฑ ํ•œ ๋ฒˆ ์‹คํ–‰๋˜๋Š” componentDidMount์˜ ์ตœ์‹  ๋ฒ„์ „์ด๋ผ๊ณ ๋งŒ ์น˜๋ถ€ํ•ด ์˜จ ๋‚˜๋ฅผ ๋งค์šฐ ์นœ๋‹ค. ํ™”๋ฉด์ด๋ž‘ ๋ฐ์ดํ„ฐ๊ฐ€ ๋”ฐ๋กœ ๋…ธ๋Š” ๋ฒ„๊ทธ๊ฐ€ ์™œ ํ„ฐ์กŒ๋Š”์ง€ ์ด์ œ์•ผ ๋ฏธ์Šคํ„ฐ๋ฆฌ๊ฐ€ ํ’€๋ ธ๋‹ค.

๐Ÿ’ก "useEffect๋Š” ์ƒ๋ช…์ฃผ๊ธฐ API๊ฐ€ ์•„๋‹ˆ๋ผ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ์˜ ์™„๋ฒฝํ•œ '๋™๊ธฐํ™” ์ฒด์ œ'๋‹ค. ํŒŒ์ƒ ์ƒํƒœ ์—ฐ์‚ฐ์— ์“ธ๋ฐ์—†์ด ๋‚จ์šฉํ•˜์ง€๋„ ๋ง์ž!"

'์—์–ด์ปจ ์˜จ๋„ ๋™๊ธฐํ™”' ๋น„์œ ๋ฅผ ๋“ค์œผ๋‹ˆ๊นŒ ๋จธ๋ฆฌ๊ฐ€ ๋ง‘์•„์ง€๋Š” ๊ธฐ๋ถ„์ด๋‹ค. ์ด์ œ ๋ Œ๋”๋ง ๋‹จ๊ณ„์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํŒŒ์ƒ ์ƒํƒœ๋Š” ๋ฌด์กฐ๊ฑด ๋ฐ–์œผ๋กœ ๋นผ์•ผ์ง€. ์˜ํ˜ธ ๋‹˜ ๋•์— ์ฝ”๋“œ์˜ ์•…์ทจ๋ฅผ ํ•˜๋‚˜ ๋” ์•Œ์•„์ฐจ๋ฆฌ๊ฒŒ ๋๋‹ค. ์ง‘์— ๊ฐ€์„œ ์˜ค๋Š˜์€ ๋งฅ์ฃผ ํ•œ ์บ” ๊นŒ๋ฉฐ ์ง„์งœ ํ‘น ์‰ด ์ž๊ฒฉ์ด ์žˆ๋‹ค ๋‚ด ์ž์‹ !


๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. useEffect์˜ ์ง„์ •ํ•œ ๋ชฉ์ ๊ณผ ๊ฐ€์žฅ ๋ถ€ํ•ฉํ•˜๋Š” ์„ค๋ช…์€ ๋ฌด์—‡์ธ๊ฐ€์š”?

  • A) ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ™”๋ฉด์— ๋งˆ์šดํŠธ(์ถ”๊ฐ€)๋˜๊ฑฐ๋‚˜ ์–ธ๋งˆ์šดํŠธ(์ œ๊ฑฐ)๋˜๋Š” ์‹œ์ ์„ ์ •ํ™•ํžˆ ๊ฐ์ง€ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•จ.
  • B) ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์˜ ์‹œ์Šคํ…œ(์˜ˆ: ๋ธŒ๋ผ์šฐ์ € DOM API, ์„œ๋ฒ„ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ, ์„œ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)์„ ํ˜„์žฌ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ(State)์™€ ์ผ์น˜(Synchronize)์‹œํ‚ค๊ธฐ ์œ„ํ•จ.
  • C) ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ(ํ•„ํ„ฐ๋ง, ๋งตํ•‘ ๋“ฑ)์ด ๋ฉ”์ธ ๋ Œ๋”๋ง์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋„๋ก ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ๊ฒฉ๋ฆฌํ•˜์—ฌ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•จ.
  • D) ์‚ฌ์šฉ์ž์˜ ํด๋ฆญ ์ด๋ฒคํŠธ ๋“ฑ ๋ชจ๋“  ์ƒํ˜ธ์ž‘์šฉ ํ”ผ๋“œ๋ฐฑ ๋กœ์ง์„ ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•จ.

โœ… ์ •๋‹ต: B

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค: ๋งŒ์•ฝ ๋ฌด๊ฑฐ์šด ์—ฐ์‚ฐ์„ ์บ์‹ฑํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด useMemo๋ฅผ ์จ์•ผ ํ•˜๋ฉฐ(C ์˜ค๋‹ต), ์‚ฌ์šฉ์ž ํด๋ฆญ ์ด๋ฒคํŠธ๋ฅผ ๋‹ค๋ฃฐ ๋• useEffect๊ฐ€ ์•„๋‹ˆ๋ผ ๊ทธ๋ƒฅ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ(onClick)๋ฅผ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค(D ์˜ค๋‹ต). ํŠนํžˆ A๋Š” ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ ์‹œ์ ˆ์˜ ๊ตฌ์‹œ๋Œ€์  ๋งˆ์ธ๋“œ์ž…๋‹ˆ๋‹ค. useEffect๋Š” ์˜ค๋กœ์ง€ ์™ธ๋ถ€ ์„ธ๊ณ„(React ํŒจ๋Ÿฌ๋‹ค์ž„์ด ํ†ต์ œ ๋ชปํ•˜๋Š” ๊ณณ)์™€์˜ ๋™๊ธฐํ™”(Syncing) ๋งŒ์„ ์œ„ํ•ด ์˜ˆ์•ฝ๋œ ์•„์ฃผ ๋น„์‹ผ(๋А๋ฆฐ) ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

Q2. ๋‹ค์Œ ์˜์ฒ ์ด์˜ ์ฝ”๋“œ ์ค‘ ๋ถˆํ•„์š”ํ•˜๊ฒŒ useEffect๋ฅผ ๋‚จ์šฉํ•œ ํ”์ (์•ˆํ‹ฐ ํŒจํ„ด)์„ ์ œ๊ฑฐํ•˜๊ณ , ์–ด๋–ป๊ฒŒ ๊ณ ์ณ์•ผ ํ• ์ง€ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

function ProfileForm() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [fullName, setFullName] = useState('');
 
  useEffect(() => {
    setFullName(firstName + ' ' + lastName);
  }, [firstName, lastName]);
  
  return (/* ... */);
}

โœ… ์ •๋‹ต ๋ฐ ์ฃผ๊ด€์‹ ํ•ด์„ค:

๊ณ ์นœ ์ฝ”๋“œ:

function ProfileForm() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  
  // Effect์™€ ๋ถ€์ˆ˜์ ์ธ State๋ฅผ ๋ชฝ๋•… ์‚ญ์ œํ•˜๊ณ , ๋ Œ๋”๋ง ๋‹จ๊ณ„์—์„œ ๊ทธ๋ƒฅ ํŒŒ์ƒ(๊ณ„์‚ฐ)ํ•ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.
  const fullName = firstName + ' ' + lastName;
  
  return (/* ... */);
}

์ด์œ (Why): ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” ๋‚ด๋ถ€ State ํ›… ํ˜ธ์ถœ ์ดํ›„ ~ return ๋ฌธ ์‚ฌ์ด์˜ 1๊ธ‰(top-level) ๊ณต๊ฐ„์—์„œ ๋ฒŒ์–ด์ง€๋Š” ์—ฐ์‚ฐ์„ ๋ Œ๋”๋ง์˜ ์ผ๋ถ€๋กœ ์นฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ firstName์„ ๊ณ ์น˜๋ฉด ๋ Œ๋”๋ง ์Šค๋ƒ…์ƒท์ด ์ƒˆ๋กœ ์ฐํž ํ…Œ๋‹ˆ, ๊ตณ์ด useEffect๋ผ๋Š” ๊ฑฐ์ฐฝํ•œ '์™ธ๋ถ€ ๋™๊ธฐํ™” ์žฅ์น˜' ์•ˆ์— ๋„ฃ์–ด๋’€๋‹ค๊ฐ€ ๋˜๋‹ค์‹œ ๊ฐ•์ œ๋กœ ๋ฆฌ๋ Œ๋”๋ง (setFullName)์„ ์œ ๋ฐœํ•  ํ•„์š”๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค! ๊ธฐ์กด์˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ผ๋ฆฌ ์งฌ๋ฝ•ํ•ด์„œ ๋ฌด์–ธ๊ฐ€ ๋„์ถœํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ์ฃผ์ € ์—†์ด State์™€ Effect๋ฅผ ํŒŒ๊ดดํ•˜๊ณ  ์ผ๋ฐ˜ const ๋ณ€์ˆ˜๋กœ ๋นผ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Q3. useEffect ์•ˆ์—์„œ ์™ธ๋ถ€ ์‹œ์Šคํ…œ ์—ฐ๊ฒฐ(e.g., WebSocket.connect())์„ ๋งบ๊ณ  ๋‚˜์„œ, ํ•จ์ˆ˜ ๋‚ด๋ถ€ ํ•˜๋‹จ์— return () => { WebSocket.disconnect() } ํ˜•ํƒœ์˜ ํด๋ฆฐ์—…(Cleanup) ํ•จ์ˆ˜ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ทผ๋ณธ์ ์ธ ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”? '๋™๊ธฐํ™”' ํŒจ๋Ÿฌ๋‹ค์ž„ ์ธก๋ฉด์—์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

โœ… ์ •๋‹ต ๋ฐ ์ฃผ๊ด€์‹ ํ•ด์„ค:

๋™๊ธฐํ™”๋ž€ '์ƒํƒœ๋ฅผ ์ตœ์‹ ์œผ๋กœ ์ผ์น˜์‹œํ‚จ๋‹ค'๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ๊ณผ๊ฑฐ์˜ ์ƒํƒœ(์˜›๋‚  ๋ฐฉ ๋ฒˆํ˜ธ, ๊ตฌ๋ฒ„์ „ ์œ ์ € ์•„์ด๋””)๋กœ ๋งบ์–ด๋‘์—ˆ๋˜ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ๋™๊ธฐํ™” ์ž‘์—…์„ ํŒŒ๊ดด(Cleanup)ํ•˜์ง€ ์•Š์€ ์ฑ„ ์ƒˆ๋กœ์šด ๋™๊ธฐํ™”๋ฅผ ๋งบ์œผ๋ฉด, ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—๋Š” ๊ณผ๊ฑฐ ์—ฐ๊ฒฐ์„ ๋“ค๊ณผ ํ˜„์žฌ ์—ฐ๊ฒฐ์„ ๋“ค์ด ์ข€๋น„์ฒ˜๋Ÿผ ๋ฌดํ•œํžˆ ์ฆ์‹ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค(๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜).
๋”ฐ๋ผ์„œ **"์ƒˆ๋กœ์šด ๊ทœ์น™(์˜์กด์„ฑ ๋ฐฐ์—ด ๊ฐ’)์œผ๋กœ ๋ฐ”๊นฅ ์„ธ์ƒ๊ณผ ๋‹ค์‹œ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•œ๋‹ค๋ฉด, ๋ฌด์กฐ๊ฑด ์ด์ „์— ๋‚ด๊ฐ€ ์–ด์งˆ๋Ÿฌ ๋†“์•˜๋˜ ๊ตฌํ˜• ๋™๊ธฐํ™” ์ž”ํ•ด๋ฌผ๋“ค์„ ๊นจ๋—์ด ์น˜์šฐ๊ณ  ์ƒˆ๋กœ ์‹œ์ž‘ํ•˜๋ผ"**๋Š” ๊ฐ•์ œ์„ฑ์„ ๋ถ€์—ฌํ•˜๊ธฐ ์œ„ํ•ด ํด๋ฆฐ์—… ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.