과제 링크
https://adds9810.github.io/front_6th_chapter2-3/
과제 체크포인트
기본과제
목표 : 전역상태관리를 이용한 적절한 분리와 계층에 대한 이해를 통한 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가 정상적으로 작동하는가?
최종과제
- 폴더구조와 나의 멘탈모데일이 일치하나요?
- 다른 사람이 봐도 이해하기 쉬운 구조인가요?
과제 셀프회고
컨디선 난조로 언제나 괴발새발이었지만 더 괴발새발 했던 한주였습니다.ㅜ 매 회차 새로운걸 알게 되는 것 좋은데 기한 안에 이해하면서 적용이란 쉽지 않은 것 같습니다. 질문은 못하고 다른분들 코드나 토론하는거 들으면서 이렇게 생각하면서 짤 수 있구나를 많이 알게된 한 주였습니다.(항해 끝나면 꼭 나왔던 것들 정리하고 해보자 다짐도...)
이번 과제를 통해 이전에 비해 새롭게 알게 된 점이 있다면 적어주세요.
FSD(Feature-Sliced Design) 아키텍처를 통해 대규모 애플리케이션에서 코드를 체계적으로 구조화하는 방법에 대해 알게 되었습니다. 이런 개념에 대해 몰라 작업시 일관성 없이 코드를 모아두곤 했는데 shared → entities → features → widgets → pages 순서로 계층을 나누면서 각 부분의 책임이 명확해지고 코드의 위치를 예측하기 쉬워졌습니다.(그렇지만 FSD의 개념 이해 미흡과 도메인, ui기준으로 나누던 습관이 있어 좀 불편...) 또한 Zustand와 TanStack Query를 함께 사용하여 클라이언트 상태와 서버 상태를 효과적으로 분리하는 방법을 경험했습니다. Zustand로 UI 상태를 관리하고, TanStack Query로 서버 데이터를 관리하면서 각 도구의 장점을 최대한 활용할 수 있다는 것을 깨달았습니다. 특히 TanStack Query의 캐싱과 낙관적 업데이트 기능을 통해 사용자 경험을 크게 향상시킬 수 있다는 점이 새로웠습니다.
본인이 과제를 하면서 가장 애쓰려고 노력했던 부분은 무엇인가요?
FSD(Feature-Sliced Design) 아키텍처 원칙을 지키며 코드를 구조화하는 데 가장 많은 노력을 기울였습니다. shared → entities → features → widgets → pages 순서로 체계적으로 진행하면서, 각 계층별로 적절한 책임을 분리하고 코드의 응집도를 높이고 결합도를 낮추려 꾸준히 리팩토링했습니다. 각 엔티티별로 API 로직과 모델을 분리하며, 마지막에 PostManager 위젯을 더 작은 단위의 위젯(FilterBar, SearchBar, PostTable 등)으로 분리한 것이 가장 큰 성과였습니다.
아직은 막연하다거나 더 고민이 필요한 부분을 적어주세요.
FSD 아키텍처에서 features 계층을 더 세분화하는 방법이 막연합니다. 현재는 도메인별로만 나누어져 있는데, features/post 안에 search, create, edit 등 기능별로 더 나눴어야 하지 않았나 싶습니다. 시간이 부족해서 현재에 만족하지만, 실제로는 어느 정도까지 세분화해야 하는지에 대한 기준이 명확히 해서 더 나눌수 있으면 나눠봐야겟다 생각했습니다.
또한, TanStack Query의 낙관적 업데이트(Optimistic Updates) 적용이 아직은 막연하게 느껴집니다. 이번 과제에서는 기본적인 useMutation의 onSuccess 콜백에서 쿼리를 무효화하는 방식으로 데이터 동기화를 처리했지만, 사용자 경험을 즉각적으로 개선할 수 있는 낙관적 업데이트를 실제 프로덕션 환경에서 자신 있게 적용하려면 더 깊은 이해와 연습이 필요할 것 같습니다.
이번에 배운 내용 중을 통해 앞으로 개발에 어떻게 적용해보고 싶은지 적어주세요.
이번 과제를 통해 UI 기준(페이지별)으로만 구현하던 기존 방식에서 벗어나, FSD의 명확한 구분 기준을 어느 정도 적용할 수 있게 되었습니다. 완전한 적용은 아니지만, 이제 어느 정도 구분을 갖고 코드를 나눌 수 있는 기준을 갖게 된 것 같습니다. 또한 AI의 도움을 받아 TanStack Query의 캐싱 전략 최적화나 suspense와 결합한 로딩 UX 구현 같은 고급 기능들이 있다는 것을 알게 되었습니다. 아직 직접 구현해보지는 못했지만, 이런 기술들이 존재한다는 것을 알게 된 것만으로도 큰 수확이었다고 생각합니다.
챕터 셀프회고
클린코드와 아키테쳑 챕터 함께 하느라 고생 많으셨습니다! 지난 3주간의 여정을 돌이켜 볼 수 있도록 준비해보았습니다. 아래에 적힌 질문들은 추억(?)을 회상할 수 있도록 도와주려고 만든 질문이며, 꼭 질문에 대한 대답이 아니어도 좋으니 내가 느꼈던 인사이트들을 자유롭게 적어주세요.
클린코드: 읽기 좋고 유지보수하기 좋은 코드 만들기
- 더티코드를 접했을 때 어떤 기분이었나요? ^^; 클린코드의 중요성, 읽기 좋은 코드란 무엇인지, 유지보수하기 쉬운 코드란 무엇인지에 대한 생각을 공유해주세요
결합도 낮추기: 디자인 패턴, 순수함수, 컴포넌트 분리, 전역상태 관리
- 거대한 단일 컴포넌트를 봤을때의 느낌! 처음엔 막막했던 상태관리, 디자인 패턴이라는 말이 어렵게만 느껴졌던 시절, 순수함수로 분리하면서 "아하!"했던 순간, 컴포넌트가 독립적이 되어가는 과정에서의 깨달음을 들려주세요
응집도 높이기: 서버상태관리, 폴더 구조
- "이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간, FSD를 적용해보면서의 느낌, 나만의 구조를 만들어가는 과정, TanStack Query로 서버 상태를 분리하면서 느낀 해방감(?)등을 공유해주세요
리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문
- FSD 구조의 적절성 - Post와 Comment 도메인 분리 : 현재 Post와 Comment를 별도 entities로 분리했는데, 실제로는 Post를 클릭하면 댓글을 불러오고, 댓글 추가 시 Post의 댓글 목록이 업데이트되는 밀접한 관계입니다. 이런 구조가 적절한지, 아니면 Post와 Comment를 하나의 도메인으로 통합하는 것이 더 나을지 리뷰받고 싶습니다.
- TanStack Query 쿼리 키 관리 전략 : 현재는
['posts'],['comments', postId]와 같이 단순한 형태로 쿼리 키를 사용하고 있는데, 필터링이나 정렬이 추가될 경우['posts', { limit: 10, skip: 0, tag: 'react' }]같은 복잡한 쿼리 키가 필요할 것 같습니다. 이런 경우를 대비한 쿼리 키 팩토리 함수나 구조화된 쿼리 키 패턴에 대한 조언을 구합니다. - 상태 관리 도구 조합 패턴 : Zustand와 TanStack Query를 함께 사용할 때, 특히 댓글 추가/수정 시
onSuccess에서queryClient.setQueryData로 직접 캐시를 조작하는 현재 방식이 올바른 패턴인지, 그리고 더 나은 방법이 있는지 리뷰받고 싶습니다.
과제 피드백
수고했습니다. 지난 3주간 클린코드를 비롯한 소프트웨어 공학적으로 결합도 낮추기 응집도 높이기를 위한 이론과 프론트엔드에서의 적용등을 통해서 좋은 코드와 구조에 대한 다각도의 시야가 생겼기를 기대합니다.
"질문은 못하고 다른분들 코드나 토론하는거 들으면서 이렇게 생각하면서 짤 수 있구나를 많이 알게된 한 주였습니다.(항해 끝나면 꼭 나왔던 것들 정리하고 해보자 다짐도...)"
"이번 과제를 통해 UI 기준(페이지별)으로만 구현하던 기존 방식에서 벗어나, FSD의 명확한 구분 기준을 어느 정도 적용할 수 있게 되었습니다. 완전한 적용은 아니지만, 이제 어느 정도 구분을 갖고 코드를 나눌 수 있는 기준을 갖게 된 것 같습니다."
좋아요. 우리가 함께 토론하며 공부를 하고자 하는 것이 다른 사람의 관점을 우리가 옆에서 배울 수 있기 때문이죠. 다른 사람의 시야를 습득하는것은 아주 좋은 공부 방법입니다. 꼭 정리해보기 바래요!
코드에 대한 구분이 생겼다는 것이 참 좋네요. FSD자체를 잘 하려고 하기 보다는 FSD를 통해서 고민했던 내용을 바탕으로 코드를 작성하거나 볼때 계층과 모듈을 한번 떠올려 볼 수 있게 되기를 바랍니다.
FSD 구조의 적절성 - Post와 Comment 도메인 분리 : 현재 Post와 Comment를 별도 entities로 분리했는데, 실제로는 Post를 클릭하면 댓글을 불러오고, 댓글 추가 시 Post의 댓글 목록이 업데이트되는 밀접한 관계입니다. 이런 구조가 적절한지, 아니면 Post와 Comment를 하나의 도메인으로 통합하는 것이 더 나을지 리뷰받고 싶습니다.
=> 서로 밀접한 관계이나 각자의 기능적 독립성이 있는 관계이므로 엔티티는 분리가 되는 것이 맞습니다. 엔티티는 interface를 기준으로 생각해보면 좋아요.
Q) TanStack Query 쿼리 키 관리 전략 : 현재는 ['posts'], ['comments', postId] 와 같이 단순한 형태로 쿼리 키를 사용하고 있는데, 필터링이나 정렬이 추가될 경우 ['posts', { limit: 10, skip: 0, tag: 'react' }] 같은 복잡한 쿼리 키가 필요할 것 같습니다. 이런 경우를 대비한 쿼리 키 팩토리 함수나 구조화된 쿼리 키 패턴에 대한 조언을 구합니다.
=> 네, 지금 접근하듯이 접근하면 됩니다. queryKey의 경우 REST api의 구조와 동일합니다. path는 배열로 searchQuery는 Object로 관리하면 됩니다.
Q) 상태 관리 도구 조합 패턴 : Zustand와 TanStack Query를 함께 사용할 때, 특히 댓글 추가/수정 시 onSuccess에서 queryClient.setQueryData로 직접 캐시를 조작하는 현재 방식이 올바른 패턴인지, 그리고 더 나은 방법이 있는지 리뷰받고 싶습니다.
=> 올바른 패턴이라기 보다는 서버의 응답을 기다리지 않고 화면의 데이터를 먼저 변경하고 적용하는 방식을 낙관적 업데이트라고 하죠. 이를 사용하기 위해서 Tanstack에서는 직접 캐시를 조작하는 방식으로 적용합니다.
=> 낙관적 업데이트를 하면 사용자 경험이 확실히 좋아집니다. 로딩이 없는 것처럼 느낄 수 있죠. 그렇지만 그만큼 코드의 작성과 고민해야할 포인트가 늘어납니다. 사용성이 중요한 경우에는 꼭 해야하는 방식이고 그렇지 않은 경우에는 비용에 맞춰서 진행하면 됩니다.
수고하셨습니다.