localStorage - 1
새로고침하면 모든 state 데이터는 리셋된다. 왜냐면 새로고침하면 브라우저는 html css js 파일들을 처음부터 읽기 때문이다.
이게 싫다면 state 데이터를 서버로 보내서 DB 에 영구저장하면 되는데, 서버가 없는 경우 차선책으로 localStorage 를 이용해도 된다. localStorage 는 유저의 브라우저에 정보를 저장하고 싶을 때 쓰는 공간으로 정보를 반영구적으로 저장이 가능하다.
저장된 정보는 크롬개발자 도구에서 Application 탭에 들어가면 확인할 수 있다.

- localStorage 에는 사이트마다 5MB 정도의 문자 데이터 저장 가능 (문자만 저장가능)
- object 자료와 비슷하게 key/value 형태로 저장
- 유저가 브라우저 청소를 하지 않는 이상 영구적으로 남아있음 (브라우저 청소시 삭제됨)
사진에서 볼 수 있듯이 SessionStorage 라는 것도 있는데, SessionStorage 는 브라우저를 끄면 정보가 날아가기 때문에 휘발성 있는 데이터를 저장하고 싶을 때 사용하면 된다.
localStorage 문법
js 파일 아무데서나 다음 문법을 쓰면 localStorage 에 데이터를 입출력할 수 있다.
// 데이터 추가
localStorage.setItem('데이터이름', '데이터'); // localStorage.setItem('key', 'value');
// 데이터 읽기
localStorage.getItem('데이터이름');
// 데이터 삭제
localStorage.removeItem('데이터이름')
※ 참고
SessionStorage 문법은 localStorage 문법과 똑같이 사용하면 된다.
// 데이터 추가
socalStorage.setItem('데이터이름', '데이터'); // socalStorage.setItem('key', 'value');
// 데이터 읽기
socalStorage.getItem('데이터이름');
// 데이터 삭제
socalStorage.removeItem('데이터이름')
localStorage 에 array/object 자료 저장하기
localStorage 는 문자만 저장할 수 있는 공간이라 array/object 를 바로 저장할 수는 없다.
강제로 array/object 를 저장해보면 문자로 바꿔서 저장해주는데 그렇게 되면 array/object 자료가 깨져서 저장이 된다.
그래서 localStorage 에 array/object 를 저장하려면 자료를 JSON 으로 변환한 후에 저장해주면 된다. JSON 은 문자 취급을 받는데, JSON 은 그냥 따옴표친 array/object 자료이다.
- JSON.stringify()
JSON.stringify() 함수에 array/object 를 집어넣으면 그 자리에 JSON 으로 변환된 것을 남겨준다.
localStorage.setItem('obj', JSON.stringify({name:'kim'}) );
- JSON.parse()
그럼 JSON 으로 localStorage 저장된 자료를 다시 꺼내어 사용하려면 어떻게 해야할까?
저장된 자료를 localStorage.getItem 으로 읽어오면 당연히 JSON 이 나온다. 이제 전과 반대로 JSON 을 array/object 로 변환해야 한다. 이때는 JSON.parse() 함수에 꺼내온 자료를 넣어 JSON -> array/object 로 변환하면 된다.
var a = localStorage.getItem('obj');
var b = JSON.parse(a)
숙제:
1. 누가 Detail페이지 접속하면
2. 현재 페이지에 보이는 상품id 가져와서
3. localStorage에 watch항목에 있던 [ ] 에 추가
App 컴포넌트가 실행될 때 localStorage 에 array 를 JSON 으로 변환해서 저장
-> 상세페이지에 접속해서 해당 아이템의 id 를 기록할 array 를 미리 만들어둔 것
// App.js
useEffect(()=>{
localStorage.setItem('watched', JSON.stringify([]))
}, [])
상세페이지에 접속했을 때 페이지에 보이는 상품 id 를 찾아서 변수에 저장해둠
localStorage 에 저장된 데이터는 입력/출력만 가능하고 수정이 불가능
-> watched 에 저장되어 있던 데이터를 꺼내 JSON.parse() 로 JSON -> array 로 변환
-> 변환 후 변수에 저장해둔 현재 페이지에 보이는 상품의 id 를 push 해줌
-> 중복 제거를 위해 Set 자료형으로 바꿨다가 다시 array 로 바꾸어 줌
-> 이제 수정한 array 를 다시 JSON 으로 변환하고 localStorage 에 저장시킴
// Detail.js
let item = props.shoes.find((x)=> x.id == id)
useEffect(()=>{
let 꺼낸거 = localStorage.getItem('watched')
꺼낸거 = JSON.parse(꺼낸거)
꺼낸거.push(찾은상품.id)
꺼낸거 = new Set(꺼낸거)
꺼낸거 = Array.from(꺼낸거)
localStorage.setItem('watched', JSON.stringify(꺼낸거))
}, [])
근데 이렇게만 코드를 짜면 App 페이지에 가서 새로고침을 할 때마다 [] 가 새롭게 만들어져 기존에 저장되어 있던 정보들이 사라진다.
그래서 if 문을 사용해서 watched 가 존재하지 않는 경우에만 watched 를 localStorage 에 저장하도록 만들었다.
useEffect(() => {
if (!(localStorage.getItem('watched'))) {
localStorage.setItem('watched', JSON.stringify([]))
}
}, [])
※ 참고
- localStorage 에 state 를 자동저장 되게 만들고 싶다면
직접 코드를 짜는 방법도 있지만, redux-persist 같은 라이브러리를 설치해서 쓰면 redux store 안에 있는 state 를 자동으로 localStorage 에 저장해주고, state 변경될 때마다 그에 맞게 localStorage 에 업데이트도 알아서 해준다. 하지만 셋팅 문법이 복잡하고 귀찮다는 단점이 있다.
그래서 요즘 신규 사이트들은 Redux 대신 Jotai, Zustand 같은 라이브러리를 사용한다. 같은 기능을 제공하고 셋팅도 거의 필요없고 문법이 훨씬 간단하다.
실시간 데이터가 중요하면 react-query
ajax 요청을 하다보면 아래와 같은 기능들이 필요할 때가 있다
- 몇 초마다 자동으로 데이터 다시 가져오게 하기
- 요청 실패시 몇 초 간격으로 재시도하게 하기
- 다음 페이지 미리 가져오기
- ajax 성공/실패시 각각 다른 html 보여주기
직접 개발해도 되지만 이럴 때는 react-query 라는 라이브러리를 설치해서 사용하면 되는데, react-query 는 SNS, 코인거래소 같은 실시간 데이터를 보여줘야 하는 사이트들이 쓰면 유용하다.
react-query 설치 & 셋팅
- react-query 설치하기
터미널 열어서 아래 명령어 치고 설치하기
npm install react-query@3
- 셋팅
index.js 파일을 열고 1, 2, 3 번
import { QueryClient, QueryClientProvider, useQueryr } from "react-query" //1번: import
const queryClient = new QueryClient() //2번
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<QueryClientProvider client={queryClient}> //3번: 감싸기
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</QueryClientProvider>
);
추가
useQuery 쓸 때는 문자열일 경우 '작명' 배열일 경우는 ['작명']
// 문자열
useQuery('작명', ...)
// 배열
useQuery(['작명'], ...)
react-query 로 ajax 요청하는 법
그냥 ajax 요청을 해도 되지만 react-query 를 써서 ajax 요청을 날리면 더 편리한 기능을 제공한다.
useQuery 를 상단에서 import 해온 뒤에 useQuery() 로 ajax 요청을 감싸주면 된다.
function App(){
let result = useQuery('작명', ()=>
axios.get('https://codingapple1.github.io/userdata.json')
.then((a)=>{ return a.data })
)
}
장점1. ajax 요청 성공/실패/로딩중 상태를 쉽게 파악할 수 있다.
result 변수에 ajax 현재 상태가 알아서 저장된다.
- ajax 요청이 로딩중: result.isLoading 이 true
- ajax 요청이 실패: result.error 가 true
- ajax 요청이 성공: result.data 안에 데이터가 들어옴
그래서
ajax 로딩중엔 <A/>, ajax 성공시엔 <B/>, ajax 실패시엔 <C/> 이렇게 보여주세요~
이렇게 코딩할 수 있다.
원래 이렇게 개발하려면 state 부터 만들어야 하지만 useQuery 를 사용하면 간단하게 만들 수 있다.
function App(){
let result = useQuery('작명', ()=>
axios.get('https://codingapple1.github.io/userdata.json')
.then((a)=>{ return a.data })
)
return (
<div>
{ result.isLoading && '로딩중' }
{ result.error && '에러남' }
{ result.data && result.data.name }
</div>
)
}
장점2. 알아서 자주 ajax 재요청을 해준다.
페이지 체류하고 나서 일정시간이 경과하거나, 사용자가 다른 창으로 갔다가 다시 페이지로 돌아오거나 다시 메인페이지로 돌아가거나 이런 경우에 알아서 ajax 요청을 해준다.
(재요청하는 것을 refetch 라고 한다)
너무 자주 ajax 가 일어난다면 staleTime 을 사용해서 refetch 간격을 조절해주면 된다.
let result = useQuery('작명', ()=>{
return axios.get('https://codingapple1.github.io/userdata.json').then((a)=>{
return a.data
})
}, { staleTime: 2000})
장점3. 실패시 재시도를 알아서 해준다
잠깐 인터넷이 끊겼거나 서버가 죽었다면 ajax 요청이 실패하게 되는데, react-query 를 사용하면 4-5 번정도를 알아서 재시도 해주기 때문에 편리하다.
장점4. ajax 로 가져온 결과는 state 공유가 필요없다
지금 App 컴포넌트에서 유저이름을 가져오는 ajax 요청을 날리고 있다고 해보자.
그리고 그 유저이름 결과가 Detail 컴포넌트에서도 필요하다면 유저이름을 props 로 해당 컴포넌트로 전송해야 한다.
근데 react-query 를 사용하면 props 전송이 필요없다.
그냥 Detail 컴포넌트에 유저이름 ajax 요청하는 코드를 똑같이 또 적으면 된다. react-query 는 똑똑하기 때문에 같은 ajax 요청이 2개 있으면 1개만 날려주고, 캐싱기능이 있기 때문에 이미 같은 ajax 요청을 한 적이 있다면 우선 그걸 가져와서 쓴다.
※ 참고
react-query 가 주장하는 장점은 server-state(DB 데이터) 를 프론트엔드에서 실시간으로 동기화해주는 걸 도와주는 것이라고 한다.
근데 ajax 요청을 몇 초마다 계속 날려서 가져오는 방식이라 http1 을 쓰는 서버나 브라우저라면 좀 비효율적일 수도 있다.
실시간으로 서버에서 데이터를 자주 보내려면 웹소켓이나 server-sent events 같은 가벼운 방식들도 있다. 그래서 react-query 는 ajax 관련 기능 개발을 편하게 할 수 있는데에 더 의의가 있다.
근데 http2 나 http3 을 지원하는 브라우저나 서버를 이용한다면 GET POST 요청을 자주해도 서버 부담이 적을 수 있어서 상관이 없을 듯하다.
※ 참고
RTK Query 라이브러리
Redux Tookit 을 설치한 경우 RTK Query 라는 것도 기본적으로 사용할 수 있는데 react-query 와 비슷한 기능을 제공한다.
(다만 기본 셋팅 코드는 조금 더 지저분하다)
RTK Query 는 사실 다른 용도로 많이 쓰인다.
ajax 요청 후 Redux state 변경을 하고 싶을 때 Redux state 변경함수 안에서 ajax 요청을 할 수 없기 때문에 컴포넌트 안에서 해야한다.
근데 ajax 요청하는 코드가 다양하고 많으면 컴포넌트 안의 코드는 길어지고 관리하기 힘들어지는데, 그런 것을 Slice 안에서 관리할 수 있도록 도와준다. 그리고 ajax 요청하는 코드가 100만개 있으면 그걸 편리하게 관리할 수 있도록 도와준다.
'웹 > 24-StudyWithPnP' 카테고리의 다른 글
[React+JS/리액트] 웹 스터디 - state 변경함수 사용할 때 주의점: async (0) | 2024.08.06 |
---|---|
[React+JS/리액트] 웹 스터디 11주차 (0) | 2024.07.12 |
[React+JS/리액트] 웹 스터디 9주차 (0) | 2024.07.04 |
[React+JS/리액트] 웹 스터디 8주차 (0) | 2024.06.12 |
[React+JS/리액트] 웹 스터디 7주차 (0) | 2024.06.05 |