๐ก 05. useEffect ํ๊ดดํ๊ธฐ (1): ์ง์ค โ ์๋ช ์ฃผ๊ธฐ๊ฐ ์๋๋ผ ๋๊ธฐํ๋ค
๐ ๊ฐ์
useEffect๋ฅผ ๋จ์ํ ์ปดํฌ๋ํธ ๋ง์ดํธ/์ธ๋ง์ดํธ ์์ ์ ์คํ๋๋ ์๋ช ์ฃผ๊ธฐ API๋ก ์คํดํ ๋ ๋ฐ์ํ๋ ๋ฌธ์ ์ ๊ทธ ์ง์ ํ ์ญํ (๋๊ธฐํ)์ ๋ฐฐ์๋๋ค.
๐ฏ ์ด ์น์ ์ ์ฝ๊ณ ๋๋ฉด:
useEffect๋ฅผcomponentDidMount๊ฐ์ ์๋ช ์ฃผ๊ธฐ ๋ฉ์๋๋ก ์๊ฐํ๋ ๋ก์ ๋ฉํ ๋ชจ๋ธ์ ๋ฒ๋ฆด ์ ์๋ค.- "๋ฆฌ์กํธ์ ์ํ(State)์ ์ธ๋ถ ์์คํ (Network, DOM)์ ์ํ๋ฅผ ์ธ์ ๋ ๊ฐ๊ฒ ๋ง์ถ๋ค(๋๊ธฐํ)"๋ ๊ฐ๋ ์ ์ค๋ช ํ ์ ์๋ค.
- ๋ถํ์ํ
useEffect์ฌ์ฉ์ ์ฆ๊ฐ ์ฐพ์๋ด์ด ์ญ์ ํ ์ ์๋ค.
๐ ๋ชฉ์ฐจ
- ๐ค ์ ์์์ผ ํ๋๊ฐ: ๋ก์ ์๋ช ์ฃผ๊ธฐ์ ๋ง๋ น
- ๐๏ธ ๋น์ ๋ก ๋จผ์ ์ดํดํ๊ธฐ
- ๐งฉ ๋๊ธฐํ(Synchronization)์ ์๋ฒฝํ ์ ์ฉ
- ๐ฅ ์๋ฌ ํด๊ฒฐ ์นดํ๋ก๊ทธ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 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>;
}์ด์ ๋ฆฌ์กํธ๋ ์ด๋ ๊ฒ ์๋ํด:
roomId = 1๋ก ๋ ๋๋ง โ 1๋ฒ ๋ฐฉ ์ฐ๊ฒฐ!- ์ ์ ๊ฐ ๋ฐฉ์ 2๋ก ๋ฐ๊ฟ (
roomId = 2๋ ๋๋ง ์ค๋ ์ท ์์ฑ) - ๋ฆฌ์กํธ: "์ด? ๊ท์น(
[roomId])์ด ๋ฐ๋์๋ค? ๋ค์ ๋๊ธฐํํด์ผ๊ฒ ๋ค." - ๋ฆฌ์กํธ: ๋จผ์ 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)ํ์ง ์์ ์ฑ ์๋ก์ด ๋๊ธฐํ๋ฅผ ๋งบ์ผ๋ฉด, ๋ฐฑ๊ทธ๋ผ์ด๋์๋ ๊ณผ๊ฑฐ ์ฐ๊ฒฐ์ ๋ค๊ณผ ํ์ฌ ์ฐ๊ฒฐ์ ๋ค์ด ์ข๋น์ฒ๋ผ ๋ฌดํํ ์ฆ์ํ๊ฒ ๋ฉ๋๋ค(๋ฉ๋ชจ๋ฆฌ ๋์).
๋ฐ๋ผ์ **"์๋ก์ด ๊ท์น(์์กด์ฑ ๋ฐฐ์ด ๊ฐ)์ผ๋ก ๋ฐ๊นฅ ์ธ์๊ณผ ๋ค์ ๋๊ธฐํํด์ผ ํ๋ค๋ฉด, ๋ฌด์กฐ๊ฑด ์ด์ ์ ๋ด๊ฐ ์ด์ง๋ฌ ๋์๋ ๊ตฌํ ๋๊ธฐํ ์ํด๋ฌผ๋ค์ ๊นจ๋์ด ์น์ฐ๊ณ ์๋ก ์์ํ๋ผ"**๋ ๊ฐ์ ์ฑ์ ๋ถ์ฌํ๊ธฐ ์ํด ํด๋ฆฐ์
ํจ์๋ฅผ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค.