
이번 PR에서는 관리자 기본 화면 데이터를 server props로 옮기는 작업을 했다.
그러다 상태를 업데이트하지 않고 렌더링만 하는 경우에는 props로 내리는데 Context를 이용하는 방안을 제안 받았다.
상태를 업데이트하지 않고 렌더링만 하는 경우에는 props로 내리는데 Context를 이용하는거를 생각해 보시면 어떨까 싶어요.
이벤트 목록 전체를 레이아웃에서 불러온다면 프롭스 드릴링 방지를 위해서 Context로 내리는 것도 방법일거 같아요.
그런데 Context로 바꾼다면 이벤트 목록에서 가져오는것고 방법일거 같아요.
events처럼 공통으로 읽기만 하는 데이터라면, 굳이 여러 단계로 props를 넘기기보다 Context로 묶는 것도 자연스럽지 않니? 라는 의견이였다.
실제로 Context의 가장 큰 장점 중 하나는 중간 컴포넌트를 건너뛰면서 공통 데이터를 아래에서 바로 꺼내 쓸 수 있다는 점이다.
특히 레이아웃에서 가져온 events를 사이드바, 헤더, 셀렉터 같은 하위 트리 여러 곳에서 공통으로 읽는 이런 상황에선 충분히 나올 수 있는 의견이다.
대략적으로 알고 있는 내용이긴 했지만 짚고 넘어가보자!
특히 events처럼 레이아웃에서 가져온 데이터를 사이드바, 헤더, 셀렉터 같은 하위 트리 여러 곳에서 공통으로 읽는다면 충분히 생각해볼 수 있는 방식이다.
우리 프로젝트는 전달 경로가layout -> Sidebar -> EventSelector 정도였고, 여기서 중간 컴포넌트가 단순 전달자도 아니었다.
Sidebar 자체도 events, user를 실제로 사용하고 있고.
그러니까 중간에서, 너무 많이, 전달만 하고 있는가? 를 기준으로 봤을 때, 아직은 Context가 꼭 필요할 정도는 아니라고 생각했다.
context는 중간 컴포넌트를 건너뛸 수 있어 프롭스 드릴링을 줄일 수 있다는 장점이 있어요.
다만 현재는 데이터를 소비하는 지점이 제한적이고, 전달도 layout -> Sidebar -> EventSelector 정도의 2-step 수준이라 props로도 충분해보여요. 중간 컴포넌트에서도 전달만 하는게 아닌 값을 사용하고 있구요.
현재 구조에서는 우선은 props로 두는 편이 더 단순하고 관계도 명확하다고 생각합니당
이렇게 답변한 이유는 Context가 틀린 선택지라서가 아니라, 지금 구조에서 props만으로도 충분한 부분이 더 많았기 때문이다.
서버 레이아웃이 events, user를 읽고, 그 값을 실제로 필요한 컴포넌트에 내려주고, 하위 컴포넌트는 받은 값을 그대로 렌더링한다.
누가 어떤 데이터를 받고 쓰는지가 props 쪽이 더 명확하게 드러나기도 하고.
이후에 events 내용을 더 많은 하위 컴포넌트에서 공통으로 소비하거나, 현재보다 프롭스 드릴링 비용이 더 커지는 상황이 오면 그때 다시 context 도입을 고려해볼 수 있을 것 같습니다.
정리하면
2-step 수준이라 props 비용이 크지 않았다.반대로 아래 상황이 오면 Context를 다시 보는 게 맞다고 생각한다.
events를 여러 하위 컴포넌트가 광범위하게 공통 소비할 때그때는 server props -> top-level provider -> 하위 소비 구조가 더 잘 맞을 수 있다.
invalidateQueries 이슈Context 얘기와 직접 같은 댓글은 아니었지만 살짝 끼워놓자면
업데이트한 이벤트 데이터만 업데이트 하면되지 않을까 싶은데 차이가 있나요? updateEvent 내부에서 invalidateQueries하고 있어요.
여기에 대해 이렇게 답변했다.
이전에는 관리자 페이지 전체적으로 useAdminEventQuery를 구독하고 있어서 invalidateQueries만으로 이벤트 상세 UI가 갱신됐습니다.
지금은 해당 쿼리를 사용하지 않고 서버에서 받은 initialEvent prop을 렌더링하고 있어서, invalidateQueries만으로는 전체 페이지 값이 바로 최신값으로 바뀌지 않습니다.
지금은 상세 페이지와 사이드바/헤더가 서버 데이터 기반으로 분리되어 있습니다.
왜냐면 이번 작업 이후 기본 데이터의 소유권이 이미 예전과 달라졌기 때문이다.
이전에는 같은 클라이언트 query 캐시를 여러 화면이 같이 보고 있어서 invalidateQueries가 의미 있었는데 지금은
initialEventevents이렇게 서버 기준 데이터가 각 영역에 내려가는 구조다.
그래서 수정 후에는 router.refresh()로 현재 경로의 서버 컴포넌트를 다시 렌더링해서, 서버에서 조회한 props와 레이아웃 데이터를 함께 최신값으로 맞춰야 했다.
이 지점까지 오면 이제 Context를 넣는다고 해서 해결되는 게 아니게 된다..
이미 이번 변경의 중심은 "공통 읽기 데이터를 클라이언트 캐시에서 다시 끌어오는 구조"가 아니라 "서버가 읽고 서버가 내려주는 구조"였기 때문이다.
즉 이번에 Context를 넣더라도, 그건 서버에서 받은 값을 더 편하게 소비하기 위한 레이어에 가깝지, 데이터 소유권 자체를 바꾸는 선택은 아니었다.
router.refresh()로 서버 기준 데이터를 다시 맞추는 흐름여기까지를 먼저 단순하게 정리했고,
리뷰에서 Context 얘기가 여러 번 나온 덕분에 오히려 좀 더 확신이 생겼다.
공통 읽기 전용 데이터라고 해서 바로 Context로 가는 건 아니고,
현재 트리에서 실제 드릴링 비용이 어느 정도인지,
중간 컴포넌트가 전달만 하는지,
그리고 지금 풀어야 하는 문제가 데이터 접근 편의인지 아니면 데이터 소유권 정리인지.
앞으로 비슷한 상황에서 이렇게 기준을 잡으면 좋겠다.
자세한 PR 내용과 내 최종 답변은 https://github.com/gomin-people/Stamplo/pull/295 이곳에서~