개발자
안녕하세요 react를 이용해서 복잡한 작성 페이지를 만들고있습니다. 아래의 타입은 예시입니다. type payload = { name: string; message: string; type: string; url: { pc: string; mobile: string; }; contents: { images: { url: string; name: string; }[]; buttons: { name: string; url: string; }[]; }; conditions: { ... }, .... }; 위처럼 복잡한 데이터를 서버로 보내줘야해서 데이터를 관리해야하는데 현재는 페이지내에 구조가 복잡하고 컴포넌트도 매우많아 props drilling이 너무 심해질거같아서 recoil, jotai와 같은 상태관리 라이브러리를 이용해서 작업을 진행하고있습니다. 이러한 상황에서 관리하는 데이터를 한객체에 모아서 관리하는게 좋은지 아니면 const nameAtom = atom(''); const messageAtom = atom(''); const typeAtom = atom(''); const urlAtom = atom({ pc: '', mobile: ''}); .... 처럼 일일히 쪼개서 관리하는게 맞는 방향인지 모르겠어서 질문드립니다 ! (사수가없어서 물어볼곳이없어요...) 현재는 아래와같이 쪼개서 작업한뒤 submit시에 합쳐주는 방식으로 구현해놓았는데 atom 갯수가 20개 정도 되버리니까 너무 복잡해보여서 이게맞나... 싶어서 질문드리게되었습니다.
답변 2
안녕하세요! 상태관리 관련 자주 고민하게되는 부분에 대한 질문을 주셨네요! 사실 완전 정답은 없기 때문에 앱의 성능 최적화와 DX 사이에서의 적당한 타협점을 찾는게 나름의 요령 아닐까 싶습니다🥲 먼저 질문자님의 방식처럼 atom을 나눠 사용하게 되면 컴포넌트 별로 필요한 데이터만 사용하고 업데이트 하며 렌더링을 최적화하기에 용이하다는 장점이 있지만, 말씀하신대로 관리하기가 너무 복잡해질 수 있습니다. 반대로 한 객체에 모아 관리하게 되면 사용은 편리하지만, 하나의 프로퍼티만 업데이트 되어도 그 객체를 참조중인 모든 컴포넌트가 업데이트 된다는 점에서 렌더링 최적화에 대한 고민이 생기기도 합니다. 일단 위와 같은 상황에서 저의 추천은 "한 객체에 모아 관리하기" 입니다! 후에 어차피 submit시에 내용을 다시 합쳐줘야 하는 구조라면 굳이 다 분리 시켜놔야할 이유가 없기도 하니까요. 대신, 렌더링 이슈가 고민이 된다거나 프로퍼티 개별관리가 필요한 케이스에는 selector 와 selectorFamily를 활용하시면 될 듯 합니다! (Jotai에서는 selectAtom 등 활용) 공식문서를 찾아보시면 제일 좋고, 관련해서 간단한 사용법 정리해둔 블로그를 찾아서 함께 공유드려요! https://velog.io/@2ast/React-Recoil-selector%EB%A1%9C-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%B5%9C%EC%A0%81%ED%99%94%EC%97%90-%EA%B8%B0%EC%97%AC%ED%95%98%EA%B8%B0
안녕하세요. 제가 생각으로는 위에서 말씀하신 것과 같이 복잡한 form를 구현할 경우에는 recoil, jotai와 같은 atomic 구조의 라이브러리 보다는 zustand와 redux를 사용하는 것이 더 좋을 것 같다는 생각이 듭니다. atom을 변수값을 작은 단위로 구성하면 스프레드 연산(...)등을 활용해서 전송할 데이터를 통합해야 하는 번거로움이 있을 것 같습니다. zustand로 store.ts 파일에 사용할 API 타입과 state를 정의한 후에 입력하는 단위로 컴포넌트를 나눈 뒤에 사용하는 컴포넌트 UI에서 데이터를 입력하면 상태값을 구독하고 변경하도록 하는 방법을 고려해 볼수 있을것 같습니다. 아울러, 데이터 입력시에 유효성 체크 같은 기능이 필요하다면, react-hook-form, formik과 같은 라이브러리를 사용하는 것을 권해드리고 싶습니다.
1// store.ts
2
3type Payload = {
4 name: string;
5 message: string;
6 type: string;
7 url: {
8 pc: string;
9 mobile: string;
10 };
11 contents: {
12 images: {
13 url: string;
14 name: string;
15 }[];
16 buttons: {
17 name: string;
18 url: string;
19 }[];
20 };
21
22const initialState : Payload = {
23 name : ' ',
24 message: ' ' ,
25 type: ' ',
26 url: {
27 pc: ' ',
28 mobile: ' ',
29 },
30 ...
31 }
32
33export const usePayloadStore = create<Payload>((set) => ({
34 payloadInfo: initialState,
35 setPayloadInfo: (newInfo) => set((state) => ({
36 payloadInfo: { ...state.payloadInfo, ...newInfo },
37 }))
38 }));
39
40/////// Payload.tsx
41
42export default function Payload( ) {
43
44 return(
45 <>
46 <Name/>
47 <Message/>
48 <Url/>
49 <Contents/>
50 ...
51 </>
52 )
53}
54
55/////// Name.tsx
56
57export default function Name( ) {
58
59 const name = usePayloadStore (state => state.payloadInfo.name );
60 const setPayloadInfo= usePayloadStore (state => state.setPayloadInfo);
61
62 return(
63 <Input onChange={(e :
64 React.ChangeEvent<HTMLInputElement>) => {
65 setPayloadInfo({name : e.target.value })
66 }}
67 value={name}
68 />
69 )
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2024년 03월 29일
지금과 같은 상황에서는 재사용 가능한 공통 로직이 있거나 특정 상태 관련 작업이 자주 발생한다면 atom을 별도로 분리해서 관리하는 것이 좋을 수 있습니다. 따라서 각각의 상태를 별도의 atom으로 관리하다 보면 결국 코드가 복잡해지곤 합니다. 그러나 만약 어떤 상태들이 서로 밀접하게 연관되어 있다면, 그룹화하여 하나의 atom으로 관리하는 것이 좋습니다. 당신의 경우처럼 많은 양의 데이터를 다루는 경우에는 이 방법이 더욱 유리할 수 있습니다. 이전에 질문한 예제에서 URL, buttons 또는 images와 같은 내부 객체 구조를 가진 키값들은 각각의 atom으로 분리될 수 있겠죠. 한 객체 내부에서 어느 정도 그룹화를 할 수 있다면, 너무 단편적으로 atom을 분리하는 것보다 더 깔끔하게 코드를 유지할 수 있습니다. 만약 해당 페이지가 매우 복잡하고 컴포넌트도 많다면 Redux 같은 전역 상태 관리 라이브러리를 고려해볼 만 합니다. Redux는 큰 애플리케이션에서 상태 관리를 좀 더 체계적으로 할 수 있게 해줍니다. 하지만 작은 프로젝트에서는 오버헤드가 될 수 있으니 주의해야 합니다. 따라서 어떤 상황에 있는지, 그리고 각 상태 값들이 얼마나 밀접하게 연결되어 있는지에 따라서 선택하는 것이 가장 중요합니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!