작성
·
369
0
이전 강의에서 물어본 사항들을 이번 강의에서 설명하시네유ㅠㅠ 보고 질문드릴걸 그랬습니다!
useSWR이 동일한 키 값이면 동일한 data를 공유한다는것 까지는 이해했고, 리덕스를 대체할 수 있다는것까지도 알겠습니다. 근데 이 둘 간에 분명히 차이점이 있는데 이를 제대로 이해했는지 잘 모르겠어서 확인 차 질문드립니다!
동일한 키 값이란 말은 결국 동일한 url이라는 말인데, 동일한 url로 처리할 수 있는 요청들이 제한적이기 때문에 결국 SWR 공간들이 분할될 수 밖에 없다고 생각하는데요( 필요할 때 useSWR로 값을 불러올 수 있지만, 서로 다른 url에서 서로 다른 구조의 data를 응답받았을 때, 리덕스 스토어의 경우 initialState에 전체를 다 때려박아넣은 다음, 요청의 response 값을 initialState에 채워넣거나 수정하는 식으로 관리하지만, SWR의 경우 이와같은 조작을 하려면 서버에서 매번 data구조를 거대하게 리턴해야해서 효율이 너무 떨어지기 때문에 실용적인 측면에서 불가능하다 생각되서 분할되었다고 표현 ).
그럼에도 불구하고 코드 전체적으로 보았을 때 swr에서 사용되는 url들, 즉 키 값들은 한정적이기 때문에 같은 키값에서 사용되는 데이터들만 골라서 쓰면 전역공간처럼 쓸 수는 있을 것 같지만, 리덕스와 같은 완전한 전역공간은 아닌 것으로 예상됩니다.
swr은 키값과 지역공간을 매핑해서 사용함. 필요에 따라 동일한 키값을 부여해서 데이터 공유가 가능하므로, 전역공간처럼 사용할 수 있음.
리덕스는 지역이고 뭐고 필요없이 그냥 전역공간 그 자체를 만들어서 사용함.
이렇게 이해했는데 얼추 맞나요?
수정) 비동기요청에 사용하는 fetcher들의 then에 동기useSWR('global',...)를 호출해서 비동기요청 then구문마다 global 키값에 데이터를 채워넣는 식으로 사용하면 리덕스 스토어를 완전히 대체하는 방법일까요?
답변 1
0
잘 이해가 안 되는데 왜 swr을 지역공간이라고 생각하시죠? 그리고 swr의 키는 아무 문자열이나 가능한 만큼 한정적이라고도 생각하지 않습니다. swr이라고 서버에서 왜 거대한 데이터를 response해야하나요? 필요한 데이터만 response하면 됩니다.
리덕스를 대체하려할때 global이라는 키에다 두는 것도 잘 이해가 안 됩니다. 이미 swr은 그 자체로 전역공간이라서 딱히 의미가 없을 것 같습니다.
말씀하신 부분은 이해했습니다. 다만, 이 문제는 redux의 특성 때문에 그렇습니다. 요즘에는 오히려 리덕스가 독특한 편이라고 해도 됩니다. redux는 전역 스토어를 하나만 둡니다. redux가 1세대라고 친다면 2세대인 mobx나 3세대인 recoil, zustand, jotai같은 리덕스를 대체하는 라이브러리는 스토어를 여러 개 두는 것으로 추세를 달리하고 있습니다. swr도 이들과 2,3세대 같은 역할을 할 수 있는 것입니다. 따라서 말씀하신 대로 redux와는 방법이 다르다고 정리하겠습니다.
mobx, recoil, swr 등에서는 어떻게 하나의 스토어에서 다른 스토어의 데이터를 접근할까 생각해보면 swr도 답이 나옵니다. 다른 스토어에서 값을 꺼내와서 원하는 스토어에서 사용하는 방법밖에 없습니다.
이게 전역 스토어를 하나 두는 것과 여러개 두는 것의 차이이자 장단점이겠지요.
결론을 내리자면 리덕스 패턴에 맞추어서 2,3세대 상태관리 라이브러리를 생각하면 안 됩니다. swr은 swr만의 데이터 저장 및 처리 방식이 있고 리덕스와는 다릅니다. 따라서 그걸 익히셔야 합니다.
노드버드 예제를 들어보겠습니다.
노드버드 예제의 initialState는 다른 거추장스러운걸 제외시킨다면 결국 핵심은 state.user의 me와 state.post의 mainPosts 라고 생각합니다.
한편, me와 mainPosts에 접근하기 위해서는 위처럼 단순히 store만 선언해주고, store.user.me이거나 store.post.mainPosts로 접근하면 됩니다. 비구조화할당과 리턴값을 state.user, state.post를 하는 이유는 prefix없이 편하게 me와 mainPosts로 접근하기 위해서지요.
핵심은, 스토어를 이용하고있다면 사용자는 단 하나의 store=useSelector((state)=>state) 를 선언하고 호출하기만 하면 모든 프로퍼티로 접근이 가능하다는 겁니다.
useSWR을 예로 들자면 다음처럼 진행할 수 있겠지요.
fetcher를 GET호출이라고 가정한다면, me와 mainPosts를 얻기 위해서는 서로 다른 경로로 요청을 해야합니다. 왜냐면 me와 mainPosts는 데이터구조가 다르기 때문에 me의 모든 정보와 mainPosts의 모든 정보를 매번 response하기보다는 라우터를 따로 하고 각각의 response만 하는 것이 효율적이기 때문입니다.
리덕스의 경우, 이미 스토어의 프로퍼티에서 그 구조가 정의되어 있습니다. store.user.me와 store.post.mainPosts 프로퍼티들은 각각의 라우터에서 response하는 데이터 타입과 동일한 타입이기 때문에, 그냥 그 곳에 draft를 이용하든 뭘 하든 이미 만들어져 있는 공간에 데이터를 채워넣는 방식입니다.
한편, SWR은 키값이 달라지기 때문에 data1과 data2는 서로 공유하는 값이 아니게 됩니다. 위쪽 SWR의 data의 타입은 store.user.me의 데이터타입이고, 아래쪽 SWR의 data의 타입은 store.post.mainPosts의 데이터타입입니다. data1의 변경이 발생하면 리액트는 data1의 변경을 감지하겠지만, data2는 data1과 아무 상관이 없기 때문에 실제로 변경이 발생하지도 않고, 변경이 감지되지도 않습니다. 물론 이는 리덕스에서도 마찬가지입니다. me가 변경된다고 해서 mainPosts가 변경되는 것이 아니니까요.
그러나, SWR의 경우 키값이 다르기 때문에 서로 다른 데이터타입을 가지는 SWR공간이 2개가 존재하는 것이죠. data1과 data2는 어느 한쪽에서 서로 접근이 불가능합니다. data1과 data2가 서로 동시에 속하는 store같은 것이 있는 것이 아니기 때문에, data1에서 어떤 식으로 접근을 해도 data2로 접근이 안 됩니다. 반면 리덕스의 경우 store만 선언한다면, store.user.me로 me 데이터에 접근할 수 있고, store.post.mainPosts로 mainPosts로 접근할 수 있습니다.
이를 해소하려면 키값을 동일하게 준 다음, fetcher를 다르게 하는 방법이 있겠습니다
이같은 방법을 통하면, 위쪽 SWR의 data와 아래쪽 SWR의 data가 서로 공유는 되겠지요, 같은 키 값을 가지고 있으니까,
그러나 fetcher1과 fetcher2의 get요청의 response 타입은 서로 다르기 때문에, 실제 작동에서 data2가 변경이 일어난다면, 공유값이기 때문에 data1을 참조하는 쪽에서도 변경을 감지합니다. 그러나 서버는 data2의 데이터타입을 리턴하기 때문에, data1을 참조하는 쪽은 data1의 구조에 맞게 코드를 작성했기 때문에 data2의 구조로 response가 발생하면 당연히 에러가 발생합니다.
이러한 에러를 없애기 위해서는 라우터 분리를 없애던가, /api/user/me와 /api/post/mainposts는 각각의 response타입을 합집합시킨 타입으로써의 response를 보내줘야하는데 이는 상당히 비효율적이고 비현실적입니다. 때문에 그냥 차라리 키값을 다르게 하는 방법을 사용합니다.
이런 이유로 swr을 지역공간으로 생각하고, 리덕스를 전역공간으로 생각하고 있습니다. 짧은 지식으로 생각이 잘 전달됐는지 잘 모르겠습니다..ㅜ
swr은 거대한 데이터를 response할 필요도 없고 필요한 데이터만 response를 하면 되는 것이 당연합니다. 단, swr을 리덕스처럼 단 하나의 스토어를 가지는 구조로 100퍼센트 흉내를 내기위해서는 response를 거대하게 해야하기 때문에 비효율적이고, 단지 리덕스의 기능을 100퍼센트 흉내를 내기 위해서라면 swr만의 방법, 필요한 데이터는 필요할 때만 요청하는 방법을 쓰면 충분히 가능하다는 것은 인지를 하고 있습니다.
제가 궁금했던 것은 위와 같이 생각해도 되느냐였던 것인데 설명이 짧았던 것 같습니다.
swr로 리덕스를 대체할 수 없다라고 주장하는 것이 아닙니다. swr만의 방법으로 리덕스를 100퍼센트 대체할 수 있지만, 그 방법이 리덕스와 다르다고 생각되어서 그 차이를 확인받고자 질문글을 올렸습니다.
리덕스 구조 자체를 대체하려고할 때 global을 키값으로 주는 방법은, 리덕스 스토어에 접근하듯이 data.user.me, data.post.mainPosts로 바로 접근할 수 있게 하려면 어떤 방법이 있을까 고민하다가 생각난 방법입니다. const{ data: store } = useSWR('global',...)의 동기 SWR함수를 호출해서 store를 뽑아내고, store에 리덕스 스토어 구조를 타입값으로 주고, 모든 비동기 요청의 fetcher에 대해서 then구문에서 store에 response들을 채워넣는 방식을 생각해봤는데 효율적인지 비효율적인지는 모르겠고 단지 이게 가능한건지 아닌건지가 궁금해서 질문 드렸었습니다!