This message was deleted.
# 질문
s
This message was deleted.
h
GraphQL로 데이터 의존성을 관리하고 있다면 나머지 UI 상태가 글로벌에서 관리해야할 이유가 거의 없어집니다. 저는 UI 상태에 대한 맥락을 공유해야한다면 그 때마다 컨텍스트를 생성해서 사용합니다.
“상태 관리“와 “데이터 의존성“은 나눠서 생각할 수 이씅ㄹ 것 같습니다
사실 local state management가 이름을 그렇게 지어서 그렇지 실제로는 쓸일이 많지 않아요
컨커런트 리액트에서는 state와 resource라는 프리미티브를 분리하고 있고, 여기서 GraphQL이 관리하는건 state가 아니라 resource죠.
👍 1
t
저도 Data Fetching해서 받아온 데이터는 Apollo에 넣고, 뭐 사이드바 접고 편다던지하는건 MobX 쓰고있어요 ㅋㅋ
o
예를 들어 어떤 데이터 30개를 fetch 해와서 30개를 리스트로 그렸습니다. 이 때 유저가 리스트에서 어떤 걸 선택할 때마다 선택된 object를 갖고 여러 컴포넌트들이 render 해야한다고 할 때, 유저가 id 3 인 걸 선택했다, id 9 인걸 선택했다, 이렇게 선택된 게 무엇인지 어떻게 관리하나요? 제 생각에는 다음과 같은 선택지들이 있을 거 같습니다. 1. mobx 나 컨텍스트에 선택된 id 만 저장해놓고, 반응해야하는 컴포넌트들은 이 id 를 가지고 apollo client cache 에서 가져와서 그린다. 2. 선택되면 apollo client cache 에서 선택된 object 를 가져와서 그 object 를 통째로 mobx 나 컨텍스트에 저장해놓는다. (이 경우 30개를 refetch 했을 때 object 가 바뀌어도 mobx 에 있는 object 는 그대로니까 랜더가 안될 거 같은데 맞나요?) 3. Apollo client local state management 에 doc 에 나와있는대로 관리한다. 혹은 다른 분들은 이런 상태관리를 어떻게 하시는지 궁금합니다.
h
이 때 유저가 리스트에서 어떤 걸 선택할 때마다 선택된 object를 갖고 여러 컴포넌트들이 render 해야한다고 할 때, 유저가 id 3 인 걸 선택했다, id 9 인걸 선택했다, 이렇게 선택된 게 무엇인지 어떻게 관리하나요?
이거 케이스 조금만 더 구체적이면 답변 가능할 것 같아요
요구사항에 따라 다를거같긴한데 persistent 해야 한다면 리졸버를 하나 만들어 쓸 것 같고, 아니면 그냥 컨텍스트 하나 만들거같아요
그리고 graphql 클라들은 데이터들 전부 불변객체로 관리하고 있으니 굳이 id 만 dispatch 할게 아니라 통째로 컨텍스트에 넣는게 더 나을 것 같네요 여러모로
요는 예시에서 “지금 선택된 사용자” 라는게 어떤 의미를 가지는지 정의하는게 중요한 것 같습니다. 이게 도메인에서 중요한 의미를 갖는다면 데이터 그래프에, 단순히 UI 흐름 상 있는 휘발성 맥락이라면 리액트 컨텍스트에
뭐 특별히 redux, mobx 같은거로 서비스 레이어를 추가로 관리하고 ㅣㅇㅆ다면 써도 뭐 괜찮을거같긴한데요
개인적으로는 좀 복잡할거같다는 생각이…
o
완전 휘발성 맥락입니다. 예를 들어 맛집 object 가 있습니다. 필드는 id, 이름, 전화번호, 운영여부, 대표메뉴 가격을 갖습니다. 화면 왼쪽에 맛집 목록을 fetch 해와서 맛집 이름을 리스트로 보여주고 있습니다. 사용자가 이 리스트에서 맛집을 선택하면 화면 오른쪽에는 선택된 맛집에 대한 이름 전화번호 운영여부 가격대가 나옵니다. 화면 상단에 검색창에는 타이핑 할 때 맛집 목록을 auto suggestion 해주는데 선택되어 있는 맛집이 있을 경우 그건 제외합니다. 화면 구석 어딘가에는 선택된 맛집 대표 메뉴 가격에 뭔가 곱하고 더하고 해서 숫자를 보여줍니다. 새로고침 버튼을 누르면 맛집 목록을 전부 refetch 해오고 refetch 로 선택되었던 맛집의 필드 값이 바뀌었으면 각 컴포넌트들이 싱크되어 re-render 되어야합니다. 앱을 재실행하면 선택된 맛집정보는 날아가도 됩니다. (완전 휘발성입니다.) 이럴 때 선택된 맛집 정보를 어떻게 갖고 있어야 할 지 궁금합니다. 예를 들어 컨텍스트나 mobx 에다가 선택된 맛집 object 를 통째로 넣고 있으면 refetch 될 때 맛집 정보가 바꼇더라도 컨텍스트나 mobx 는 그걸 모르니까 re-render 를 위해 object 를 컨텍스트나 mobx 에 다시 갈아끼워 넣어야 할 것 같은데, 컨텍스트나 mobx 에서 선택된 맛집 id 만 들고있고 각 컴포넌트가 apollo-client-cache 에서 id 로 맛집 object 를 들고와서 랜더하고 있다면 refetch 시에도 알아서 re-render 가 될 것 같습니다. 이런 생각들을 하다가 이게 맞나? 다른 분들은 이런 UI 상태 정보를 어떻게 처리하지? 궁금해서 질문글을 올렸습니다.
h
하나하나 짚어보면 좋을 것 같습니다. 일단 맛집 object 라는게 휘발성 맥락이라고 하셨는데 제가 볼 때는 조금 다른 것 같습니다. • 맛집 이라는 맥락은 원격에서 가져온 가게 데이터에 기반하는 derived data 일 것입니다. • UI Tree의 거의 최상단에서 부터 흐르는 맥락으로 보이네요. 이 맥락이 상단 검색창이나 화면 구석구석에서 사용되는 것으로 보입니다. • 더 정확히는 "맛집을 선택한다" 라는 사용자 이벤트가 맥락으로 존재합니다 • 이 맥락을 통해 앱의 다양한 유즈케이스가 추가로 정의됩니다. 이 경우에는 단순히 새로고침하면 없어져도 된다고 해서 "휘발성" 맥락으로 취급하기 힘들다고 생각합니다. 영구적이진 않아도 라이프사이클이 꽤 넓은, 고쳐 말하면 순수하게 UI 에 국한된 정보(모달이 열렸는지 닫혔는지 같이)가 아니잖아요. 이럼 react context를 만들어 쓴다 쳐도 어차피 거의 최상단에 위치하게 됩니다. 캐시 사용은 정확히 이럴 때 고려되면 좋을 것 같습니다. 말씀하신거 처럼 graphql client 들의 cache 는 다른 상태관리자들의 store 와 관리 주체를 제외하고는 개념이 동일하고 구현도 유사하기 때문에 여러 개 사용할 필요 없이 apollo client를 사용하셔도 됩니다.
mobx 를 쓰냐 마냐는 그냥 API 취향일거같긴 한데요 apollo client 로 관리할 때의 특징을 짚어드리면
schema 기반이고 선언적으로 다루는 정도가 장점일수도 단점일수도 있습니다 (말씀하신대로 스키마 선언하고 @client 쿼리 만들고 하는게 말이죠)
근데 사실 apollo inmemory cache 는 그냥 스토어 쓰듯이 readData, writeData 하면서 써도 잘 돌긴해요
React도 Apollo도 그닥 권장하는 패턴은 아닙니다
예를 들어 컨텍스트나 mobx 에다가 선택된 맛집 object 를 통째로 넣고 있으면 refetch 될 때 맛집 정보가 바꼇더라도 컨텍스트나 mobx 는 그걸 모르니까 re-render 를 위해 object 를 컨텍스트나 mobx 에 다시 갈아끼워 넣어야 할 것 같은데, 컨텍스트나 mobx 에서 선택된 맛집 id 만 들고있고 각 컴포넌트가 apollo-client-cache 에서 id 로 맛집 object 를 들고와서 랜더하고 있다면 refetch 시에도 알아서 re-render 가 될 것 같습니다.
변경은 잘 감지합니다. apollo client api 로 가져온 슬라이스는 전부 불변객체이라 내부 모양이 바뀌면 참조가 바뀌어요
즉, 알아서 구독하고 re-render 합니다. 외부 스토어가 추가로 있다면 참조가 바뀌었을 때 메시지만 쏘면 (action dispatch) 되겠죠
pollo-client 랑 mobx 랑 두 곳에서 상태관리를 하고 렌더링을 observe 하고 있는 게 깔끔하지 않은 느낌도 들어서 apollo-client 로 통일해야겠다는 생각도 들구요.
장기적으로 코드 뿐만 아니라 양쪽 동기화를 사용자 코드로 하는 것이기 때문에 일관성까지 깨먹을 위험이 있습니다. 역할이 겹쳐서요. 같이 쓰려면 역할을 잘 나누어 격리해야 하고, 아니라면 한쪽으로 밀어버리시는 걸 추천드려요
o
감사합니다. 뭔가 감이 올 거 같아요. 설명해주신 내용이 뭔가 꽤 큰 graph 를 다룬 경험이 있어야 알 수 있는 것들 인 것 같아서 graphql 다룬지 얼마 안 된 저한테 큰 도움이 될 거 같습니다.
👍 1