과제 체크포인트
기본과제
목표 : 전역상태관리를 이용한 적절한 분리와 계층에 대한 이해를 통한 FSD 폴더 구조 적용하기
- 전역상태관리를 사용해서 상태를 분리하고 관리하는 방법에 대한 이해
- Context API, Jotai, Zustand 등 상태관리 라이브러리 사용하기
- FSD(Feature-Sliced Design)에 대한 이해
- FSD를 통한 관심사의 분리에 대한 이해
- 단일책임과 역할이란 무엇인가?
- 관심사를 하나만 가지고 있는가?
- 어디에 무엇을 넣어야 하는가?
체크포인트
- 전역상태관리를 사용해서 상태를 분리하고 관리했나요?
- Props Drilling을 최소화했나요?
- shared 공통 컴포넌트를 분리했나요?
- shared 공통 로직을 분리했나요?
- entities를 중심으로 type을 정의하고 model을 분리했나요?
- entities를 중심으로 ui를 분리했나요?
- entities를 중심으로 api를 분리했나요?
- feature를 중심으로 사용자행동(이벤트 처리)를 분리했나요?
- feature를 중심으로 ui를 분리했나요?
- feature를 중심으로 api를 분리했나요?
- widget을 중심으로 데이터를 재사용가능한 형태로 분리했나요?
심화과제
목표: 서버상태관리 도구인 TanstackQuery를 이용하여 비동기코드를 선언적인 함수형 프로그래밍으로 작성하기
- TanstackQuery의 사용법에 대한 이해
- TanstackQuery를 이용한 비동기 코드 작성에 대한 이해
- 비동기 코드를 선언적인 함수형 프로그래밍으로 작성하는 방법에 대한 이해
체크포인트
- 모든 API 호출이 TanStack Query의 useQuery와 useMutation으로 대체되었는가?
- 쿼리 키가 적절히 설정되었는가?
- fetch와 useState가 아닌 선언적인 함수형 프로그래밍이 적절히 적용되었는가?
- 캐싱과 리프레시 전략이 올바르게 구현되었는가?
- 낙관적인 업데이트가 적용되었는가?
- 에러 핸들링이 적절히 구현되었는가?
- 서버 상태와 클라이언트 상태가 명확히 분리되었는가?
- 코드가 간결하고 유지보수가 용이한 구조로 작성되었는가?
- TanStack Query의 Devtools가 정상적으로 작동하는가?
최종과제
- 폴더구조와 나의 멘탈모데일이 일치하나요?
- 다른 사람이 봐도 이해하기 쉬운 구조인가요?
과제 셀프회고
이번 과제를 통해 이전에 비해 새롭게 알게 된 점이 있다면 적어주세요.
- Jotai를 활용한 전역 상태 관리의 효율성: 기존에 복잡하게 관리되던 UI 상태(특히 모달의 열림/닫힘, 데이터 등)를 Jotai의 아톰(atom)을 활용하여 훨씬 간결하고 직관적으로 관리할 수 있게 되었습니다. 각 컴포넌트가 필요한 상태만 구독하고 업데이트함으로써 불필요한 리렌더링을 줄이고 성능을 최적화하는 방법을 체감했습니다.
- TanStack Query를 통한 서버 상태 관리의 해방감: 데이터 페칭, 캐싱, 동기화, 에러 처리 등 서버 상태 관리에 필요한 복잡한 로직들을 TanStack Query가 대신 처리해주면서, 비동기 데이터 관리에 대한 부담을 크게 줄일 수 있었습니다. useQuery, useMutation 훅을 통해 서버와의 상호작용을 선언적으로 관리하는 방식이 매우 강력하다는 것을 깨달았습니다.
- UI 컴포넌트의 재사용성과 모듈화: 모달과 같은 재사용 가능한 UI 요소들을 widgets 및 features/ui 디렉토리로 분리하는 과정을 통해, 컴포넌트의 책임과 역할을 명확히 하고 재사용성을 극대화하는 방법을 익혔습니다. 이는 코드의 응집도를 높이고 유지보수를 용이하게 하는 데 크게 기여했습니다.
본인이 과제를 하면서 가장 애쓰려고 노력했던 부분은 무엇인가요?
- 코드의 모듈화 및 관심사 분리: 특히 모달 관련 로직과 UI를 분리하고, 게시물 추가/수정 기능의 로직을 캡슐화하는 등 각 기능의 책임 범위를 명확히 하려고 노력했습니다. 이를 통해 특정 기능의 변경이 다른 부분에 미치는 영향을 최소화하고, 코드의 가독성과 유지보수성을 높이고자 했습니다.
- 상태 관리 라이브러리(Jotai, TanStack Query)의 적절한 활용: 어떤 상태를 전역으로 관리하고, 어떤 상태를 서버 상태로 관리할지 고민하며 각 라이브러리의 장점을 최대한 활용하려고 애썼습니다. 특히 Jotai를 이용해 UI 상태를 세밀하게 제어하고, TanStack Query로 서버 데이터를 효율적으로 관리하는 데 집중했습니다.
아직은 막연하다거나 더 고민이 필요한 부분을 적어주세요.
- Jotai 아톰의 세분화 및 의존성 관리: 아톰을 너무 세분화할 경우 발생할 수 있는 관리의 복잡성이나, 아톰 간의 의존성이 커질 때의 문제점에 대해 더 고민이 필요합니다. 어떤 단위로 아톰을 정의하는 것이 가장 효율적인지에 대한 기준을 명확히 하고 싶습니다.
- FSD(Feature-Sliced Design)와 같은 아키텍처 패턴의 깊이 있는 이해 및 적용: 현재 프로젝트 구조가 FSD와 유사한 형태를 띠고 있지만, 각 레이어(entities, features, widgets, pages, shared) 간의 명확한 역할과 상호작용 원칙에 대해 더 깊이 이해하고 실제 프로젝트에 완벽하게 적용하는 연습이 필요하다고 생각합니다.
이번에 배운 내용 중을 통해 앞으로 개발에 어떻게 적용해보고 싶은지 적어주세요.
- 새로운 프로젝트 시작 시 Jotai와 TanStack Query 조합 적극 활용: 이번 과제를 통해 두 라이브러리의 강력함을 체감했으므로, 앞으로 진행할 프론트엔드 프로젝트에서 이 조합을 기본 상태 관리 스택으로 적극적으로 도입하고 싶습니다.
- 재사용 가능한 UI 컴포넌트 라이브러리 구축: 모달과 같이 반복적으로 사용되는 UI 요소들을 shared/ui나 widgets와 같은 형태로 분리하여 재사용성을 높이는 경험을 바탕으로, 나아가 프로젝트 전반에 걸쳐 재사용 가능한 컴포넌트 라이브러리를 구축하는 연습을 해보고 싶습니다.
- 클린 아키텍처 원칙 적용: 이번에 경험한 모듈화 및 관심사 분리 노력을 바탕으로, 앞으로는 더 큰 규모의 프로젝트에서도 클린 아키텍처 원칙을 적용하여 견고하고 확장 가능한 코드베이스를 구축하는 데 집중할 것입니다.
챕터 셀프회고
클린코드와 아키테쳑 챕터 함께 하느라 고생 많으셨습니다! 지난 3주간의 여정을 돌이켜 볼 수 있도록 준비해보았습니다. 아래에 적힌 질문들은 추억(?)을 회상할 수 있도록 도와주려고 만든 질문이며, 꼭 질문에 대한 대답이 아니어도 좋으니 내가 느꼈던 인사이트들을 자유롭게 적어주세요.
클린코드: 읽기 좋고 유지보수하기 좋은 코드 만들기
- 더티코드를 접했을 때 어떤 기분이었나요? ^^; 클린코드의 중요성, 읽기 좋고 유지보수하기 쉬운 코드란 무엇인지에 대한 생각을 공유해주세요
- 더티코드를 접했을 때의 경험: 처음에는 기능 구현에 급급하여 코드를 작성하다 보니, 나중에 다시 보거나 수정해야 할 때 어디를 건드려야 할지 막막하고, 작은 수정이 예상치 못한 버그로 이어지는 경험을 자주 했습니다. 특히 거대한 함수나 컴포넌트 안에서 여러 책임이 뒤섞여 있을 때의 답답함은 이루 말할 수 없었습니다.
- 클린코드의 중요성: 클린코드는 단순히 코드를 예쁘게 만드는 것을 넘어, 개발 생산성과 팀 협업의 핵심이라는 것을 깨달았습니다. 읽기 좋은 코드는 디버깅 시간을 단축시키고, 새로운 기능 추가를 용이하게 하며, 동료 개발자들이 코드를 이해하고 기여하는 데 큰 도움을 줍니다.
- 읽기 좋고 유지보수하기 쉬운 코드란:
- 명확한 이름 짓기: 변수, 함수, 클래스 이름만으로도 그 역할과 목적을 유추할 수 있어야 합니다.
- 단일 책임 원칙(SRP) 준수: 하나의 함수나 컴포넌트는 하나의 책임만 가져야 합니다. 이를 통해 변경의 파급 효과를 줄일 수 있습니다.
- 작고 응집된 함수/컴포넌트: 코드를 작은 단위로 쪼개어 각 단위가 명확한 역할을 수행하도록 합니다.
- 불필요한 주석 제거 및 자가 설명적인 코드 작성: 코드가 스스로를 설명하도록 작성하고, 주석은 '왜' 그렇게 했는지에 대한 이유를 설명하는 데 사용합니다.
결합도 낮추기: 디자인 패턴, 순수함수, 컴포넌트 분리, 전역상태 관리
- 거대한 단일 컴포넌트를 봤을때의 느낌! 처음엔 막막했던 상태관리, 디자인 패턴이라는 말이 어렵게만 느껴졌던 시절, 순수함수로 분리하면서 "아하!"했던 순간, 컴포넌트가 독립적이 되어가는 과정에서의 깨달음을 들려주세요
- 거대한 단일 컴포넌트의 문제점: 모든 로직과 UI가 한 컴포넌트에 몰려있는 경우, 코드를 이해하는 데 시간이 오래 걸리고, 특정 기능을 수정하려 할 때 다른 기능에 영향을 줄까 봐 두려웠습니다. 재사용은 꿈도 꾸기 어려웠습니다.
- 상태 관리의 막막함과 해결: 초기에는 useState와 useContext만으로 복잡한 전역 상태를 관리하는 것이 어렵게 느껴졌습니다. 특히 모달의 열림/닫힘 상태나 사용자 정보와 같은 전역적으로 필요한 데이터들을 어떻게 효율적으로 전달하고 업데이트할지 고민이 많았습니다. 하지만 Jotai와 같은 전역 상태 관리 라이브러리를 도입하면서, 상태를 아톰 단위로 분리하고 필요한 컴포넌트에서만 구독하는 방식이 훨씬 깔끔하고 성능에도 이점을 준다는 것을 깨달았습니다.
- 순수 함수와 컴포넌트 분리의 "아하!" 모먼트: 특정 로직을 순수 함수로 분리하거나, UI와 로직을 분리하여 컴포넌트를 독립적으로 만드는 과정에서 코드의 테스트 용이성이 높아지고, 재사용성이 극대화되는 것을 경험했습니다. 특히 모달 컴포넌트들을 widgets로 분리하고, 각 모달 내부의 상태 관리 로직을 Jotai 아톰으로 캡슐화하면서, 컴포넌트가 훨씬 독립적이고 재사용 가능한 단위가 되는 것을 보며 큰 깨달음을 얻었습니다. 이는 결합도를 낮추는 실질적인 방법임을 체감했습니다.
응집도 높이기: 서버상태관리, 폴더 구조
- "이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간, FSD를 적용해보면서의 느낌, 나만의 구조를 만들어가는 과정, TanStack Query로 서버 상태를 분리하면서 느낀 해방감(?)등을 공유해주세요
- 코드 위치에 대한 고민: 프로젝트 초기에는 어떤 코드를 어디에 두어야 할지 항상 고민이었습니다. 특히 API 호출 로직, UI 컴포넌트, 비즈니스 로직 등이 뒤섞여 있어 파일 구조가 점점 복잡해지는 경향이 있었습니다.
- FSD 적용 경험: entities, features, widgets, pages, shared와 같은 폴더 구조를 적용하면서, 각 코드의 책임과 위치가 명확해지는 것을 느꼈습니다. "이 코드는 대체 어디에 둬야 하지?"라는 고민이 줄어들고, 새로운 기능을 추가하거나 기존 기능을 수정할 때 해당 기능과 관련된 파일들을 한눈에 파악하기 쉬워졌습니다. 이는 코드의 응집도를 높이는 데 매우 효과적인 방법이었습니다.
- TanStack Query를 통한 서버 상태 분리의 해방감: 이전에는 useEffect와 useState를 조합하여 직접 서버 데이터를 관리하고, 로딩, 에러, 캐싱 등을 수동으로 처리해야 했습니다. 이 과정에서 많은 보일러플레이트 코드가 발생하고, 복잡성이 증가했습니다. 하지만 TanStack Query를 도입하면서, 서버 상태와 클라이언트 상태를 명확히 분리하고, 데이터 페칭 및 동기화에 대한 모든 복잡성을 라이브러리에 위임할 수 있게 되었습니다. 이는 마치 무거운 짐을 내려놓은 듯한 '해방감'을 주었으며, 개발자가 비즈니스 로직에 더 집중할 수 있게 해주었습니다.
리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문
- 모달 관리를 어떻게 하시나요? - 개인적으로 모달을 전역상태관리 라이브러리를 이용해 관리하는 게 베스트 프랙티스인지 잘 모르겠습니다.
- 현재 프로젝트에서는 Jotai 아톰을 활용하여 각 모달의 열림/닫힘 상태와 모달에 전달될 데이터를 관리하고 있습니다. 예를 들어, addPostModalAtom과 같은 아톰을 만들어 모달의 가시성을 제어하고, postDetailModalDataAtom과 같이 모달에 필요한 데이터를 담는 아톰을 별도로 두어 관리합니다.
- 모달을 띄우는 컴포넌트에서는 해당 모달 아톰의 상태를 업데이트하여 모달을 열고, 모달 내부에서는 닫기 버튼 클릭 시 아톰 상태를 초기화하여 모달을 닫는 방식입니다.
- 이러한 방식이 모달 관리에 있어 가장 효율적이고 확장 가능한 방법인지, 혹은 여러 종류의 모달이 중첩되거나, 모달 간의 복잡한 상호작용이 필요할 때의 베스트 프랙티스가 궁금합니다.
과제 피드백
안녕하세요 진희님! 클린코드 마지막 챕터 잘 진행해주셨네요 ㅎㅎ 고생하셨어요!!
모달 관리를 어떻게 하시나요?
jotai로 모달을 다 관리하는건 어렵다고 생각해요 ㅎㅎ 특히 여러 개의 모달이 있을 때, jotai에서 이를 관리하기가 무척 까다롭답니다. 그래서 저는 context를 사용하는 방법이 좋지 않나!? 라고 생각하는데요, 일단 context의 경우 react에서 제공하는 api이기 때문에 라이브러리로 만들어서 관리하기도 수월해요!
그리고 modal이 jotai를 직접적으로 의존하기보단, 한 단계의 추상화된 레이어 (useModal 같은)를 만들고 이를 의존하도록 작성해주시면 좋을 것 같아요! 그렇게 해야 jotai를 사용하다가 다른 라이브러리로 바꾸거나 context로 바꿀 때 유연해진답니다 ㅎㅎ
"가장 효율적이고 확장 가능한 방법"이라는건 사실... 딱히 정해져있다고 생각하지 않아요. 어떤 프로젝트에서는 진희님께서 만들어주신 모달이 최적의 코드일 것이고, 어떤 프로젝트에서는 다양한 요구사항으로 인해 다르게 쓰일 수 있으니까요!
"모달간의 복잡한 상호작용"의 경우, 모달끼리는 상호작용을 하지 않도록 하는게 좋다고 생각해요 ㅎㅎ 그냥 모달은 "데이터의 UI 표현"일 뿐이고, 데이터를 다뤄야 하는거죠.
말씀해주신 상황도 Context와 Modal이 1:1로 매칭되는 상황이면 대체로 해결되지 않을까!? 라는 생각이 드네요.