๐ปWEB FrontEnd (66) ์ธ๋ค์ผํ ๋ฆฌ์คํธํ PWA(Progressive Web App) PWA(Progressive Web App) ์น์ฌ์ดํธ๋ฅผ ์๋๋ก์ด๋/iOS ๋ชจ๋ฐ์ผ ์ฑ์ฒ๋ผ ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋๋ ์ผ์ข ์ ์น๊ฐ๋ฐ ๊ธฐ์ (์ฅ์ ) 1. ์ค๋งํธํฐ, ํ๋ธ๋ฆฟ ๋ฐํํ๋ฉด์ ์ฌ๋ฌ๋ถ ์น์ฌ์ดํธ๋ฅผ ์ค์น ๊ฐ๋ฅํฉ๋๋ค. (์ ๊ฑฐ ์ค์น๋ ์ฑ ๋๋ฅด๋ฉด ์๋จ URL๋ฐ๊ฐ ์ ๊ฑฐ๋ ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ๊ฐ ๋น๋๋ค. ์ผ๋ฐ ์ฌ์ฉ์๋ ์ฑ์ด๋ ๊ตฌ๋ถ์ ๋ชปํจ) 2. ์คํ๋ผ์ธ์์๋ ๋์ํ ์ ์์ต๋๋ค. service-worker.js ๋ผ๋ ํ์ผ๊ณผ ๋ธ๋ผ์ฐ์ ์ Cache storage ๋๋ถ์ ๊ทธ๋ ์ต๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฒ์๋ง๋ค ๋ ์ ์ฉํ๊ฒ ๋ค์. 3. ์ค์น ์ ๋ ๋น์ฉ์ด ๋งค์ฐ ์ ์ต๋๋ค. ์ฑ์ค์น๋ฅผ ์ ๋ํ๋ ๋ง์ผํ ๋น์ฉ์ด ์ ๊ฒ๋ค์ด ์ข๋ค๋ ๊ฒ๋๋ค. ๊ตฌ๊ธํ๋ ์ด ์คํ ์ด ๋ฐฉ๋ฌธํด์ ์ฑ ์ค์นํ๊ณ ๋ค์ด๋ฐ๊ฒ ํ๋๊ฑด ํญ์ ๋งค์ฐ ๋์ ๋ง์ผํ ๋น์ฉ์ด ๋ญ๋๋ค. ๊ทผ๋ฐ PWA๋ผ๋ฉด ์น์ฌ์ด.. ์ฑ๋ฅ๊ฐ์ (3) - batching, useTransition, useDeferredValue batching - state๋ณ๊ฒฝํจ์๋ฅผ ์ฐ๋ฌ์์ 3๊ฐ ์ฌ์ฉํ๋ฉด ์ฌ๋ ๋๋ง๋ ์๋ 3๋ฒ ๋์ด์ผํ์ง๋ง ๋ฆฌ์กํธ๋ ๋๋ํ๊ฒ๋ ์ฌ๋ ๋๋ง์ ๋ง์ง๋ง์ 1ํ๋ง ์ฒ๋ฆฌํด์ค๋ค. ์ด๋ฐ ์ฌ๋ ๋๋ง ๋ฐฉ์ง๊ธฐ๋ฅ์ batching์ด๋ผ๊ณ ํ๋ค. - ๊ทผ๋ฐ ๋ฌธ์ ๋ ajax์์ฒญ, setTimeout์์ state๋ณ๊ฒฝํจ์๊ฐ ์๋ ๊ฒฝ์ฐ batching์ด ์ผ์ด๋์ง ์๋๋ค. ๋ฆฌ์กํธ 17๋ฒ์ ๊น์ง ๊ทธ๋ฐ ์์ผ๋ก ์ผ๊ด์ ์ด์ง ์๊ฒ ๋์ํ๋๋ฐ18๋ฒ์ ์ดํ ๋ถํฐ๋ ์ด๋ ์๋ ๊ฐ์ ์ฌ๋ ๋๋ง์ ๋ง์ง๋ง์ 1๋ฒ๋ง ๋๋ค. - batching ๋๋๊ฒ ์ซ๊ณ state๋ณ๊ฒฝํจ์ ์คํ๋ง๋ค ์ฌ๋ ๋๋ง์ํค๊ณ ์ถ์ผ๋ฉด flushSync๋ผ๋ ํจ์๋ฅผ ์ฐ๋ฉด ๋๋ค. setCount(1) setName(2) setValue(3) //์ฌ๊ธฐ์ 1๋ฒ๋ง ์ฌ๋ ๋๋ง๋จ useTransition useTransi.. ์ฑ๋ฅ๊ฐ์ (2) - ์ฌ๋ ๋๋ง ๋ง๋ ๋ฒ ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ ๋๋ง๋๋ฉด ๊ฑฐ๊ธฐ ์์ ์๋ ์์์ปดํฌ๋ํธ๋ ํญ์ ํจ๊ป ์ฌ๋ ๋๋ง๋๋ค. ์ด๋ฐ ์ฌ๋ ๋๋ง์ ๋ง๊ณ ์ถ์ ๋ ์์์ memo๋ก ๊ฐ์ธ๋์ผ๋ฉด ๋๋ค. memo()๋ก ์ปดํฌ๋ํธ ๋ถํ์ํ ์ฌ๋ ๋๋ง ๋ง๊ธฐ step 1) memo๋ฅผ 'react' ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก๋ถํฐ import ํด์์ step 2) ์ํ๋ ์ปดํฌ๋ํธ ์ ์๋ถ๋ถ์ ๊ฐ์ผ๋ค. ๊ทผ๋ฐ ์ปดํฌ๋ํธ๋ฅผ let ์ปดํฌ๋ํธ๋ช = function( ){ } ์ด๋ฐ ์์ผ๋ก ๋ง๋ค์ด์ผ ๊ฐ์ ์ ์๋ค. import {memo, useState} from 'react' let Child = memo( function(){ console.log('์ฌ๋ ๋๋ง๋จ') return ์์์ }) function Cart(){ let [count, setCount] = useState(0) return ( .. ์ฑ๋ฅ๊ฐ์ (1) - lazy import lazy import - ๋ฆฌ์กํธ ์ฌ์ดํธ๋ค์ ์ฒซ ํ์ด์ง ๋ก๋ฉ์๋๊ฐ ๋งค์ฐ ๋๋ฆด ์ ์๋๋ฐ ๊ทธ๊ฒ ์ซ๋ค๋ฉด js ํ์ผ์ ์๊ฒ ์ชผ๊ฐ๋ฉด ๋๋ค. - ์ชผ๊ฐ๋ ๋ฐฉ๋ฒ์ import ๋ฌธ๋ฒ์ ์ฝ๊ฐ ๊ณ ์น๋ฉด ๋๋๋ฐ ์ง๊ธ ํ์ด์ง์์ ์ฌ์ฉํ์ง ์๊ณ ์๋ ์ปดํฌ๋ํธ๋ค์ lazy import ํด๋์ผ๋ฉด ์ข๋ค. - ๋จ์ : lazy๋ฌธ๋ฒ์ผ๋ก importํ ์ปดํฌ๋ํธ๋ค์ ๋ก๋ํ ๋๋ ๋ก๋ฉ์๊ฐ์ด ๋ฐ์ํ ์ ์๋ค. 1. lazy() (App.js) import Detail from './routes/Detail.js' import Cart from './routes/Cart.js' ↓↓↓ (App.js) import {lazy, Suspense, useEffect, useState} from 'react' const Detail = lazy( () =.. react-query : ์ค์๊ฐ ๋ฐ์ดํฐ๊ฐ ์ค์ํ ๋? ajax ์์ฒญํ๋ค๋ณด๋ฉด ์ด๋ฐ ๊ธฐ๋ฅ๋ค์ด ๊ฐ๋ ํ์ํด์ง๋ค. - ๋ช์ด๋ง๋ค ์๋์ผ๋ก ๋ฐ์ดํฐ ๋ค์ ๊ฐ์ ธ์ค๊ฒ ํ๋ ค๋ฉด? - ์์ฒญ์คํจ์ ๋ช์ด ๊ฐ๊ฒฉ์ผ๋ก ์ฌ์๋? - ๋ค์ ํ์ด์ง ๋ฏธ๋ฆฌ๊ฐ์ ธ์ค๊ธฐ? - ajax ์ฑ๊ณต/์คํจ์ ๊ฐ๊ฐ ๋ค๋ฅธ html์ ๋ณด์ฌ์ฃผ๋ ค๋ฉด? 1. react-query ์ค์น & ์ ํ (terminal) npm install react-query (index.js) import { QueryClient, QueryClientProvider } from "react-query" //1๋ฒ const queryClient = new QueryClient() //2๋ฒ const root = ReactDOM.createRoot(document.getElementById('root')); root.render( //3๋ฒ ); .. localStorage 1. localStorage ๋ฌธ๋ฒ ์ถ๊ฐ, ์ฝ๊ธฐ, ์ญ์ ๋ฌธ๋ฒ localStorage.setItem('๋ฐ์ดํฐ์ด๋ฆ', '๋ฐ์ดํฐ'); localStorage.getItem('๋ฐ์ดํฐ์ด๋ฆ'); localStorage.removeItem('๋ฐ์ดํฐ์ด๋ฆ') 2. localStorage์ array/object ์๋ฃ๋ฅผ ์ ์ฅํ๋ ค๋ฉด ๋ฌธ์๋ง ์ ์ฅํ ์ ์๋ ๊ณต๊ฐ์ด๋ผ array/object๋ฅผ ๋ฐ๋ก ์ ์ฅํ ์๋ ์๋ค. ํธ๋ฒ์ผ๋ก array/object -> JSON ์ด๋ ๊ฒ ๋ณํํด์ ์ ์ฅํ๋ฉด ๋๋ค. (JSON์ ๋ฌธ์์ทจ๊ธ) JSON.stringify() ๋ผ๋ ํจ์์ array/object๋ฅผ ์ง์ด๋ฃ์ผ๋ฉด ๊ทธ ์๋ฆฌ์ JSON์ผ๋ก ๋ณํ๋๊ฑธ ๋จ๊ฒจ์ค๋ค. localStorage.setItem('obj', JSON.stringify({name:'ki.. Redux (2) - state ๋ณ๊ฒฝ 1. store์ state ๋ณ๊ฒฝํ๋ ๋ฒ step 1) store.js ์์ state ์์ ํด์ฃผ๋ ํจ์ ์์ฑ - slice ์์ reducers : { } ์ด๊ณ ๊ฑฐ๊ธฐ ์์ ํจ์ ๋ง๋ค๋ฉด ๋๋ค. (ํจ์ ์๋ช ์ ์์ ๋กญ๊ฒ) - ํ๋ผ๋ฏธํฐ ํ๋ ์๋ช ํ๋ฉด ๊ทธ๊ฑด ๊ธฐ์กด state๊ฐ ๋๋ค. - return ์ฐ์ธก์ ์๋ก์ด state ์ ๋ ฅํ๋ฉด ๊ทธ๊ฑธ๋ก ๊ธฐ์กด state๋ฅผ ๋ณ๊ฒฝํด์ค๋ค. let user = createSlice({ name : 'user', initialState : 'kim', reducers : { //state ์์ ํด์ฃผ๋ ํจ์ changeName(state){ return 'john ' + state }, ์์ ํจ์2(state){ return ... }, } }) step 2) ์์ฑํ ์์ ํจ์(changeNam.. Redux (1) : props ์์ด state ๊ณต์ ๊ฐ๋ฅ Redux Redux๋ props ์์ด state๋ฅผ ๊ณต์ ํ ์ ์๊ฒ ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค. 1. Redux ์ค์น npm install @reduxjs/toolkit react-redux โป redux toolkit : redux์ ๊ฐ์ ๋ฒ์ (๋ฌธ๋ฒ์ด ์ข ๋ ์ฌ์์ง) ๊ทผ๋ฐ ์ค์นํ๊ธฐ ์ ์ package.json ํ์ผ์ ์ด์ด์ "react", "react-dom" ํญ๋ชฉ์ ๋ฒ์ ์ ํ์ธํ๋ค. ์ด๊ฑฐ ๋๊ฐ๊ฐ 18.1.x ์ด์์ด๋ฉด ์ฌ์ฉ๊ฐ๋ฅํ๋ค. โฒ ๊ทธ๊ฒ ์๋๋ฉด ์ง์ ๋๊ฐ๋ฅผ 18.1.0 ์ด๋ ๊ฒ ์์ ํ ๋ค์ ํ์ผ์ ์ฅํ๊ณ ํฐ๋ฏธ๋์์ npm install ๋๋ฅด๋ฉด ๋๋ค. 2. Redux ์ ํ โ ์๋ฌด๊ณณ(์๋ฅผ ๋ค๋ฉด, src ํด๋ ์)์ด๋ state๋ค์ ๋ณด๊ดํ๋ ํ์ผ์ธ store.js ํ์ผ์ ๋ง๋ค์ด์ ์๋ ์ฝ๋๋ฅผ ๋ณต๋ถํด์ค๋ค. (s.. Ajax๋ก ์๋ฒ์ ํต์ Ajax๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ค์ ์ธ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค. XMLHttpRequest fetch() axios 1. axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ 1) axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น npm install axios 2) App.js์ axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ import import axios from 'axios' 3) AJAX GET ์์ฒญํ๊ธฐ { axios.get('https://codingapple1.github.io/shop/data2.json').then((๊ฒฐ๊ณผ)=>{ console.log(๊ฒฐ๊ณผ.data) }) .catch(()=>{ console.log('์คํจํจ') }) //๋์์ ajax ์์ฒญ ์ฌ๋ฌ๊ฐํ๋ ค๋ฉด Promise.all( [axios.get('URL1'), axios.get('URL2')] ) }}>๋ฒํผ.. ์ปดํฌ๋ํธ์ Lifecycle ์ปดํฌ๋ํธ์ Lifecycle ์ปดํฌ๋ํธ๊ฐ ์คํ๋๊ณ ์ข ๋ฃ๋๋ ๊ณผ์ ์ ํน์ ์์ ๋ณ๋ก ๋๋์ด ๋ ๊ฒ ์ปดํฌ๋ํธ๋ 1. ์์ฑ์ด ๋ ์๋ ์๊ณ (mount) 2. ์ฌ๋ ๋๋ง์ด ๋ ์๋ ์๊ณ (update) 3. ์ญ์ ๊ฐ ๋ ์๋ ์์ต๋๋ค. (unmount) Lifecycle Hook ํจ์ํ ์ปดํฌ๋ํธ์์๋ ํด๋์คํ ์ปดํฌ๋ํธ์ ๊ธฐ๋ฅ(React State, Lifecycle Method)์ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋ค์ด์ฃผ๋ ๊ธฐ๋ฅ์ด๋ค. Hook์ ๋ชจ๋ use๋ก ์์ํ๋ค๋ ํน์ง์ด ์๋ค. ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ์ฌ์ฌ์ฉ ๋ ์ ์๋ ๋ก์ง์ด๋ผ๋ฉด ์ฌ์ฉ์๊ฐ ์ ์ํด์ ๋ง๋ค ์ ์๋ค. => custom hooks 1) ํด๋์คํ ์ปดํฌ๋ํธ์ Lifecycle Hook class Detail2 extends React.Component { component.. ์ด์ 1 2 3 4 ยทยทยท 7 ๋ค์