과제 체크포인트
배포 링크
https://minjaeleee.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 구조 설계를 경험해보니 ‘좋은 코드’에는 정답은 없는 것 같습니다. 다만, 구성원들의 경험마다, 애플리케이션 규모, 비즈니스 모델, 환경 등에 따라 구성원들에게 더 좋은 경험을 제공해줄 수 있는 코드를 작성하는 것이 ‘좋은 코드’를 작성하는 것이다라는 것을 배웠습니다.
제 설명이 피상적이지만 FSD 구조를 설계하는 것이 저에게는 너무나 어려운 과제였고.. 좋은 코드를 작성하기 위한 하나의 방법인 FSD를 찍먹하면서 느낀 점이라.. 제가 수료하고 몇 번을 더 반복하고, 동료 개발자들의 원칙과 실제 사례들을 더 습득해야 온전히 좋은 코드라는 것을 더 이해할 수 있을 것 같습니다..
본인이 과제를 하면서 가장 애쓰려고 노력했던 부분은 무엇인가요?
Layer(계층), Slice(도메인), Segment(역할) 기준으로 체계적인 분리
예를 들어, Shared Layer 계층에서는 비즈니스 로직 없는 순수한 UI 컴포넌트와 유틸리티를 제공하는 계층으로 내부 Segment들은 ui, lib, api로 구성했습니다. 각각의 Segment들은 아래와 같은 역할을 하게 됩니다.
- ui/: 재사용 가능한 UI 컴포넌트
- lib/: 공통 유틸리티 함수
- api/: 공통 API 설정
이런 분리로 비즈니스 로직과 UI 로직을 완전하게 분리하고, 도메인별 높은 응집도로 구조화 할 수 있었습니다. 단방향 의존성 관리 아래와 같은 계층을 기준으로 단방향 의존성 관리 원칙을 지키고자 했습니다.
app → pages → widgets → features → entities → shared
지난 과제에서 계층을 먼저 나누고 싶은대로 나누니 결합도가 너무 높아지고 데이터의 흐름이 일관적이지 않아서 가독성이 많이 떨어지고, 전역 상태로 관리하려는 시도가 너무 어려웠습니다. 그래서 이번에는 시작하기 전, 전체 상태를 zustand를 적용해서 store 파일 내부의 훅을 만든 다음, FSD 설계 원칙에 따라 파일을 분리하고 적절하게 필요한 계층에서 store 훅 내부 로직들을 분리시키고자 시도했는데.. 어찌저찌 잘 적용되어지지 않았습니다. 그래도, 단방향 의존성 관리 원칙을 지키기 위해 이를 props drilling을 하는 구조가 되었지만 이러한 단방향 의존성을 지키기 위해서 노력했습니다. entities는 상위 계층이나 외부 의존 없이 단일적인 기능을 수행하도록, features는 entities를 의존하고, shared/ui를 의존하는구조, widgtes는 features와 entities에만 의존하는 단방향 구조를 만들었습니다.
이러한 노력을 통해서 코드에 대한 이해도와 가독성을 향상 시켰고, 계층별 책임 분리가 더 완성된 느낌이었습니다.
아직은 막연하다거나 더 고민이 필요한 부분을 적어주세요.
Features 계층에서 볼륨을 얼마나 가져가야 할지 고민됩니다.
이 Features 계층의 구조를 만들었다, 삭제 했다, 다시 만들었다 이 과정만 2~3 일동안 반복했는데요! 각 도메인마다 CRUD 기능이 있을테고, list, filter 와 같은 복합적인 기능도 있을테지만 저는 post를 add-post, delete-post를 Slice로 구분하기보다는 post-crud, comment를 comment-management와 같이 crud를 통합적으로 관리할 수 있는 Slice로 구분했습니다. 가장 큰 이유는 도메인 응집도를 높이기 위함이였습니다.
이 방법이 더 실용적일 것이라는 생각을 했습니다. 그런데, 단점을 생각해보자니 내부적으로 규모가 커질수록 너무 복잡해지지 않을까? 단위 테스트가 불편하지 않을까?라는 생각이 듭니다.
무엇이 더 좋은 구조인지 모르겠습니다 ㅠ
이번에 배운 내용 중을 통해 앞으로 개발에 어떻게 적용해보고 싶은지 적어주세요.
사실 FSD 구조를 그대로 지금 현재 현업에 적용하기는 어려울 것 같습니다. 다만 제가 직접 경험해보니 응집성을 높이고, 결합도를 낮추고, 단일 책임 원칙을 가지고 독립적인 기능을 수행하고, 비즈니스 로직과 상태, UI 로직들이 잘 분리되고, 선언적으로 프로그래밍하고.. 이러한 원칙들이 DX 향상, 테스트성, 확장성, 품질 등에 큰 영향을 끼친다는 것을 확실히 배웠습니다.
제가 이 과제를 수행하기 전까지는 정말 외우기만 했거든요. 직접 거대한 코드를 리팩토링 하는 과제를 마주하니 조금 더 선명하게 그려지는 느낌이었습니다. 이러한 원칙들을 바탕으로 팀원들과 환경에 맞게 소통하며 좋은 코드를 만들어보고 싶습니다.
챕터 셀프회고
클린코드와 아키테쳑 챕터 함께 하느라 고생 많으셨습니다! 지난 3주간의 여정을 돌이켜 볼 수 있도록 준비해보았습니다. 아래에 적힌 질문들은 추억(?)을 회상할 수 있도록 도와주려고 만든 질문이며, 꼭 질문에 대한 대답이 아니어도 좋으니 내가 느꼈던 인사이트들을 자유롭게 적어주세요.
클린코드: 읽기 좋고 유지보수하기 좋은 코드 만들기
- 더티코드를 접했을 때 어떤 기분이었나요? ^^; 클린코드의 중요성, 읽기 좋은 코드란 무엇인지, 유지보수하기 쉬운 코드란 무엇인지에 대한 생각을 공유해주세요
- 이 질문에 대한 답을 이미 위에서부터 써내려왔네요.. ㅎㅎ!!
- 응집성을 높이고, 결합도를 낮추고, 단일 책임 원칙을 가지고 독립적인 기능을 수행하고, 비즈니스 로직과 상태, UI 로직들이 잘 분리되고, 선언적으로 프로그래밍하고.. 이러한 원칙들이 DX 향상, 테스트성, 확장성, 품질 등에 큰 영향을 끼친다는 것을 확실히 배웠습니다. 제가 이 과제를 수행하기 전까지는 정말 외우기만 했거든요. 직접 거대한 코드를 리팩토링 하는 과제를 마주하니 조금 더 선명하게 그려지는 느낌이었습니다. 이러한 원칙들을 바탕으로 팀원들과 환경에 맞게 소통하며 좋은 코드를 만들어보고 싶습니다.
결합도 낮추기: 디자인 패턴, 순수함수, 컴포넌트 분리, 전역상태 관리
- 거대한 단일 컴포넌트를 봤을때의 느낌! 처음엔 막막했던 상태관리, 디자인 패턴이라는 말이 어렵게만 느껴졌던 시절, 순수함수로 분리하면서 "아하!"했던 순간, 컴포넌트가 독립적이 되어가는 과정에서의 깨달음을 들려주세요
응집도 높이기: 서버상태관리, 폴더 구조
- "이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간, FSD를 적용해보면서의 느낌, 나만의 구조를 만들어가는 과정, TanStack Query로 서버 상태를 분리하면서 느낀 해방감(?)등을 공유해주세요
- 처음에는 너무 막막하고 그냥 읽기 실었습니다.. ㅋㅋㅋ 불편함, 불쾌하다라는 감정을 느끼게 되었습니다. 분명히 다른 기능들을 수행하는 비즈니스 로직들을 순수함수로 분리하며 내부를 굳이 읽지 않아도 추상화된 함수를 보며 코드가 술술 이해되는 현상을 느끼게 되었고, 또 UI만 관리하는 프레젠테이션 패턴을 사용하며 공통 컴포넌트를 만드니 UI 로직은 거의 화면을 통해서만 체크하고 비즈니스 로직에 더 집중할 수 있으니 개발자 경험이 많이 향상되어 즐거웠습니다!
리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문
- 위 내용처럼 Features 계층의 규모가 적절한가? 단점을 고려하여 설계한 구조가 적절했는지? 더 나은 방법이 있다면 어떤 방법인 사례가 있을지 궁금합니다!
과제 피드백
안녕하세요 민재님! 6주차 과제 잘 진행해주셨네요 ㅎㅎ
제가 직접 FSD 구조 설계를 경험해보니 ‘좋은 코드’에는 정답은 없는 것 같습니다. 다만, 구성원들의 경험마다, 애플리케이션 규모, 비즈니스 모델, 환경 등에 따라 구성원들에게 더 좋은 경험을 제공해줄 수 있는 코드를 작성하는 것이 ‘좋은 코드’를 작성하는 것이다라는 것을 배웠습니다.
좋은 인사이트라고 생각해요! 코드에 대한 정답보단 나의 생각을 찾아가는 과정이라고 생각합니다 ㅎㅎ
위 내용처럼 Features 계층의 규모가 적절한가? 단점을 고려하여 설계한 구조가 적절했는지? 더 나은 방법이 있다면 어떤 방법인 사례가 있을지 궁금합니다!
widget 에다가 책임을 몰아넣을 수도 있을 것 같아요 ㅎㅎ 결국 기능이 많아지면 어떤 구간은 뚱뚱해질 수 밖에 없는데, 어떤 구간에 이를 몰아주는게 좋을까? 에 대한 결정이라고 생각합니다. 저희 팀은 use-case 라는 계층을 하나 더 만들어서 진행하고 있땁니다!
고생하셨습니다 민재님!