-
๋ฆฌ์กํธ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๊ฐ์ ํ๋ ์์ํฌ์ธ๊ฐ์
-
React์์ ํจ์ ์ปดํฌ๋ํธ์ ํด๋์ค ์ปดํฌ๋ํธ์ ์ฐจ์ด ๐ฅ
-
๋ฆฌ์กํธ ์ฌ์ฉ์์ ๋ถ์ํจ๊ณผ๋ก ์ธํด ์๊ธฐ๋ ๋ฌธ์ ์ ์ด ์๋ค๋ฉด ๐ฅ
- ๋ถ์ ํจ๊ณผ๋ฅผ ์ผ์ผํค๋ ํจ์ (๋ถ์ ํจ์)
- ๋ถ์ ํจ๊ณผ๋ฅผ ์ผ์ผํค์ง ์๋ ํจ์ (์์ ํจ์)
- ์์ฝ
-
์ปดํฌ๋ํธ์ ๋ผ์ดํ ์ฌ์ดํด ๋ฉ์๋ ๐ฅ
- ์ดํด
- ๋ฉ์๋ ์ข ๋ฅ
-
- useState
- useEffect
- useReducer
- useMemo
- useCallback
- useRef
- ์ปค์คํ Hooks
-
๋ฆฌ์กํธ์์ setState๋ ๋น๋๊ธฐ ๋์์ธ๊ฐ์ ๋๊ธฐ ๋์์ธ๊ฐ์?
-
setState๊ฐ ๋น๋๊ธฐ ๋์์ ์ทจํ์ ๋ ์ป์ ์ ์๋ ์ด์ ์ ๋ฌด์์ธ๊ฐ์?
-
๋ฆฌ์กํธ์ ์ฑ๋ฅ๊ฐ์ ๋ฐฉ๋ฒ์ ๋ํด์ ์ค๋ช ํด์ฃผ์ธ์
-
์ปดํฌ๋ํธ์์ ์ด๋ฒคํธ๋ฅผ ์คํ์ํค๊ธฐ ์ํด์๋ ์ด๋ป๊ฒ ํธ๋ค๋งํด์ผ ํ๋์
-
- SPA์ ๋จ์
-
- TTV, TTI
-
์๋ฒ์ฌ์ด๋ ๋ ๋๋ง์ ์ง์ํ๊ธฐ ์ํ ๋ฆฌ์กํธ API๋ฅผ ์๊ณ ์๋์
-
Next๋ฅผ ๊ตฌ์ฑํ๋ ๊ธฐ๋ณธ ์ค์ ํ์ผ์ ๋ํด์ ์๊ณ ์๋์?
-
์ฌ์ ๋ ๋๋ง์ ์ํด ์ฌ์ฉํด ๋ณธ ํจ์๊ฐ ์๋์
-
suspense๊ฐ ๋ญ๊ฐ์?
-
suspense๋ก ๊ฐ๋ฅํ ๊ฒ์ ์ด๋ค ๊ฒ๋ค์ด ์๋์?
ํด๋น ๋ฌธ๋จ์ ๊ถ์คํ๋์ ํ๋ ์์ํฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฐจ์ด๋ฅผ ๋ฐํ์ผ๋ก ๋ง๋ค์ด์ก์ต๋๋ค.
๋ฆฌ์กํธ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๊ณ ๋ด์ผ ํ ๊น์ ์๋๋ฉด, ํ๋ ์ ์ํฌ๋ผ๊ณ ๋ด์ผ ํ ๊น์? ์ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์ ์ํฌ์ ๊ฐ๋ ์ ๋ํด์ ๊ฐ๋จํ๊ฒ ์ค๋ช ํด ๋ณด๊ฒ ์ต๋๋ค.
1.ํ๋ ์์ํฌ
ํ๋ ์์ํฌ๋ Application ๊ฐ๋ฐ์ ์ฝ๋์ ํ์ง, ํ์์ ์ธ ์ฝ๋, ์๊ณ ๋ฆฌ์ฆ, ์ํธํ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋ ๊ฐ์ ๊ธฐ๋ฅ๋ค์ ์ด๋์ ๋ ๊ตฌ์ฑ์ด ๋์ด์๋ ๋ผ๋(๊ตฌ์กฐ)๋ฅผ ์ ๊ณตํ๋๋ก ๋ง๋ค์ด์ง๊ฑธ ํ๋ ์์ํฌ๋ผ๊ณ ํฉ๋๋ค.
์กฐ๊ธ ์ด๋ ต๊ฒ ์ค๋ช ๋๋ ธ๋๋ฐ, ๊ฐ๋ฐ ๊ตฌ์กฐ๋ ์ค๊ณ ์ ์ ๊ณต๋๋ ์ธํฐํ์ด์ค์ ์งํฉ์ ๋๋ค. ์์ฑ๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์๋์ง๋ง ์ด๋์ ๋ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ๊ณต๋ ํ๋ ์์ํฌ์ ๊ตฌ์กฐ์์ ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํด์ผํฉ๋๋ค.
2.๋ผ์ด๋ธ๋ฌ๋ฆฌ
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํน์ ๊ธฐ๋ฅ์ ๋ํ API(๋๊ตฌ / ํจ์)๋ฅผ ๋ชจ์ ์งํฉ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๊ณ ํฉ๋๋ค.
๊ทธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ์ํด ๋ถ๋ฌ์์ ํธ์ถํ๋ ๋ฐฉ์์ ์๊ฐํ์๋ฉด ์ฌ์ธ๋ฏ ํฉ๋๋ค.
3.ํ๋ ์์ํฌ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฐจ์ด
์์ ๋ด์ฉ์ผ๋ก๋ง ๋ดค์๋๋ ๋จ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ชจ์ด๋ฉด ํ๋ ์์ํฌ์ฒ๋ผ ๋ณด์ผ ์ ์์ต๋๋ค.
์ ๋ ๊ทธ๋ ๊ฒ ์๊ฐํ๊ณ ์์๊ณ ์ ๊ทธ๋ฆฌ๊ณ ํฌ๊ฒ ํ๋ฆฐ ์๊ฐ๋ ์๋๊ฑฐ ๊ฐ์ต๋๋ค๋ง
์๋ฃ๋ฅผ ์ฐพ์๋ณด๋ ํ ๋น์ ์คํ๋ง์ ์๋์ ๊ฐ์ ๋ด์ฉ์ด ์์ต๋๋ค.
ํ๋ ์์ํฌ๋ ๋จ์ง ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋ ๋ฐ์ ํ์ด๋, ํ์ฅํด์ ์ฌ์ฉํ ์ ์๋๋ก ์ค๋น๋ ์ถ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์งํฉ์ด ์๋๋ค.
ํ๋ ์์ํฌ๊ฐ ์ด๋ค ๊ฒ์ธ์ง ์ดํดํ๋ ค๋ฉด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ ์์ํฌ๊ฐ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ์์์ผ ํ๋ค.
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๋ ์ ํ๋ฆฌ์ผ์ด์
ํ๋ฆ์ ์ง์ ์ ์ดํ๋ค.
๋จ์ง ๋์ํ๋ ์ค์ ํ์ํ ๊ธฐ๋ฅ์ด ์์ ๋ ๋ฅ๋์ ์ผ๋ก ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ๋ฟ์ด๋ค.
๋ฐ๋ฉด์ ํ๋ ์์ํฌ๋ ๊ฑฐ๊พธ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๊ฐ ํ๋ ์์ํฌ์ ์ํด ์ฌ์ฉ๋๋ค.
ํ๋ ์์ํฌ์๋ ๋ถ๋ช
ํ ์ ์ด์ ์ญ์ ๊ฐ๋
์ด ์ ์ฉ๋์ด ์์ด์ผ ํฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๋ ํ๋ ์์ํฌ๊ฐ ์ง๋์ ํ์์ ์๋์ ์ผ๋ก ๋์ํด์ผ ํฉ๋๋ค.
์ดํ๋ฆฌ์ผ์ด์ ์ flow๋ฅผ ๋๊ฐ ์ ์ดํ๋๋๊ฐ ํ๋ ์์ํฌ์ธ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ์ง ๊ตฌ๋ถํ ์ ์์์ต๋๋ค.
1. ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ ํ๋ฉด๊ตฌ์ฑ
๋ฆฌ์กํธ๋ ํ๋ฉด์ ํ ๋ถ๋ถ์ ์ปดํฌ๋ํธ
๋ผ๋ ๋จ์๋ก ๋๋ ์ ์์ผ๋ฉฐ ๋
๋ฆฝ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋ค. ๋๊ท๋ชจ ์น ์ ํ๋ฆฌ์ผ์ด์
์์ ์ปดํฌ๋ํธ๋ ์ญํ ๊ณผ ๊ธฐ๋ฅ์ ๋ฐ๋ผ ๋ฐ๋ก ๊ด๋ฆฌํ๊ธฐ ์ฉ์ดํ๋ฉฐ, ๋ฐ๋ณต๋๋ ๋ถ๋ถ์ ๋์ฒดํ ์ ์๊ฒ ํด์ฃผ์ด์ ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ฌ์ค๋ค. ๋ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ์ ํ๋ฉด์ ๊ตฌ์ฑํ๋ค๋ฉด ๋ธ๋ก ์๊ธฐ์ฒ๋ผ ์ปดํฌ๋ํธ๋ฅผ ์์์ ๋น ๋ฅด๊ณ ํจ์จ์ ์ผ๋ก ํ๋ฉด์ ๊ตฌ์ฑํ ์ ์๋ค.
2. Virtual DOM์ผ๋ก ์ธํ ์ถฉ๋ถํ ๋น ๋ฅธ ์๋
- Virtual DOM์ UI์ ์ด์์ ์ธ ๋๋ โ๊ฐ์โ์ ์ธ ํํ์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ณ ReactDOM๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํด โ์ค์ โ DOM๊ณผ ๋๊ธฐํํ๋ ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ ์ ๋๋ค. ์ด ๊ณผ์ ์ ์ฌ์กฐ์ ์ด๋ผ๊ณ ํฉ๋๋ค. ์ด ์ ๊ทผ๋ฐฉ์์ด React์ ์ ์ธ์ API๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. React์๊ฒ ์ํ๋ UI์ ์ํ๋ฅผ ์๋ ค์ฃผ๋ฉด DOM์ด ๊ทธ ์ํ์ ์ผ์นํ๋๋ก ํฉ๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ ์ฑ ๊ตฌ์ถ์ ์ฌ์ฉํด์ผ ํ๋ ์ดํธ๋ฆฌ๋ทฐํธ ์กฐ์, ์ด๋ฒคํธ ์ฒ๋ฆฌ, ์๋ DOM ์ ๋ฐ์ดํธ๋ฅผ ์ถ์ํํฉ๋๋ค.
3. SPA(์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์
)
- ์ฅ์ : ์๋ฒ์ ์์์ ์๋ ์ ์๋ค. & ๋ ์ข์ ์ฌ์ฉ์ ๊ฒฝํ์ ๋๋ฆด ์ ์๋ค.
- ๋จ์ : ์ฌ์ฉ์์ ์ธํฐ๋ ์ ์ด ๋ง์ ๊ฒฝ์ฐ์๋ ์๋ฒ์ ์์์ด ๋ง์ด ์ฌ์ฉ๋๊ณ ๋ถํ์ํ ํธ๋ ํฝ์ด ๋ญ๋น ๋ ์ ์๋ค.
๋ฆฌ์กํธ ์ฌ์ฉํ๋ ์ด์ ๋ ์ด๋ฌํ ์ฅ์ ๋๋ฌธ์ด๋ค
- component๋ฅผ ์ฌ์ฉํด์ ์ ์ง๋ณด์๊ฐ ์ฉ์ด (ํ์ํ ๋ถ๋ถ์ component๋ง ๋ ๋๋ง ๋๋ค. ์ต์ ํ๋ ๋ ๋๋ง์ด ๊ฐ๋ฅ)
- ์ํ๊ณ๊ฐ ๋๊ณ , ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ ๊ฐ๋ฅ
- virtual DOM์ ํ์ฉํ์ฌ ๋น ๋ฅธ ๋ ๋๋ง์ด ๊ฐ๋ฅ
- ๋ฆฌ์กํธ ๋ค์ดํฐ๋ธ๋ฅผ ํ์ฉํ์ฌ ์ฑ ๊ฐ๋ฐ ๊ฐ๋ฅ
DOM(Document Object Model)์ XML์ด๋ HTML ๋ฌธ์์ ์ ๊ทผํ๊ธฐ ์ํ ์ผ์ข ์ ์ธํฐํ์ด์ค๋ค. DOM์ ๋ฌธ์์ ๊ตฌ์กฐํ๋ ํํ(structured representation)์ ์ ๊ณตํ๋ฉฐ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๊ฐ DOM ๊ตฌ์กฐ์ ์ ๊ทผํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ฌ ๊ทธ๋ค์ด ๋ฌธ์ ๊ตฌ์กฐ, ์คํ์ผ, ๋ด์ฉ ๋ฑ์ ๋ณ๊ฒฝํ ์ ์๊ฒ ๋๋๋ค.
HTTP response > DOM tree > CSSOM tree > render tree > painting
DOM์ ์๋ก์ด ์์ฒญ์ด ์์ผ๋ฉด ์์ ๊ฐ์ ํํ๋ฅผ ๊ฑฐ์ณ ๋ฆฌ๋ ๋๋ง์ ํ๊ฒ ๋๋ค. DOM์ ์๋๋ ๋๋ฆฌ์ง ์๋ค. ํ์ง๋ง ๋งค๋ฒ ์๋กญ๊ฒ ๊ตฌ์ฑํ๊ธฐ ๋๋ฌธ์, ์์ด ์์ฒญ ๋ง์ผ๋ฉด ๋ถ๋ช ํผํฌ๋จผ์ค๊ฐ ๋จ์ด์ง ๊ฒ์ด๋ค. ์ฌ๊ธฐ์ ์ด์ Virtual DOM์ ์ฅ์ ์ด ๋์ค๊ฒ ๋๋ค.
๋ฆฌ์กํธ๋ Virtual DOM์ ์ฌ์ฉํ์ฌ ์ค์ DOM์ ์ ๊ทผํ์ฌ ์กฐ์ํ๋ ๋์ , ์ด๋ฅผ ์ถ์ํํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ์ฌ ์ฌ์ฉํฉ๋๋ค. ๋ง์น ์ค์ DOM์ ๊ฐ๋ฒผ์ด ์ฌ๋ณธ๊ณผ ๋น์ทํฉ๋๋ค. ํ์ง๋ง Virtual DOM์ ๋ง ๊ทธ๋๋ก ์ค์ ๋ธ๋ผ์ฐ์ ์ DOM์ด ์๋ ๋ฆฌ์กํธ๊ฐ ๊ด๋ฆฌํ๋ ๊ฐ์์ DOM์ ์๋ฏธํ๋ค. ๊ฐ์ DOM์ ์น ํ์ด์ง๊ฐ ํ์ํด์ผ ํ DOM์ ์ผ๋จ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ณ ๋ฆฌ์กํธ๊ฐ ์ค์ ๋ณ๊ฒฝ์ ๋ํ ์ค๋น๊ฐ ์๋ฃ๋์ ๋ ์ค์ ๋ธ๋ผ์ฐ์ ์ DOM์ ๋ฐ์ํ๋ค. DOM ๊ณ์ฐ์ ๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ๋ฉ๋ชจ๋ฆฌ์์ ๊ณ์ฐํ๋ ๊ณผ์ ์ ํ ๋ฒ ๊ฑฐ์น๊ฒ ๋๋ค๋ฉด ์ค์ ๋ก๋ ์ฌ๋ฌ ๋ฒ ๋ฐ์ํ์ ๋ ๋๋ง ๊ณผ์ ์ ์ต์ํํ ์ ์๊ณ ๋ธ๋ผ์ฐ์ ์ ๊ฐ๋ฐ์์ ๋ถ๋ด์ ๋ ์ ์๋ค.
๋ฆฌ์กํธ์์ ๋ฐ์ดํฐ๊ฐ ๋ณํ์ฌ ์น ๋ธ๋ผ์ฐ์ ์ ์ค์ DOM์ ์ ๋ฐ์ดํธํ ๋๋ ๋ค์ ์ธ ๊ฐ์ง ์ ์ฐจ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ ์ฒด UI๋ฅผ Virtual DOM์ ๋ฆฌ๋ ๋๋ง
- ์ด์ ๋ด์ฉ๊ณผ ํ์ฌ ๋ด์ฉ์ ๋น๊ต
- ๋ฐ๋ ๋ถ๋ถ๋ง ์ค์ DOM์ ์ ์ฉ
Virtual DOM์ ์ฌ์ฉํ๋ค๊ณ ํด์ ์ฌ์ฉํ์ง ์์ ๋์ ๋น๊ตํ์ฌ ๋ฌด์กฐ๊ฑด ๋น ๋ฅธ ๊ฒ์ ์๋๋๋ค. ๋ฆฌ์กํธ ๋งค๋ด์ผ์๋ ๋ค์ ๋ฌธ์ฅ์ด ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ๋ค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ๋ฆฌ์กํธ๋ฅผ ๋ง๋ค์์ต๋๋ค.
์ง์์ ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋ณํํ๋ ๋๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์
๊ตฌ์ถํ๊ธฐ
๊ทธ๋ ์ต๋๋ค. ๊ฒฐ๊ตญ์๋ ์ ์ ํ ๊ณณ์ ์ฌ์ฉํด์ผ ๋ฆฌ์กํธ๊ธฐ ์ง๋ ์ง๊ฐ๋ฅผ ๋น๋ก์ ๋ฐํํ ์ ์์ต๋๋ค. ๋ฆฌ์กํธ๋ฅผ ์ฌ์ฉํ์ง ์์๋ ์ฝ๋ ์ต์ ํ๋ฅผ ์ด์ฌํ ํ๋ฉด DOM ์์ ์ด ๋๋ ค์ง๋ ๋ฌธ์ ๋ฅผ ๊ฐ์ ํ ์ ์๊ณ , ๋ ์์ ์ด ๋งค์ฐ ๊ฐ๋จํ ๋๋ ์คํ๋ ค ๋ฆฌ์กํธ๋ฅผ ์ฌ์ฉํ์ง ์๋ ํธ์ด ๋ ๋์ ์ฑ๋ฅ์ ๋ณด์ด๊ธฐ๋ ํฉ๋๋ค.
๋ฆฌ์กํธ์ Virtual DOM์ด ์ธ์ ๋ ์ ๊ณตํ ์ ์๋ ๊ฒ์ ๋ฐ๋ก ์ ๋ฐ์ดํธ ์ฒ๋ฆฌ ๊ฐ๊ฒฐ์ฑ์ ๋๋ค. UI๋ฅผ ์ ๋ฐ์ดํธํ๋ ๊ณผ์ ์์ ์๊ธฐ๋ ๋ณต์กํจ์ ๋ชจ๋ ํด์ํ๊ณ , ๋์ฑ ์ฝ๊ฒ ์ ๋ฐ์ดํธ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
๋ธ๋ผ์ฐ์ ์ ๋ ๋๋ง์ HTML๊ณผ CSS ๋ฆฌ์์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์น ํ์ด์ง์ ํ์ํ UI๋ฅผ ๊ทธ๋ฆฌ๋ ๊ณผ์ ์ ๋๋ค. ๋ฆฌ์กํธ์ ๋ ๋๋ง์ ๊ฒฝ์ฐ ๋ธ๋ผ์ฐ์ ์ ๋ ๋๋ง๊ณผ ๊ตฌ๋ถ ์ง์ ์ ์์ต๋๋ค.
๋ธ๋ผ์ฐ์ ๊ฐ ๋ ๋๋ง์ ํ์ํ DOM ํธ๋ฆฌ๋ฅผ ๋ง๋๋ ๊ณผ์ ์ผ๋ก ๋ธ๋ผ์ฐ์ ๋ ๋๋ง๋ณด๋ค ๋จผ์ ์คํ๋ฉ๋๋ค. ๋ฆฌ์กํธ ์ ํ๋ฆฌ์ผ์ด์ ํธ๋ฆฌ ์์ ์๋ ๋ชจ๋ ์ปดํฌ๋ํธ๋ค์ด ํ์ฌ ์์ ๋ค์ด ๊ฐ์ง๊ณ ์๋ props์ state์ ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ์ด๋ป๊ฒ UI๋ฅผ ๊ตฌ์ฑํ๊ณ ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ด๋ค DOM ๊ฒฐ๊ณผ๋ฅผ ๋ธ๋ผ์ฐ์ ์ ์ ๊ณตํ ๊ฒ์ธ์ง ๊ณ์ฐํ๋ ์ผ๋ จ์ ๊ณผ์ ์ ๋๋ค.
๋ฆฌ์กํธ ํ์ด๋ฒ๋ ๋ฆฌ์กํธ์์ ๊ด๋ฆฌํ๋ ํ๋ฒํ ์๋ฐ์คํฌ๋ฆฝํธ ๊ฐ์ฒด๋ค. ํ์ด๋ฒ๋ ํ์ด๋ฒ ์ฌ์กฐ์ ์(fiber reconciler)๊ฐ ๊ด๋ฆฌํ๋๋ฐ, ๊ฐ์ DOM๊ณผ ์ค์ DOM์ ๋น๊ตํด ๋ณ๊ฒฝ ์ฌํญ์ ์์งํ๋ฉฐ, ๋ง์ฝ ์ด ๋ ์ฌ์ด์ ์ฐจ์ด๊ฐ ์์ผ๋ฉด ๋ณ๊ฒฝ์ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ ํ์ด๋ฒ๋ฅผ ๊ธฐ์ค์ผ๋ก ํ๋ฉด์ ๋ ๋๋ง์ ์์ฒญํ๋ ์ญํ ์ ํ๋ค.
๋ฆฌ์กํธ ํ์ด๋ฒ๋ ๋ฆฌ์กํธ ์ฑ์์ ๋ฐ์ํ๋ ์ ๋๋ฉ์ด์ , ๋ ์ด์์, ๊ทธ๋ฆฌ๊ณ ์ฌ์ฉ์ ์ธํฐ๋ ์ ์ ์ฌ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋๋ ๋ฐ์์ฑ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ์ด ๋ชฉํ์ด๋ค.
๋ชจ๋ ๊ณผ์ ์ ๋น๋๊ธฐ๋ก ์ผ์ด๋๋ฉฐ, ์์ ์ ์ค์ผ์ค๋งํ๊ธฐ๋ ํ๋ค. ์ ๋๋ฉ์ด์ ๊ณผ ๊ฐ์ด ์ฐ์ ์์๊ฐ ๋์ ์์ ์ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ฑฐ๋, ๋ฎ์ ์์ ์ ์ฐ๊ธฐ์ํค๋ ๋ฑ ์ข ๋ ์ ์ฐํ๊ฒ ์ฒ๋ฆฌ๋๋ค.
๊ณผ๊ฑฐ ๋ฆฌ์กํธ์ ์กฐ์ ์๊ณ ๋ฆฌ์ฆ์ ์คํ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ด๋ฃจ์ด์ ธ ํ๋์ ์คํ์ ๋ ๋๋ง์ ํ์ํ ์์ ๋ค์ด ์์ด๋ฉด ์ด ์คํ์ด ๋น ๋๊น์ง ๋๊ธฐ์ ์ผ๋ก ์์ ์ด ์ด๋ฃจ์ด์ก๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์ ํน์ง์ธ ์ฑ๊ธ ์ค๋ ๋๋ผ๋ ์ ์ผ๋ก ์ธํด ์ด ๋๊ธฐ์ ์ธ ์์ ์ ์ค๋จ๋ ์ ์์๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ตญ ๋ฆฌ์กํธ์ ๋นํจ์จ์ฑ์ผ๋ก ์ด์ด์ก๋ค. ์ด๋ฌํ ๊ธฐ์กด ๋ ๋๋ง ์คํ์ ๋นํจ์จ์ฑ์ ํํํ๊ธฐ ์ํด ๋ฆฌ์กํธ ํ์ ์ด ์คํ ์กฐ์ ์ ๋์ ํ์ด๋ฒ๋ผ๋ ๊ฐ๋ ์ ํ์์ํจ๋ค.
ํ์ด๋ฒ ํธ๋ฆฌ๋ ๋ฆฌ์กํธ ๋ด๋ถ์์ ๋ ๊ฐ๊ฐ ์กด์ฌํ๋ค. ํ์ฌ ๋ชจ์ต์ ๋ด์ ํ์ด๋ฒ ํธ๋ฆฌ์ ์์ ์ค์ธ ์ํ๋ฅผ ๋ํ๋ด๋ workInProgress ํธ๋ฆฌ๋ค. ๋ฆฌ์กํธ ํ์ด๋ฒ์ ์์ ์ด ๋๋๋ฉด ๋ฆฌ์กํธ๋ ๋จ์ํ ํฌ์ธํฐ๋ง ๋ณ๊ฒฝํด workInProgress ํธ๋ฆฌ๋ฅผ ํ์ฌ ํธ๋ฆฌ๋ก ๋ฐ๊ฟ๋ฒ๋ฆฐ๋ค. ์ด๋ฌํ ๊ธฐ์ ์ ๋๋ธ ๋ฒํผ๋ง์ด๋ผ๊ณ ํ๋ค.
๋๋ธ ๋ฒํผ๋ง์ ๋ ๋ ๋จ๊ณ์ ์ปค๋ฐ ๋จ๊ณ ์ค ์ปค๋ฐ ๋จ๊ณ์์ ์ํ๋๋ค.
๋ฆฌ์กํธ์ ํ์ด๋ฒ ์ํคํ ์ฒ์์ ํ์ฌ ๋ชจ์ต์ ๋ด์ ํ์ด๋ฒ ํธ๋ฆฌ(current fiber tree)์ ์์ ์ค์ธ ํธ๋ฆฌ(workInProgress fiber tree)๋ ์ค์ DOM๊ณผ Virtual DOM๊ณผ ๋ค์๊ณผ ๊ฐ์ด ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค.
- ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ(current fiber tree)
- ์ด ํธ๋ฆฌ๋ ํ์ฌ ํ๋ฉด์ ๋ ๋๋ง๋์ด ์๋ UI์ ์ํ๋ฅผ ๋ํ๋ ๋๋ค.
- ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ์ ๋ ธ๋๋ค์ ์ค์ DOM ๋ ธ๋์ 1:1 ๋์ ๊ด๊ณ๋ฅผ ๊ฐ์ง๋๋ค.
- ์ฆ, ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ๋ ์ค์ DOM์ ํ์ฌ ๋ชจ์ต์ ๊ฐ์์ ์ผ๋ก ํํํฉ๋๋ค.
- ์์ ์ค์ธ ํ์ด๋ฒ ํธ๋ฆฌ(workInProgress fiber tree)
- ์ด ํธ๋ฆฌ๋ ๋ค์ ๋ ๋๋ง ์์ ์ ์ ๋ฐ์ดํธ๋ UI ์ํ๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
- ์์ ์ค์ธ ํธ๋ฆฌ๋ Virtual DOM์ ์ญํ ์ ํฉ๋๋ค. ์ฌ๊ธฐ์ ์๋ก์ด Virtual DOM ํธ๋ฆฌ๊ฐ ์์ฑ๋๊ณ ๊ณ์ฐ๋ฉ๋๋ค.
- ์์ ์ค์ธ ํธ๋ฆฌ์์ ๊ณ์ฐ๋ ๋ณ๊ฒฝ ์ฌํญ์ ์ค์ DOM์ ๋ฐ์๋๊ธฐ ์ ์ reconciliation ๊ณผ์ ์ ๊ฑฐ์นฉ๋๋ค.
- Reconciliation(์ฌ์กฐ์ ) ๊ณผ์
- React๋ ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ์ ์์ ์ค์ธ ํธ๋ฆฌ๋ฅผ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ๋ ๋ถ๋ถ์ ์ฐพ์๋ ๋๋ค.
- ์ด๋ ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์ค์ DOM์ ๋ฐ์๋๋ฉฐ, ๋ถํ์ํ DOM ์กฐ์์ ์ต์ํํฉ๋๋ค.
- Reconciliation ๊ณผ์ ์ด ์๋ฃ๋๋ฉด ์์ ์ค์ธ ํธ๋ฆฌ๊ฐ ์๋ก์ด ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
- DOM ์ ๋ฐ์ดํธ
- Reconciliation ๋จ๊ณ์์ ๋ฐ๊ฒฌ๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์ค์ DOM์ ๋ฐ์๋ฉ๋๋ค.
- React๋ ๊ฐ๋ฅํ ํ ์ต์ํ์ DOM ๋ณ๊ฒฝ ์์ ์ ์ํํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.
- ์ด ๊ณผ์ ์์ ์ค์ DOM๊ณผ ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ๊ฐ ๋๊ธฐํ๋ฉ๋๋ค.
์์ฝํ๋ฉด, ํ์ฌ ํ์ด๋ฒ ํธ๋ฆฌ๋ ์ค์ DOM์ ํ์ฌ ์ํ๋ฅผ ๋ํ๋ด๊ณ , ์์ ์ค์ธ ํธ๋ฆฌ๋ Virtual DOM์ ์ญํ ์ ํ์ฌ ๋ค์ ๋ ๋๋ง ์์ ์ ๊ณ์ฐํฉ๋๋ค. Reconciliation ๊ณผ์ ์ ๊ฑฐ์ณ ๋ณ๊ฒฝ ์ฌํญ์ด ์ค์ DOM์ ๋ฐ์๋๊ณ , ์์ ์ค์ธ ํธ๋ฆฌ๊ฐ ์๋ก์ด ํ์ฌ ํธ๋ฆฌ๊ฐ ๋ฉ๋๋ค. ์ด๋ฌํ ํ์ด๋ฒ ์ํคํ ์ฒ ๋๋ถ์ React๋ ํจ์จ์ ์ผ๋ก UI ์ ๋ฐ์ดํธ๋ฅผ ๊ด๋ฆฌํ๊ณ ๋ถํ์ํ DOM ์กฐ์์ ํผํ ์ ์์ต๋๋ค. ๋ํ ์ด ๊ณผ์ ์์ ํ๋ ์ ๋จ์๋ก ์์ ์ ๋ถํ ํ์ฌ ์ฑ์ ๋ฐ์์ฑ์ ํฅ์์ํต๋๋ค.
๋ ๋ ๋จ๊ณ(Render Phase)
์ด ๋จ๊ณ์์๋ Virtual DOM ํธ๋ฆฌ์ ๋ณ๊ฒฝ์ฌํญ์ ๊ณ์ฐํ๊ณ ๋ฉ๋ชจ๋ฆฌ์ ์๋ก์ด Virtual DOM ํธ๋ฆฌ๋ฅผ ์์ฑํฉ๋๋ค. React๋ ์ด์ Virtual DOM๊ณผ ํ์ฌ ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด Virtual DOM ํธ๋ฆฌ๋ฅผ ๋ง๋ญ๋๋ค. ์ด ๊ณผ์ ์์ React๋ ๋ฌด์์ด ๋ณ๊ฒฝ๋์๋์ง ํ์ ํ๊ณ ์ต์ํ์ DOM ๋ณ๊ฒฝ์ฌํญ์ ๊ณ์ฐํฉ๋๋ค. ๋ ๋๋ง ๋จ๊ณ๋ ์์ ํ ๋ฉ๋ชจ๋ฆฌ ์์์ ์ด๋ฃจ์ด์ง๋ฉฐ ์ค์ DOM์๋ ์๋ฌด๋ฐ ๋ณํ๊ฐ ์ผ์ด๋์ง ์์ต๋๋ค.
์ปค๋ฐ ๋จ๊ณ(Commit Phase)
๋ ๋๋ง ๋จ๊ณ์์ ๊ณ์ฐ๋ ๋ณ๊ฒฝ ์ฌํญ์ ์ค์ DOM์ ๋ฐ์ํ๋ ๋จ๊ณ์ ๋๋ค. React๋ ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์ค์ DOM์ ์ ๋ฐ์ดํธํฉ๋๋ค. ์ด ๋จ๊ณ์์ React๋ ํ์ํ DOM ๋ ธ๋๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ถ๊ฐ, ๋ณ๊ฒฝ ๋ฐ ์ ๊ฑฐํฉ๋๋ค. ๋ํ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ฑ์ ์ ๋ฐ์ดํธ๋ ์ํ๋ฉ๋๋ค. ์ปค๋ฐ ๋จ๊ณ๊ฐ ์๋ฃ๋๋ฉด ๋ณ๊ฒฝ๋ DOM์ด ํ๋ฉด์ ๋ฐ์๋ฉ๋๋ค.
๋ ๋๋ง๊ณผ ์ปค๋ฐ ๋จ๊ณ๋ฅผ ๋ถ๋ฆฌํจ์ผ๋ก์จ React๋ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค:
๋ฉ๋ชจ๋ฆฌ ์์์ ๋ ๋๋ง ์์ ์ ์ํํ๋ฏ๋ก DOM ์์ ์ ๋นํด ๋น ๋ฆ ๋๋ค. ์ค์ DOM ๋ณ๊ฒฝ์ ์ต์ํ์ผ๋ก ์ ์ง๋์ด ๋๋ฆฐ DOM ์กฐ์์ ์ค์ ๋๋ค. ๋ ๋๋ง ๋จ๊ณ์์ ์ ๋ฐ์ดํธ ๋ก์ง์ ์ค๋จํ ์ ์์ด ์ฌ์ฉ์ ์ํธ์์ฉ์ ๋์ฑ ๋ฐ์์ ์ ๋๋ค.
์ด๋ ๊ฒ React์ ๋ ๋จ๊ณ ๋ ๋๋ง ๋ฐฉ์์ Virtual DOM์ ํตํด ๋ณ๊ฒฝ ์ฌํญ์ ํจ์จ์ ์ผ๋ก ๊ณ์ฐํ๊ณ ๋ฐฐ์น ์ฒ๋ฆฌํ์ฌ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.
ํด๋์ค ์ปดํฌ๋ํธ์ ๊ฒฝ์ฐ
- ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ๊ตฌ์กฐ๋ฅผ ๋๊ณ ์์ผ๋ฉฐ, state๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ํด์๋ constructor (์์ฑ์) ํจ์๋ฅผ ํ์๋ก ํฉ๋๋ค
- ์์ฑ์ ํจ์๋ฅผ ํตํด state๋ฅผ ์ด๊ธฐํํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํจ์ ์ปดํฌ๋ํธ์ ๋นํด์ ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ณ , ์ฌ์ด์ฆ๊ฐ ์ปค์ง ์ ์์ต๋๋ค.
- state ๊ธฐ๋ฅ ๋ฐ ๋ผ์ดํ ์ฌ์ดํด ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ์์ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ค
- render ํจ์๊ฐ ๊ผญ ์์ด์ผ ํ๊ณ , ๊ทธ ์์์ ๋ณด์ฌ ์ฃผ์ด์ผ ํ JSX๋ฅผ ๋ฐํํด์ผ ํ๋ค.
ํจ์ ์ปดํฌ๋ํธ๋ ํด๋์คํ ์ปดํฌ๋ํธ๋ณด๋ค
- Hooks ๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ์ ํจ์๋ฅผ ํตํด state๋ฅผ ์ด๊ธฐํํ์ง ์๋๋ผ๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค (
useState()
๋ฑ) - ์ ์ธํ๊ธฐ๊ฐ ์ข ๋ ํธํ๊ณ ๋ฉ๋ชจ๋ฆฌ ์์์ ๋ ์ฌ์ฉํ๋ค๋ ์ฅ์ ์ด ์๋ค
- ์ ๊ณต๋๋ hook ํจ์๋ฟ๋ง ์๋๋ผ ์ปค์คํ ํ ์ ์์ฑํ์ฌ ๋์์ํฌ ์ ์๋ค
- ํ๋ก์ ํธ๋ฅผ ์์ฑํ์ฌ ๋น๋ํ ํ ๋ฐฐํฌํ ๋๋ ํจ์ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฒฐ๊ณผ๋ฌผ์ ํ์ผ ํฌ๊ธฐ๊ฐ ๋ ์์ต๋๋ค
ํจ์ ์ปดํฌ๋ํธ๋ state์ ๋ผ์ดํ์ฌ์ดํด API์ ์ฌ์ฉ์ด ๋ถ๊ฐ๋ฅํ๋ค๋ ์ ์ธ๋ฐ, ์ด๋ฅผ ํด๊ฒฐ ํ๊ธฐ ์ํด v16.8 ์ ๋ฐ์ดํธ ์ดํ์ ์ ์ฉ๋ Hooks๋ฅผ ํตํด ํด๊ฒฐ๋์์ต๋๋ค.
๋ฆฌ์กํธ์์ ํจ์ํ ์ปดํฌ๋ํธ๋ผ๊ณ ๋ถ๋ฅด์ง ์๊ณ ํจ์ ์ปดํฌ๋ํธ๋ผ๊ณ ๋ถ๋ฅด๋ ์ด์ ๊ฐ ๋ฌด์์ธ๊ฐ์
(๋ต๋ณ ์ถ์ฒ - ํ ์ค์ ํ๋ก ํธ์๋ ์ธ์ฑ๋)
์๋ ๋ฆฌ์กํธ ์ธก์์๋ ํจ์ํ ์ปดํฌ๋ํธ ๋ผ๋ ๋จ์ด๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ํ์ง๋ง ์ด๋ฌํ ๋ค์ด๋ฐ์ด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ๊ณผ ๋น์ทํ๊ณ , ์ถฉ๋ถํ ํผ๋์ ์ผ๊ธฐํ ์ ์์์ต๋๋ค. ์ฒ์ ๋ฆฌ์กํธ์ ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ๋ฐฐ์ฐ๋ ์
์ฅ์์๋ 'ํจ์ํ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ด ๊ฐ๋ฅํด์ง๋ค'
์ ๊ฐ์ ํผ๋์ ๋๋ ์ ์์๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๊ฐ ๋ฆฌ์กํธ์์ ์ฌ์ฉํ๋ ํจ์ ์ปดํฌ๋ํธ ๋ ํ (hook)์ด ๋ค์ด๊ฐ๊ณ , ์ด ํ ์ผ๋ก ์ฌ์ด๋ ์ดํํธ ๋ฅผ ๋น๋ฒํ ์ผ์ผํค๊ธฐ ๋๋ฌธ์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์์ ํจ์๋ฅผ ์งํฅํ๋๋ฐ, ์ฌ์ด๋ ์ดํํธ๋ฅผ ๋น๋ฒํ ์ผ์ผํค๋ ๋ฆฌ์กํธ์ ํจ์ ์ปดํฌ๋ํธ๊ฐ ํจ์ํ ์ปดํฌ๋ํธ๋ก ๋ณด๊ธฐ๋ ์ด๋ ต๋ค๋ ๊ฒ์ ๋๋ค.
2018๋ ์ดํ ๋ฆฌ์กํธ ์ธก์์๋ ํจ์ํ ์ปดํฌ๋ํธ ๊ฐ ์๋ ํจ์ ์ปดํฌ๋ํธ ๋ก ์ด๋ฆ์ ๋ค์ ์ ํ์ต๋๋ค.
Rename "functional component" to "function component"
-
props : ์ปดํฌ๋ํธ ์์ฑ์ ์ค์ ํ ๋ ์ฌ์ฉํ๋ ์์์ด๋ค. props๊ฐ์ ํด๋น ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์ค์ ํ ์ ์์ต๋๋ค.
-
state : ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๋ฐ๋์ ์๋ ๊ฐ์ ์๋ฏธํ๋ค. props๋ ์ปดํฌ๋ํธ๊ฐ ์ฌ์ฉ๋๋ ๊ณผ์ ์์ ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ์ค์ ํ๋ ๊ฐ์ด๋ฉฐ, ์ปดํฌ๋ํธ ์์ ์ ํด๋น props๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. props๋ฅผ ๋ฐ๊พธ๋ ค๋ฉด ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ๋ฐ๊พธ์ด ์ฃผ์ด์ผ ํฉ๋๋ค.
props๊ฐ ์ปดํฌ๋ํธ๊ฐ์ ์ ๋ฌ๋ฐ๋ ๊ฒ์ด๋ผ๊ณ ํ๋๋ฐ ์์์์ ๋ถ๋ชจ๋ก๋ ์ ๋ฌํ ์ ์๋๊ฐ
-
๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์ค์ ํ ์ ์์ผ๋ฉฐ, ๋ถ๋ชจ์์ ์์์ผ๋ก๋ง ๋ฐ์ดํฐ๋ฅผ ์ค ์ ์๋ค. (์์์ด props๋ฅผ ํตํด ๋ถ๋ชจ์๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ค ์ ์๋ค๋ ๋ป์ด๋ค.)
-
์์์์ ๋ถ๋ชจ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ ๋ฐฉ๋ฒ = ํจ์๋ฅผ ์ด์ฉํ๋ค.
- ์์์ props๋ฅผ ์ฌ์ฉํด์ ๋ถ๋ชจ์๊ฒ ๋ฐ์ดํฐ๋ฅผ ๊ฑด๋ค์ค ์ ์๋ค. ๋ฐ๋ผ์ ๋ถ๋ชจ๊ฐ ํจ์๋ฅผ ๋ฃ์ด props๋ก ์์์๊ฒ ๋๊ฒจ์ฃผ๋ฉด, ์์์ด ๋ฐ์ดํฐ๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฃ์ด ํธ์ถํ๋ ๋ฐฉ์์ผ๋ก ๋์ํ๋ค. ์ฆ, ๋ถ๋ชจ๊ฐ props๋ก ํจ์๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ์์์ด ๊ทธ ํจ์๋ฅผ ์ด์ฉํด ๊ฐ์ ๊ฑด๋ค์ฃผ๋ ๋ฐฉ์์ด๋ค.
๋งํฌ ๋ฒจ๋กํผํธ๋ ์ ํ๋ธ
๋ฆฌ๋์ค๋ ํ์ด์ค๋ถ์์ ๋ฆฌ์กํธ๊ฐ ํจ๊ป ์๊ฐํ FLUX ์ํคํ
์ณ๋ก ๊ตฌํํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
์์ ์ฝ๋
type StoreState = {
count: number;
};
type Action = { type: 'add'; payload: number };
function reducer(state: StoreState, action: Action) {
const { type: ActionType, payload } = action;
if (ActionType === 'add') {
return {
count: state.count + payload,
};
}
throw new Error(`Unexpected action type: ${ActionType}`);
}
export default function App() {
const [state, dispatcher] = useReducer(reducer, { count: 0 });
function handleClick() {
dispatcher({ type: 'add', payload: 1 });
}
return (
<div>
<p>{state.count}</p>
<button onClick={handleClick}>Add</button>
</div>
);
}
๊ทธ๋ ๋ค๋ฉด FLUX๋ ๋ญ๊น์? FLUX๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํ๋ ์์ํฌ๊ฐ ์๋ ์ถ์์ ์ธ ๊ฐ๋ ์ ๋๋ค.
MVC
ํจํด์์ ์๋ฑกํฅ์ ์ธ ๋ฐ์ดํฐ ํ๋ฆ์ ๊ฐ์กฐํ๋ ๊ฒ๊ณผ ๋ฌ๋ฆฌ FLUX
ํจํด์์๋ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ๊ฐ์กฐํฉ๋๋ค.
MVC
ํจํด์ ๊ฒฝ์ฐ ์ฌ์ฉ์์ ์ด๋ ํ ํ์(์ก์
)๊ฐ ์์ ๋, ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ค๊ณ๋ ์ปจํธ๋กค๋ฌ
๋ฅผ ํตํด ๋ชจ๋ธ
์ ๋ณํํ๊ณ ์ด๋ฅผ ๋ทฐ
์ ๋ฐ์ํฉ๋๋ค.
๋ณด์ฌ์ ธ์ผ ํ ๋ทฐ
๊ฐ ์ ๊ฑฐ๋, ๋ณ๊ฒฝ๋ ๋ชจ๋ธ
์ด ๋ง์ง ์๋ค๋ฉด ๋งค์ฐ ํจ์จ์ ์ธ ๊ตฌ์กฐ์ผ ๊ฒ์
๋๋ค.
ํ์ง๋ง, ๋ชจ๋ธ
๊ณผ ๋ทฐ
๊ฐ ๋ณต์กํ๊ฒ ์ฝํ ์๋ค๋ฉด ์ด๋ค ๋ชจ๋ธ์ด ๋ณํ๋์ด ๋ทฐ๊ฐ ๋ณ๊ฒฝ๋์๋์ง ์ ๋๋ก ํ์ธํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ์๊น๋๋ค.
์ค์ ๋ก ํ์ด์ค๋ถ
์์๋ MVC
ํจํด์ผ๋ก ์ค๊ณํ ๊ตฌ์กฐ ๋๋ฌธ์, ์์ง ์ฝ์ง ์์ ๋ฉ์ธ์ง๋ฅผ ํ์ํ์ง๋ง, ์ค์ ๋ก ๋ค์ด๊ฐ ๋ณด๋ฉด ์๋ก์ด ๋ฉ์ธ์ง๊ฐ ์๋ ๊ฒฝ์ฐ๊ฐ ์์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋์จ ๋จ๋ฐฉํฅ ๋ฐ์ดํฐ ํ๋ฆ์ ์ ์ดํ๋ ํจํด์ด FLUX
์
๋๋ค.
์ฌ์ฉ์์ ํ์ ์ก์
์ ๋์คํจ์ณ
์ ์ํด ํต์ ๋ฉ๋๋ค. ๋์คํจ์ฒ
๊ฐ ์คํ ์ด
๋ฅผ ์
๋ฐ์ดํธํ๊ณ ๋ณ๊ฒฝ๋ ์คํ ์ด
์ ๋ํ ๋ทฐ
๋ฅผ ๋ฆฌ๋ ๋๋งํฉ๋๋ค.
๋ทฐ
์์๋ ์คํ ์ด
์ ์ง์ ์ ๊ทผํ์ง ์์ผ๋ฉฐ, ๋์คํจ์ฒ
๋ก ๋ค์ ์ก์
์ ๋ณด๋ด๊ณ ์คํ ์ด
๋ฅผ ์
๋ฐ์ดํธํ ๋ค, ๋ค์ ๋ทฐ
๋ฅผ ๋ฆฌ๋ ๋๋งํ๋ ๋จ๋ฐฉํฅ์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค.
FLUX
ํจํด์ ์ด๋ฌํ ๋จ๋ฐฉํฅ์ ์ธ ๋ฐ์ดํฐ ํ๋ฆ ๊ตฌ์กฐ๋ฅผ ํตํด ์ด๋ค ์ก์
์ด ๋์คํจ์ฒ์ ์ํด ์ด๋ค ๊ฒฐ๊ณผ๋ฅผ ๋ณ๊ณ ๋ณํ๋๋์ง ๋ช
ํํ ํ์
ํ๊ณ ์์๋ณผ ์ ์์ต๋๋ค.
๋ฆฌ๋์ค๋ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค ํ๋๋ก ์ฌ๋ฌ ๊ฐ์ง ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๊ณ ์์ต๋๋ค.
๋ฆฌ๋์ค๋ Store(์คํ ์ด)๋ผ๋ ๋ณ์๋ฅผ ์ด์ฉํ์ฌ ์ ์ญ ์ํ๊ด๋ฆฌ๋ฅผ ํ๊ฒ ๋ฉ๋๋ค.
์ ์ญ์ผ๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ props <-> state๋ฅผ ํตํด ๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์์ ์ปดํฌ๋ํธ๋ก, ์์์ ์์ ์ปดํฌ๋ํธ๋ก ๋ด๋ ค์ฃผ์ง ์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ญ์ํ๋ ๋จ์ผ ์ ์ฅ์ ๋ด์ ํธ๋ฆฌ์ ์ ์ฅ๋ฉ๋๋ค
- ์ํ(state)๋ ์ฝ๊ธฐ ์ ์ฉ์ ๋๋ค.
- ์์ ํจ์์ ์ํด์ ๋ณ๊ฒฝ๋์ด์ผ ํฉ๋๋ค.
ctrl + F '๋ถ์ ํจ๊ณผ๋ฅผ ์ผ์ผํค์ง ์๋ ํจ์ (์์ ํจ์)'
ctrl + F '๋ถ์ํจ๊ณผ๊ฐ ์๋ ๋ฐฐ์ด์ ํ๋กํ ํ์
๋ฉ์๋'
๊ฐ์ฒด๋ ์ค์ ๋ฐ์ดํฐ ๊ฐ์ด ์๋ ์ฐธ์กฐ ๊ฐ์ ๊ฐ์ง๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋ณต์ฌํ์ฌ ๋์ผํ ์ฐธ์กฐ ๊ฐ์ ๊ฐ์ง๋ ๊ฐ์ฒด ์ค ํ๋๋ผ๋ ๋ณ๊ฒฝ๋๋ค๋ฉด, ๋ชจ๋ ๊ฐ์ฒด์ ๋ด๋ถ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๊ฒ์ ๋๋ค.
...์ฐ์ฐ์
๋ฅผ ํตํด ๋ณต์ฌํ ๊ฒฝ์ฐ A์ B๋ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋๋ผ๋ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ํ ๋น ๋ฐ์ ์ํ๊ฐ ๋ฉ๋๋ค. ๋ฐ๋ผ์ A์ B ๋ด๋ถ์ ๊ฐ์ ๊ฐ๋๋ผ๋(๊ฐ์ ๋ณด์ด๋๋ผ๋) ์ฐธ์กฐํ๋ ๊ฐ์ฒด๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค.
์ด๋ฏธ ๋ณต์ฌ๋ฅผ ํ ํ๋ฆฐํธ ๋ฌผ์ A ์ธ์๋ฌผ์ ๋์๋ฅผ ํ๋๋ผ๋ B ์ธ์๋ฌผ์ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค
๋ฆฌ์กํธ์์๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ๊ฐ์ฒด ํ์ ๋๋ ๋ฐฐ์ด ํ์์ ๋ฐ์ดํฐ๋ฅผ ๋ง์ด ๋ค๋ฃจ๊ฒ ๋๋๋ฐ, ์๋ณธ ๋ฐฐ์ด์ด ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ ์๋ํ ๋์๊ณผ ๋ค๋ฅด๊ฒ ๋์ํ ์ ์์ผ๋ฉฐ, ์ด๋ค ํจ์์ ์ํด ๋ถ์ํจ๊ณผ(side effect)๊ฐ ๋ฐ์ํ๋์ง ์ฐพ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
let A = {
name: 'junhee',
age: 25,
job: 'student',
};
B = { ...A };
console.log('A', A);
console.log('B', B);
/*
A { name: 'junhee', age: 25, job: 'student' }
B { name: 'junhee', age: 25, job: 'student' }
*/
B = { ...A, job: 'frontend developer' };
console.log('A', A);
console.log('B', B);
/*
A { name: 'junhee', age: 25, job: 'student' }
B { name: 'junhee', age: 25, job: 'frontend developer' }
*/
๋ฆฌ๋์ ๋ด๋ถ์์ ๋ถ๋ณ์ฑ์ ์งํค๋ ์ด์ ๋? ์ ๊ฐ ์ฐ์ฐ์์ ๋จ์ ์ ํด๊ฒฐํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ธ๊ฐ
์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ ์ด ๋ค ๊ฐ์ง ๊ฒฝ์ฐ์ ์ ๋ฐ์ดํธํฉ๋๋ค.
- props๊ฐ ๋ฐ๋ ๋
- state๊ฐ ๋ฐ๋ ๋
- ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋
- this.forceUpdate๋ก ๊ฐ์ ๋ก ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํ ๋
๋ฆฌ๋์์ initial state์๋ ์๋ฒ์์ ๋๊ฒจ๋ฐ๋ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ์ ์ญ์ผ๋ก ํด๋น ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ ์ฅ์ ์ญํ ์ ํฉ๋๋ค.
๋ถ๋ณ์ฑ์ ์งํด์ผ๋ก์จ ๊ฐ๊ฐ์ ๊ณ ์ ํ ์ฐธ์กฐ๊ฐ์ ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํด์ ์ฌ์ฉํจ์ผ๋ก์จ ์ด๋ค ํจ์๊ฐ ํธ์ถ๋์ ๋ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ค๋ฉด ์๊ธธ ์ ์๋ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง๊ณผ ๋ถ์ํจ๊ณผ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
ํ์ง๋ง ...spread
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ๋ณต์ฌํด ์ฌ์ฉํ ๊ฒฝ์ฐ ๊ฐ์ฒด์ ๊น์ด์ ๋ฐ๋ผ, ๋ก์ง ๊ตฌ์ฑ์ด ๋งค์ฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค.
const nextState = {
...state,
posts: state.posts.map((post) =>
post.id === 1
? {
...post,
comments: post.comments.concat({
id: 3,
text: '์๋ก์ด ๋๊ธ',
}),
}
: post
),
};
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ immer
๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
produce
, draft
๋ผ๋ ํค์๋๋ฅผ ์ฌ์ฉํด์ ๊ธฐ์กด์ ... spread
์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ ๋ถ๋ณ์ฑ์ ์ ์งํด์ฃผ๋ฉฐ ๋ถํ์ํ ๋ถ์ํจ๊ณผ(side effect)๋ฅผ ๋ง์์ค๋๋ค.
const nextState = produce(state, (draft) => {
const post = draft.posts.find((post) => post.id === 1);
post.comments.push({
id: 3,
text: '์ ์ ๋ง ์ฝ๋ค!',
});
});
๋ถ์ํจ๊ณผ ์๋ "์์ํจ์" ๋ง๋ณด๊ธฐ
๋ถ์ํจ๊ณผ๋ ํจ์๊ฐ ๋ง๋ค์ด์ง ๋ชฉ์ ๊ณผ๋ ๋ค๋ฅธ ํจ๊ณผ ๋๋ ๋ถ์์ฉ์ ๋๋ค.
๋ ์ฝ๊ฒ ๋งํ๋ฉด ํจ์์ ์์ํ ์ ์๋ ์ผ์ด ์๊ธธ ๊ฐ๋ฅ์ฑ์ด ์กด์ฌํ๋ค๋ฉด ์ด ํจ์๋ ๋ถ์ ํจ๊ณผ๋ฅผ ๊ฐ์ง ์ ์๋ ํจ์๊ฐ ๋ฉ๋๋ค.
/* ์ฝ๋ ์ฐธ์กฐ (https://maxkim-j.github.io/posts/js-pure-function) */
// http ์์ฒญ์ ๋ณด๋ด๋ ํจ์ : ์์ํจ์ ๋ ์ ์์
const getData = () => {
axios.get('http://data.url')
.then(...)
.catch(...)
}
// ์
๋ ฅ ๋ดํฌํ ํจ์ : ์์ํจ์ ๋ ์ ์์
const typeInput = () => {
const input = prompt("Message");
return input;
}
// ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ ๋ณ๊ฒฝํ๋ ํจ์ : ์์ํจ์ ๋ ์ ์์
const changeParams = (arr, elem) => {
arr.push(elem);
return arr;
}
ํจ์์ ์ํ์์ ๋ญ๊ฐ ์๊ธฐ์น ์์ ์ผ์ด ์๊ธธ ๊ฐ๋ฅ์ฑ์ด ์๋ ํจ์๋ ์์ํจ์๊ฐ ๋ ์ ์์ต๋๋ค. ๋น๋๊ธฐ ์์ฒญ์ ๋ณด๋ด๋ ํจ์๋ ์์ฒญ์ด ์คํจํ ๊ฐ๋ฅ์ฑ์ด ์์ต๋๋ค. ์ ๋ ฅ์ ํฌํจํ๋ ํจ์๋ ์ ๋ ฅ์ ๋ฐ๋ผ ์ถ๋ ฅ์ด ๋ฌ๋ผ์ง ๊ฐ๋ฅ์ฑ์ด ์๊ธฐ ๋๋ฌธ์ ์์ํจ์๊ฐ ๋ ์ ์์ฃ .
๋งค๊ฐ๋ณ์๋ก ๋ค์ด์จ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ๋ ํจ์ ์ญ์ ์์ํจ์๊ฐ ๋ ์ ์์ต๋๋ค. ๋ฐฐ์ด๊ณผ ๊ฐ์ ์ฐธ์กฐ ์๋ฃํ ๊ฐ์ฒด๋ฅผ ์ด๋ค ํจ์ ์์์ ์ง์ ๋ณ๊ฒฝํ๋ค๋ฉด, ๋์ค์ ์ด ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ๋ ๋ค๋ฅธ ํจ์์ ์์ ์ ์ํฅ์ ๋ฏธ์น ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ค์์ ์ข ๋ ์์ธํ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
๋ถ์ ํจ์๋ผ๋ ๋ง์ด ๋ถ์ ์ ์ธ ๋์์ค๋ฅผ ๋ดํฌํ๋ ๊ฒ๋ ๊ฐ์ง๋ง, ๋ง ๋์๊ฑด ์๋๋๋ค. ๋น๋๊ธฐ http ์์ฒญ์ฒ๋ผ ๋ถ์ํจ๊ณผ๊ฐ ํ์ํ ๊ฒฝ์ฐ๋ ์์ต๋๋ค.
ํจ์์ ๋งค๊ฐ๋ณ์๋ก ๋ค์ด์จ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ๋ ๊ฒ์ ํผํ๊ธฐ๋ง ํด๋, ์์ํจ์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค. ๋งค๊ฐ๋ณ์์ ๋ํ ์ง์ ์กฐ์์ ํผํ๋ ์ด์ ๋ ์ด ๋งค๊ฐ๋ณ์๊ฐ ๋ ์ด๋์ ์ฐ์ผ์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ๋๋ค.
/* ์ฝ๋ ์ฐธ์กฐ (https://maxkim-j.github.io/posts/js-pure-function) */
const num_arr = [1, 2, 3, 4, 5];
// ๋งค๊ฐ๋ณ์์ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ๋ ๋ถ์ํจ์
const addSixImpure = (arr) => {
// ๋งค๊ฐ๋ณ์์ ์ง์ 6 ์ถ๊ฐ
arr.push(6);
return arr;
};
// ๋งค๊ฐ๋ณ์๋ฅผ ๋ณต์ฌํ ๊ฐ์ ๋ณ๊ฒฝํ๋ ์์ํจ์
const addSixPure = (arr) => {
// ํผ์นจ ์ฐ์ฐ์๋ก ์๋ก์ด ๋ฐฐ์ด์ 6 ์ถ๊ฐ
newArr = [...arr, 6];
return newArr;
};
// ๋งค๊ฐ๋ณ์ arr์ 6์ด ์๋์ง ํ์ธํ๋ ํจ์
const hasSix = (arr) => {
if (arr.includes(6)) {
return true;
} else {
return false;
}
};
const new_arr = addSixImpure(num_arr);
console.log(hasSix(num_arr)); // true
addSixPure()
๊ณผ addSixInpure()
๋ ์ธ๋ป ๋ณด๋ฉด ๋ณ ์ฐจ์ด๊ฐ ์์ด ๋ณด์ด์ง๋ง, addSixInpure()
๋ ๋งค๊ฐ๋ณ์์ ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ๋ ๋ถ์ํจ์์ด๊ณ , addSixPure()
๋ ๋งค๊ฐ๋ณ์ ๊ฐ์ ๋ณต์ฌํด์ ๋ณ๊ฒฝํ๋ ์์ํจ์์
๋๋ค.
addSixInpure()
๋ num_arr์ ์ง์ ๋ฐ๊ฟจ๊ธฐ ๋๋ฌธ์ ํจ์๊ฐ ์คํ๋๋ฉด num_arr์ ๊ฐ์ด [1,2,3,4,5,6]
์ผ๋ก ์๊ตฌํ ๋ฐ๋๋๋ค. ๊ทธ๋์ hasSix()
ํจ์์ ๊ฒฐ๊ณผ๋ก๋ true
๋ฅผ ๋ฐํํ๊ฒ ๋์ฃ .
ํ์ง๋ง ๊ฐ๋ฐ์์ ์๋๊ฐ ๋ณ์ new_arr
์ addSix
ํจ์๋ฅผ ํธ์ถํ ์๋ก์ด ๋ฐฐ์ด์ ํ ๋นํ๊ณ ๋ ํ, ๊ฐ์ด [1,2,3,4,5]
์ธ num_arr
์ ๋ํด์ 6์ด ์๋์ง ํ๋จํ๊ณ ์ถ์๋ ๊ฑฐ์๋ค๋ฉด ์ฝ๋๋ ์๋๋๋ก ์คํ๋์ง ์์์ต๋๋ค. ์๋๋๋ก๋ผ๋ฉด false๊ฐ ๋์์ผ ํ๋๋ฐ, num_arr
์ด ์ด๋ฏธ ๋ณ๊ฒฝ๋์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ฐ๋ผ์ ์ด๋ฐ ๊ฒฝ์ฐ์๋ addSix
ํจ์๊ฐ num_arr
์ ์ง์ ๋ณ๊ฒฝํด์๋ ์๋ฉ๋๋ค. ๋์ ์ ์ด๋ฐ ์ฝ๋๊ฐ ํ์ํ์ฃ
const new_arr = addSixPure(num_arr);
console.log(hasSix(num_arr)); // false
addSixPure()
๋ num_arr์ ์ง์ ์กฐ์ํ์ง ์๊ธฐ ๋๋ฌธ์ num_arr
์ ์ฒ์ ํ ๋น๋์๋ ๊ฐ์ ๋ฐ๋์ง ์์ต๋๋ค. ๋ฐ๋ผ์ hasSix(num_arr)
์ ๊ฒฐ๊ณผ๋ false์
๋๋ค.
์ด ์์๋ ์์ํจ์๊ฐ ๋ง์์ง์๋ก ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์์ธกํ ์ ์์์ ์ ์ ์๊ฒ ํด์ค๋๋ค. addSixInpure()
๊ฐ 6์ num_arr์ ์ถ๊ฐํด๋ฒ๋ฆฐ ๋ถ์ํจ๊ณผ ๋๋ฌธ์ hasSix()
์ ๊ฒฐ๊ณผ๊ฐ ๋ถ์ ํํด์ก์ต๋๋ค. ์ ์ธ๋ ๋ณ์๋ค์ ์ง์ ์กฐ์ํ์ง ์์์๋ก ํจ์๋ค์ ๋ถ์ํจ๊ณผ ์์ด ๊ฐ๋ฐ์์ ์๋๋๋ก ์์ง์ผ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
React state๋ ์ง์ ์กฐ์์ ํผํ๋ ๋ฐฉ์์ผ๋ก ๋ถ์ํจ๊ณผ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.(state, props๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ฆฌ๋ ๋๋ง์ด ๋๊ธฐ ๋๋ฌธ์ ์๋์น ์๊ฒ ๋ถ์ํจ๊ณผ๋ฅผ ๊ฐ์ง ํจ์๋ค๋ก ์ธํด ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ด ์ฆ์์ง ์ ์๋ค) Redux์ reducer๋ ์์ํจ์์ฌ์ผ๋ง ํ๋๋ฐ, store๊ฐ์ ๋ณ๊ฒฝํ๋ ํจ์๊ฐ ๋ถ์ํจ๊ณผ๋ฅผ ๋๋ฐํ์ง ์์์ผ store ๋ด๋ถ์ ๊ฐ๋ค์ด ์์ ํ๊ฒ ๋ณดํธ๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ฒ๋ค๊ฐ ์์ํจ์๋ ๊ฐ์ ์ ๋ ฅ์ ๋ํด ํญ์ ๊ฐ์ ์ถ๋ ฅ์ ๋ณด์ฅํ๋, ํ ์คํธ ํ๊ธฐ๋ ์ฌ์์ง์ฃ . ํจ์ ํ๋ก๊ทธ๋๋ฐ์๋ ํต์ฌ์ ์ธ ๊ฐ๋ ์ผ๋ก ์ฐ์ธ๋ค๊ณ ํ๋๋ฐโฆ ํฌ์คํ ์ ํด๋ณด๋ฉฐ ๋๋๊ฑด๋ฐ ์ ๋ง ์์ง ๋๋ฌด ๋ง๋ณด๊ธฐ๋ง ํด๋ณธ ๊ฒ ๊ฐ๋ค์. ํ์ฉ์ ํด๋ณด๋ฉด์ ์์ํจ์๊ฐ ์ค์ง์ ์ผ๋ก ์ด๋ค ์ด์ ์ ๊ฐ์ ธ์ค๋์ง ํฌ์คํ ํด๋ณผ ์ ์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
๋ถ์ํจ๊ณผ๊ฐ ์๋ ๋ฐฐ์ด์ ํ๋กํ ํ์ ๋ฉ์๋
const arr = [1];
// push ๋ฉ์๋๋ ์๋ณธ ๋ฐฐ์ด(arr)์ ์ง์ ๋ณ๊ฒฝํ๋ค.
arr.push(2);
console.log(arr); // [1, 2]
// concat ๋ฉ์๋๋ ์๋ณธ ๋ฐฐ์ด(arr)์ ์ง์ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ก์ด ๋ฐฐ์ด์ ์์ฑํ์ฌ ๋ฐํํ๋ค.
const result = arr.concat(3);
console.log(arr); // [1, 2]
console.log(result); // [1, 2, 3]
/*
๋ถ์ํจ๊ณผ๊ฐ ์๋ ๋ฐฐ์ด์ ํ๋กํ ํ์
๋ฉ์๋
Array.isArray
Array.prototype.indexOf
Array.prototype.push (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.pop (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.unshift (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.shift (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.concat
Array.prototype.splice ๐ (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.slice
Array.prototype.join ๐ (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.reverse ๐ (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.fill ๐ (์๋ณธ ๋ฐฐ์ด์ ๋ณ๊ฒฝํ๋ค - ๋ถ์ํจ๊ณผ o)
Array.prototype.includes
*/
๋ผ์ดํ์ฌ์ดํด ๋ฉ์๋์ ์ข ๋ฅ๋ ์ด ์ํ ๊ฐ์ง์ ๋๋ค.
- will ์ ๋์ฌ๊ฐ ๋ถ์ ๋ฉ์๋๋ ์ด๋ค ์์ ์ ์๋ํ๊ธฐ ์ ์ ์คํ๋๋ ๋ฉ์๋์ ๋๋ค.
- Did ์ ๋์ฌ๊ฐ ๋ถ์ ๋ฉ์๋๋ ์ด๋ค ์์ ์ ์๋ํ ํ์ ์คํ๋๋ ๋ฉ์๋์ ๋๋ค.
์ด ๋ฉ์๋๋ค์ ์ฐ๋ฆฌ๊ฐ ์ปดํฌ๋ํธ ํด๋์ค์์ ๋ฎ์ด ์จ ์ ์ธํจ์ผ๋ก์จ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ผ์ดํ์ฌ์ดํด์ ์ด ์ธ ๊ฐ์ง, ์ฆ ๋ง์ดํธ, ์ ๋ฐ์ดํธ, ์ธ๋ง์ดํธ ์นดํ ๊ณ ๋ฆฌ๋ก ๋๋๋๋ค.
- ๋ง์ดํธ
-
DOM์ด ์์ฑ๋๊ณ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋๋ ๊ฒ์ ๋ง์ดํธ๋ผ๊ณ ํ๋ค.
-
componentDidMount : ์ปดํฌ๋ํธ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์์ ๋ํ๋ ํ ํธ์ถํ๋ ๋ฉ์๋์ด๋ค.
- ์ ๋ฐ์ดํธ
์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ ์ด ๋ค ๊ฐ์ง ๊ฒฝ์ฐ์ ์ ๋ฐ์ดํธํฉ๋๋ค.
-
Props๊ฐ ๋ฐ๋ ๋
-
state๊ฐ ๋ฐ๋ ๋
-
๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋
-
this.forceUpdate๋ก ๊ฐ์ ๋ก ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํ ๋
-
componentDidUpdate : ์ปดํฌ๋ํธ์ ์ ๋ฐ์ดํธ(๋ฆฌ๋ ๋๋ง) ์์ ์ด ๋๋ ํ ํธ์ถํ๋ ๋ฉ์๋์ ๋๋ค.
- ์ธ๋ง์ดํธ
-
๋ง์ดํธ์ ๋ฐ๋ ๊ณผ์ , ์ฆ ์ปดํฌ๋ํธ๋ฅผ DOM์์ ์ ๊ฑฐํ๋ ๊ฒ์ ๋งํ๋ค.
-
componentWillUnmount : ์ปดํฌ๋ํธ๊ฐ ์น ๋ธ๋ผ์ฐ์ ์ฌ์์ ์ฌ๋ผ์ง๊ธฐ ์ ์ ํธ์ถํ๋ ๋ฉ์๋์ด๋ค.
Hooks๋ ๋ฆฌ์กํธ ๋ฒ์ 16.8์ ์๋ก ๋์ ๋ ๊ธฐ๋ฅ์ผ๋ก ํจ์ ์ปดํฌ๋ํธ์์๋ ์ํ ๊ด๋ฆฌ๋ฅผ ํ ์ ์๋ useState ๋ ๋๋ง ์งํ ์์ ์ ์ค์ ํ๋ useEffect ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ๊ธฐ์กด์ ํจ์ ์ปดํฌ๋ํธ์์ ํ ์ ์์๋ ๋ค์ํ ์์ ์ ํ ์ ์๊ฒ ํด์ค๋ค
- useState
- ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ Hook์ด๋ค. ์ฒซ ๋ฒ์งธ ์์๋ ์ํ ๊ฐ, ๋ ๋ฒ์งธ ์์๋ ์ํ๋ฅผ ์ค์ ํ๋ ํจ์์ด๋ค.
- ์ด ํจ์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฃ์ด์ ํธ์ถํ๋ฉด ์ ๋ฌ๋ฐ์ ํ๋ผ๋ฏธํฐ๋ก ๊ฐ์ด ๋ฐ๋๊ณ ์ปดํฌ๋ํธ๊ฐ ์ ์์ ์ผ๋ก ๋ฆฌ๋ ๋๋ง ๋ฉ๋๋ค
import { useState } from 'react';
const [value, setValue] = useState(0);
const MyReact = (function () {
const global = {};
let index = 0;
function useState(initialState) {
if (!global.states) {
// ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒด์ states ๋ฐฐ์ด์ ์ด๊ธฐํํ๋ค.
// ์ต์ด ์ ๊ทผ์ด๋ผ๋ฉด ๋น ๋ฐฐ์ด๋ก ์ด๊ธฐํํ๋ค.
global.states = [];
}
// states ์ ๋ณด๋ฅผ ์กฐํํด์ ํ์ฌ ์ํ๊ฐ์ด ์๋์ง ํ์ธํ๊ณ ์๋ค๋ฉด ์ด๊น๊ฐ์ผ๋ก ์ค์ ํ๋ค.
const currentState = global.states[index] || initialState;
// states์ ๊ฐ์ ์์์ ์กฐํํ ํ์ฌ ๊ฐ์ผ๋ก ์
๋ฐ์ดํธํ๋ค.
global.states[index] = currentState;
// ์ฆ์ ์คํ ํจ์๋ก setter๋ฅผ ๋ง๋ ๋ค.
const setState = (function () {
// ํ์ฌ index๋ฅผ ํด๋ก์ ๋ก ๊ฐ๋ฌ๋์ ์ดํ์๋ ๊ณ์ํด์ ๋์ธํ index์ ์ ๊ทผํ ์ ์๋๋ก ํ๋ค.
let currentIndex = index;
return function (value) {
global.states[currentIndex] = value;
// ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ค. ์ค์ ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ ์ฝ๋๋ ์๋ตํ๋ค.
};
})();
/**
* useState๋ฅผ ์ธ ๋๋ง๋ค index๋ฅผ ํ๋์ฉ ์ถ๊ฐํ๋ค. ์ด index๋ setState์์ ์ฌ์ฉ๋๋ค.
* ์ฆ, ํ๋์ state๋ง๋ค index๊ฐ ํ ๋น๋ผ ์์ด ๊ทธ index๊ฐ ๋ฐฐ์ด์ ๊ฐ(global.states)์ ๊ฐ๋ฆฌํค๊ณ ํ์ํ ๋๋ง๋ค ๊ทธ ๊ฐ์ ๊ฐ์ ธ์ค๊ฒ ํ๋ค.
**/
index = index + 1;
return [currentState, setState];
}
function Component() {
const [value, setValue] = useState(0);
//...
return <div>{value}</div>;
}
})();
- useEffect
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋๋ง๋ค ํน์ ์์ ์ ์ํํ๋๋ก ์ค์ ํ ์ ์๋ Hook ์ ๋๋ค. ํด๋์คํ ์ปดํฌ๋ํธ์ componontDidMount์ componentDidUpdate๋ฅผ ํฉ์น ํํ๋ก ๋ณด์๋ ๋ฌด๋ฐฉํฉ๋๋ค
๋ง์ดํธ๋ง ์คํ์ํค๊ณ ์ถ์ ๊ฒฝ์ฐ
: ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ๋น์ด์๋ ๋ฐฐ์ด์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค
useEffect(() => {
console.log('๋ง์ดํธ๋ ๋๋ง ์คํ๋ฉ๋๋ค.');
}, []);
ํน์ ๊ฐ์ด ์
๋ฐ์ดํธ๋ ๋๋ง ์คํํ๊ณ ์ถ์ ๊ฒฝ์ฐ
: ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋๋ ๋ฐฐ์ด ์์ ๊ฒ์ฌํ๊ณ ์ถ์ ๊ฐ์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค
useEffect(() => {
console.log(name);
}, [name]);
๋ท ์ ๋ฆฌ ํ๊ธฐ
:
- ์ ๋ฆฌ : useEffect๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๋๋ง๋๊ณ ๋ ์งํ๋ง๋ค ์คํ๋๋ฉฐ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ ๋ฐฐ์ด์ ๋ฌด์์ ๋ฃ๋์ง์ ๋ฐ๋ผ ์คํ๋๋ ์กฐ๊ฑด์ด ๋ฌ๋ผ์ง๋๋ค
useEffect๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๋๋ง๋๊ณ ๋ ์งํ๋ง๋ค ์คํ๋๋ฉฐ, ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ ๋ฐฐ์ด์ ๋ฌด์์ ๋ฃ๋์ง์ ๋ฐ๋ผ ์คํ๋๋ ์กฐ๊ฑด์ด ๋ฌ๋ผ์ง๋๋ค.
์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋๊ธฐ ์ ์ด๋ ์ ๋ฐ์ดํธ๋๊ธฐ ์ง์ ์ ์ด๋ ํ ์์ ์ ์ํํ๊ณ ์ถ๋ค๋ฉด useEffect์์ ๋ท์ ๋ฆฌ(cleanup) ํจ์๋ฅผ ๋ฐํํด ์ฃผ์ด์ผ ํฉ๋๋ค.
์ธ๋ง์ดํธ ์์ ์์ ํ ์ฝ๋๋ฅผ ๋ฃ์ด์ค๋ค๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค.
useEffect(() => {
console.log("๋ ๋๋ง์ด ์๋ฃ๋์์ต๋๋ค!");
console.log("none clean up: ", { name, nickname });
return () => {
console.log("clean up!");
console.log("clean up name: ", { name });
};
}
- useReducer
- useReducer๋ useState๋ณด๋ค ๋ ๋ค์ํ ์ปดํฌ๋ํธ ์ํฉ์ ๋ฐ๋ผ ๋ค์ํ ์ํ๋ฅผ ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ ๋ฐ์ดํธํด ์ฃผ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ Hook์ ๋๋ค. ๋ฆฌ๋์๋ ํ์ฌ ์ํ, ๊ทธ๋ฆฌ๊ณ ์ ๋ฐ์ดํธ๋ฅผ ์ํด ํ์ํ ์ ๋ณด๋ฅผ ๋ด์ ์ก์ ๊ฐ์ ์ ๋ฌ๋ฐ์ ์๋ก์ด ์ํ์ ๋ฐํํ๋ ํจ์์ ๋๋ค. ๋ฆฌ๋์ ํจ์์์ ์๋ก์ด ์ํ๋ฅผ ๋ง๋ค ๋๋ ๋ฐ๋์ ๋ถ๋ณ์ฑ์ ์ง์ผ์ฃผ์ด์ผ ํฉ๋๋ค.
type State = {
count: number,
};
type Action = { type: 'up' | 'down' | 'reset', payload?: State };
function init(count: State): State {
return count;
}
const initialState: State = { count: 0 };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'up':
return { count: state.count + 1 };
case 'down':
return { count: state.count - 1 };
case 'reset':
return init(action.payload || { count: 0 });
default:
throw new Error(`Unexpected action type ${action.type}`);
}
}
export default function App() {
const [state, dispatcher] = useReducer(reducer, initialState, init);
function handleUpButtonClick() {
dispatcher({ type: 'up' });
}
function handleDownButtonClick() {
dispatcher({ type: 'down' });
}
function handleResetButtonClick() {
dispatcher({ type: 'reset', payload: { count: 1 } });
}
return (
<div>
<h1>{state.count}</h1>
<button onClick={handleDownButtonClick}>+</button>
<button onClick={handleDownButtonClick}>-</button>
<button onClick={handleResetButtonClick}>reset</button>
</div>
);
}
useReducer๋ฅผ ์ฌ์ฉํ๋ ๋ชจ์ต์ด ์ธ๋ป ๋ณด๋ฉด ๋ณต์กํด ๋ณด์ผ ์ ์์ง๋ง useReducer์ ๋ชฉ์ ์ ๊ฐ๋จํฉ๋๋ค. ๋ณต์กํ ํํ์ state๋ฅผ ์ฌ์ ์ ์ ์๋ dispatcher๋ก๋ง ์์ ํ ์ ์๊ฒ ๋ง๋ค์ด ์ค์ผ๋ก์จ state ๊ฐ์ ๋ํ ์ ๊ทผ์ ์ปดํฌ๋ํธ์์๋ง ๊ฐ๋ฅํ๊ฒ ํ๊ณ , ์ด๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์ธ ์ ์๋ ์ปดํฌ๋ํธ ๋ฐ์ ๋ ๋ค์, state์ ์ ๋ฐ์ดํธ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ํด ๋ dispatcher๋ก๋ง ์ ํํ๋ ๊ฒ์ด๋ค.
state์ ๊ฐ์ ๋ณ๊ฒฝํ๋ ์๋๋ฆฌ์ค๋ฅผ ์ ํ์ ์ผ๋ก ๋๊ณ ์ด์ ๋ํ ๋ณ๊ฒฝ์ ๋น ๋ฅด๊ฒ ํ์ธํ ์ ์๊ฒ๋ ํ๋ ๊ฒ์ด useReducer์ ๋ชฉ์ ์ด๋ค.
- useMemo
useMemo๋ฅผ ์ฌ์ฉํ๋ฉด ํจ์ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ๋ฐ์ํ๋ ์ฐ์ฐ์ ์ต์ ํํ ์ ์์ต๋๋ค. ๋จผ์ ๋ฆฌ์คํธ์ ์ซ์๋ฅผ ์ถ๊ฐํ๋ฉด ์ถ๊ฐ๋ ์ซ์๋ค์ ํ๊ท ์ ๋ณด์ฌ ์ฃผ๋ ํจ์ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํด ๋ด ์๋ค.
๊ทธ๋ฐ๋ฐ ์ซ์๋ฅผ ๋ฑ๋กํ ๋๋ฟ๋ง ์๋๋ผ ์ธํ ๋ด์ฉ์ด ์์ ๋ ๋๋ ์ฐ๋ฆฌ๊ฐ ๋ง๋ getAverage ํจ์๊ฐ ํธ์ถ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ธํ ๋ด์ฉ์ด ๋ฐ๋ ๋๋ ํ๊ท ๊ฐ์ ๋ค์ ๊ณ์ฐํ ํ์๊ฐ ์๋๋ฐ, ์ด๋ ๊ฒ ๋ ๋๋งํ ๋๋ง๋ค ๊ณ์ฐํ๋ ๊ฒ์ ๋ญ๋น๊ฒ ์ง์?
useMemo Hook์ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ์์ ์ ์ต์ ํํ ์ ์์ต๋๋ค. ๋ ๋๋งํ๋ ๊ณผ์ ์์ ํน์ ๊ฐ์ด ๋ฐ๋์์ ๋๋ง ์ฐ์ฐ์ ์คํํ๊ณ , ์ํ๋ ๊ฐ์ด ๋ฐ๋์ง ์์๋ค๋ฉด ์ด์ ์ ์ฐ์ฐํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ฌ์ฉํ๋ ๋ฐฉ์์ ๋๋ค.
์ฝ๋ ๋ณด๊ธฐ
import React, { useCallback, useMemo, useRef, useState } from 'react';
const getAverage = (numbers) => {
console.log('ํ๊ท ๊ฐ ๊ณ์ฐ ์ค..');
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const inputEl = useRef();
const onChange = useCallback((e) => {
setNumber(e.target.value);
}, []); // ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋ ๋๋ง ํจ์ ์์ฑ
const onInsert = useCallback(
(e) => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
inputEl.current.focus();
},
[number, list] // number ํน์ list๊ฐ ๋ฐ๋์์ ๋๋ง ํจ์ ์์ฑ
);
const avg = useMemo(() => getAverage(list), [list]);
return (
<div>
<input value={number} onChange={onChange} ref={inputEl} />
<button onClick={onInsert}>๋ฑ๋ก</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>ํ๊ท ๊ฐ:</b> {avg}
</div>
</div>
);
};
export default Average;
- useCallback
- useMemo์ ์๋นํ ๋น์ทํ ํจ์์ด๋ค. ์ฃผ๋ก ๋ ๋๋ง ์ฑ๋ฅ์ ์ต์ ํ ํด์ผํ๋ ์ํฉ์์ ์ฌ์ฉํ๋ค. ์ด Hook์ ์ฌ์ฉํ๋ฉด ๋ง๋ค์ด๋จ๋ ํจ์๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋ค. useCallback์ ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์๋ ์์ฑํ๊ณ ์ถ์ ํจ์๋ฅผ ๋ฃ๊ณ , ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์๋ ๋ฐฐ์ด์ ๋ฃ์ผ๋ฉด ๋๋ค. ์ด ๋ฐฐ์ด์๋ ์ด๋ค ๊ฐ์ด ๋ฐ๋์์ ๋ ํจ์๋ฅผ ์๋ก ์์ฑํด์ผ ํ๋์ง ๋ช ์ํด์ผ ํ๋ค.
const onChange = useCallback((e) => {
setNumber(e.target.value);
}, []); // ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋ ๋๋ง ํจ์ ์์ฑ
const onInsert = useCallback(
(e) => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
},
[number, list] // number ํน์ list๊ฐ ๋ฐ๋์์ ๋๋ง ํจ์ ์์ฑ
);
useMemo(() => {
const fn = () => {
console.log(โhello world!โ);
};
return fn;
}, [])
onChange์ฒ๋ผ ๋น์ด ์๋ ๋ฐฐ์ด์ ๋ฃ๊ฒ ๋๋ฉด ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋ ๋จ ํ ๋ฒ๋ง ํจ์๊ฐ ์์ฑ๋๋ฉฐ, onInsert์ฒ๋ผ ๋ฐฐ์ด ์์ number์ list๋ฅผ ๋ฃ๊ฒ ๋๋ฉด ์ธํ ๋ด์ฉ์ด ๋ฐ๋๊ฑฐ๋ ์๋ก์ด ํญ๋ชฉ์ด ์ถ๊ฐ๋ ๋๋ง๋ค ํจ์๊ฐ ์์ฑ๋ฉ๋๋ค.
ํจ์ ๋ด๋ถ์์ ์ํ ๊ฐ์ ์์กดํด์ผ ํ ๋๋ ๊ทธ ๊ฐ์ ๋ฐ๋์ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ ์์ ํฌํจ์์ผ ์ฃผ์ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด onChange์ ๊ฒฝ์ฐ ๊ธฐ์กด์ ๊ฐ์ ์กฐํํ์ง ์๊ณ ๋ฐ๋ก ์ค์ ๋ง ํ๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด์ด ๋น์ด ์์ด๋ ์๊ด์์ง๋ง, onInsert๋ ๊ธฐ์กด์ number์ list๋ฅผ ์กฐํํด์ nextList๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด ์์ number์ list๋ฅผ ๊ผญ ๋ฃ์ด ์ฃผ์ด์ผ ํฉ๋๋ค.
์ฐธ๊ณ ๋ก ๋ค์ ๋ ์ฝ๋๋ ์์ ํ ๋๊ฐ์ ์ฝ๋์ ๋๋ค.
useCallback(() => {
console.log('hello world!');
}, []);
useMemo(() => {
const fn = () => {
console.log('hello world!');
};
return fn;
}, []);
- useRef
- ๋ฐ๋๋ผ ์๋ฐ์คํฌ๋ฆฝํธ์์ DOM ์์๋ฅผ ์กฐ์ํ๊ธฐ ์ํด querySelector๋ getElementById ๋ฑ์ ์ฌ์ฉํ๋ค๋ฉด, ๋ฆฌ์กํธ์์๋ useRef ํ ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- useRef๋
.current
ํ๋กํผํฐ์ ๋ณ๊ฒฝ๊ฐ๋ฅํ ๊ฐ์ ๋ด๊ณ ์๋ ๊ฐ์ฒด์ ๋๋ค .current
ํ๋กํผํฐ๋ฅผ ๋ณ๊ฒฝํ๋๋ผ๋ ๋ฆฌ๋ ๋๋ง์ ์ ๋ฐํ์ง ์์ต๋๋ค. ref ๊ฐ์ฒด ์์ ๊ฐ์ ๋ฆฌ์กํธ ์๋ช ์ฃผ๊ธฐ์ ๋ ๋ฆฝ์ ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค
import React, { useRef, Component } from 'react';
class RefSample extends Component {
input = useRef();
handleFocus = () => {
this.input.current.focus();
};
render() {
return (
<div>
<input ref={input} />
</div>
);
}
}
export default RefSample;
- useMemo ํจ์๋ ๋ฉ๋ชจ์ด์ ์ด์
๋
๊ฐ
์ ๋ฐํํ๋ค - useCallback ํจ์๋ ๋ฉ๋ชจ์ด์ ์ด์
๋
ํจ์
๋ฅผ ๋ฐํํ๋ค
Memoization(๋ฉ๋ชจ์ด์ ์ด์
)
ํ๋ก๊ทธ๋จ ์คํ ์ ์ด์ ์ ๊ณ์ฐํ ๊ฐ์ ์ ์ฅํ๋ค
์ํ๋ ๊ฐ์ด ๋ฐ๋์ง ์์๋ค๋ฉด ์ด์ ์ ์ฐ์ฐํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ค์ ์ฌ์ฉํ๋ ๋ฐฉ์์
๋๋ค.
๋ฆฌ์กํธ์์ ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ์ ๋ฆฌ๋ ๋๋ง๋ฉ๋๋ค
- props๊ฐ ๋ฐ๋ ๋
- state๊ฐ ๋ฐ๋ ๋
- ๋ถ๋ชจ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋
์ปดํฌ๋ํธ๋ state์ ๋ถ๋ชจ๋ก๋ถํฐ ์ ๋ฌ๋ฐ์ props ๋ฑ ๋ค์ํ ์กฐ๊ฑด์ ์ํด ์ฝ๊ฒ ๋ฆฌ๋ ๋๋ง์ด ๋ ์ ์์ต๋๋ค.
๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ด๊ฐ ๋ง๋ ์๋น์ค์ ์ฑ๋ฅ ์ ํ์ ๊ฐ์ฅ ํฐ ์์ธ์ด ๋๊ธฐ๋ ํฉ๋๋ค.
์ด๋ ๊ฒ ํน์ ์ํฉ (๊ฐ, ๋๋ ํจ์๊ฐ ๋ณ๊ฒฝ๋ ๋)์ ๋ง๊ฒ ๋ฆฌ๋ ๋๋ง์ด ๋ ์ ์๋๋ก useMemo์ useCallback ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์์กด์ฑ ๋ฐฐ์ด๋ก ์ด๋ค ๊ฐ์ ์ํด ๋ฐ๋๋ ์ง ํ์ธํ๊ธฐ ์ํด์๋ ํด๋น ํจ์์ ๋ ๋ฒ์งธ ์ฝ๋ฐฑ์ธ []
๋ฐฐ์ด ๋ด๋ถ์ ๊ฐ์ ๋ณด๋ฉด ๋ฉ๋๋ค.
// useMemo
const avg = useMemo(() => getAverage(list), [list]); // list ๋ผ๋ ๊ฐ์ด ๋ณ๊ฒฐ๋ ๋'๋ง' getAverage ํจ์๋ฅผ ์ฌ ํธ์ถํ๋ ์ฉ๋์
๋๋ค
// useCallback
const onInsert = useCallback(
(e) => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
},
[number, list] // number ํน์ list๊ฐ ๋ฐ๋์์ ๋๋ง onInsert ํจ์ ์์ฑ
);
// useMemo
<div>
<b>ํ๊ท ๊ฐ:</b> {avg}
</div>
// useCallback
<button onClick={onInsert}>๋ฑ๋ก</button>
useCallback์ ์ฌ์ฉํ ๋์ ์ฌ์ฉํ์ง ์๊ณ ํจ์๋ฅผ ์ ์ธํ ๋๋ ์ด๋ค ์ฐจ์ด๊ฐ ์๋์?
useCallback ํ ํจ์๋ ์ฐ๋ฆฌ๊ฐ ๋ฉ๋ชจ์ด์ ์ด์ ์ ํ ์ ์๋๋ก ํ์ฉํ๋ ๋ฆฌ์กํธ์ ํ ์ ๋๋ค. ์ฆ, ์ข ์์ฑ ์ค ํ๋๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ํจ์๊ฐ ๋ค์ ์์ฑ๋ฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ๊ตฌ์ฑ ์์๊ฐ ์์ฃผ ๋ ๋๋ง๋๊ณ ํด๋น ๊ธฐ๋ฅ์ ์ฌ์์ฑํ๋ ๋ฐ ๋น์ฉ์ด ๋ง์ด ๋๋ ์ํฉ์์ ์ฑ๋ฅ ์ต์ ํ์ ์ ์ฉํ ์ ์์ต๋๋ค.
์ด์ ๋ฐ๋๋ก useCallback์ ์ฌ์ฉํ์ง ์๊ณ ํจ์๋ฅผ ์ ์ธํ๋ ๊ฒฝ์ฐ ๋งค ๋ ๋๋ง๋ง๋ค ํจ์๋ฅผ ์๋กญ๊ฒ ์ ์ธํฉ๋๋ค.
ํจ์ ์ด๊ธฐํ(์ ์ธ, initialize) ๊ธฐ๋ฅ๊ณผ ํจ๊ป 'useCallback' ํ ํจ์๋ฅผ ์ฌ์ฉํ ์ง ์ฌ๋ถ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํน์ ์๊ตฌ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
๊ธฐ๋ฅ์ด ๋น๊ต์ ๊ฐ๋จํ๊ณ ์ฌํ ๋น์ฉ์ด ๋ง์ด ๋ค์ง ์๋๋ค๋ฉด 'useCallback'์ ์ฌ์ฉํ ํ์๊ฐ ์์ ์๋ ์๋ค.
๊ทธ๋ฌ๋ ํจ์๋ฅผ ๋ค์ ๋ง๋๋ ๊ฒ์ด ๋ ๋ณต์กํ๊ฑฐ๋ ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ฒฝ์ฐ์๋ ์ด ํจ์์ ํจ๊ป 'useCallback'์ ์ฌ์ฉํ๋ฉด ์์ฉ ํ๋ก๊ทธ๋จ์ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
useRef๋ ๊ตฌ์ฑ์์๊ฐ ๋ณ๊ฒฝ๋ ๋ ์ฌ๋ ๋๋ฅผ ํธ๋ฆฌ๊ฑฐํ์ง ์์์ผ ํ๋ ๊ฐ์ ์ ์ฅํด์ผ ํ ๋ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
์๋ฅผ ๋ค์ด DOM ๋ ธ๋์ ๋ํ ์ฐธ์กฐ ๋๋ ์์ฃผ ์ ๋ฐ์ดํธ๋์ง๋ง ๊ตฌ์ฑ ์์์ ๋ชจ์์๋ ์ํฅ์ ๋ฏธ์น์ง ์๋ ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์ด ํฌํจ๋ฉ๋๋ค.
๋ฐ๋ฉด, useState๋ ๊ตฌ์ฑ ์์๊ฐ ๋ณ๊ฒฝ๋ ๋ ๋ค์ ๋ ๋๋ง์ ํธ๋ฆฌ๊ฑฐํด์ผ ํ๋ ๊ฐ์ ์ ์ฅํด์ผ ํ ๋ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
ํ๋ฉด์ ์ผ๋ถ ๋ด์ฉ์ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๊ฐ์ด๋ ์์ ์ ๋ ฅ์ ํ์ฌ ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์ด ์์ ๋๋ค.
๋ฐ๋ผ์ ํ๋ฉด์ ์ผ๋ถ ๋ด์ฉ์ ํ์ํ์ง ์๋ ๊ฒฝ์ฐ, ๋ ๋๋ง์ ์ํฅ์ ๋ฐ์ง ์์๋ ๋๋ ๊ฒฝ์ฐ์ useRef๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ฆฌ๋ ๋๋ง์ ์กฐ๊ธ ๋ ํจ์จ์ ์ผ๋ก ํธ๋ค๋งํ ์ ์์ต๋๋ค.
function Example() {
const [count, setCount] = React.useState(0);
useEffect(()=>{
console.log('in useEffect:', count)
},[count])
const onClickButton = () => {
console.log("before", count);
setCount(count + 1);
// setCount(prev => prev+1);
console.log("after", count);
};
return <button onClick={onClickButton}>{count}</button>;
}
>>>
/*
before 0
after 0
in useEffect 1
*/
state ๊ฐ์ ๊ฐฑ์ ํ๋ ํจ์์ธ setState
๋ ๋น๋๊ธฐ๋ก ๋์ํ๋ ํ
ํจ์์
๋๋ค
React๋ ์์ ์ธ๊ธํ๋ฏ state, props ๊ฐ์ ๋ฐ๋ผ re-rendering์ด ์ผ์ด๋์ฃ .
๊ทธ๋ฐ๋ฐ ๋ง์ฝ์ ํ ์ปดํฌ๋ํธ ์์์ ์ฌ๋ฌ state ๊ฐ์ ์ฐ์์ผ๋ก ๋ฐ๊ฟ์ฃผ๋ ์ผ์ด ์๊ธด๋ค๋ฉด ์ฌ๋ฌ๋ฒ ๋น๊ตํ๊ณ ๋ค์ ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์คํ๋ฉ๋๋ค.
๋๋ฌด ๋นํจ์จ์ ์ด๊ณ ์ฑ๋ฅ์ด ๋น์ฐํ ์์ข์ ๊ฒ ์ ๋๋ค. ๋ ์ด์ค์ ๋ฐ๋์ง ์์๋ ๋๋ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง ๋ค์ ๋ฐ์ํ ๊ฒ์ผ๋ก๋ ์์์ด ๋ฉ๋๋ค
์ด์ ๋๋นํ์ฌ ๋ฆฌ์กํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ state๋ฅผ ๋ค์ ์ค์ ํ๋ ํจ์์ธ setState๋ฅผ ๋น๋๊ธฐ ํจ์๋ก ์ฒ๋ฆฌํด์ ์ปดํฌ๋ํธ ๋ด์ ๋น๋๊ธฐ ํจ์๋ฅผ ์ฒ๋ฆฌํ๋ ์ฝ๋ฐฑํ๊ฐ ๋ค ๋น์์ง๋ฉด ๋ฆฌ๋ ๋๋งํ๋๋ก ์ค๊ณํ์ต๋๋ค.
๊ทธ ๋ง์ธ ์ฆ, ํด๋น ํจ์ ๋ด์์ ๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ํจ์๊ฐ ๋ชจ๋ ์คํ๋ ๋ค์ ๋ง์ง๋ง์ setState๋ฅผ ์ฒ๋ฆฌํ๋ค๋ ์ด์ผ๊ธฐ๊ฒ ์ฃ ?
const onClickButton = () => {
console.log('before', count); // ----> ๋๊ธฐํจ์
setCount(count + 1); // ----> ๋น๋๊ธฐํจ์
console.log('after', count); // ----> ๋๊ธฐํจ์
};
์์ ๋งํ์ง๋ง, setState๊ฐ ๋น๋๊ธฐ ๋์์ ์ทจํจ์ผ๋ก์จ ์๋ฐ์คํฌ๋ฆฝํธ ๋ด์ ์คํ์ปจํ ์คํธ ์คํ์ด ๋์๊ฐ ๋ ๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ ํจ์๋ค์ ๋ชจ๋ ๋์ํ ๋ค์ ํ์ ์กด์ฌํ๋ ๋น๋๊ธฐ์ ์ธ ํจ์๋ค์ ์ด๋ฒคํธ ๋ฃจํ์ ์ํด ๊บผ๋ด์์ ์คํ์ํต๋๋ค.
setState๊ฐ ๋๊ธฐ์ ์ผ๋ก ์คํ๋๋ค๋ฉด, ํ ์ปดํฌ๋ํธ ๋ด๋ถ์ ์กด์ฌํ๋ ํจ์์ ์ํด state ๊ฐ์ด ์ฐ์์ ์ผ๋ก ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ ๋ฆฌ์กํธ์ ์ปดํฌ๋ํธ ๋ฆฌ๋ ๋๋ง ์กฐ๊ฑด์ ์ํด ์ง์์ ์ผ๋ก ๋ฆฌ๋ ๋๋ง์ด ๋ ๊ฒ์ ๋๋ค.
๋ฆฌ์กํธ ํ ํจ์๋ฅผ ๋ฐํ์ผ๋ก ํ ์๋ช ์ฃผ๊ธฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
๋ธ๋ผ์ฐ์ ๊ฐ ๋ ๋๋ง๋ ๋ .js
ํ์ผ์ ๋ธ๋ผ์ฐ์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ ์์ง์ผ๋ก ๊ถํ์ ๋๊ฒจ .js
ํด๋น ํ์ผ์ ํ์ฑ๋๊ณ ๊ทธ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
์ ๊ทธ๋ฆผ์ ํ
๋ผ์ดํ ์ฌ์ดํด์ ๋ณด์๋ค์ํผ ๋ธ๋ผ์ฐ์ ๊ฐ ์คํฌ๋ฆฐ์ ํ์ธํ
์์
์ด ์๋ฃ๋ ์ดํ์ ์ฐ๋ฆฌ๋ useEffect
๋ฅผ ์คํํ๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ก์์ต๋๋ค.
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด ๋ ๋๋งํ ๋ useState(0)
๊ณผ ๊ฐ์ ์ด๊ธฐ useState์ ๊ฐ์ด ๋น ๊ฐ์ด๋ผ๋ฉด, 0์ ์ถ๋ ฅํ๋ค๊ฐ useEffect๋ฅผ ํตํด ๊ฐ์ด ์ฑ์์ง๋ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ก์์ต๋๋ค.
// ์ฝ๋ ์ฐธ๊ณ : https://merrily-code.tistory.com/46
import { useEffect, useState } from 'react';
function App() {
const [age, setAge] = useState(0);
const [name, setName] = useState('');
useEffect(() => {
setAge(25);
setName('์ฐฌ๋ฏผ');
}, []);
return (
<>
<div className='App'>{`๊ทธ์ ์ด๋ฆ์ ${name} ์ด๋ฉฐ, ๋์ด๋ ${age}์ด ์
๋๋ค.`}</div>
</>
);
}
export default App;
useLayoutEffect ํ ์ ๋ฐ๋ก ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ํ ์ ๋๋ค.
useLayoutEffect
๋ ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋ฉด์ DOM์ ๊ทธ๋ฆฌ๊ธฐ ์ ์ ์ดํํธ๋ฅผ ์ํํฉ๋๋ค .
๋ฐ๋ผ์ ์ ์ฝ๋์ ์คํ ์์๋ ๋ฌ๋ผ์ง๊ฒ ๋ฉ๋๋ค.
-
๋ ์ด์์ ์ดํํธ ๋ด๋ถ์ setNumber, setName ํธ์ถ
-
<div>๊ทธ์ ์ด๋ฆ์ ์ฐฌ๋ฏผ์ด๋ฉฐ, ๋์ด๋ 25์ด ์ ๋๋ค.</div>
๋ฅผ ํ์ธํธ
// ์ฝ๋ ์ฐธ๊ณ : https://merrily-code.tistory.com/46
import { useLayoutEffect, useState } from 'react';
function App() {
const [age, setAge] = useState(0);
const [name, setName] = useState('');
useLayoutEffect(() => {
setAge(25);
setName('์ฐฌ๋ฏผ');
}, []);
return (
<>
<div className='App'>{`๊ทธ์ ์ด๋ฆ์ ${name} ์ด๋ฉฐ, ๋์ด๋ ${age}์ด ์
๋๋ค.`}</div>
</>
);
}
export default App;
์ ๊ฐ ์ฌ์ฉํด ๋ณธ ์ฑ๋ฅ ๊ฐ์ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- hook ํจ์ ์ฌ์ฉ (useMemo, useCallback)
- ์ฝ๋ ์คํ๋ฆฌํ (react.lazy(), Next.js ํ๋ ์์ํฌ ์ฌ์ฉ ๋ฑ)
์ด๋ฒคํธ๋ก ์ค์ ํ ํจ์๋ฅผ ํธ์ถํ๋ ๊ฒ์ด ์๋ ์ง์ ๋ฃ์ด ์ค ๋๋ ํ์ดํ ํจ์ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ๋ฃ์ด ์ฃผ์ด์ผ ํฉ๋๋ค
case 1: ์๋ํ์ง ์๋ ๋ฌธ๋ฒ
<button onClick={this.setState({ number: number + 1})}> (x)
case 2: ์๋ํ๋ ๋ฌธ๋ฒ
<button onClick={()=> this.setState({ number: number + 1}; )}> (o)
or
case 3: ์์ ํจ์๋ก ๋นผ์ฃผ๊ณ ํด๋น ํจ์๋ฅผ ๋ถ๋ฌ ์ฌ์ฉํ๋ค.
const plusNum = (number) => {
setState(number : number + 1);
}
...
<button onClick={plusNum}>+ 1 </button>
SPA๋ Single Page Application(์ฑ๊ธ ํ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ )์ ์ฝ์ด์ ๋๋ค. ๋ง ๊ทธ๋๋ก ํ ๊ฐ์ ํ์ด์ง๋ก ์ด๋ฃจ์ด์ง ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ผ๋ ์๋ฏธ์ ๋๋ค. ์ ํต์ ์ธ ์น ํ์ด์ง๋ ๋ค์๊ณผ ๊ฐ์ด ์ฌ๋ฌ ํ์ด์ง๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
๊ธฐ์กด์๋ ์ฌ์ฉ์๊ฐ ๋ค๋ฅธ ํ์ด์ง๋ก ์ด๋ํ ๋๋ง๋ค ์๋ก์ด html์ ๋ฐ์ ์ค๊ณ , ํ์ด์ง๋ฅผ ๋ก๋ฉํ ๋๋ง๋ค ์๋ฒ์์ ๋ฆฌ์์ค๋ฅผ ์ ๋ฌ๋ฐ์ ํด์ํ ๋ค ํ๋ฉด์ ๋ณด์ฌ ์ฃผ์์ต๋๋ค. ์ด๋ ๊ฒ ์ฌ์ฉ์์๊ฒ ๋ณด์ด๋ ํ๋ฉด์ ์๋ฒ ์ธก์์ ์ค๋นํ์ต๋๋ค. ์ฌ์ ์ html ํ์ผ์ ๋ง๋ค์ด์ ์ ๊ณตํ๊ฑฐ๋, ๋ฐ์ดํฐ์ ๋ฐ๋ผ ์ ๋์ ์ธ html์ ์์ฑํด์ฃผ๋ ํ ํ๋ฆฟ ์์ง์ ์ฌ์ฉํ๊ธฐ๋ ํ์ฃ .
์์ฆ์๋ ์น์์ ์ ๊ณต๋๋ ์ ๋ณด๊ฐ ์ ๋ง ๋ง๊ธฐ ๋๋ฌธ์ ์๋ก์ด ํ๋ฉด์ ๋ณด์ฌ ์ฃผ์ด์ผ ํ ๋๋ง๋ค ์๋ฒ ์ธก์์ ๋ชจ๋ ๋ทฐ๋ฅผ ์ค๋นํ๋ค๋ฉด ์ฑ๋ฅ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ํธ๋ํฝ์ด ๋๋ฌด ๋ง์ด ๋์ฌ ์๋ ์๊ณ , ์ฌ์ฉ์๊ฐ ๋ชฐ๋ ค ์๋ฒ์ ๋์ ๋ถํ๊ฐ ์ฝ๊ฒ ๊ฑธ๋ฆด ์๋ ์์ต๋๋ค. ๊ทธ๋์ ๋ฆฌ์กํธ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํน์ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ทฐ(View) ๋ ๋๋ง์ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ด๋นํ๋๋ก ํ๊ณ , ์ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ธ๋ผ์ฐ์ ์ ๋ถ๋ฌ์์ ์คํ์ํจ ํ์ ์ฌ์ฉ์์์ ์ธํฐ๋์ ์ด ๋ฐ์ํ๋ฉด ํ์ํ ๋ถ๋ถ๋ง ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ฐ์ดํธํด ์ค๋๋ค. ๋ง์ฝ ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ํ์ํ๋ค๋ฉด ์๋ฒ API๋ฅผ ํธ์ถํ์ฌ ํ์ํ ๋ฐ์ดํฐ๋ง ์๋ก ๋ถ๋ฌ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
์ฌ์ฉ์์์ ์ธํฐ๋ ์ ์ด ๋ฐ์ํ๋ฉด ํ์ํ ๋ถ๋ถ๋ง ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ฐ์ดํธ (JSON ํ์์ผ๋ก ์์ฒญํจ)
[์ถ์ฒ : https://babytiger.netlify.app/posts/SPA/]
์ฑ๊ธ ํ์ด์ง๋ผ๊ณ ํด์ ํ๋ฉด์ด ํ ์ข ๋ฅ์ธ ๊ฒ์ ์๋๋๋ค. SPA์ ๊ฒฝ์ฐ ์๋ฒ์์ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ๋ ํ์ด์ง๋ ํ ์ข ๋ฅ์ด์ง๋ง, ํด๋น ํ์ด์ง์์ ๋ก๋ฉ๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ฌ ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ์ ์ฃผ์ ์ํ์ ๋ฐ๋ผ ๋ค์ํ ํ๋ฉด์ ๋ณด์ฌ ์ค ์ ์์ต๋๋ค.
๋ค๋ฅธ ์ฃผ์์ ๋ค๋ฅธ ํ๋ฉด์ ๋ณด์ฌ ์ฃผ๋ ๊ฒ์ ๋ผ์ฐํ ์ด๋ผ๊ณ ํฉ๋๋ค. ๋ฆฌ์กํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฒด์ ์ด ๊ธฐ๋ฅ์ด ๋ด์ฅ๋์ด ์์ง ์๊ธฐ ๋๋ฌธ์, ๋ธ๋ผ์ฐ์ ์ API๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๊ด๋ฆฌํ๊ฑฐ๋, ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด ์์ ์ ๋์ฑ ์ฝ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
๋ฆฌ์กํธ ๋ผ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ฆฌ์กํธ ๋ผ์ฐํฐ(react-router), ๋ฆฌ์น ๋ผ์ฐํฐ(reach-router), Next.js ๋ฑ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ์ด๋ฌํ ๋ฆฌ์กํธ ๋ผ์ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์ด๋ฃจ์ด์ง๋ ๋ผ์ฐํ ์ ์์ฃผ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋๋ก ํด ์ค๋๋ค. ๋ ๋์๊ฐ ๋์ค์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง์ ํ ๋๋ ๋ผ์ฐํ ์ ๋์์ฃผ๋ ์ปดํฌ๋ํธ๋ค์ ์ ๊ณตํด ์ค๋๋ค.
SPA์ ๋จ์ ์ ์ฑ์ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ด ๋๋ฌด ์ปค์ง๋ค๋ ๊ฒ์ ๋๋ค. ํ์ด์ง ๋ก๋ฉ ์ ์ฌ์ฉ์๊ฐ ์ค์ ๋ก ๋ฐฉ๋ฌธํ์ง ์์ ์๋ ์๋ ํ์ด์ง์ ์คํฌ๋ฆฝํธ๋ ๋ถ๋ฌ์ค๊ธฐ ๋๋ฌธ์ด์ฃ . ํ์ง๋ง ํ์ ๋ฐฐ์ธ ์ฝ๋ ์คํ๋ฆฌํ (code splitting)์ ์ฌ์ฉํ๋ฉด ๋ผ์ฐํธ๋ณ๋ก ํ์ผ๋ค์ ๋๋์ด์ ํธ๋ํฝ๊ณผ ๋ก๋ฉ ์๋๋ฅผ ๊ฐ์ ํ ์ ์์ต๋๋ค.
๋ฆฌ์กํธ ๋ผ์ฐํฐ์ฒ๋ผ ๋ธ๋ผ์ฐ์ ์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ฐํ ์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ง ์๋ ์ผ๋ฐ ํฌ๋กค๋ฌ์์๋ ํ์ด์ง์ ์ ๋ณด๋ฅผ ์ ๋๋ก ์์งํด ๊ฐ์ง ๋ชปํ๋ค๋ ์ ์ฌ์ ์ธ ๋จ์ ์ด ๋ฐ๋ฆ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ตฌ๊ธ, ๋ค์ด๋ฒ, ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ์์ง์ ๊ฒ์ ๊ฒฐ๊ณผ์ ํ์ด์ง๊ฐ ์ ๋ํ๋์ง ์์ ์๋ ์์ต๋๋ค. ๋ํ, ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋ ๋๊น์ง ํ์ด์ง๊ฐ ๋น์ด ์๊ธฐ ๋๋ฌธ์ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ด ๋ก๋ฉ๋์ด ์คํ๋๋ ์งง์ ์๊ฐ ๋์ ํฐ ํ์ด์ง๊ฐ ๋ํ๋ ์ ์๋ค๋ ๋จ์ ๋ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ฐ ๋ฌธ์ ์ ๋ค์ ๋คํํ ๋์ค์ ๋ฐฐ์ฐ๊ฒ ๋ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(server-side-rendering)์ ํตํด ๋ชจ๋ ํด๊ฒฐํ ์ ์์ต๋๋ค.
๋ฆฌ์กํธ๋ ๋ํ์ ์ธ CSR(client side rendering)์ ๋๋ค. ์ด๋ฌํ ๋ฆฌ์กํธ์ CSR์ ์ธ ๋ถ๋ถ์์ SSR ์ ์ผ๋ก ๋ฐ๊ฟ ์ฃผ๊ธฐ ์ํด์ next.js์ ๊ฐ์ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
SSR์ ์ฌ์ฉํ๋ ๊ฐ์ฅ ํฐ ์ด์ ๋ ํจ์จ์ ์ธ SEO๋ฅผ ์ํด์ ์ ๋๋ค. ์๋ ๋ฌธ๋จ์์ ๋ค๋ฃจ๊ฒ ์ง๋ง, SEO๋ google, naver์ ๊ฐ์ ๊ฒ์ ์์ง๋ค์ด ์ฐ๋ฆฌ์ ์น์ฌ์ดํธ์์ html ํ๊ทธ์์ ๋ด์ฉ์(title, meta-data ๋ฑ๋ฑ,,,) ๋ถ์ํ์ฌ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์๋ง์(์ฌ์ฉ์๊ฐ ์ํ๋) ์ ๋ณด๋ฅผ ์ฐพ์ ์ ์๊ฒ ํ๋ ๊ธฐ๋ฅ์ ๋๋ค. ๋ฆฌ์กํธ๋ CSR์ผ๋ก ์๋๋๋๋ฐ, ์ฌ์ฉ์๊ฐ ์ฐ๋ฆฌ์ ํด๋น ๋๋ฉ์ธ์ ์ ์ํ๋ฉด, ํด๋ผ์ด์ธํธ ์๋ฒ(์ฌ์ฉ์์ ์ปดํจํฐ)๊ฐ html๊ณผ js ๋ฑ์ ํ์ผ์ ๋ค์ด๋ฐ์ ๋ณด์ฌ์ฃผ๋ ํ์์ ๋๋ค. CSR ์ํ์์๋ ์ฌ์ ์ html์ ๊ฐ์ง๊ณ ์์ง ์๊ธฐ ๋๋ฌธ์ ๊ฒ์ ์์ง์ ๋ ธ์ถ๋๋ ๋น๋๊ฐ ํ์ ํ ์ ๊ฑฐ๋, ๋ธ๋ผ์ฐ์ ์ ๋ฐ๋ผ ๊ฒ์ ์์ง์ ํด๋น ์ ๋ณด๊ฐ ๋ ธ์ถ๋์ง ์์ ๊ฒ์์ ํด๋ ๋์ค์ง ์์ ์ ์์ต๋๋ค.(๋๋ฉ์ธ์ ํตํด ์ ์ํ๋ ๊ฒ์ ๊ฐ๋ฅํด์ง๋ ์ ๋, ํด๋น ์ฌ์ดํธ์ ๊ด๋ จ๋ ์ ๋ณด๋ฅผ ๊ฒ์ ์์ง์ด ํฌ๋กค๋งํ์ง ๋ชปํ ์ ์์)๊ทธ๋์ SSR์ ํตํด ์๋ฒ๊ฐ ์ฌ์ ์ html๊ณผ ์ผ๋ถ js ํ์ผ์ ๋๊ฒจ์ฃผ๊ฒ ๋๋ฉด, ๊ฒ์ ์์ง์์ ์ด๋ฅผ ์บ์นํ์ฌ ์ฌ์ฉ์๊ฐ ์ํ๋ ์ ๋ณด๊ฐ ๋ด๊ธด ์ฐ๋ฆฌ ์ฌ์ดํธ๋ฅผ ๋ณด์ฌ์ค ์ ์์ ๊ฒ์ ๋๋ค.
SEO๋, Search Engine Optimization์ ์ฝ์๋ก, SEO๋ ๊ตฌ๊ธ, ๋ค์ด๋ฒ์ ๊ฐ์ ๊ฒ์ ์์ง๋ค์ด ์๋ฒ์ ๋ฑ๋ก๋ ์น์ฌ์ดํธ๋ฅผ ํ๋ํ๋์ฉ ๋์ ๋ค๋๋ฉด์ ์น์ฌ์ดํธ์ HTML ๋ฌธ์๋ฅผ ๋ถ์ํด์ค๋๋ค. ์ด๋ HTML์ ์ฌ์ฉ๋ ํ๊ทธ๋ฅผ ๋ฐํ์ผ๋ก ์ฌ์ฉ์๊ฐ ๊ฒ์ํ ๋, ์น์ฌ์ดํธ๋ฅผ ๋น ๋ฅด๊ฒ ๊ฒ์ํ ์ ์๊ฒ ๋์์ค๋๋ค. ํ์ง๋ง, CSR์์ ์ฌ์ฉ๋๊ณ ์๋ HTML์ body๋ ํ ํ ๋น์ด ์๋ค๊ฐ(div id="root"์ ๋ฆฌ์กํธ ํน์ฑ), ์ฌ์ฉ์๊ฐ ํด๋น ๋๋ฉ์ธ์ ๊ฐ์ง ํ์ด์ง์ ์ ๊ทผํ๋ฉด, ํด๋ผ์ด์ธํธ ์๋ฒ์์ js ๋ฐ html ํ๊ทธ๋ฅผ ๋ถ๋ฌ์ค๋ ํ์์ด๊ธฐ ๋๋ฌธ์ ์ฌ์ ์ html ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ง ์์ต๋๋ค. ๊ทธ๋์ ๊ฒ์ ์์ง์ด ํด๋น ๋๋ฉ์ธ์ ์ ๊ทผํ ๋ ์ด๋ ค์์ด ์์ต๋๋ค. (์ฐ๋ฆฌ ์ฌ์ดํธ๋ฅผ ๊ฒ์ ์์ง์ ํตํด ๋ค์ํ ํค์๋๋ฅผ ํตํด ์ ์ ๋๋ ๊ฒ์ด ํ๋ค๋ค why? ๊ฒ์ ์์ง์ด ์ฐ๋ฆฌ html ํ์ผ์ ๋ถ์ํ ์ ์๊ธฐ ๋๋ฌธ์ why? CSR ํ์์ ์ฌ์ฉ์๊ฐ ์ ๊ทผํด์ผ html, js ๋ฑ์ ํ์ผ์ ๋ถ๋ฌ์ค๊ธฐ ๋๋ฌธ์) ๋ฐ๋ผ์, ๊ฒ์ ์์ง์ ํตํด ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ์ฌ ์ป๊ณ ์ํ๋ ์ ๋ณด๋ฅผ ์ ๋ ฅํ์๋, ๊ฒ์ ์์ง์ด ์ฐ๋ฆฌ์ ์น ์ฌ์ดํธ์์ ํด๋น ๋ด์ฉ์ ์บ์นํ๋๋ฐ ์ด๋ ค์์ด ์์ต๋๋ค.
๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ SEO ์ฆ, ๊ฒ์ ์์ง ์ต์ ํ๋ฅผ ํด์ฃผ๊ธฐ ์ํด, SSR์ ์ฌ์ฉํ์ฌ ์ฌ์ ์ html ๋ฌธ์๋ฅผ ๊ฒ์ ์์ง์ด ์ฐพ์ ์ ์๋๋ก ์ ๊ณตํ์ฌ SEO๋ฅผ ํฅ์์ํฌ ์ ์๊ฒ ๋ฉ๋๋ค. SSR์ ์๋ฒ์์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์ฌ์ ์ html ํ์ผ์ ๋ง๋ค๊ฒ ๋๊ณ ์ด๋ ๊ฒ ๋ง๋ค์ด์ง HTML ํ์ผ์ ์ผ๋ถ ์ด๊ธฐ ์ธํ ์ ํ์ํ js์ ํจ๊ป ํด๋ผ์ด์ธํธ ์๋ฒ์ ๋ณด๋ด์ฃผ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ํด๋ผ์ด์ธํธ ์ธก์์๋ ์๋ฒ์์ ๋ง๋ค์ด์ค ๋ฌธ์๋ฅผ ๋ฐ์ ์์ ๋ฐ๋ก ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค ์ ์๊ฒ ๋๋ ๊ฑฐ์ฃ . ์ด๋ ๊ฒ SSR์ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ฌ์ ์ HTML ๋ฌธ์๋ฅผ ํด๋ผ์ด์ธํธ ์ธก์ผ๋ก ์ ๋ฌํ๊ธฐ ๋๋ฌธ์, ํ์ด์ง ๋ก๋ฉ์ด ๋นจ๋ผ์ง๊ณ , ๊ฒ์ ์์ง์ด ์ฌ์ฉ์์ ์์ฒญ์ ๋ฐ๋ผ ๊ฒ์์ด๋ฅผ ์ฐพ์ ๋(๋ฐ์ดํฐ๋ฅผ ํฌ๋กค๋งํ ๋), ์ฐ๋ฆฌ์ ์น์ฌ์ดํธ์ ํด๋น ๊ฒ์์ด๊ฐ ํฌํจ๋์ด ์๋ค๋ฉด ์ฐ๋ฆฌ ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ํจ์จ์ ์ธ SEO๊ฐ ๋ ์ ์์ต๋๋ค.
ํ์ง๋ง SSR์ด CSR์ ๋ชจ๋ ๋ฌธ์ ์ ์ ํด๊ฒฐ์ฑ ์ด ๋์ง๋ ์์ต๋๋ค. ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ ์ ๋ฐ์์ค๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ฒซ ๋ฒ์งธ๋ก blinking issue๊ฐ ์ฌ์ ํ ์กด์ฌํ๊ณ (ํ์ด์ง๊ฐ ๋์ด๊ฐ ๋๋ง๋ค ๊น๋นก์ why? html ๋ฐ js ํ์ผ์ ์๋ก ๋ฐ์์ค๊ธฐ ๋๋ฌธ์), ๋ ๋ฒ์งธ๋ก ์ฌ์ฉ์๊ฐ ์ฆ๊ฐํจ์ ๋ฐ๋ผ ์๋ฒ๋ ์ฌ์ฉ์์ ์์ฒญ์ ์ํด ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ HTML์ ๋ง๋ค์ด์ผ ํ๋ฏ๋ก ๊ณผ๋ถํ๊ฐ ์ฌ ์ ์์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ์ฌ์ฉ์๊ฐ ๋น ๋ฅด๊ฒ ์น์ฌ์ดํธ๋ฅผ ํ์ธํ ์๋ ์์ง๋ง, SSR์ ๋ชจ๋ jsํ์ผ์ ๋ค์ด ๋ฐ์ ์ํ๊ฐ ์๋๊ธฐ ๋๋ฌธ์, jsํ์ผ์ด ์์ ํ ๋ค์ด๋ก๋ ๋์ง ์์ ์ํ์์ ํ์ด์ง์ ์ฌ๋ฌ ๋ถ๋ถ์ ํด๋ฆญํ๋ฉด, ์๋์ด ๋์ง ์๋ ๋ถ๋ถ์ด ์กด์ฌํ ์ ์์ต๋๋ค.
TTV๋ ๋ณด์ฌ์ง๋ ์์ (Time To View), TTI๋ ์ธํฐ๋ ์ ์ฌ์ฉ์์์ ํต์ ์ด ๊ฐ๋ฅํด์ง๋ ์์ (Time To Interact)์ ๋๋ค
CSR์ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๊ณผ ๋์์ ๋ชจ๋ html๊ณผ js๋ฅผ ๋ถ๋ฌ์จ ์ํ์ด๊ธฐ ๋๋ฌธ์, TTV๊ณผ ๋จ๊ณผ ๋์์ TTI ๋ชจ๋ ๋์ ์ธ ํ๋์ ํ ์ ์๊ฒ ๋ฉ๋๋ค.
ํ์ง๋ง, SSR์ html๊ณผ ์ผ๋ถ jsํ์ผ์ ์๋ฒ๋ก๋ถํฐ ์ฌ์ ์ ๋ฐ์ ๋์๊ธฐ ๋๋ฌธ์ TTV ์ํ์์๋ TTI๊ฐ ์ ๋ถ ํ์ฑํ๋์ด ์์ง๋ ์์ต๋๋ค
์ต์ข ์ ์ผ๋ก CSR์ ๋ง์ด ์ฌ์ฉํ๋ค๋ฉด, ์ฐ๋ฆฌ๊ฐ ์ต์ข ์ ์ผ๋ก ๋ฒ๋ค๋งํ์ฌ ์ฌ์ฉ์๊ฒ์ ๋ณด๋ด์ฃผ๋ js ํ์ผ์ ์ด๋ป๊ฒ ํ๋ฉด ํจ์จ์ ์ผ๋ก ๋ง์ด ๋ถํ ํ์ฌ ์ฒซ ๋ฒ์งธ๋ก ์ฌ์ฉ์๊ฐ ๋ณด๊ธฐ ์ํด์ ํ์ํ ์ ๋ง ํ์์ ์ธ html ์์๋ง ๋ณด๋ผ ์ ์์์ง ๊ณ ๋ฏผํด๋ด์ผ ํ๊ณ , SSR์ ๊ฒฝ์ฐ ์ฌ์ฉ์๊ฐ ๋ณด๊ณ , ์ธํฐ๋ ์ (TTI)ํ๋ ์ด ์๊ฐ์ ๋จ์ฐจ๋ฅผ ์ค์ด๊ธฐ ์ํด์ ์ด๋ค ๋ ธ๋ ฅ์ ํ ์ ์์์ง ๊ณ ๋ฏผํด๋ด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค๋ฉด ์ด๋ป๊ฒ ํ๋ฉด ์กฐ๊ธ ๋ ๋งค๋๋ฌ์ด UI์ UX๋ฅผ ์ ๊ณตํ ์ ์์์ง์ ๋ํ ๊ณ ๋ฏผ๋ค์ด ํฌํจ๋ฉ๋๋ค.
์์ฆ์๋ SSR, CSR ๋ฟ๋ง ์๋๋ผ SSG(Static Site Generation)๋ํ ๋ ๋๋ง ๋ฐฉ๋ฒ์ผ๋ก ๋ฑ์ฅํ์์ต๋๋ค. SSG๋ ๋ฆฌ์กํธ๋ฅผ ์๋ก ๋ค๋ฉด 'Gatsby' ๋๋ 'Next'์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ๊ฐ์ ์ผ๋ก ์ฌ์ฉํ์ฌ ๋ ๋๋ง์ ํ๋ ๊ฒ์ธ๋ฐ, ์นํ์ด์ง๋ฅผ ์ ์ ์ผ๋ก ๋ฏธ๋ฆฌ ์์ฑํด๋๊ณ , ์๋ฒ์ ๋ฐฐํฌํด๋๋ ๊ฒ์ ๋๋ค. SSG์์๋ ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ html ํ์ผ๊ณผ ํจ๊ป ๊ฐ์ง๊ณ ์์ ์ ์๊ธฐ ๋๋ฌธ์, ๋์ ์ธ ์์๋ ์ถฉ๋ถํ ์ถ๊ฐํ ์ ์์ต๋๋ค. Next์์๋ SSR๋ฟ๋ง ์๋๋ผ, static generation, no pre-rendering, pre-rendering์ํ๋ฅผ ๋ชจ๋ ์ง์ํ๊ธฐ ๋๋ฌธ์ ๋ฆฌ์กํธ๋ก ์์ ์ ๊ณ์ํ๋ค๋ฉด next.js๋ฅผ ๋ฐฐ์๋ณด๋ ๊ฒ๋ ๋งค์ฐ ํจ๊ณผ์ ์ผ ๊ฒ๋๋ค.
์ด๋ค ๊ฒ์ด ์ต๊ณ ๋ค, ์ ์ผ ๋ซ๋ค๋ผ๋ ํ๋จ ๋ณด๋ค๋ ์ฐ๋ฆฌ๊ฐ ๋ง๋ค์ด์ผ ํ๋ ์น์ฌ์ดํธ ํน์ฑ์ ๋ง๊ฒ ๋ค์ํ ๋ฐฉ์์ ๋ ๋๋ง์ ํ์ฉํ์ฌ ํ์ด์ง๋ฅผ ๊ตฌ์ฑํ๋ค๋ฉด ์ต์ ์ ์ ํ์ด ๋ ๊ฒ์ ๋๋ค.
renderToString
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ์ฌ ์ ์ HTML ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
- SSR ์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ API์ ๋๋ค.
renderToStaticMarkup
- renderToString๊ณผ ์ ์ฌํ์ง๋ง, ์ผ๋ถ ๋ฐ์ดํฐ ๋ฆฌ์กํธ ๋ด๋ถ ๋ฐ์ดํฐ ์์ฑ์ ์ถ๊ฐํ์ง ์์ต๋๋ค.
- ์ ์ ํ์ด์ง ์์ฑ ์ ์ฌ์ฉ๋ฉ๋๋ค.
renderToNodeStream > renderToPipeableStream
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ์ฌ Node.js ์คํธ๋ฆผ์ ๋ฐํํฉ๋๋ค.
- ๋์ฉ๋ ์ปดํฌ๋ํธ๋ฅผ ์คํธ๋ฆฌ๋ฐํ๊ฑฐ๋ ํ๋ก์ ์๋ฒ์์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
- React 18 ๋ฒ์ ์์ renderToPipeableStream ์ผ๋ก ๋ฉ์๋๊ฐ ๋ณ๊ฒฝ๋์์ต๋๋ค.
renderToStaticNodeStream
- renderToNodeStream๊ณผ ์ ์ฌํ์ง๋ง, ๋ฐ์ดํฐ ์์ฑ์ ์ถ๊ฐํ์ง ์์ต๋๋ค.
- ์ ์ ํ์ด์ง ์์ฑ ์ ์คํธ๋ฆฌ๋ฐ ๋ ๋๋ง์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
hydrate
- ์๋ฒ์์ ๋ ๋๋ง๋ HTML ์ฝ๋๋ฅผ ๋ธ๋ผ์ฐ์ ์์ ์ธ์ํ๊ณ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ฐ๊ฒฐํ๋ ์ญํ ์ ํฉ๋๋ค.
- ํด๋ผ์ด์ธํธ ์ธก์์ ์๋ฒ ๋ ๋๋ง ๋งํฌ์ ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ฐ๊ฒฐํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- ์ด๋ฏธ ๋ ๋๋ง๋ HTML์ด ์๋ค๋ ๊ฐ์ ํ์ ์์ ์ ์ํํฉ๋๋ค
- renderToString, renderToNodeStream ๋ฑ์ผ๋ก ์์ฑ๋ HTML ์ปจํ ์ธ ์ ์๋ฐ์คํฌ๋ฆฝํธ ํธ๋ค๋ฌ๋ ์ด๋ฒคํธ๋ฅผ ๋ถ์ด๋ ์ญํ ์ ํฉ๋๋ค
์ฐธ๊ณ ์๋ฃ 1 ๐ฅ ์ฐธ๊ณ ์๋ฃ 2 ๐ฅ
hydration = ์ํ = ์ฐ๋ฆฌ ๋ชธ์ ์๋ถ์ ๋ณด์ถฉํ๋ ํ์
ํ์ด๋๋ ์ด์ ์ด๋, ๋ฆฌ์กํธ์์ ์๋ฒ์ฌ์ด๋ ๋ ๋๋ง ํน์ SSG(์คํํฑ ์ฌ์ดํธ ์ ๋ค๋ ์ด์ )์ ์คํํ HTML ๊ฒฐ๊ณผ๋ฌผ์ ๋ฐ์์จ ๋ค, ๋ธ๋ผ์ฐ์ ์์ ์ด๊ฒ์ ๋ค์ ๋ฆฌ์กํธ ํธ๋ฆฌ์ ๋ง๊ฒ ํ์ฑํ๋ ํ์์ด๋ค.
์ถ์ฒ (https://simsimjae.tistory.com/389)
์๋ฒ๊ฐ ์์ฑ๋ HTML์ ๋ด๋ ค์ค๋ค. ์ด๋ Dehydrate๋ ์๋ถ์ ์์ค๋ค๋ ๋ป์ด๋ค. ๋ค์ ๋งํด์ ๋์ ์ธ๊ฒ์ ์ ์ ์ผ๋ก ๋ง๋๋ ํ์๋ฅผ Dehydrate๋ผ๊ณ ํํํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋์ JS๊ฐ ์คํ๋๋ฉด์ ๋ฆฌ์กํธ๊ฐ ์ ์ ์ธ HTML๊ณผ store๋ฅผ ๋์ ์ธ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ํธ๋ฆฌ์ store๋ก ๋ณํํ๋ ๊ณผ์ ์ด ์ผ์ด๋๋๋ฐ, ์ด๊ฑธ (Re)hydrate๋ผ๊ณ ํ๋ค. ๋ง์น ์๋ถ๊ธฐ ์๋ ์ ์ ์ธ ์ํ์์ ์๋ถ ๋์น๋ ๋์ ์ธ ์ํ๋ก ๋ณํํ๊ฒ์ด๋ค. ๋ฌธ์ ๋ ์ด๋ ๊ฒ rehydrate๊ฐ ์ผ์ด๋๋ฉด์ ์ธ๋ฐ์์ด ํ๋ฉด์ด ํ๋ฒ๋ ๊ทธ๋ ค์ง๋ ํ์์ด ๋ฐ์ํ๋ค๋๊ฒ์ด๋ค. ์๋๋ฉด ๋ฆฌ์กํธ๋ ์๋ฒ์์ ์์ฑ๋ HTML์ด ๋ด๋ ค์์ ์ด๋ฏธ ํ๋ฉด์ ์ ๋๋ก ๋ ๋๋ง์ด ๋ฌ๋์ง ์๋ฌ๋์ง ๋ชจ๋ฅด๊ณ ์์ ์ด ํ ์ผ์ ๊ทธ๋ฅ ํ์ ๋ฟ์ด๋ค. ๊ทธ๋์ SSR์ ํ๋ ๊ฒฝ์ฐ์๋ ReactDom์ render๋ฉ์๋๊ฐ ์๋๋ผ hydrate ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ๋งํ์๋ค.
์ด hydrate ๋จ๊ณ์์,
- ๋ ๋๋งํ ๊ฒฐ๊ณผ๋ฌผ์ด ์ด๋ค ์ปดํฌ๋ํธ์ธ์ง ํ์ธํ๋ค
- ๊ฐ ์ปดํฌ๋ํธ์ ๊ฑธ๋ฆฐ ์ด๋ฒคํธ ๋ค์ ์ค์ DOM์ ๊ฑธ์ด์ฃผ๋ ๋์์ ํ๊ฒ ๋๋ค
ํ์ด๋๋ ์ด์ ์ด ์๋ชป๋์์ ๋, ์ฐ๋ฆฌ๊ฐ ๋ง์ฃผํ๋ ๋ฌธ์ ๋ค์ ๊ฑฐ์ 1๋ฒ ๊ณผ์ ์ด ์๋ชป๋์ด์ ์ผ์ด๋๋ค.
Next.JS์์ ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํ๋ ReactDOM.hydrate ํจ์๋ ๋ค์๊ณผ ๊ฐ์ ์ผ์ ํ๋ค.
- ์๋ฒ์์ ๋ฐ์์จ DOM tree์ ์์ฒด์ ์ผ๋ก ๋ ๋๋งํ tree๋ฅผ ๋น๊ตํ๋ค
- ๋ tree ์ฌ์ด์ ์ฐจ์ด(diff, diffrence)๋ฅผ ์ป์ด๋ธ ๋ค, ์์ฒด์ ์ผ๋ก(ํด๋ผ์ด์ธํธ์ฌ์ด๋) ๋ ๋๋ง ํ tree์ ๋ง์ถฐ patch๋ฅผ ์ ์ฉํ๋ค
hydration์ด ๋์ด์ผ ์ง์ง ๋ฆฌ์กํธ ์ปดํฌ๋ํธ
์๋ฒ์์ ๋ด๋ ค์ค HTML๋ก ๋ ๋๋ง ๋ ํ๋ฉด์ ๊ทธ๋ฅ ๋จ์ํ ๊ทธ๋ฆผ์ผ ๋ฟ์ด๋ค. ๋ฆฌ์กํธ๊ฐ ๊ด๋ฆฌํ์ง ์๋ ํ๋ฉด์ด๋ค. SSR์ ํ๋๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ฆฌ์กํธ๊ฐ ๊ด๋ฆฌํ๊ฒ ํ๊ธฐ ์ํด์๋ hydration์ ๊ผญ ํ์ํ ์์ ์ด๋ค.
๊ฒฐ๋ก
๋ฆฌ์กํธ์์ hydration์ด๋ผ๊ณ ํ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ "์๋ฒ์ฌ์ด๋ ๋ ๋๋ง์ผ๋ก ๋ง๋ค์ด์ง ์๋ถ์ด ์๋ ์ ์ ์ธ HTML๊ณผ State๋ก๋ถํฐ ์๋ถ์ ๋ณด์ถฉํ๋ ๊ณผ์ (๋์ ์ธ ์ํ๋ก ๋ณํ)์ธ hydrate๊ฐ ์ผ์ด๋๊ธฐ ๋๋ฌธ" ์ด๋ผ๊ณ ์ถ์ธกํด๋ณธ๋ค.
์ฐธ๊ณ ์๋ฃ: Velog, Next.js 100% ํ์ฉํ๊ธฐ
- SSR์ ๊ธฐ๋ฐ์ผ๋ก ์๋ฒ์ ์ฌ์ ์ ์ ์ฅ๋ ๋ ๋ํธ๋ฆฌ(render tree)์ HTML์ ๋ก๋
- โ ๋ฐฉ์์
์ฌ์ ๋ ๋๋ง(pre-render)
์ดํ์๋ CSR ์ฌ์ฉ - ํ์ด์ง๊ฐ ๊ทธ๋ ค์ง ์ดํ์ ํ์ด์ง ๋ด๋ถ์์ ๋์ ์ธ ๋ฐ์ดํฐ๋ฅผ ํจ์น
(axios, fetch, XMLHttpRequest)
ํ๋ ๊ณผ์ ์CSR
๋ฐฉ์์ ๋ฐ๋ฅธ๋ค. - ๋ง์ฝ ํ์ด์ง๊ฐ ๋ก๋๋ ๋ ํจ๊ฒ ๋ฐ์ดํฐ๊ฐ ํจ์นญ๋์ด์ผ ํ๋ ์ํฉ์ด๋ผ๋ฉด(pre-render)
- next.js์ ๋ฐ์ดํฐ ํจ์นญ ๋ฐฉ์ (โ getInitialProps/ โก getStaticProps / โข getStaticPath / โฃ getServerSideProps) ์ ์ด์ฉํด ์ฒซ ๋ ๋๋ง ์์ HTML ํ์ผ ๋ฟ๋ง ์๋๋ผ ๋ฐ์ดํฐ๊ฐ ํจ์นญ๋ ์ ์๋๋ก ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
์ถ์ฒ: ํด๋ก ์ฝ๋ฉ์ผ๋ก ์์ํ๋ Next.js
1. ์ฌ์ ๋ ๋๋ง ๋ฐ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง
- ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ๋ ๋๋ง ํ๊ฒฝ๋ณด๋ค ๋น ๋ฅธ ๋ ๋๋ง์ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค.
2. Hot Code Reloading์ ์ง์
- Next ๊ฐ๋ฐ ํ๊ฒฝ์์๋ ์ฝ๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์ ์ฅ๋๋ฉด ์์ฉ ํ๋ก๊ทธ๋จ์ ์๋์ผ๋ก ๋ค์ ๋ก๋ํฉ๋๋ค.
3. ์๋ ์ฝ๋ ๋ถํ
- ์๋ ์ฝ๋ ๋ถํ ๊ธฐ๋ฅ ๋๋ถ์ ์ฝ๋์ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ๊ฐ ๋ฒ๋ค๋ก ๋ฌถ์ฌ ๊ฐ ํ์ด์ง์ ํจ๊ป ์ ๊ณต๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก, ๋ถํ์ํ ์ฝ๋๊ฐ ํ์ด์ง์ ๋ก๋๋์ง ์๊ฒ ๋ฉ๋๋ค.
4. ์ค์ ์ด ํ์์์
-
๋ฅ์คํธ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์นํฉ๊ณผ ๋ฐ๋ฒจ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด๋ฏธ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง ๋ฐ ๊ฐ๋ฐ์ ํ์ํ ์ค์ ์ด ๋์ด ์์ผ๋ฏ๋ก ๋น ๋ฅด๊ฒ ๊ฐ๋ฐ์ ์์ํ ์ ์์ต๋๋ค.
-
์ฌ์ฉํ๊ณ ์ถ์ ํ๋ฌ๊ทธ์ธ์ด ์๋ค๋ฉด ์์ฝ๊ฒ ์ถ๊ฐํ์ฌ ์ฌ์ฉํ ์ ์๋๋ก ์ง์์ ํ๊ณ ์์ต๋๋ค.
5. ํ์
์คํฌ๋ฆฝํธ๊ฐ ๋ด์ฅ๋จ
6. ํ์ผ๊ธฐ๋ฐ ๋ด๋น๊ฒ์ด์
๊ธฐ๋ฅ
-
๋ฆฌ์กํธ์์๋ ๋ผ์ฐํธ๋ฅผ ์ํด์ 'react-router'๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ฐํ ์ค์ ์ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
-
๊ทธ๋ก ์ธํด ํ์ด์ง์ ๊ฒฝ๋ก์ ๋ํ์ฌ ์ง์ ์ค์ ์ ํด์ฃผ์ด์ผ ํ์์ต๋๋ค.
-
ํ์ง๋ง ๋ฅ์คํธ๋ ํ์ผ ์์คํ ๊ธฐ๋ฐ ๋ผ์ฐํ ์ ์ฌ์ฉํฉ๋๋ค.
-
ํด๋์ ๊ฒฝ๋ก์ ๋ฐ๋ผ ํ์ด์ง์ ๊ฒฝ๋ก๊ฐ ์ค์ ๋์ด ๊ตฌ์ถ์ด ๋น ๋ฅด๊ณ ๊ด๋ฆฌ๊ฐ ํธ๋ฆฌํ๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค.
๐ pages ํด๋ ์์๋ ๋ฅ์คํธ์์ ์ค์ํ ์ญํ ์ ํ๋ ํน๋ณํ ํ์ผ๋ค์ด ์์ต๋๋ค.
- ๐_app.jsx (tsx)
- ๐_document.jsx (tsx)
- ๐_error.jsx (tsx)
- ๐404.jsx (tsx)
๐_app.jsx
App ์ปดํฌ๋ํธ๋ ๋ชจ๋ ํ์ด์ง์ ๊ณตํต ํ์ด์ง ์ญํ ์ ํฉ๋๋ค.
App ์ปดํฌ๋ํธ๋ฅผ ์ด์ฉํ์ฌ ๋ชจ๋ ํ์ด์ง๋ค์ ์ด๊ธฐํํ์ฌ ๋ค์๊ณผ ๊ฐ์ ์ญํ ์ ํ ์ ์์ต๋๋ค.
- ํ์ด์ง๋ค์ ๊ณตํต๋ ๋ ์ด์์
- ํ์ด์ง๋ฅผ ํ์ํ ๋ ์ํ ์ ์ง
- ์ถ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ์ด์ง์ ์ฃผ์
- ๊ธ๋ก๋ฒ CSS ์ถ๊ฐ
๐ pages/_app.jsx
import Header from '../components/Header';
const MyApp = ({ Component, pageProps }) => {
return (
<>
<Header />
<Component {...pageProps} />
<style jsx global>
{`
body {
margin: 0;
}
`}
</style>
</>
);
};
export default MyApp;
๐_document.jsx
์ฌ์ฉ์ ์ ์ Document๋ ์ผ๋ฐ์ ์ผ๋ก ์์ฉ ํ๋ก๊ทธ๋จ <HTML>
๋ฐ <body>
ํ๊ทธ๋ฅผ ๋ณด๊ฐํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๋ํ๋จผํธ๋ฅผ ์ด์ฉํ์ฌ <title>
, <description>
, <meta>
๋ฑ ํ๋ก์ ํธ์ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ HTML ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ณ ,
ํฐํธ๋ ์ธ๋ถ api, cdn ๋ฑ์ ๋ถ๋ฌ์ค๋๋ก ํ ์ ์์ต๋๋ค.
๋ํ CSS-in-JS์ ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง์ ์ํ ์ค์ ์ ํ ๋ ์ฌ์ฉํฉ๋๋ค.
Head ํ๊ทธ์ meta ํ๊ทธ๋ฅผ ์ถ๊ฐํ์ฌ ํด๋น ํ๋ก์ ํธ์ ๋ํ ์ ๋ณด๋ฅผ ์ถ๊ฐํ ์ ์๊ณ , ๊ตฌ๊ธ ํฐํธ ๋ฑ์์ ์ ๊ณตํ๋ ํฐํธ๋ฅผ link ๋ก ๋ถ๋ฌ์ ์ ์ญ์ผ๋ก ์ ์ฉ์ํฌ ์ ์์ต๋๋ค.
๐ pages/_document.jsx
import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
render() {
return (
<Html lang="ko">
<Head>
<meta name="title" content="๊นํ๋ธ ๋ ํฌ์งํ ๋ฆฌ" />
<meta name="description" content="๊นํ๋ธ ๋ ํผ์งํ ๋ฆฌ ๋ฆฌ์คํธ์
๋๋ค" />
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans:400,700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+KR:400,700&display=swap&subset=korean"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
๐_error.jsx
๋ฅ์คํธ์์๋ ๋น๋ ๋ ํ๋ก๋์ ํ๊ฒฝ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด ์๋ฌ ํ์ด์ง๋ก ๋์ด๊ฐ๊ฒ ๋ฉ๋๋ค.
๋ฐ๋ก ๋ผ์ฐํ ๊ฒฝ๋ก๋ฅผ ์ค์ ํ์ง ์๋๋ผ๋, ๋น๋ ๋ ํ๋ก๋ํธ ํ๊ฒฝ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค๋ฉด ์๋ฌ ํ์ด์ง๋ก ์๋์ ์ผ๋ก ๋์ด๊ฐ๋๋ค.
์ถ๊ฐ์ ์ผ๋ก ์๋ฌ ์ํฉ์ ๋ฐ๋ผ์ 500, 404 ๋ฑ๋ ์ถ๊ฐํ ์ ์์ต๋๋ค
๐ pages/_error.jsx
const Error = () => {
return (
<div>
<p>์๋ฌ๊ฐ ๋ฐ์ํ์ต๋๋ค</p>
</div>
);
};
export default Error;
- getInitialProps
- getStaticProps
- getStaticPath
- getServerSideProps
getInitialProps
Next 9.3 ๋ฒ์ ์ด์ ์ getInitialProps๋ง์ผ๋ก ์ฌ์ ๋ ๋๋ง ๊ด๋ จ ๋ฌธ์ ๋ฅผ ์ ๋ถ ํด๊ฒฐํ์ง๋ง, 9.3๋ฒ์ ๋ถํฐ๋ getInitialProps๊ฐ 3๊ฐ์ง๋ก ๋ถ๋ฆฌ๋์์ต๋๋ค
- getStaticProps
- getStaticPath
- getServerSideProps
getStaticProps
- ๋น๋์ ๊ณ ์ ๋๋ ๊ฐ์ผ๋ก ๋น๋ ์ดํ์๋ ์์ ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค
- data๋ฅผ ๋น๋ ์์ ๋ฏธ๋ฆฌ ๋ก๊ฒจ์ ์ ์ ์ผ๋ก(static ํ๊ฒ) ์ ๊ณตํฉ๋๋ค
- ๋งค ์ ์ ์ ์์ฒญ๋ง๋ค fetchํ ํ์๊ฐ ์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง ํ์ด์ง๋ฅผ ๋ ๋๋งํ ๋ ์ ๋ฆฌํฉ๋๋ค
- ์ ์ ์ ๊ตฌ์ ๋ฐ์ง ์๊ณ ํผ๋ธ๋ฆญํ๊ฒ ์บ์ํ ์ ์๋ ๋ฐ์ดํฐ
- SEO ๋ฑ์ ์ด์๋ก ์ธํด ๋น ๋ฅด๊ฒ ๋ฏธ๋ฆฌ ๋ ๋๋งํด์ผ๋ง ํ๋ ํ์ด์ง
getStaticPath
- ๋์ ๋ผ์ฐํ + getStaticProps๋ฅผ ์ํ ๋ ์ฌ์ฉ
- ์ ์ํ์ง ์์ ํ์ ๊ฒฝ๋ก๋ ์ ๊ทผํด๋ ํ๋ฉด์ด ๋จ์ง ์๋๋ค (error ํ์ด์ง๋ก ๋ผ์ฐํ )
- ๋์ ๋ผ์ฐํ ์, ๋ผ์ฐํ ๋๋ ๊ฒฝ์ฐ์ ์๋ฅผ ํ๋ํ๋ ๋ฃ์ด์ผ ํฉ๋๋ค
getServerSideProps
- ๋น๋์ ์๊ด์์ด, ๋งค ํ์ด์ง ์์ฒญ๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ์๋ฒ๋ก๋ถํฐ ๊ฐ์ ธ์ต๋๋ค
์ฐธ๊ณ , ๋ฆฌ์กํธ ์ฝ๋ฆฌ์ - suspense
suspense๊ฐ ๋ญ๊ฐ์?
suspense๋ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ๋ฅผ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๋๋ค.
suspense๋ '์ปดํฌ๋ํธ๊ฐ ์ฝ์ด๋ค์ด๊ณ ์๋ ๋ฐ์ดํฐ๊ฐ ์์ง ์ค๋น๋์ง ์์๋ค'๊ณ React์ ์๋ ค์ค ์ ์๋, ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ฌ์ฉํ ์ ์๋ ๋ฉ์ปค๋์ฆ ์ ๋๋ค.
์ดํ์ React๋ ๋ฐ์ดํฐ๊ฐ ์ค๋น๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ ธ๋ค๊ฐ UI๋ฅผ ๊ฐฑ์ ํ ์ ์์ต๋๋ค.
์ฅ๊ธฐ์ ์ธ ๊ด์ ์ผ๋ก๋, Suspense๊ฐ ๋ฐ์ดํฐ ์ถ์ฒ์ ์๊ด์์ด ์ปดํฌ๋ํธ๋ก๋ถํฐ ๋น๋๊ธฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๋ฐ์ ์ฌ์ฉ๋๋ ์ฃผ๋ ๋ฐฉ์์ผ๋ก ๊ฑฐ๋ญ๋๊ธธ ๋ฐ๋ผ๊ณ ์์ต๋๋ค.
์์ ์ฝ๋ ๋ณด๊ธฐ
const resource = fetchProfileData();
function ProfilePage() {
return (
<Suspense fallback={<h1>Loading profile...</h1>}>
<ProfileDetails />
<Suspense fallback={<h1>Loading posts...</h1>}>
<ProfileTimeline />
</Suspense>
</Suspense>
);
}
function ProfileDetails() {
// ์์ง ๋ก๋ฉ์ด ์๋ฃ๋์ง ์์๋๋ผ๋, ์ฌ์ฉ์ ์ ๋ณด ์ฝ๊ธฐ๋ฅผ ์๋ํฉ๋๋ค
const user = resource.user.read();
return <h1>{user.name}</h1>;
}
function ProfileTimeline() {
// ์์ง ๋ก๋ฉ์ด ์๋ฃ๋์ง ์์๋๋ผ๋, ๊ฒ์๊ธ ์ฝ๊ธฐ๋ฅผ ์๋ํฉ๋๋ค
const posts = resource.posts.read();
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.text}</li>
))}
</ul>
);
}
suspense๋ก ๊ฐ๋ฅํ ๊ฒ์ ์ด๋ค ๊ฒ๋ค์ด ์๋์?
-
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค(axios, SWR, react-query)์ด React์ ๊น๊ฒ ๊ฒฐํฉํ ์ ์๋๋ก ํด์ค๋๋ค
-
์๋์ ์ผ๋ก ์ค๊ณ๋ ๋ก๋ฉ ์ํ๋ฅผ ์กฐ์ ํ ์ ์๋๋ก ํด์ค๋๋ค. suspense๋ ๋ฐ์ดํฐ๊ฐ ์ด๋ป๊ฒ ๋ถ๋ฌ์ ธ์ผ ํ๋์ง๋ฅผ ์ ํ์ง ์๊ณ , ์ฑ์ ์๊ฐ์ ์ธ ๋ก๋ฉ ๋จ๊ณ๋ฅผ ๋ฐ์ ํ๊ฒ ํต์ ํ ์ ์๋๋ก ํด์ค๋๋ค
-
๊ฒฝ์ ์ํ(Race Condition)๋ฅผ ํผํ ์ ์๋๋ก ๋์ต๋๋ค. await๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ๋น๋๊ธฐ ์ฝ๋๋ ์ข ์ข ์ค๋ฅ๊ฐ ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค. suspense๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋๊ธฐ์ ์ผ๋ก ์ฝ์ด์ค๋ ๊ฒ์ฒ๋ผ ๋๊ปด์ง๊ฒ ํด์ค๋๋ค.
LCP(Largest Contentful Paint)๋ ์น ํ์ด์ง์์ ๊ฐ์ฅ ํฐ ์ฝํ ์ธ ์์๋ฅผ ๋ก๋ํ๊ณ ์ฌ์ฉ์๊ฐ ๋ณผ ์ ์๋ ๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์ธก์ ํ๋ ์ฑ๋ฅ ์งํ์ ๋๋ค.
์ด๊ฒ์ ์น ํ์ด์ง์ ๋ก๋ฉ ์๋์ ๋ํ ์ฌ์ฉ์์ ์ธ์์ ๋ฐ์ํ๊ณ ์น ํ์ด์ง์ ๋ํ ์ฌ์ฉ์์ ์ฐธ์ฌ์ ์ํฅ์ ๋ฏธ์น ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ํ ์งํ์ ๋๋ค.
LCP๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด lazy load, ์ด๋ฏธ์ง ํฌ๊ธฐ ๋ฐ ํ์ ์ต์ ํ, CDN(์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ) ๋ฑ์ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ๋ฐ ๋น๋์ค์ ๊ฐ์ ๋์ฉ๋ ์ฝํ ์ธ ์์์ ๋ก๋๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค. ๋ํ HTML, CSS ๋ฐ JavaScript ํ์ผ์ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์๋ฒ์ ๋ํ ์์ฒญ ์๋ฅผ ์ต์ํํ์ฌ ์น ํ์ด์ง์ ์ ์ฒด ๋ก๋๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค.
Chrome DevTools์ Lighthouse ๊ฒ์ฌ ๋๋ WebPageTest์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์น ํ์ด์ง์ LCP๋ฅผ ์ธก์ ํ ์ ์์ต๋๋ค.
FCP(First Contentful Paint)๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์น ํ์ด์ง์ ์ฒซ ๋ฒ์งธ ์ฝํ ์ธ ์์๋ฅผ ๋ ๋๋งํ๋ ๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์ธก์ ํ๋ ์ฑ๋ฅ ์งํ์ ๋๋ค. ์ด ๋ด์ฉ ์์๋ ํ ์คํธ, ์ด๋ฏธ์ง ๋๋ ์ฌ์ฉ์๊ฐ ๋ณผ ์ ์๋ ๋ค๋ฅธ ์ ํ์ ๋ด์ฉ์ผ ์ ์์ต๋๋ค.
FCP๋ ์น ํ์ด์ง์ ๋ก๋ฉ ์๋์ ๋ํ ์ฌ์ฉ์์ ์ธ์์ ๋ฐ์ํ๊ณ ์น ํ์ด์ง์ ๋ํ ์ฌ์ฉ์์ ์ฐธ์ฌ์ ์ํฅ์ ๋ฏธ์น ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ํ ์งํ์ ๋๋ค.
FCP๋ฅผ ๊ฐ์ ํ๊ธฐ ์ํด HTML, CSS ๋ฐ JavaScript ํ์ผ์ ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์๋ฒ์ ๋ํ ์์ฒญ ์๋ฅผ ์ต์ํํ์ฌ ์น ํ์ด์ง ๋ก๋๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค. ๋ํ ๋ก๋ ํ๋ก์ธ์ค์์ ์ฐ์ ์์๋ฅผ ์ง์ ํ์ฌ ์์ ๋ด์ฉ๊ณผ ๊ฐ์ ์ค์ํ ๋ฆฌ์์ค์ ๋ก๋๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค.
React์ Controlled ํจํด์ ํผ ์์์ ์ํ๋ฅผ React ์ปดํฌ๋ํธ์ state๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ์์ ๋๋ค. ์ด ํจํด์ ์ฌ์ฉํ๋ฉด React๊ฐ ํผ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ์ ์ดํ ์ ์๊ฒ ๋ฉ๋๋ค.
Controlled ํจํด์ ์ฃผ์ ํน์ง:
-
์ํ ๊ด๋ฆฌ:
- ํผ ์์์ ๊ฐ์ React์ state๋ก ๊ด๋ฆฌํฉ๋๋ค.
- ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ฐ๋ผ state๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
-
๊ฐ ์ค์ :
- ํผ ์์์ value ์์ฑ์ state ๊ฐ์ผ๋ก ์ค์ ํฉ๋๋ค.
-
์ด๋ฒคํธ ํธ๋ค๋ง:
- onChange ์ด๋ฒคํธ๋ฅผ ํตํด ์ฌ์ฉ์ ์ ๋ ฅ์ ๊ฐ์งํ๊ณ state๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
์์ ์ฝ๋:
import React, { useState } from 'react';
function ControlledForm() {
const [inputValue, setInputValue] = useState('');
const handleChange = (event) => {
setInputValue(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
console.log('Submitted value:', inputValue);
};
return (
<form onSubmit={handleSubmit}>
<input type='text' value={inputValue} onChange={handleChange} />
<button type='submit'>Submit</button>
</form>
);
}
Controlled ํจํด์ ์ฅ์ :
-
๋ฐ์ดํฐ ์ผ๊ด์ฑ: React๊ฐ ํผ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ์ ์ดํ๋ฏ๋ก UI์ ์ํ ๊ฐ์ ์ผ๊ด์ฑ์ ๋ณด์ฅํฉ๋๋ค.
-
์ฆ์ ์ ํจ์ฑ ๊ฒ์ฌ: ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ฐ๋ผ ์ฆ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๊ณ ํผ๋๋ฐฑ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
-
์กฐ๊ฑด๋ถ ๋นํ์ฑํ: ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ํผ ์์๋ฅผ ์ฝ๊ฒ ๋นํ์ฑํํ ์ ์์ต๋๋ค.
-
๊ฐ ํฌ๋งทํ : ์ ๋ ฅ๊ฐ์ ์ฆ์ ํฌ๋งทํ ํ๊ฑฐ๋ ๋ณํํ ์ ์์ต๋๋ค.
์ฃผ์์ฌํญ:
-
์ฑ๋ฅ: ๋ง์ ์์ ํผ ์์๊ฐ ์๋ ๊ฒฝ์ฐ, ๊ฐ ์ ๋ ฅ๋ง๋ค ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ ์ ์์ด ์ฑ๋ฅ์ ์ํฅ์ ์ค ์ ์์ต๋๋ค.
-
๋ณต์ก์ฑ: ๊ฐ๋จํ ํผ์ ๊ฒฝ์ฐ Uncontrolled ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๊ฐ๋จํ ์ ์์ต๋๋ค.
Controlled ํจํด์ React์์ ํผ์ ๋ค๋ฃฐ ๋ ๊ถ์ฅ๋๋ ๋ฐฉ์์ด๋ฉฐ, ํนํ ๋ณต์กํ ํผ์ด๋ ๋์ ์ธ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
Uncontrolled ํจํด์ React์์ ํผ ์์์ ์ํ๋ฅผ ์ง์ React์ state๋ก ๊ด๋ฆฌํ์ง ์๊ณ , DOM์ด ๋ด๋ถ์ ์ผ๋ก ๊ด๋ฆฌํ๋๋ก ํ๋ ๋ฐฉ์์ ๋๋ค. ์ด ๋ฐฉ์์ ์ฃผ๋ก ref๋ฅผ ์ฌ์ฉํ์ฌ ํ์ํ ๋๋ง DOM์์ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค.
Uncontrolled ํจํด์ ์ฃผ์ ํน์ง:
-
์ํ ๊ด๋ฆฌ:
- React์ state๋ฅผ ์ฌ์ฉํ์ง ์๊ณ DOM์ด ์์ฒด์ ์ผ๋ก ์ํ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
- ํ์ํ ๊ฒฝ์ฐ์๋ง ref๋ฅผ ํตํด DOM์์ ๊ฐ์ ์ฝ์ด์ต๋๋ค.
-
๊ฐ ์ค์ :
- ์ด๊ธฐ๊ฐ์ ์ค์ ํ๋ ค๋ฉด defaultValue ์์ฑ์ ์ฌ์ฉํฉ๋๋ค.
-
์ด๋ฒคํธ ํธ๋ค๋ง:
- onChange ์ด๋ฒคํธ๋ฅผ ๋ฐ๋์ ์ฌ์ฉํ ํ์๊ฐ ์์ต๋๋ค.
์์ ์ฝ๋:
import React, { useRef } from 'react';
function UncontrolledForm() {
const inputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
console.log('Submitted value:', inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input type='text' defaultValue='' ref={inputRef} />
<button type='submit'>Submit</button>
</form>
);
}
Uncontrolled ํจํด์ ์ฅ์ :
-
๊ฐ๋จ์ฑ: ๊ฐ๋จํ ํผ์ ๊ฒฝ์ฐ ์ฝ๋๊ฐ ๋ ๊ฐ๊ฒฐํด์ง ์ ์์ต๋๋ค.
-
์ฑ๋ฅ: React์ state๋ฅผ ์ฌ์ฉํ์ง ์์ผ๋ฏ๋ก ์ ๋ ฅ ์๋ง๋ค ๋ฆฌ๋ ๋๋ง์ด ๋ฐ์ํ์ง ์์ต๋๋ค.
-
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํตํฉ: React ์ธ๋ถ์ DOM ๊ธฐ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํตํฉํ๊ธฐ ์ฝ์ต๋๋ค.
-
ํ์ผ ์ ๋ ฅ: file input๊ณผ ๊ฐ์ด ์ฝ๊ธฐ ์ ์ฉ ๊ฐ์ ๋ค๋ฃฐ ๋ ์ ์ฉํฉ๋๋ค.
์ฃผ์์ฌํญ:
-
์ ํจ์ฑ ๊ฒ์ฌ: ์ฆ๊ฐ์ ์ธ ์ ํจ์ฑ ๊ฒ์ฌ๋ ์ ๋ ฅ๊ฐ ๋ณํ์ด ์ด๋ ต์ต๋๋ค.
-
๋์ UI: ์ ๋ ฅ๊ฐ์ ๋ฐ๋ผ UI๋ฅผ ๋์ ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ ์ด๋ ต์ต๋๋ค.
-
๊ฐ ์ด๊ธฐํ: ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์์ผ๋ก ์ ๋ ฅ๊ฐ์ ์ด๊ธฐํํ๊ฑฐ๋ ๋ณ๊ฒฝํ๊ธฐ ์ด๋ ต์ต๋๋ค.
Uncontrolled ํจํด์ ๊ฐ๋จํ ํผ์ด๋ ์ฑ๋ฅ ์ต์ ํ๊ฐ ํ์ํ ๊ฒฝ์ฐ, ๋๋ ๋น-React ์ฝ๋์์ ํตํฉ์ด ํ์ํ ๊ฒฝ์ฐ์ ์ ์ฉํ ์ ์์ต๋๋ค. ํ์ง๋ง React ๊ณต์ ๋ฌธ์์์๋ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ Controlled ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๊ถ์ฅํ๊ณ ์์ต๋๋ค.
Controlled์ Uncontrolled ํจํด์ ๊ฐ๊ฐ์ ์ฅ๋จ์ ์ด ์์ผ๋ฏ๋ก, ์ํฉ์ ๋ฐ๋ผ ์ ์ ํ ํจํด์ ์ ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.