ํ์ผ ๋ณ์ Deep-Dive
ํ์ผ ๋ณ์ Deep-Dive ๊ด๋ จ
์๋ก
์ ๊ฐ ์ํด์๋ ์คํ ๋ฆฌFE๊ฐ๋ฐํ์์๋ ์นด์นด์คํ์ด์ง, ์นด์นด์ค์นํฐ, ํํ์ค ๋ฑ์ ๋ค์ํ ์น ์๋น์ค๋ฅผ ๊ฐ๋ฐํ๊ณ ์ด์ํ๊ณ ์์ต๋๋ค. ์น ์๋น์ค์ ๊ท๋ชจ๊ฐ ์ปค์ง๊ณ ์ ๊ณตํ๋ ๊ธฐ๋ฅ๋ค์ด ๋ง์์ง๋ค ๋ณด๋ ๋ค์ํ ์ ํ์ ์ํ(state)๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๊ณ ๋ฏผํด์ผ ํ๋๋ฐ์. ์ด ๊ธ์์๋ ์ ํฌ ํ์์ ํน์ ์ ํ์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํ๊ณ ์๋ ํ์ผ ๋ณ์์ ๋ํด ์๊ฐํ๊ณ ํ์ผ ๋ณ์์ ๋ํ ์ด์ ๋ ธํ์ฐ๋ฅผ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค.
Redux
์ฒ์์ ํ๋ก์ ํธ๋ฅผ ๊ฐ๋ฐํ ๋๋ ์ํ์ ๋ํด์ ๊น์ด ์๊ฐํ ํ์๊ฐ ์์์ต๋๋ค. ๋ชจ๋ ์ํ๋ฅผ ํ ๊ณณ์์ ํต์ผ๋ก ๊ด๋ฆฌํด๋ ์ถฉ๋ถํ๋ค๊ณ ์๊ฐํ๊ณ ์ค์ ๋ก ํ๋ก์ ํธ์ ๊ท๋ชจ๊ฐ ์์ ๋์๋ ์ ํ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ๋ฐ๋ผ์ ๋ํ์ ์ธ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค ํ๋์ธ Redux๋ฅผ ์ฌ์ฉํด ํ๋์ ์ ์ญ ์คํ ์ด(store)์์ ํ๋ก์ ํธ์ ๋ชจ๋ ์ํ๋ฅผ ๊ด๋ฆฌํ์ต๋๋ค.
๋ง์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์์ Redux๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ๊ฒฐ์ ํ๋ ์ด์ ๋ฅผ ๋ช ๊ฐ์ง ๋ฝ์๋ณด์๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
Redux ๋ฏธ๋ค์จ์ด
Redux๋ ์ก์ ์ด ํธ๋ฆฌ๊ฑฐ๋์ด ๊ทธ๋ก ์ธํ ์ํ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์คํ ์ด์ ๋ฐ์๋๊ธฐ๊น์ง์ ๊ณผ์ ์ ์ ์ดํ๊ณ ํ์ฅํ ์ ์๋ ๋ฏธ๋ค์จ์ด ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. redux-thunk๋ redux-saga์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ๋ฏธ๋ค์จ์ด์ ์ํฉ๋๋ค.
Redux Toolkit
ํ๋์ Redux ํ๋ก์ฐ๋ฅผ ์ ์ํ๊ธฐ ์ํด์๋ ์๋นํ ๋ง์ ์ฝ๋๊ฐ ํ์ํฉ๋๋ค. ์ก์ ์ ์ ์ํ๊ณ ๋ฆฌ๋์๋ฅผ ๊ตฌํํด์ผ ํ๋ฉฐ ์คํ ์ด์ ์ํ๋ฅผ ์ถ๊ฐํด์ผ ํ๊ณ , ๋น๋๊ธฐ ์์ ์ด ํ์ํ๋ค๋ฉด thunk ํจ์๋ saga๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค. Redux Toolkit์ ์ฌ์ฉํ๋ฉด ์ด์ ๊ฐ์ ์ผ๋ จ์ ํ๋ก์ฐ๋ฅผ ๋งค์ฐ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋ API๋ค์ ์ ๊ณตํฉ๋๋ค.
Redux Devtools
Redux์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ค ํ๋๋ ์ํ์ ๋ถ๋ณ์ฑ์ ์ ์งํจ์ผ๋ก์จ ์ํ ๋ณ๊ฒฝ์ ํ์คํ ๋ฆฌ๋ฅผ ์ฝ๊ฒ ์ถ์ ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ redux devtools ๋๊ตฌ๋ฅผ ํตํด ์ด๋ฌํ ์ํ ๋ณ๊ฒฝ ํ์คํ ๋ฆฌ๋ฅผ ์ฝ๊ฒ ํ์ธํ ์ ์์ต๋๋ค.
์ด์ฒ๋ผ Redux๊ฐ ์ ๊ณตํ๋ ์ฌ๋ฌ ์ด์ ์ ํ์ฉํด ์ํ๋ฅผ ์ ๊ด๋ฆฌํ๊ณ ์์๋๋ฐ, ํ๋ก์ ํธ์ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก ํ๊ณ๊ฐ ์ฐพ์์์ต๋๋ค. ์๋ฒ๋ก๋ถํฐ ๋ฐ์์ค๋ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ถ๊ฐ๋ saga ์ฝ๋๊ฐ ๋ง์์ง๋ค ๋ณด๋ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ ธ์ ํ๋์ Redux ํ๋ก์ฐ๋ฅผ ๋ฐ๋ผ๊ฐ๊ธฐ๊ฐ ์ด๋ ค์์ก์ต๋๋ค. ํน์ ํ์ด์ง์์ ํ ๋ฒ์ ๋๋ฌด ๋ง์ ์ก์ ์ ํธ๋ฆฌ๊ฑฐ ํ๋ค๋ณด๋ Redux Devtools๊ฐ ๋ถํ๋ฅผ ๋ฒํฐ์ง ๋ชปํ๊ณ ๋ค์ด๋์ด๋ฒ๋ฆฌ๋ ์ํฉ๋ ์ข ์ข ๋ฐ์ํ์ต๋๋ค. ์ด๋ค ๊ฐ์ด ์ฃผ๊ธฐ์ ์ผ๋ก ๋ณ๊ฒฝ๋๋ ๊ฐ์ด๊ณ ์ด๋ค ๊ฐ์ด ํ ๋ฒ ์ด๊ธฐํ๋๊ณ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฐ์ธ์ง๋ฅผ ํ ๋์ ํ์ ํ๊ธฐ ํ๋ค์ด์ก์ต๋๋ค. Redux ์์ฒด์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ ์๋๋๋ค. Redux๋ ๋ชจ๋ ์ํ๋ฅผ ํ๋์ ์ ์ฅ์ ์์์ ๊ด๋ฆฌํ๋ค๋ ๊ธฐ๋ณธ ์์น์ ์ถฉ์คํ ์งํค๊ณ ์์ต๋๋ค. ๋ฌธ์ ์ ๋ํ ์ฑ ์์ ๋ชจ๋ ์ํ๋ฅผ Redux์ ์ ์ฅํด์ ๊ด๋ฆฌํ๊ณ ์ ํ๋ ์ ํฌ ํ์๊ฒ ์์์ต๋๋ค. Redux์ ๋ฉ์ธํ ์ด๋์ธ Mark Erikson์ ์์ ์ ๋ธ๋ก๊ทธ์ ๋ค์๊ณผ ๊ฐ์ ๋ง์ ๋จ๊ธด ์ ์ด ์์ต๋๋ค.
โRedux is Overusedโ
Redux๊ฐ ๋ถํ์ํ ์์ญ๊น์ง ๋๋ฌด ๋จ์ฉ๋๊ณ ์๋ค๋ ๋ป์ ๋๋ค. Mark Erikson์ด ์ง์ ํ ๊ฒ์ฒ๋ผ ์ ํฌ ํ์ Redux๋ฅผ ๋ชจ๋ ๊ณณ์์ ๋จ์ฉํด์ ์ฌ์ฉํ๊ณ ์์๊ณ , ์ด๋ก ์ธํด ํ๊ณ๋ฅผ ๋ง์ดํ์ต๋๋ค.
์ํ์๋ ์ ํ์ด ์์ต๋๋ค.
ํ์์ ์ฌ์ฉํ๋ ์ํ ๊ด๋ฆฌ ๋ฐฉ์์ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด์๋ Redux๋ฅผ ํตํ ์ํ ๊ด๋ฆฌ์ ์์กด์ฑ์ ์ต๋ํ ์ค์ฌ์ผ ํ์ต๋๋ค. Redux๋ก ๊ด๋ฆฌํ ํ์๊ฐ ์๋ ์ํ ๊ฐ์๋ ๋ฌด์์ด ์๋์ง ํ์ธํ๋ ๋์ค ์ํ๋ฅผ ์ ํ๋ณ๋ก ๊ตฌ๋ถํ ์ ์๋ค๋ ์ฌ์ค์ ๋ฐ๊ฒฌํ๊ณ , ์ด๋ฅผ ํตํด ์ ํฌ ํ์์ Redux๋ก ๊ด๋ฆฌํ๊ณ ์๋ ์ํ๋ค์ ์๋์ ๊ฐ์ ์ ํ๋ณ๋ก ๋ถ๋ฅํ ์ ์์์ต๋๋ค.
- ์๋ฒ ์ํ: API ์์ฒญ ๋ฐ ์๋ต์ ๋ํ ์ํ
- ์ถ์ ์ด ํ์ํ ์ํ: ๊ฐ์ ๋ณ๊ฒฝ์ผ๋ก ์ธํด UI๊ฐ ๋ฆฌ๋ ๋๋ง ๋์ด์ผ ํ๊ฑฐ๋ ํน์ ๋ก์ง์ ํธ๋ฆฌ๊ฑฐ ์์ผ์ผ ํ๋ ๋ฑ ๊ฐ์ ๋ณ๊ฒฝ์ ๊ณ์ํด์ ์ถ์ ํด์ผ ํ๋ ์ํ
- ์ถ์ ์ด ๋ถํ์ํ ์ํ: ๊ฐ์ด ๋ณ๊ฒฝ๋์ด๋ ๋ณ๋์ ๋ก์ง์ด ์ํ๋ ํ์๊ฐ ์์ด์ ๊ฐ์ ๋ณ๊ฒฝ์ ์ถ์ ํ ํ์๊ฐ ์๋ ์ํ
์๋ฒ ์ํ์ ๊ฒฝ์ฐ ๊ธฐ์กด์ redux-saga ๋ฏธ๋ค์จ์ด๋ฅผ ํตํด ๋น๋๊ธฐ API ์์ฒญ ๊ด๋ จ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๋ถ๋ถ์ด์์ต๋๋ค. ์๋ฒ ์ํ๋ ๊ตณ์ด Redux์ ์ ์ญ ์คํ ์ด๋ก ๊ด๋ฆฌํ ํ์ ์์ด react-query์ ๋ฐ์ดํฐ ์บ์ฑ ๊ธฐ๋ฅ์ ํ์ฉํ๋ฉด ์ํ ๊ด๋ฆฌ๋ฅผ ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋ค๋ ์ฌ์ค์ ๋ฐ๊ฒฌํ์ต๋๋ค. ๋ฐ๋ผ์ redux-saga ๋ฏธ๋ค์จ์ด๋ฅผ ์ ๊ฑฐํ๊ณ react-query ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์๋ฒ ์ํ๋ฅผ ๊ด๋ฆฌํ๋๋ก ์ผ๊ด ๋ณ๊ฒฝํ์ต๋๋ค.
Info
react-query๋ฅผ ํ์ฉํ ์๋ฒ ์ํ ๊ด๋ฆฌ๋ esme์ ๋ธ๋ก๊ทธ ๊ธ์์ ๋ ์์ธํ ๋ด์ฉ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
์ถ์ ์ด ํ์ํ ์ํ๋ค์ ์ฌ์ ํ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๊ด๋ฆฌํด ์ค์ผ ํ์ต๋๋ค. ๋ค๋ง Redux ๋ฏธ๋ค์จ์ด๋ฅผ ๋ ์ด์ ํ์ฉํ์ง ์๊ธฐ๋ ํ๊ณ , ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ๋ณ๊ฒฝ๋๋ UI๋ฅผ ๊ด๋ฆฌํ๋ ์ ๋์ ๋จ์ํ ์ํ๋ค์ Redux๋ก ๊ด๋ฆฌํ๊ธฐ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋๋ฌด ๋ฌด๊ฒ๋ค๊ณ ํ๋จํ์ต๋๋ค. ๋ฐ๋ผ์, Redux๋ณด๋ค ํจ์ฌ ๊ฐ๋ฒผ์ด Zustand๋ผ๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์ถ์ ์ด ํ์ํ ์ต์ํ์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋๋ก ๊ฒฐ์ ํ์ต๋๋ค.
์ถ์ ์ด ๋ถํ์ํ ์ํ๋ค์ ๊ฐ๋ฅํ๋ฉด ๋ณ๋์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ์ฌ๊ธฐ์์ ๋งํ๋ โ์ถ์ ์ด ๋ถํ์ํ ์ํโ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋๋ผ๋ ๋ณ๋์ ๋ก์ง์ ์ํํ ํ์๊ฐ ์์ผ๋ ๋จ์ํ ๊ฐ๋ฐ ํธ์๋ฅผ ์ํด ์ ์ญ store์ ๋ฃ์ด์ ๊ด๋ฆฌํ๋ ์ํ์ด๊ฑฐ๋, window.navigator.userAgent
๋ฅผ ํตํด ์ ์ ์๋ ์ ์ ์ ํ๊ฒฝ ์ ๋ณด์ ๊ฐ์ด ์ฌ์ฉ์ ์์ฒญ์ ๋ํด ๊ฒฐ์ ๋๋ฉฐ ๊ฐ์ด ๋์ค์ ๋ณ๊ฒฝ๋ ์ ์๋ ์ํ๋ฅผ ์๋ฏธํฉ๋๋ค.
์ง๊ธ๋ถํฐ ์ ํฌ ํ์์ ์ถ์ ์ด ๋ถํ์ํ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๊ณ ์๋ ํ์ผ ๋ณ์๊ฐ ๋ฌด์์ธ์ง๋ถํฐ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
ํ์ผ ๋ณ์
์ด ๊ธ์์ ๋งํ๋ ํ์ผ ๋ณ์๋ ๋ฌด์์ธ๊ฐ์?
ํ์ผ ๋ณ์๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ๋ค์ ๋ํด ์ค๋ช ํ๊ธฐ ์ ์ ์ฐ์ ์ด ๊ธ์์ ๋งํ๋ ํ์ผ ๋ณ์๊ฐ ์ ํํ ๋ฌด์์ธ์ง๋ถํฐ ์ง๊ณ ๋์ด๊ฐ ํ์๊ฐ ์์ต๋๋ค. ์๋ํ๋ฉด ์๋ฐ์คํฌ๋ฆฝํธ ์ํ๊ณ์์ โํ์ผ ๋ณ์โ๋ผ๋ ์ฉ์ด๋ ์๋ฐํ ๋งํด ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋ณ์๋ฅผ ํ๋ ์ ์ธํ๋ฉด ํด๋น ๋ณ์๊ฐ ์ด๋ ์์น์ ์ ์ธ๋์๋๊ฐ์ ๋ฐ๋ผ โ์ค์ฝํโ๊ฐ ํ ๋น๋ฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ ์๋ ค์ง ์ค์ฝํ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- Global Scope (์ ์ญ ๋ฒ์): ์ฝ๋์ ๋ชจ๋ ์์ญ์์ ์ ์ธ๋ ๋ณ์์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ ์ญ ๋ฒ์์ ์ ์ธ๋ ๋ณ์๋ฅผ ๋ณดํต ์ ์ญ ๋ณ์๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
- Function Scope (ํจ์ ๋ฒ์): ํจ์ ๋ด๋ถ์ ์ ์ธ๋ ๋ณ์์ ๊ฒฝ์ฐ ํจ์ ์ธ๋ถ์์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๋ฉฐ ์ค์ง ํจ์ ๋ด๋ถ์์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค.
- Block Scope (๋ธ๋ก ๋ฒ์): ES6 ๋ฌธ๋ฒ์์ ์๋ก ๋์ ๋ let ๊ณผ const ์ ์ธ๋ฌธ์ผ๋ก ์ธํด ์ถ๊ฐ๋ ์ค์ฝํ๋ก, ์ค๊ดํธ ๋ด๋ถ์ let ๋๋ const๋ก ์ ์ธ๋ ๋ณ์๋ ์ค๊ดํธ ์ธ๋ถ์์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ๋ฉฐ ์ค์ง ์ค๊ดํธ ๋ด๋ถ์์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค.
ES6์์๋ ์ฌ๊ธฐ์ ๋ํด โ๋ชจ๋โ์ด๋ผ๋ ๊ฐ๋ ์ด ์๋กญ๊ฒ ๋์ ๋จ์ ๋ฐ๋ผ ํ๋์ ์ค์ฝํ๊ฐ ์ถ๊ฐ๋์๋๋ฐ, ๋ฐ๋ก Module Scope(๋ชจ๋ ๋ฒ์) ์ ๋๋ค.
Javascript ES6 ๋ฌธ๋ฒ์ ์ฌ์ฉํ ๊ฒฝ์ฐ ํน์ ํ์ผ ๋ด์์ export ๋ฌธ์ ์ฌ์ฉํ๋ค๋ฉด ํด๋น ํ์ผ ์์ฒด๊ฐ ํ๋์ ๋ชจ๋์ด ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ํ์ผ ๋ด์์ ๋ณ์๋ฅผ ์ ์ธํ๋ฉด ํด๋น ๋ณ์๋ ์ ์ธ๋ ํ์ผ ๋ด์์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ฉฐ ์ธ๋ถ์์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์๋์ ๊ฐ์ด example.js
๋ผ๋ ํ์ผ ๋ด์์ ์ ์ญ์ผ๋ก var1์ด๋ผ๋ ๋ณ์๋ฅผ ์ ์ธํ๋ค๋ฉด var1์ example.js
ํ์ผ ๋ด์์ ์ ์๋ ํจ์ ๋ฑ์์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ฉฐ ์ธ๋ถ ํ์ผ์์๋ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค.
example.js
let var1;
export function func1() {
...
}
์ด ๊ธ์์ ๋งํ๋ ํ์ผ ๋ณ์๋ ์ด์ฒ๋ผ ํน์ ํ์ผ(๋ชจ๋) ๋ด์ ์ ์ญ์ผ๋ก ์ ์๋์ด ์ค์ฝํ๊ฐ ํ์ผ ๋ด๋ถ๋ก ํ์ ๋ ๋ณ์๋ผ๊ณ ์ ์ํ๊ฒ ์ต๋๋ค.
๋ค์ ๋งํด ํ์ผ ๋ณ์๋ ๋ชจ๋ ๋ฒ์ ์ ์ญ ๋ณ์ (Module Scope Global Variable) ๋ผ๊ณ ํ ์ ์๊ฒ ์ต๋๋ค๋ง, ์ ํฌ ํ์์๋ ์ด๋ ๊ฒ ๊ธด ์ด๋ฆ ๋์ โํ์ผ์ ์ข ์๋ ๋ณ์๋คโ๋ผ๋ ์๋ฏธ๋ฅผ ์ง๊ด์ ์ผ๋ก ์ ์ ์๋ ํ์ผ ๋ณ์ ๋ผ๋ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ํ์ผ ๋ณ์๋ ์ด๋ป๊ฒ ๋์ํ๋ฉฐ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์?
์์ Redux๋ฅผ ํตํด ๊ฐ์ ๋ณ๊ฒฝ์ ์ถ์ ํ ํ์๊ฐ ์๋ ๊ฐ๋ค์ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๊ฒ ๋ค๊ณ ์ธ๊ธํ์ต๋๋ค. ์ด ๊ธ์์๋ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ํ์ผ ๋ณ์๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์๋ฒ ์ฌ์ด๋์์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋๋ ์ ์ค๋ช ํด ๋๋ฆด ํ ๋ฐ, ์ฐ์ ํด๋ผ์ด์ธํธ ์ฌ์ด๋๋ถํฐ ์๊ฐํ๊ฒ ์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด ์จ๋ผ์ธ ์ผํ๋ชฐ ์น์ฌ์ดํธ๋ฅผ ์ด์ํ๋๋ฐ ์ ์ ์ ํ๊ฒฝ์ด ๋ชจ๋ฐ์ผ ํ๊ฒฝ์ธ์ง PC ํ๊ฒฝ์ธ์ง์ ๋ฐ๋ผ ์น ์ฌ์ดํธ์ UI์ UX๋ฅผ ๋ค๋ฅด๊ฒ ์ ๊ณตํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํ๊ฒ ์ต๋๋ค. ๋จ์ํ๊ฒ๋ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ณ๋์ ์์ด์ฝ์ ๋ณด์ฌ์ค๋ค๊ฑฐ๋, ๋ ๋์๊ฐ์ PC ํ๊ฒฝ์์๋ ๋ชจ๋ฌ์ ๋ณด์ฌ์ฃผ๊ณ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์๋ ํ ์คํธ ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๋๋ก ๋์์ ์์ ํ ๋ถ๊ธฐํ ์๋ ์์ต๋๋ค.
์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ์ ์ ๊ฐ ํ์ด์ง์ ์ต์ด ์ง์ ํ์ ๋ ์ ์ ์ userAgent ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ ํ, ์ด๋ฅผ ๋ฐํ์ผ๋ก ์ ์ ๊ฐ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์ธ์ง ์๋์ง๋ฅผ isMobile ์ด๋ผ๋ ๋ถ๋ฆฌ์ธ ๋ณ์์ ์ ์ฅํด ๊ด๋ฆฌํ๊ณ ์ ํฉ๋๋ค. ์ด ์ฑ ์ ๋ชจ๋ ์์๋ ์ด isMobile์ด๋ผ๋ ๊ฐ์ ์ด๋ป๊ฒ ๊ด๋ฆฌํ ์ง์ ์ด์ ์ ๋ง์ถ๊ฒ ์ต๋๋ค.
Info
์์๋ฅผ ์ต๋ํ ๋จ์ํํ๊ธฐ ์ํด์ Boolean ํ์ ๋ณ์์ธ isMobile์ ํ์ฉํ์ผ๋ ์ค ์๋น์ค์์๋ isMobile ๋ณด๋ค ํจ์ฌ ๋ณต์กํ๊ณ ๋ ์๋ฏธ์๋ ๊ฐ๋ค๋ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ์ ํฌ ํ์์๋ ์ ์ ์ ์ก์ธ์ค ํ ํฐ ์ ๋ณด๋ ๋๋ฐ์ด์ค ID์ ๊ฐ์ ์ ์ ๊ด๋ จ ์ ๋ณด๋ค๋ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๊ณ ์์ต๋๋ค.
์ด isMobile ๋ณ์๋ฅผ Redux ์คํ ์ด์์ ์ํ ๊ฐ์ผ๋ก ๊ด๋ฆฌํ๋๋ก ๊ตฌํํ ์๋ ์์ต๋๋ค. ํน์ ๋๋ฉ์ธ์ ์ข ์๋ ์ ๋ณด๊ฐ ์๋๊ณ ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ํ์ฉ๋ ์ ์๋ ์ ๋ณด์ด๋ ์ ์ญ ์คํ ์ด์ ์ ์ฅํด๋๊ณ ํ์ํ ๋๋ง๋ค ๊บผ๋ด ์ฐ๋ฉด ํธํ๊ฒ ์ฃ . ์ ์ ์ ํ๊ฒฝ์ ์ ์ ๊ฐ ์น ์ฌ์ดํธ์ ๋จ์์๋ ๋์ ๋ฐ๋์ง ์๋ ์ ๋ณด์ด๋ฏ๋ก isMobile์ ๊ฐ์ ํ์ด์ง ์ต์ด ์ง์ ์ ํ ๋ฒ๋ง ์ด๊ธฐํํด ์ค๋ค๊ณ ๊ฐ์ ํ์ ๋, ์๋์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ ๊ฒ์ ๋๋ค.
client/
state.js
// isMobile์ด๋ผ๋ ์ํ๋ฅผ redux store์ ์ ์ํฉ๋๋ค.
const initialState = {
isMobile: undefined,
}
client/
_app.js
const isMobile = useSelector(store => store.isMobile);
const dispatch = useDispatch();
// userAgent ์ ๋ณด๋ฅผ ๋ถ์ํด ๋ชจ๋ฐ์ผ ํ๊ฒฝ์ธ์ง ์ฌ๋ถ๋ฅผ ๋ฆฌํดํ๋ ํจ์
function parseUserAgent(userAgent) {
...
}
// ํ์ด์ง ์ต์ด ์ง์
์ isMobile ์ ๋ณด๋ฅผ ํ ๋ฒ ๊ฐฑ์ ํด์ค๋๋ค.
useEffect(() => {
dispatch(actions.setIsMobile(parseUserAgent(window.navigator.userAgent)));
}, []);
_app์์ ์ ์ ์ userAgent ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก Redux ์คํ ์ด์ isMobile
์ํ ๊ฐ์ ๊ฐฑ์ ํด ์ฃผ๊ณ ์์ต๋๋ค. ์ฐ๋ฆฌ์ ๋ชฉํ๋ ์ต๋ํ Redux๋ก ๊ด๋ฆฌ๋๋ ๊ฐ๋ค์ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๋๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ด๋ฏ๋ก, ์ด ๊ฐ์ Redux๋ฅผ ํตํด โ๊ด๋ฆฌโํ ํ์๊ฐ ์๋์ง ๊ณ ๋ฏผํด ๋ด
์๋ค.
isMobile
์ด๋ผ๋ ๊ฐ์ ํ ๋ฒ ํ ๋น๋๋ฉด ๋ ์ด์ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฐ์ด๊ธฐ ๋๋ฌธ์, ํด๋น ๊ฐ์ด ๋ณ๊ฒฝ๋๋์ง ์ค์๊ฐ์ผ๋ก ์ถ์ ํ ํ์๋ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฐ์ด๋ฏ๋ก UI ๋ฆฌ๋ ๋๋ง์ ๊ณ ๋ คํ ํ์๊ฐ ์๋ ๊ฒ์ ๋ฌผ๋ก ์ด๊ณ ์. ์ด ๋ณ์ ํ๋๋ฅผ Redux์์ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ต์ state
, action
, reducer
์ ๋ํ ์ฝ๋๋ฅผ ํ๋ก์ ํธ์ ์ถ๊ฐํด์ผ ํ๋๋ฐ, ์ด๋ ๊ฒ ํฐ ๋น์ฉ์ ๋ค์ฌ์ ๊ด๋ฆฌํ ํ์๊ฐ ์๋์ง ์์ฌ์ค๋ฝ์ต๋๋ค.
์ด isMobile
์ด๋ผ๋ ๋ณ์๋ฅผ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๋๋ก ๋ณ๊ฒฝํด ๋ณด๋ฉด ์ด๋จ๊น์? media.js
๋ผ๋ ํ์ผ์ ์์ฑํ ํ, ์๋์ ๊ฐ์ด isMobile
์ด๋ผ๋ ๋ณ์๋ฅผ ํ์ผ ๋ด์ ์ ์ญ์ผ๋ก ์ ์ธํฉ๋๋ค.
client/
media.js
let isMobile = undefined;
ํ์ผ ๋ณ์๋ ์ ์ธ๋ ํ์ผ ๋ด๋ก ์ค์ฝํ๊ฐ ํ์ ๋๊ธฐ ๋๋ฌธ์ ์ธ๋ถ์์ ์ ๊ทผ์ด ๋ถ๊ฐํฉ๋๋ค. ์ธ๋ถ์์ isMobile ๊ฐ์ ์ฐธ์กฐํ ์ ์๋๋ก getter ํจ์๋ฅผ ์ ์ํ๊ณ export๋ฅผ ํตํด ๋ด๋ณด๋ ์๋ค.
client/
media.js
let isMobile = undefined;
export function getIsMobile() {
if(isMobile === undefined) {
isMobile = parseUserAgent(window.navigator.userAgent);
}
return isMobile;
}
// userAgent ์ ๋ณด๋ฅผ ๋ถ์ํด ๋ชจ๋ฐ์ผ ํ๊ฒฝ์ธ์ง ์ฌ๋ถ๋ฅผ ๋ฆฌํดํ๋ ํจ์
function parseUserAgent(userAgent) {
...
}
์ getter ํจ์์์ ์ฃผ๋ชฉํด์ผ ํ ์ ์ ์ด๊ธฐํ ์์ ์ ๊ฐ์ ํ ๋น๊น์ง ๋ด๋นํ๊ณ ์๋ค๋ ์ ์ ๋๋ค. getter ํจ์์์๋ ๋จ์ํ ๊ฐ์ ๋ฐํํ๊ณ setter ํจ์๋ฅผ ์ถ๊ฐ๋ก ์ ์ํด ์ด์ ์ฝ๋์์์ฒ๋ผ _app์์ setter ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์๋ ์์ต๋๋ค. ํ์ง๋ง isMobile๊ณผ ๊ฐ์ด ๋ฐ๋์ ์ฑ ์์ ์์ ์ ์ด๊ธฐํ ๋ ํ์๊ฐ ์๊ณ , ํ ๋ฒ ์ด๊ธฐํ๋๋ฉด ์ถํ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฐ์์ด ํ์คํ ๊ฒฝ์ฐ์๋ ํด๋น ๊ฐ์ ์ต์ด๋ก ์ฐธ์กฐํ ๋ ์ด๊ธฐํํด ์ค๋ ๋ฌด๋ฐฉํฉ๋๋ค. ์ด๋ฅผ ์ฑ๊ธํด ํจํด์ด๋ผ๊ณ ํฉ๋๋ค.
์์ ๊ฐ์ด isMobile์ด๋ผ๋ ๊ฐ์ ํ์ผ ๋ณ์๋ก ์ ์ํด ์ฌ์ฉํ๋ค๋ฉด Redux๋ก ๊ด๋ฆฌํ ๋ ํ์ํ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ ์ ํ ์์ด ํ์ํ ๋ชจ๋ ๊ณณ์์ ๋จ์ํ getIsMobile ํจ์๋ฅผ ํธ์ถํด ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ํ์ผ ๋ณ์ ์ฌ์ฉ ์ ์ ์ํ ์ ์ ๋ฌด์์ธ๊ฐ์?
์๋ ๋ ์ํฉ์์๋ ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ ์ ์ํด์ผ ํฉ๋๋ค.
1. ํน์ ํ์ด์ง์ ๋ํด SSG๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
๋น๋ ํ์์ HTML์ ์์ฑํด ์ฃผ๋ Static Site Generation (SSG)์ ๊ฒฝ์ฐ, ํ์ผ ๋ณ์๋ฅผ ์ํฌํธํด์ ๋ ๋๋ง์ ์ฌ์ฉํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋๋ผ๋ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ๊ด๋ฆฌ๋๋ ํ์ผ ๋ณ์์ ๊ฐ์ ํ์ฉํ ์ ์๋ค๋ ์ ์ ์ ์ํด์ผ ํฉ๋๋ค. SSG๋ก ์ ๊ณต๋๋ ํ์ด์ง๋ ์จ์ ํ ์๋ฒ์์ ๋น๋ ํ์์ HTML์ด ์์ฑ๋๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ์ ํ์ฌ ์ํ๋ฅผ ์ฐธ์กฐํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ ์์์์ ์ ์ํ getIsMobile
ํจ์์ ๊ฒฝ์ฐ ์๋ฒ ํ๊ฒฝ์๋ window ๊ฐ์ฒด๊ฐ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์, ํด๋น ํจ์๋ฅผ SSG ํ์ด์ง์์ ํธ์ถํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค๋ฉด ์ ํ๋ฆฌ์ผ์ด์
๋น๋ ์์ ์ window is not defined
๋ผ๋ ์๋ฌ๋ฅผ ๋ณด๊ฒ ๋ ๊ฒ์
๋๋ค.
2. Hard Navigation์ผ๋ก ํ์ด์ง๋ฅผ ์ด๋ํ๋ ๊ฒฝ์ฐ
Hard Navigation์ด๋ window.location.href
๋ฅผ ํตํด ํน์ URL๋ก ์ด๋ํ๊ฑฐ๋ a ํ๊ทธ๋ฅผ ํตํด ํ์ด์ง๋ฅผ ์ด๋ํ๋ ๋ฑ โWeb API๋ฅผ ํ์ฉํ ํ์ด์ง ์ด๋ ๋ฐฉ์โ์ ๋ปํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจ ํ๊ฑฐ๋ ๋ธ๋ผ์ฐ์ ์ฃผ์์ฐฝ์ ์ง์ URL์ ์ณ์ ํ์ด์ง์ ์ง์
ํ๋ ๊ฒ๊ณผ ๋์ผํ๊ฒ ํ์ด์ง ์์ฒด๊ฐ ์ฒ์๋ถํฐ ๋ค์ ๊ทธ๋ ค์ง๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ์ํ ๊ฐ๊ณผ ๊ฐ์ด ์ปจํ
์คํธ์ ์ ์ง๋๋ ๋ฐ์ดํฐ์ ํจ๊ป ํ์ผ ๋ณ์ ๋ํ ์ฌ๋ผ์ง๊ฒ ๋ฉ๋๋ค.
์ด์ ๋ฐ๋๋๋ ๊ฐ๋
์ธ Soft Navigation์ Client-Side Navigation์ด๋ผ๊ณ ๋ ๋ถ๋ฆฌ๋ฉฐ, ๋ธ๋ผ์ฐ์ ์ ํ์ด์ง ์ด๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ ๋์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํด ํ์ด์ง ์ด๋์ ๊ตฌํํจ์ผ๋ก์จ ๋ ๋น ๋ฅธ ํ์ด์ง ์ด๋์ ๊ฐ๋ฅ์ผ ํ๊ณ ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ์ ์งํ ์ ์๊ฒ ํด์ค๋๋ค. ์ฐ๋ฆฌ๊ฐ React๋ก ํ๋ก์ ํธ๋ฅผ ๊ตฌํํ ๋ ๋ผ์ฐํ
์ ์ํด react-router
์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋, Next.js์์ useRouter
์ ๊ฐ์ ๋ผ์ฐํ
๊ด๋ จ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํด์ผ ํ๋ ์ด์ ์
๋๋ค.
๋ฐ๋ผ์, ์ด๋ค ์ด์ ์์๊ฑด Hard Navigation์ ํ๋ก์ ํธ์์ ์ฌ์ฉํด์ผ ํ๋ค๋ฉด ํด๋น ์์ ์ ํด๋ผ์ด์ธํธ์ ํ์ผ ๋ณ์ ๊ฐ์ด ์ ์ง๋์ง ์๋๋ค๋ ์ ์ ์ ์ํด์ผ ํฉ๋๋ค.
Deep-Dive: ํ์ด์ง ์ด๋ ์ ํ์ผ ๋ณ์์ ๊ฐ์ด ์ด๊ธฐํ๋์ง๋ ์๋์?
์ฌ๊ธฐ์ ์ด๋ฐ ์๋ฌธ์ด ๋ค ์ ์์ต๋๋ค.
ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ํ์ด์ง๊ฐ ์๋๋ผ ์ฌ์ฉํ์ง ์๋ ํ์ด์ง๋ก ์ด๋ํ๋ค๋ฉด ํ์ผ ๋ณ์์ ๊ฐ์ด ์ฌ๋ผ์ง๋ ๊ฑฐ ์๋๊ฐ? ์ด๋ํ ํ์ด์ง์์๋ ๋ ์ด์ ํ์ผ ๋ณ์๊ฐ ์ ์๋ ํ์ผ์ ์ํฌํธํ์ง ์๋๋ฐ!
ํ๋นํ ์๋ฌธ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ ํ๊ฒฝ์์๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์ฃผ๊ธฐ์ ์ผ๋ก ๋์ํ๋ฉฐ, ํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋น๋์ด ์๋ ํน์ ๋ฐ์ดํฐ๊ฐ ๋ ์ด์ ์ฐธ์กฐ๋์ง ์๋๋ค๋ฉด - ํน์ ํด๋น ๋ฐ์ดํฐ์ ๋ ์ด์ ๋๋ฌํ ์ ์๋ค๋ฉด - ๋ฉ๋ชจ๋ฆฌ์์ ํ ๋น ํด์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ง์ฝ ๋ด๊ฐ A๋ผ๋ ํ์ด์ง์์ isMobile์ด๋ผ๋ ํ์ผ ๋ณ์๋ฅผ ์ํฌํธํด์ ์ฌ์ฉํ๋ค๊ฐ ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์๋ B๋ผ๋ ํ์ด์ง๋ก ์ด๋ํ์ ๋, ์ด๋ํ ํ์ด์ง์์๋ ๋ ์ด์ isMobile์ ์ฐธ์กฐํ๋ ๊ณณ์ด ์์ผ๋ฏ๋ก ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ํ์ผ ๋ณ์๋ฅผ ์ง์๋ฒ๋ฆฌ์ง ์์๊น์?
๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ์๋ฉด ํ ๋ฒ ์ํฌํธ ๋ ES6 ๋ชจ๋์ ๋ํด์๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ํ์ผ ๋ณ์์ ๊ฐ์ด ๋ ์๊ฐ๋ ๊ฑฑ์ ์ ํ์ง ์์๋ ๋ฉ๋๋ค. ์ด๋ป๊ฒ ๊ฐ์ด ์ ์ง๋๋์ง๋ฅผ ์๊ธฐ ์ํด์๋ HTML ์คํ์ ์กฐ๊ธ ๊น์ด ์ดํด๋ณผ ํ์๊ฐ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์ด ์น ์ฌ์ดํธ์ ์ ์ํ๋ฉด ์ฌ๋ฌ๋ชจ๋ก ์น์ํ์ค document ๋ผ๋ ๊ฐ์ฒด๊ฐ ์์ฑ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๊ฐ์ฒด๋ Soft Navigation์ ํตํด URL์ด ๋ณ๊ฒฝ๋๋ ๋ฑ์ ๋์์ผ๋ก ๋ด๋ถ ๊ฐ์ด ๋ณ๊ฒฝ๋ ์๋ ์์ด๋, ํ ๋ฒ ์์ฑ๋๋ฉด ์ ์ ๊ฐ ์น ์ฌ์ดํธ๋ฅผ ์ดํํ๊ฑฐ๋ Hard Navigation์ ํตํด ๊ธฐ์กด DOM ์ ๋ณด๋ฅผ ๋ชจ๋ ์์คํ์ง ์๋ ํ ๊ณ์ ์ ์ง๋ฉ๋๋ค. HTML5์ ๋ํ ํ์ค ์คํ์ด ๋ช ์๋์ด ์๋ HTML Standard ์๋ Document์ ๋ํ ํญ๋ชฉ์ด ์กด์ฌํ๋๋ฐ, ์ด ํญ๋ชฉ์๋ ์๋์ ๊ฐ์ ๋ด์ฉ์ด ์กด์ฌํฉ๋๋ค.
๊ฐ Document ๊ฐ์ฒด๋ ์ด๊ธฐ์ ๊ฐ์ด ๋น์ด์๋ ๋ชจ๋ ๋งต (Module Map)์ ๊ฐ์ง๊ณ ์๋ค.**
๋ชจ๋ ๋งต์ด ์ ํํ ๋ฌด์์ด๊ณ ์ด๋ค ์ญํ ์ ํ๋์ง๋ Mozilla ๋ธ๋ก๊ทธ ํฌ์คํ ์ ์์ฃผ ์์ธํ๊ฒ ์ค๋ช ๋์ด ์์ต๋๋ค. ๋ค๋ง ํด๋น ๋ด์ฉ์ด ๋งค์ฐ ๊ธธ๊ธฐ ๋๋ฌธ์, ์ด ๊ธ์์๋ ๋ชจ๋ ๋งต์ด ๋ค์๊ณผ ๊ฐ์ ํน์ฑ์ ๊ฐ์ง๋ค๋ ๊ฒ๋ง ์ง๊ณ ๋์ด๊ฐ๋ ์ถฉ๋ถํฉ๋๋ค.
- ๋ชจ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ํฌํธํ๋ฉด ์ด ์ ๋ณด๊ฐ ๋ชจ๋ ๋งต์ ์ ์ฅ๋ฉ๋๋ค.
- ๋ชจ๋ ๋งต์ ๋ชจ๋ ์คํฌ๋ฆฝํธ์ ๋ํ ์บ์ ์ ์ฅ์ ์ญํ ์ ์ ๊ณตํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ง๋ง์ผ๋ก HTML5 ํ์ค ์คํ์์๋ ๋ชจ๋ ๋งต์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช ํ๊ณ ์์ต๋๋ค.
๋ชจ๋ ๋งต์ ์ํฌํธ ๋ ๋ชจ๋ ์คํฌ๋ฆฝํธ๋ค์ด Document๋ ์์ปค ๋น ํ ๋ฒ๋ง ํจ์น / ํ์ฑ / ํ๊ฐ๋๋๋ก ๋ณด์ฅํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
์ด ๋ด์ฉ๋ค์ ์กฐํฉํด ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ฒฐ๋ก ์ ๋ด๋ฆด ์ ์์ต๋๋ค.
์น ์ฌ์ดํธ ์ง์ ์ ํ ๋ฒ ์์ฑ๋๊ณ ํด์ ๋์ง ์๋ Document ๊ฐ์ฒด๋ ๋ชจ๋ ๋งต์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์ด ๋ชจ๋ ๋งต์ ํน์ ๋ชจ๋์ ๋จ ํ ๋ฒ๋ง ๊ฐ์ ธ์ค๋๋ก ๋ณด์ฅํด ์ค๋๋ค.
์ด์ ํ์ด์ง์์ ์ํฌํธ ๋ ๋ชจ๋์ด ํ์ฌ ํ์ด์ง์์ ์ฌ์ฉ๋์ง ์๋๋ค๊ณ ๊ฐ๋น์ง ์ปฌ๋ ์ ์ ํ๋ค๋ฉด, ๋ค์ ๋ชจ๋์ ์ฌ์ฉํ๋ ํ์ด์ง๋ก ์ด๋ํ์ ๋ ๋ชจ๋์ ๋ฆฌํจ์นํด์ผ ํ๋๋ฐ ์ด๋ ๋ชจ๋ ๋งต์ด ํน์ ๋ชจ๋์ ๋จ ํ ๋ฒ๋ง ํจ์นํ๋๋ก ๋ณด์ฅํด์ผ ํ๋ค๋ ์์น์ ๊นจ๋จ๋ฆฌ๋ ์ผ์ด ๋๊ฒ ์ฃ . ๋ฐ๋ผ์, ํ ๋ฒ ์ํฌํธ ๋ ๋ชจ๋์ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋์ง ์์ผ๋ฉฐ ํด๋น ๋ชจ๋์ด ์ ์ญ ๋ณ์๋ก์จ ์ฐธ์กฐํ๊ณ ์๋ ํ์ผ ๋ณ์ ๋ํ ๊ฐ๋น์ง ์ปฌ๋ ์ ๋์ง ์๋๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ฆด ์ ์์ต๋๋ค.
์๋ฒ ์ฌ์ด๋ (Node.js ํ๊ฒฝ)์์ ํ์ผ ๋ณ์๋ ์ด๋ป๊ฒ ๋์ํ๋ฉฐ ์ด๋ป๊ฒ ์ฌ์ฉํด์ผ ํ๋์?
์ง๊ธ๊น์ง๋ ํด๋ผ์ด์ธํธ ํ๊ฒฝ์์ ํ์ผ ๋ณ์๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ดค์ต๋๋ค. ๊ทธ๋ฐ๋ฐ, ๋ง์ฝ ์๋ฒ ํ๊ฒฝ์์ ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ์ ์ ๊ฐ PC์น ํ๊ฒฝ์ด ์๋๋ผ ๋ชจ๋ฐ์ผ ์น ํ๊ฒฝ์์ /pc-only ๋ผ๋ URL๋ก ์ ๊ทผ์ ์๋ํ์ ๋, ํด๋น ์์ฒญ์ /mobile-only ๋ผ๋ URL๋ก ๋ฆฌ๋ค์ด๋ ํธ ์ํค๊ธฐ ์ํด Node.js ์๋ฒ ํ๊ฒฝ์์ ๋ค์๊ณผ ๊ฐ์ Express ๋ฏธ๋ค์จ์ด๋ฅผ ์์ฑํ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค.
export async function pcOnlyMiddleware(req, res, next) {
const isMobile = parseUserAgent(req.headers['user-agent']);
if (req.path === '/pc-only' && isMobile) {
res.redirect('/mobile-only');
return;
}
next();
return;
}
์๋ฒ ์ฌ์ด๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค ๋ณด๋ ์ ์ ๊ฐ ๋ชจ๋ฐ์ผ ์น ํ๊ฒฝ์ธ์ง ์ฌ๋ถ๋ฅผ ํ์ธํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ก๊ณ , ์ด๋๋ง๋ค Request ํค๋๋ฅผ ์ผ์ผ์ด ํ์ฑํ๋ ์ฝ๋๋ฅผ ๋ฃ๊ธฐ๊ฐ ๋ฒ๊ฑฐ๋ก์ด ๋๋จธ์ง ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ํ๋ ๊ฒ๊ณผ ๋์ผํ๊ฒ isMobile์ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๊ณ ์ ํฉ๋๋ค.
server/
media.js
let isMobile = undefined;
export function getIsMobile() {
return isMobile;
}
export function setIsMobile(req) {
if(isMobile === undefined) {
isMobile = parseUserAgent(req.headers['user-agent']);
}
}
server/
mediaMiddleware.js
import { setIsMobile } from "./media.js";
export async function mediaMiddleware(req, res, next) {
setIsMobile(req);
next();
return;
}
ํ์ผ ๋ณ์ ๊ฐ ์ด๊ธฐํ์๋ request ๊ฐ์ฒด๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํด ํจํด์ ํ์ฉํ์ง ์๊ณ setIsMobile ์ด๋ผ๋ setter ํจ์๋ฅผ ์ ์ํ๋ค๋ ์ ๋ง ์ ์ธํ๋ฉด ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ๊ฑฐ์ ์ ์ฌํฉ๋๋ค. ๊ทธ๋ ๋ค๋ฉด ์ ์ฝ๋๋ ์๋ฒ ์ฌ์ด๋์์ ์ ์์ ์ผ๋ก ๋์ํ ๊น์?
์๋ฒ ์ฌ์ด๋์์ ํ์ผ ๋ณ์๋ ๋ชจ๋ ์ ์ ๊ฐ ๊ณต์ ๋ฉ๋๋ค.
์๋ฒ์์ ์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์น๋ช ์ ์ธ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ํ์ผ ๋ณ์๋ผ๋ ์์์ด ์๋ฒ์ ์ ๊ทผํ๋ ๋ชจ๋ ์ ์ ์ ๋ํด ๊ณต์ ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ์ด ๊ธ์ ๋ฉ์ธ ์ฃผ์ ๋ ์ด๋๊น์ง๋ ํ์ผ ๋ณ์์ด๊ธฐ ๋๋ฌธ์ ์๋ฒ ๋์์ ๋ํด ๊น๊ฒ ๋ค์ด๊ฐ์ง๋ ์๊ฒ ์ต๋๋ค. ์์ ํ ์ ์ ํ์ง๋ ์์ ์๋ ์์ผ๋ ์ข ๋ ์ดํดํ๊ธฐ ์ฌ์ด ๋น์ ๋ฅผ ํตํด ์ด๋ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋์ง ์ค๋ช ํด ๋ณด๊ฒ ์ต๋๋ค. ์ฌ๋ฌ๋ถ์ด ๋ธ๋ผ์ฐ์ ๋ฅผ ์ด๊ณ ํน์ ์น์ฌ์ดํธ์ ์ ์ํ๋ค๋ฉด, ์ฌ๋ฌ๋ถ์ ํด๋น ์น์ฌ์ดํธ์ ๋ํ ๋ ๋ฆฝ์ ์ธ โ์ปจํ ์คํธโ๋ฅผ ํ๋ ์์ฑํด ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ์ฌ๊ธฐ์ ๋งํ๋ ์ปจํ ์คํธ๋ ํ์ฌ ์ ์ํ ์น์ฌ์ดํธ์์ ์ฌ๋ฌ๋ถ์๊ฒ UI๋ ๊ธฐ๋ฅ๋ค์ ์ ๊ณตํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ์ํ ๊ฐ ๋ฑ์ ์๋ฏธํ๋ฉฐ, ์ด ๊ฐ์ ์ฌ๋ฌ๋ถ์ ๋ธ๋ผ์ฐ์ ์ ์ ์ฅ๋์ด ๊ด๋ฆฌ๋๋ ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ์ธ๋ถ์์ ์ฌ๋ฌ๋ถ์ ์ปจํ ์คํธ์ ์ ๊ทผํ๊ฑฐ๋ ์ ์ดํ ์ ์์ต๋๋ค. ์น ์ฌ์ดํธ์ ์ ์ํ๋ ์ ์ ๋ค์ ๊ฐ๊ฐ์ ๋ธ๋ผ์ฐ์ ์์ ๊ฐ๊ฐ์ ์ปจํ ์คํธ๋ฅผ ๊ฐ์ง๋ฉฐ ์ด ์ปจํ ์คํธ ๋ด๋ถ์ ์๋ ์์๋ค์ ์๋ก ๊ณต์ ๋์ง ์์ต๋๋ค.
์๋ฒ๊ฐ ํ๋ ๋ ์๋ค๋ ๊ฒ์ ์ปจํ ์คํธ ๊ด์ ์์ ๋ธ๋ผ์ฐ์ ๋ฅผ ํ๋๋ง ์ฌ์ฉํ๋ค๋ ๊ฒ๊ณผ ์ ์ฌํ๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๋ฅผ ํ ์ ์ ๋ง ์ฌ์ฉํ๊ณ ์๋ค๋ฉด ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ํ๋์ ์ ์ ๊ฐ ํ๋์ ์ปจํ ์คํธ๋ฅผ ๊ฐ์ง๋ ์ผ๋ฐ์ ์ด๊ณ ์์ฐ์ค๋ฌ์ด ์ํฉ์ด๋๊น์. ํ์ง๋ง ์๋ฒ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์์ ์ ์ ์ ๋ํ ์์ฒญ์ ์ฒ๋ฆฌํ ๋ชฉ์ ์ผ๋ก ๊ตฌ์ถ๋๋ฉฐ, ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ฌ๋ฌ ์ ์ ๊ฐ ์๋ฒ์ ๋์์ ์ ๊ทผํ๋ค๋ฉด, ๋ธ๋ผ์ฐ์ ๋ ํ๋๋ง ๋ ์๋๋ฐ ๊ทธ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ฌ๋ฌ ์ ์ ๊ฐ ๋์์ ์ฌ์ฉํ๊ฒ ๋๋ค๋ ๋ป์ ๋๋ค. ์ฆ, ํ๋์ ์ปจํ ์คํธ๋ฅผ ์ฌ๋ฌ ์ ์ ๊ฐ ๊ณต์ ํ๋ค๋ ๋ป์ ๋๋ค. ๋๋ ๋ถ๋ช ํ ๋ด ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธํ๋๋ฐ ์ด๋ ์๊ฐ๋ถํฐ ๋์ค์ ๋ก๊ทธ์ธํ ๋ค๋ฅธ ์ ์ ์ ๊ณ์ ์ ์ฌ์ฉํ๊ฒ ๋ ์๋ ์์ต๋๋ค. ์ฆ๊ฒจ์ฐพ๊ธฐ ํ ์ ์ด ์๋ ์ํ๋ค์ด ์ด๋ ์๊ฐ๋ถํฐ ์ฆ๊ฒจ์ฐพ๊ธฐ์ ์ถ๊ฐ๋ ์๋ ์์ฃ . ๊ฑฐ์ ํดํน์ด๋ ๋ค๋ฅผ ๋ฐ ์์ต๋๋ค.
ํ์ผ ๋ณ์๋ ๋ชจ๋์ ์ ์๋ฉ๋๋ค. ์๋ฒ์๋ ๋ธ๋ผ์ฐ์ ๊ฐ ํ๋์ด๋ฏ๋ก ๋ชจ๋๋ ํ๋๋ง ์ํฌํธ๋์ด ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๋ชจ๋์ ์๋ฒ์ ๋ชจ๋ ์ ์ ๊ฐ ๊ณต์ ํ๊ฒ ๋ฉ๋๋ค. ๋ง์ฝ ์ ์ฝ๋์ ๊ฐ์ด Express ๋ฏธ๋ค์จ์ด์ ํ์ผ๋ณ์๋ฅผ ์ ์ํ๋ค๋ฉด, ํ์ผ๋ณ์๊ฐ ์ด๊ธฐํ๋์ง ์์ ์ต์ด ์์ ์ ์๋ฒ์ ์ ๊ทผํ ์ ์ ์ ๋ฐ๋ผ isMobile์ ๊ฐ์ด ๊ฒฐ์ ๋ ๊ฒ์ด๋ฉฐ ์ด ๊ฐ์ ๋ชจ๋ ์ ์ ๊ฐ ๊ณต์ ํ๊ฒ ๋ ๊ฒ์ ๋๋ค. isMobile์ด๋ผ๋ ๊ฐ์ ๊ฐ ์ ์ ์ ๋ํด์ ๊ด๋ฆฌ๋์ด์ผ ํ๋๋ฐ, ์ด๋ ์ฐ๋ฆฌ๊ฐ ์๋ํ๋ ๋์๊ณผ๋ ์ ํ ๋ค๋ฆ ๋๋ค. ์น์ฌ์ดํธ์ ์ฒ์ ์ ์ํ A๋ผ๋ ์ ์ ๊ฐ ๋ชจ๋ฐ์ผ ์น ํ๊ฒฝ์ด๋ผ๋ฉด isMobile์ true๋ก ์ด๊ธฐํ๋ ๊ฒ์ด๊ณ , ๊ทธ ์ดํ์ ์ ์ํ B๋ผ๋ ์ ์ ๋ PC์น ํ๊ฒฝ์์๋ ๋ถ๊ตฌํ๊ณ ๋ง์น ๋ชจ์น ํ๊ฒฝ์ธ ๊ฒ์ฒ๋ผ ์ธ์๋ ๊ฒ์ด๋ผ๋ ๋ป์ ๋๋ค. isMobile์ด ๋จ์ํ ๋ชจ๋ฐ์ผ ์ฌ๋ถ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ์ด๋ผ ๋ง์ ์ด์ง ์ ์ ์ ๊ฐ์ธ์ ๋ณด๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ์ด์๋ค๋ฉด, ์ ์ B๋ ์๋์น ์๊ฒ A์ ๊ฐ์ธ์ ๋ณด์ ์ ๊ทผํ์ ๊ฒ์ ๋๋ค. ๋์ฐํ ์ํฉ์ด์ฃ . ์ฆ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์๋ฒ ์ฌ์ด๋์์ ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ด ํ์ผ ๋ณ์ ๊ฐ์ ๋ค๋ฅธ ์ ์ ์ ๊ณต์ ํ๊ฒ ๋๊ณ , ๋ค๋ฅธ ์ ์ ๊ฐ ํ์ผ ๋ณ์ ๊ฐ์ ๋ณ๊ฒฝํ๋ฉด ๋๋ ์ํฅ์ ๋ฐ๋๋ค๋ ๋ฌธ์ ์ ์ง๋ฉดํ๊ฒ ๋ฉ๋๋ค.
AsyncLocalStorage๋ฅผ ํ์ฉํด ๊ฐ๋ณ์ ์ธ ์ปจํ ์คํธ๋ฅผ ๊ฐ์ง๊ฒ ๋ง๋ค์ด๋ด ์๋ค.
๊ทธ๋ ๋ค๋ฉด ์ ํฌ๊ฐ ์ฌ์ฉํ๋ Node.js ์๋ฒ ํ๊ฒฝ์์ ํ์ผ ๋ณ์๋ฅผ ํ์ฉํ ์ ์๋ ๊ฑธ๊น์? ํ์ฌ ๋ฌธ์ ๋ โ๋ชจ๋ ์ ์ ๊ฐ ๋์ผํ ๋ธ๋ผ์ฐ์ (์ปจํ ์คํธ)๋ฅผ ์ฌ์ฉํ๋คโ๋ผ๋ ๊ณณ์์ ์ถ๋ฐํ๋ฏ๋ก, ๊ฐ ์ ์ ๊ฐ ์๋ฒ์ ์ ๊ทผํ ๋๋ง๋ค ๊ฐ๊ธฐ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ฅผ ์๋ก ๋์ ์ฌ์ฉํ๋๋ก ๊ตฌํํ๋ค๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ ๊ฒ ๊ฐ์๋ฐ์. Node.js๊ฐ 16.4 ๋ฒ์ ์ดํ๋ถํฐ ์ ์ ๊ธฐ๋ฅ์ผ๋ก ์ ๊ณตํ๋ ํด๋์ค ์ค ํ๋์ธ AsyncLocalStorage ๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค.
Info
AsyncLocalStorage ํด๋์ค๋ฅผ ์ ๊ณตํ๋ Async Hooks ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฝ์ฐ ์ ๊ณตํ๋ ๋๋ค์์ ๊ธฐ๋ฅ์ด Stability 1, ์ฆ ์คํ์ ๊ธฐ๋ฅ์ผ๋ก ์ ๊ณต๋๊ณ ์์ต๋๋ค. ์ด ๊ธ์์๋ Stable๋ก ๋ช ์๋ ์์ ์ ์ธ ๊ธฐ๋ฅ๋ค๋ง ์๊ฐํฉ๋๋ค.
Node.js์ ๊ณต์ ๋ฌธ์๋ฅผ ๋ณด๋ฉด AsyncLocalStorage์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช ํ๊ณ ์์ต๋๋ค.
Info
์ด ํด๋์ค๋ ๋น๋๊ธฐ ์์ ์ ํตํด ์ผ๊ด์ฑ์ ์ ์งํ๋ ์ ์ฅ์๋ฅผ ์์ฑํฉ๋๋ค. AsyncLocalStorage์ ๊ฐ ์ธ์คํด์ค๋ ๋ ๋ฆฝ์ ์ธ ์ ์ฅ์ ์ปจํ ์คํธ๋ฅผ ์ ์งํฉ๋๋ค. ์ฌ๋ฌ ์ธ์คํด์ค๋ ์๋ก์ ๋ฐ์ดํฐ์ ๊ฐ์ญํ ์ํ ์์ด ๋์์ ์์ ํ๊ฒ ์กด์ฌํ ์ ์์ต๋๋ค.
์ ์ค๋ช ์์ โ๋ ๋ฆฝ์ ์ธ ์ ์ฅ์ ์ปจํ ์คํธ๋ฅผ ์ ์งํ๋คโ๋ผ๋ ๋ถ๋ถ์ ์ฃผ๋ชฉํด์ผ ํฉ๋๋ค. AsyncLocalStorage๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๊ฐ ์์ฒญ๋ณ๋ก ๋ณ๋์ ์ปจํ ์คํธ๋ฅผ ์ ์งํ ์ ์๊ฒ ๋ฉ๋๋ค. ์ฆ, ๊ฐ ์ ์ ์ ๋ํด ๊ฐ๊ธฐ ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ฅผ ๋์์ฃผ๋ ์ญํ ์ ํ ์ ์๋ค๋ ์๋ฏธ์ฃ .
AsyncLocalStorage๋ Next.js
ํ๋ ์์ํฌ ์์ฒด์์๋ ์๋ฒ ์ฌ์ด๋์ headers, cookies ๋ฑ์ ์ ๊ทผํ ๋ ํ์ฉํ๊ณ ์์๋งํผ (vercel/next.js
) ํ์
์์ ํ๋ฐํ๊ฒ ์ฌ์ฉ๋๊ณ ์๋ ๊ธฐ์ ์
๋๋ค.
์์ ์๋ชป๋ ํ์ผ ๋ณ์ ์์ ๋ฅผ AsyncLocalStorage๋ฅผ ํ์ฉํด์ ๋ค์ ๊ตฌํํด ๋ด ์๋ค.
server/
media.js
import {AsyncLocalStorage} from 'async_hooks';
const isMobile = new AsyncLocalStorage();
export function getIsMobile() {
return isMobile.getStore();
}
export function setIsMobile(_isMobile, callback) {
isMobile.run(_isMobile, callback);
}
server/
mediaMiddleware.js
import { setIsMobile } from "./media.js";
export async function mediaMiddleware(req, res, next) {
const isMobile = parseUserAgent(req.headers['user-agent']);
setIsMobile(isMobile, next);
return;
}
์ฐ์ media.js
๋ผ๋ ํ์ผ์ AsyncLocalStorage
๋ผ๋ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ํ, ์ด๋ฅผ isMobile
์ด๋ผ๋ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํฉ๋๋ค. getStore
ํจ์๋ AsyncLocalStorage
์ ์ ์ฅ๋ ๊ฐ์ ๊บผ๋ด๊ธฐ ์ํด ์ฌ์ฉ๋๋ฏ๋ก ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํด getter ํจ์์ธ getIsMobile ํจ์๋ฅผ ๊ตฌํํฉ๋๋ค.
setter ํจ์์ธ setIsMobile
์์ ์ฌ์ฉ๋ run ํจ์๋ AsyncLocalStorage
์ ์ ์ฅํ ๊ฐ์ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ๋ฐ๊ณ , ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ ๋ฒ์งธ ์ธ์๋ก ๋ฐ์ต๋๋ค. ์ฝ๋ฐฑ ํจ์๋ฅผ ๋ฐ๋ ์ด์ ๋ AsyncLocalStorage
๊ฐ ์ปจํ
์คํธ ์ ์ฅ์๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ์ ๋๋ฌธ์ธ๋ฐ, ์ด ์ ์ฅ์๋ ์ฃผ์ด์ง ์ฝ๋ฐฑ ํจ์๋ก๋ถํฐ ์์ฑ๋ ๋น๋๊ธฐ ์์
์ ๋ํด์๋ง ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค. ์ฆ, ์ด๋ฏธ run ํจ์๋ฅผ ํธ์ถํด AsyncLocalStorage
์ ์ฅ์์ ํน์ ๊ฐ์ ์ ์ฅํ๋ค๊ณ ํ๋๋ผ๋ ์ฝ๋ฐฑ ํจ์๋ก๋ถํฐ ํ์๋ ์์
์ด ์๋ ์ธ๋ถ ์์
์ด๋ผ๋ฉด ์ ์ฅ์์ ์ ๊ทผํ์ง ๋ชปํฉ๋๋ค.
๋ฐ๋ผ์, AsyncLocalStorage
์ isMobile
์ ๋ณด๋ฅผ ์ ์ฅํ๋ ์ญํ ์ ๋ด๋นํ๋ mediaMiddleware
๋ฏธ๋ค์จ์ด๋ฅผ ๊ฐ์ฅ ์๋จ์ ์์น์ํจ๋ค๋ฉด ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์์ ์ ์ฌํ๊ฒ ํ์ผ ๋ณ์๋ฅผ ์์น์ ๊ตฌ์ ๋ฐ์ง ์๊ณ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ๋ mediaMiddleware
์ดํ์ ๋ชจ๋ ์๋ฒ ์์
์ ๋ํด isMobile
์ ์ํ๋ ๊ณณ์์ ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋์์ต๋๋ค. ์ปจํ
์คํธ๊ฐ ๊ณต์ ๋๋ ๋ฌธ์ ๋ ๋ ์ด์ ๊ฑฑ์ ํ ํ์๊ฐ ์์ต๋๋ค.
ํ๊ฒฝ์ ์๊ด์์ด ํ์ผ ๋ณ์๋ฅผ ์์ ๋กญ๊ฒ ๋ค๋ฃจ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ๋์?
์ฐ๋ฆฌ๋ ์ง๊ธ๊น์ง ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ ์๋ฒ ์ฌ์ด๋์์ ๊ฐ๊ฐ ํ์ผ ๋ณ์๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ดํด๋ดค์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ์ ์์๋ค์์ ์ดํด๋ดค๋ค์ํผ ํด๋ผ์ด์ธํธ์์ ์ฌ์ฉ๋๋ ํ์ผ ๋ณ์์ ์๋ฒ์์ ์ฌ์ฉ๋๋ ํ์ผ ๋ณ์๋ฅผ ๊ฐ๊ธฐ ๋ค๋ฅธ ํ์ผ์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ์ ์ธํด์ ์ฌ์ฉํ๋ค ๋ณด๋ ํ์ผ ๋ณ์๋ฅผ ์ฌ์ฉํ ๋ ์ด๋ค ํ๊ฒฝ์ธ์ง๋ฅผ ํญ์ ์ ๊ฒฝ ์จ์ค์ผ ํ๋ ๋ถ๋ถ์ด ๋ถํธํด ๋ณด์ ๋๋ค.
๋ํ isMobile
์ด๋ผ๋ ๊ฐ์ ์๋ฏธ๋ฅผ ๊ฐ์ง๋ ๋ณ์๋ฅผ ํด๋ผ์ด์ธํธ์์๋ window.navigator.userAgent
๋ผ๋ ์ ๋ณด๋ฅผ ํตํด ์ด๊ธฐํํ๊ณ ์๋ฒ์์๋ req.headers['user-agent']
๋ผ๋ โ๋ค๋ฅธ ์ ๋ณดโ๋ฅผ ํตํด ์ด๊ธฐํํ๋ค๋ ์ ๋ ๋ง์์ ๊ฑธ๋ฆฝ๋๋ค. ์ด์์ด๋ฉด ์๋ฒ์ ํด๋ผ์ด์ธํธ ํ๊ฒฝ ๋ชจ๋์์ ๊ฐ์ ์ ๋ณด๋ฅผ ๋ฐ๋ผ๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ์ต๋๋ค.
ํ์ผ ๋ณ์๋ฅผ ํ๊ฒฝ๊ณผ ์๊ด์์ด ํ ๊ณณ์์ ๊ด๋ฆฌํ๊ณ , ์๋ฒ์ ํด๋ผ์ด์ธํธ์์ ๋์ผํ ๊ฐ์ ๊ฐ์ง๋๋ก ๋ง๋ค ์๋ ์์๊น์? ์ง๊ธ๋ถํฐ ์ ํฌ ํ์์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๊ฒ ์ต๋๋ค.
1. ํด๋ผ์ด์ธํธ์ ์๋ฒ์์ ๋ชจ๋ ์ฌ์ฉํ ํ์ผ ๋ณ์๋ฅผ ์ ์ํฉ๋๋ค.
์ฐ์ ํ์ผ ๋ณ์ isMobile
์ ์๋์ ๊ฐ์ UserAgent ํด๋์ค์ ์ธ์คํด์ค๋ก ์ ์ํ๊ฒ ์ต๋๋ค. ์ ์ฒด ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ผ๋ฉฐ, ์๋์์ ๋ ์์ธํ๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
media.js
const IS_CLIENT = typeof window !== 'undefined';
class UserAgent {
#isMobileClient; // Boolean
#isMobileServer; // AsyncLocalStorage
public getIsMobile() {
if(IS_CLIENT) {
return this.#isMobileClient;
} else {
return this.#isMobileServer.get();
}
}
public setIsMobileClient(_isMobile) {
this.#isMobileClient = _isMobile;
}
public setIsMobileServer(_isMobile, callback) {
if(!this.#isMobileServer) {
this.#isMobileServer = new AsyncLocalStorage();
}
this.#isMobileServer.run(_isMobile, callback);
}
}
export const isMobile = new UserAgent();
export const isMobile = new UserAgent();
์ด์ ์์๋ค๊ณผ๋ ๋ฌ๋ฆฌ ์์๋ก ์ ์ํ UserAgent
์ด๋ผ๋ ํด๋์ค์ ์ธ์คํด์ค๋ก ํ์ผ ๋ณ์๋ฅผ ๊ด๋ฆฌํ๋๋ก ๋ณ๊ฒฝ๋์์ต๋๋ค. ์ด๋ ํ ๊ณณ์์ โํด๋ผ์ด์ธํธ์ isMobileโ๊ณผ โ์๋ฒ์ isMobileโ ๊ฐ์ ๊ฐ๊ฐ ๋ณ๋๋ก ๊ด๋ฆฌํ๊ธฐ ์ํจ์ธ๋ฐ์. ์๋ฒ์์๋ ์์ฒญ๋ณ๋ก ๋ณ๋์ ์ปจํ
์คํธ๋ฅผ ์ ์งํ๊ธฐ ์ํด AsyncLocalStorage
๋ฅผ ์ฌ์ฉํด์ผ ํ์ง๋ง ํด๋ผ์ด์ธํธ์์๋ ํด๋น ํด๋์ค๊ฐ ์ง์๋์ง ์๊ณ , ํด๋ผ์ด์ธํธ์์๋ ๋จ์ Boolean ํ๋๋ก ๊ด๋ฆฌํ ์ ์์ง๋ง ์ด ๊ฒฝ์ฐ ์๋ฒ์์ ์ปจํ
์คํธ๊ฐ ๋ถ๋ฆฌ๋์ง ์๊ธฐ ๋๋ฌธ์ ๋ถ๊ฐํผํ๊ฒ ๋ณ๋๋ก ๊ด๋ฆฌํด์ผ ํ๋ ๋ถ๋ถ์
๋๋ค.
๋ฐ๋ผ์ ์๋ฒ์ isMobile
๊ฐ์ ํด๋์ค์ isMobileServer
ํ๋๋ก ๊ด๋ฆฌํ๊ณ ํด๋ผ์ด์ธํธ๋ isMobileClient
ํ๋๋ก ๊ด๋ฆฌํ๋๋ก ๊ตฌํํ๊ณ , private(#)
์ผ๋ก ์ ์ธํ์ฌ ๋ด๋ถ ์์ฑ์ ์ง์ ์ ๊ทผํ ์ ์๋๋ก ์ ์ํฉ๋๋ค. ํ๋ ์์ฒด๋ ๋ณ๋๋ก ๊ด๋ฆฌํ๋ ์ดํ ๊ณผ์ ์์ ๋ ํ๋๊ฐ ๊ฐ์ ๊ฐ์ ๊ฐ์ง ์ ์๋๋ก ์ฒ๋ฆฌํ ์์ ์
๋๋ค.
public getIsMobile() {
if(IS_CLIENT) {
return this.#isMobileClient;
} else {
return this.#isMobileServer.get();
}
}
๋ด๋ถ์ ์ผ๋ก๋ isMobileServer์ isMobileClient ๋ ํ๋๋ก ๋๋ ์ ๊ฐ์ ๊ด๋ฆฌํ์ง๋ง, ์ค์ ๋ก getIsMobile
ํจ์๋ฅผ ํธ์ถํด ๊ฐ์ ์ฌ์ฉํ๋ ๊ณณ์์๋ ํ์ฌ ํ๊ฒฝ์ ์ ํ์๊ฐ ์๋๋ก ํจ์ ๋ด๋ถ์์ ๋ถ๊ธฐ ์ฒ๋ฆฌํฉ๋๋ค.
public setIsMobileClient(_isMobile) {
this.#isMobileClient = _isMobile;
}
public setIsMobileServer(_isMobile, callback) {
if(!this.#isMobileServer) {
this.#isMobileServer = new AsyncLocalStorage();
}
this.#isMobileServer.run(_isMobile, callback);
}
isMobile
๊ฐ์ ํ ๋นํด ์ฃผ๋ setIsMobile
ํจ์๋ ์์ฝ๊ฒ๋ ์๋ฒ์ฉ ํจ์์ ํด๋ผ์ด์ธํธ์ฉ ํจ์ ๋ ๊ฐ๋ก ๋ถ๋ฆฌ๋์์ต๋๋ค. ์ด๋ ์๋ฒ ์ฌ์ด๋์ ๊ฒฝ์ฐ ๊ฐ ์ด๊ธฐํ๋ฅผ ์ํด ๋ฐ๋์ callback
ํจ์๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
2. ์๋ฒ๊ฐ์ ํด๋ผ์ด์ธํธ์ ๋๊ฒจ์ค๋๋ค.
์์ ๊ฐ์ด ํ์ผ ๋ณ์๋ฅผ ์ ์ํด ์คฌ๋ค๋ฉด ์ด์ ํ์ผ ๋ณ์๋ฅผ ์ด๊ธฐํํ๋ setter ํจ์๋ค์ ์ด๋ ์์น์์ ์ด๋ป๊ฒ ํธ์ถํด ์ค์ผ ์๋ฒ์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๊ฐ์ ๊ฐ์ง ์ ์๋์ง ๊ณ ๋ฏผํด์ผ ํฉ๋๋ค. ์๋ฒ์ setter ํจ์๋ฅผ ํธ์ถํ๋ ์์น๋ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ์๋ฒ ์ฌ์ด๋๋ฅผ ์ค๋ช ํ ๋ ์ธ๊ธํ๋ฏ์ด ๊ฐ์ฅ ์๋จ์ ์๋ ๋ฏธ๋ค์จ์ด์์ isMobile ๊ฐ์ ์ด๊ธฐํํด ์ฃผ๋ฉด ๋ฉ๋๋ค.
mediaMiddleware.js
import { isMobile } from "./media.js";
export async function mediaMiddleware(req, res, next) {
const _isMobile = parseUserAgent(req.headers['user-agent']);
isMobile.setIsMobileServer(isMobile, next);
return;
}
๋ฌธ์ ๋ ์๋ฒ์์ Request ํค๋์ ๊ฐ์ ๋ณด๊ณ ํ๋จํ isMobile
๊ฐ์ ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ ๊ณต์ ํ ์ ์๋ ๋ฐฉ๋ฒ์
๋๋ค. ํด๋ผ์ด์ธํธ์ window.navigator.userAgent
๊ฐ์ ํ์ฉํ์ง ์๋ ๊ฒ์ด ์ฐ๋ฆฌ์ ๋ชฉํ๋๊น์. ๋ฐฉ๋ฒ์๋ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์๊ฒ ์ง๋ง, ์ด ๊ธ์์๋ Next.js์ _document
๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ๊ฒ ์ต๋๋ค.
_document๋ Next.js๊ฐ ์๋ฒ ํ๊ฒฝ์์ HTML์ ๋ ๋๋งํ ๋ <html>
๊ณผ <body>
ํ๊ทธ๋ฅผ ์
๋ฐ์ดํธํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํด ์ค๋๋ค. ๊ทธ๋ฆฌ๊ณ _document ๋ด์ ๋ก์ง์ ์ด๋๊น์ง๋ ์๋ฒ ํ๊ฒฝ์์ ์คํ๋๊ธฐ ๋๋ฌธ์, ์ ์ ์ Request ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ ์กฐ์ํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค.
๋ฐ๋ผ์ ์๋์ ๊ฐ์ด ๋ฏธ๋ค์จ์ด์์ isMobile ์ฌ๋ถ๋ฅผ ์ ์ ์ request ๊ฐ์ฒด์ ์ ์ฅํ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ณ ,
mediaMiddleware.js
import { isMobile } from "./media.js";
export async function mediaMiddleware(req, res, next) {
const _isMobile = parseUserAgent(req.headers['user-agent']);
isMobile.setIsMobileServer(isMobile, next);
+ req.isMobile = isMobile;
return;
}
_document
์์ Request ๊ฐ์ฒด์ ์ ์ฅ๋ isMobi
le ์ ๋ณด๋ฅผ ๊บผ๋ธ ํ window ๊ฐ์ฒด์ isMobile
์ ๋ณด๋ฅผ ์ ์ฅํ๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ก์จ ํด๋ผ์ด์ธํธ ํ๊ฒฝ์์ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋ ๋ window ๊ฐ์ฒด์์ ์๋ฒ์ isMobile
์ ๋ณด๋ฅผ ์ฐธ์กฐํ ์ ์์ต๋๋ค.
Info
์ค์ ๋ก ์ ์ ์๊ฒ ๋ณด์ด๋ HTML์ ํด๋น ์คํฌ๋ฆฝํธ๊ฐ ์ถ๊ฐ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์, ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌ๋๋ ๋ณ์๊ฐ ๋ณด์์ ๋ฏผ๊ฐํ ์ ๋ณด๋ผ๋ฉด ์ํธํ๋ฅผ ํด์ฃผ๋ ๋ฑ์ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. ๋ณธ ์์์์๋ ๋ณด์์ด ํฌ๊ฒ ์ค์ํ์ง ์์ isMobile
์ ๋ณด์ด๊ธฐ ๋๋ฌธ์ ์ํธํ๋ฅผ ๊ณ ๋ คํ์ง ์์์ต๋๋ค.
_document.tsx
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
const isMobile = ctx?.req?.isMobile; // ์ ์ ์ Request ๊ฐ์ฒด์์ isMobile ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
return {
...initialProps,
isMobile,
}
}
render() {
return (
<Html lang="en">
<Head>
// ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ์คํ๋ ์ธ๋ผ์ธ ์คํฌ๋ฆฝํธ๋ฅผ ์ฃผ์
ํฉ๋๋ค.
<script
dangerouslySetInnerHTML={{
__html: >`(function(){window.isMobile='${
this.props.isMobile
}'})()`,
}}
/>
</Head>
...
</Html>
)
}
}
window ๊ฐ์ฒด์ isMobile์ ์ถ๊ฐํ๋ค๋ฉด ์ด์ ๊ฑฐ์ ๋ค ์์ต๋๋ค. ํด๋ผ์ด์ธํธ ์ฌ์ด๋์์ ํ์ผ ๋ณ์๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ํด ๋ชจ๋ ํ์ด์ง์ ๋ํด ํญ์ ์ฐ์ ์ผ๋ก ์คํ๋๋ _app
์์ ๋ค์๊ณผ ๊ฐ์ด ํด๋ผ์ด์ธํธ setter ํจ์๋ฅผ ํธ์ถํ ์๋ ์์ต๋๋ค.
_app.tsx
import { isMobile } from "./media.js";
IS_CLIENT && isMobile.setIsMobileServer(window.isMobile);
ํ์ง๋ง ์ ๋ ์ฑ๊ธํด ํจํด์ ํ์ฉํด ํด๋ผ์ด์ธํธ setter ํจ์๋ฅผ ์๋ตํ๊ณ , ์ ์ญ _app์์ ์ด๊ธฐํํด ์ฃผ๋ ๋์ ์ค์ ๋ก isMobile์ ์ต์ด๋ก ์ฐธ์กฐํ ๋ ๊ฐ์ ์ด๊ธฐํํด ์ฃผ๋๋ก ๊ตฌํํด ๋ณด๊ฒ ์ต๋๋ค.
media.js
class UserAgent {
...
public getIsMobile() {
if(IS_CLIENT) {
+ if(!this.#isMobileClient) {
+ this.#isMobileClient = window.isMobile;
+ delete window.isMobile;
+ }
return this.#isMobileClient;
} else {
return this.#isMobileServer.get();
}
}
>- public setIsMobileClient(_isMobile) {
>- this.#isMobileClient = _isMobile;
>- }
}
window ๊ฐ์ฒด์์ isMobile ๊ฐ์ ํ ๋ฒ ๊บผ๋ธ ์ดํ์๋ ๋ค์ ํด๋น ๊ฐ์ ์ฐธ์กฐํ ์ผ์ด ์๊ธฐ ๋๋ฌธ์ window ๊ฐ์ฒด์์ isMobile ํ๋ ์์ฒด๋ฅผ ์ ๊ฑฐํ๋ ์ฝ๋๋ ์ถ๊ฐํ์ต๋๋ค.
์ด๋ก์จ ์ฐ๋ฆฌ๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ์์ ํ์ผ ๋ณ์๊ฐ ๊ฐ์ ๊ฐ์ ๊ฐ์ง ์ ์๋๋ก ๊ตฌํํ์ผ๋ฉฐ, ํด๋ผ์ด์ธํธ ์ฌ์ด๋์ธ์ง ์๋ฒ ์ฌ์ด๋์ธ์ง๋ฅผ ์ ํ ์ ๊ฒฝ ์ฐ์ง ์๊ณ ์ด๋์์๋ ์ง getIsMobile()
ํจ์๋ง ํธ์ถํ๋ฉด ๋์ผํ ํ์ผ ๋ณ์ ๊ฐ์ ์ฐธ์กฐํ ์ ์๊ฒ ๋์์ต๋๋ค. ํ๊ฒฝ์ ์๊ด์์ด ํ์ผ ๋ณ์๋ฅผ ์์ ๋กญ๊ฒ ๋ค๋ฃฐ ์ ์๊ฒ ๋์์ต๋๋ค.
server/
some-middleware.js
import { getIsMobile } from "./media.js";
export async function someMiddleware(req, res, next) {
// ์๋ฒ์์ getIsMobile์ ํธ์ถํ๋ฉด ํ์ผ ๋ณ์ ๊ฐ์ ์ฐธ์กฐํ ์ ์์ต๋๋ค.
const isMobile = getIsMobile();
if(isMobile) {
...
}
return;
}
client/
someComponent.js
import { getIsMobile } from "./media.js";
export function someComponent() {
// ํด๋ผ์ด์ธํธ์์๋ getIsMobile์ ํธ์ถํ๋ฉด ํ์ผ ๋ณ์ ๊ฐ์ ์ฐธ์กฐํ ์ ์์ต๋๋ค.
const isMobile = getIsMobile();
if(isMobile) {
...
}
}
๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง ํ์ผ ๋ณ์๋ ๋ฌด์์ด๊ณ , ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์์๋ณด์์ต๋๋ค. ๋ฌผ๋ก ์ฌ๊ธฐ์์ ์๊ฐํด ๋๋ฆฐ ํ์ฉ ๋ฐฉ๋ฒ๋ค์ ์ ๋ต์ด ์๋๋๋ค. ์์์์๋ getter์ setter๋ฅผ ๋ณ๋๋ก ์ ์ํ์ง๋ง ์ค์ ๋ก๋ ๋ณ์ ์์ฒด๋ฅผ export ํด์ ์ฌ์ฉํด๋ ๋ฉ๋๋ค. ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๊ณ ์ ํ๋ ๊ฐ์ด ์ด๋ค ์ฑ๊ฒฉ์ ๊ฐ์ด๋ฉฐ ์ด๋ป๊ฒ ๊ด๋ฆฌ๋๋ฉด ์ข์์ง์ ๋ฐ๋ผ ํ์ฉ๋ฒ์ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋น์ฐํ๊ฒ๋ ํ์ผ ๋ณ์๊ฐ Redux๋ฅผ ์์ ํ ๋์ฒดํ ์๋ ์์ต๋๋ค. ์ค์ ๋ก ์ ํฌ ํ์์ ๊ธฐ์กด์ Redux๋ก ๊ด๋ฆฌ๋๋ ๊ฐ์ ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ๋๋ก ๋ณ๊ฒฝํ ๋ถ๋ถ๋ ์ผ๋ถ๋ถ์ ๋ถ๊ณผํฉ๋๋ค. ํ์ผ ๋ณ์๋ก ๊ด๋ฆฌํ ์ ์๋ ๊ฐ์ด ๋ฌด์์ธ์ง ๊น์ด ์๊ฐํด ๋ณผ ํ์๊ฐ ์์ต๋๋ค.
์ด ๊ธ์ ํตํด ์ฌ๋ฌ๋ถ์๊ฒ ์ ํด๋๋ฆฌ๊ณ ์ถ์๋ ๊ฒ์ Redux๊ฐ ๋ง๋ฅ์ ๋๊ตฌ๊ฐ ์๋๋ผ๋ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๊ฐ ์น ํ๋ก๊ทธ๋๋ฐ์ ์ฒ์ ์ ํ๊ฒ ๋๋ฉด Redux๊ฐ ๋ง์น ์ ์ญ์ผ๋ก ์ํ ๊ฐ์ ๊ด๋ฆฌํ ์ ์๋ ๊ฐ์ฅ ๋ฐ์ด๋ ๋ฐฉ๋ฒ์ธ ๊ฒ์ฒ๋ผ ์ฐฉ๊ฐํ ์ ์์ต๋๋ค. ํ์ง๋ง ํ๋ก๊ทธ๋๋ฐ ์ธ๊ณ์์๋, ํนํ ์น ํ๋ก๊ทธ๋๋ฐ์ ์ธ๊ณ์์๋ ๊ถ๊ทน์ ์ ๋ต์ด๋ผ๋ ๊ฒ์ ์กด์ฌํ ์ ์์ผ๋ฉฐ ํน์ ์ํฉ์ ์ ์ ํ ๋๊ตฌ๋ฅผ ์ทจ์ฌ์ ํํด์ ์ฌ์ฉํ ์ ์์ ๋ฟ์ ๋๋ค. ๊พธ์คํ ๋ฐ์ ํ๋ ์น ์ํ๊ณ๋ก ์ธํด ์ค๋์ ์ ๋ต์ด ๋ด์ผ์ ์ค๋ต์ด ๋ ์๋ ์์ฃ .
์ฐ๋ฆฌ๋ ํ๋ก๊ทธ๋๋จธ๋ก์ ์ธ์ ๋ ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋๊ตฌ๋ฅผ ์ ํํ ์ ์๋ ์ญ๋์ด ํ์ํฉ๋๋ค. ์ด ๊ธ์์๋ ์ฌ๋ฌ๋ถ์๊ฒ ํ์ผ ๋ณ์๋ผ๋, ํน์ ์ํฉ์์ ์ฌ์ฉํ ์ ์๋ ๋๊ตฌ๊ฐ ํ๋ ์กด์ฌํ๋ค๋ ๊ฒ์ ์๊ฐํ์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ์ฝ๋ฉ ์ํ์ ๋ง์ ๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.