배포 링크
https://jun17183.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가 정상적으로 작동하는가?
최종과제
- 폴더구조와 나의 멘탈모데일이 일치하나요?
- 다른 사람이 봐도 이해하기 쉬운 구조인가요?
과제 셀프회고
이번 과제를 통해 이전에 비해 새롭게 알게 된 점이 있다면 적어주세요.
- 평소에 entity, feature, domain 등에 대한 개념이 약했는데 잘 알게 되었다.
- FSD는 말이 안 된다. 오히려 폴더 구조가 더 복잡하고 파일 위치도 헷갈린다.
- FSD는 폴더 구조를 마냥 보기 좋게 하기 것이 아니라 강제적으로 코드를 클린하게 분리하기 위함을 깨달았다. 하지만 FSD는 내 코드마저 클린하게 만드는 것엔 실패했다. 좀 더 강해져서 돌아와라.
본인이 과제를 하면서 가장 애쓰려고 노력했던 부분은 무엇인가요?
지금까지의 과제는 과제 규모에 맞게 폴더 구조를 나누고 파일을 분리했다. 그렇기에 눈에 더 잘 들어왔고 나의 멘탈모델과도 일치했다. 하지만 지난 과제에서 당장은 규모가 작겠지만 실제 필드에서 사용하는 구조를 적용해 보는 건 어떻냐는 피드백을 들었다. 그렇기에 과제 규모와 상관 없이 최대한 FSD가 추구하는 가치에 맞추려 했다. 맞추려 했는데... 하... feature가 너무 어렵다. 이번 과제는 고민하는 시간이 정말 많았다. 질문도 하고 여러 의견을 들으며 결국 하나를 결정하여도 또 다른 고민이 이어졌다. 이 과정이 너무 자주 반복되다 보니 결국 멘탈이 박살나고 의욕을 상실하여 AI에 많이 의지하게 되고 일단 완성하고 배포하는 것에 집중하게 되었다.
아직은 막연하다거나 더 고민이 필요한 부분을 적어주세요.
같은 레이어를 참조하면 안 된다고 하는데, 이 부분이 너무 어렵다. 예를 들어 "게시물 목록 불러오기" 라는 feature가 있다면 이 feature의 ui에는 Table이나 TableRow가 포함될 것이다. 근데 TableRow에 게시물 수정하기 버튼이 있다면 이 버튼은 "게시물 수정하기" 라는 feature ui에 들어가는 것이 맞지 않나? 그럼 "게시물 목록 불러오기" feature에서 "게시물 수정하기" feature의 ui를 참조해야 하는 것 아닌가? 하지만 이 경우는 같은 레이어를 참조하는 것이 아닌가? 그럼 TableRow가 widgets으로 들어가야 하는 건가?
posts와 user를 혼합하여 사용하는 게시물 목록도 마찬가지로 너무 헷갈린다. entities에는 posts와 user가 포함되어야 할 것이다. 근데 목록을 나타내기 위해선 이 둘을 합성하여 관리해야 한다. 이 합성 데이터를 "게시물 목록 불러오기" 같은 feature에서 관리하면 결국 또 다른 feature에서 이를 참조해야 한다. 그렇지 않다면 entities에서 합성 엔티티로 관리해야 할 텐데, 하나의 레이어에 posts, user, posts + user가 같이 있는 게 맞나..?
정말 너무 어렵다.
이번에 배운 내용 중을 통해 앞으로 개발에 어떻게 적용해보고 싶은지 적어주세요.
나만의 폴더 구조를 하나 만들어 보고 싶다. 이 과정에서 이번에 배운 경험을 한껏 적용해 보고 싶다.
챕터 셀프회고
클린코드와 아키테쳑 챕터 함께 하느라 고생 많으셨습니다! 지난 3주간의 여정을 돌이켜 볼 수 있도록 준비해보았습니다. 아래에 적힌 질문들은 추억(?)을 회상할 수 있도록 도와주려고 만든 질문이며, 꼭 질문에 대한 대답이 아니어도 좋으니 내가 느꼈던 인사이트들을 자유롭게 적어주세요.
클린코드: 읽기 좋고 유지보수하기 좋은 코드 만들기
- 더티코드를 접했을 때 어떤 기분이었나요? ^^; 클린코드의 중요성, 읽기 좋은 코드란 무엇인지, 유지보수하기 쉬운 코드란 무엇인지에 대한 생각을 공유해주세요
사실 말하지 않은 점이 있다. 다들 더티코드를 보고 경악을 금치 못했고 많은 분노를 샀지만, 솔직히 장난질을 많이 쳐서 그렇지 엄청 더티한 코드는 아니라고 생각했다. 이전 PR에도 장난질에 대한 분노를 남기긴 했만 과제 자체가 어렵다곤 생각하지 않았다. 5주차는 물론이고 4주차도. 다만 좀 더 공부를 충분히 진행 후에 과제를 시작했으면 어땠을까 하는 아쉬움이 남는다. 클린코드 주차가 끝나고 난 후에야 클린코드에 대해 조금은 알게 된 것 같다.
내가 생각하는 읽기 좋은 코드, 유지보수하기 쉬운 코드
- 구현부를 알 필요가 없는 코드
- 조립, 분리가 쉬운 코드
- 쓰이는 곳과 가까워 맥락을 파악하기 쉬운 코드
결합도 낮추기: 디자인 패턴, 순수함수, 컴포넌트 분리, 전역상태 관리
- 거대한 단일 컴포넌트를 봤을때의 느낌! 처음엔 막막했던 상태관리, 디자인 패턴이라는 말이 어렵게만 느껴졌던 시절, 순수함수로 분리하면서 "아하!"했던 순간, 컴포넌트가 독립적이 되어가는 과정에서의 깨달음을 들려주세요
그동안 감으로 리팩토링을 했는데, 왜 깔끔하다고 느꼈는지, 더 클린하게 만드려면 어떻게 했어야 하는지 방향을 잡은 것 같다.
- 순수 CRUD 따로 관리
- 다른 프로젝트에서도 사용할 수 있는 util, lib 분리
- 각 엔티티마다 나누기. 여러 엔티티를 사용하는 함수 지양
- View와 model 분리 등등
응집도 높이기: 서버상태관리, 폴더 구조
- "이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간, FSD를 적용해보면서의 느낌, 나만의 구조를 만들어가는 과정, TanStack Query로 서버 상태를 분리하면서 느낀 해방감(?)등을 공유해주세요
TanStack Query는 이해도, 숙련도가 낮아서 그런지 아직 이점을 느끼지 못했다. 서버상태분리는 솔루션을 보거나 다른 분들 코드를 참고할 필요가 있을 것 같다.
응집도를 높이는 데 가장 필요한 것은 나(팀)만의 멘탈모델이라고 생각한다. 내가 어떤 부분을 수정하려면 바로 마우스가 그 곳으로 향할 수 있어야 한다. 이를 위해선 나만의 확실한 기준이 중요하다. 그 기준은 기능 단위여도, 역할 단위여도 좋다.
리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문
본문에도 있는 내용이지만,
예를 들어 "게시물 목록 불러오기" 라는 feature가 있다면 이 feature의 ui에는 Table이나 TableRow가 포함될 것입니다. 근데 TableRow에 게시물 수정 버튼이 있다면 이 버튼은 "게시물 수정하기" 라는 feature ui에 들어가는 것이 맞다고 봐요. 하지만 이 경우 "게시물 목록 불러오기" 라는 feature의 ui에서 "게시물 수정하기" 라는 feature의 ui를 참조하게 되지 않나? 그렇다고 TableRow가 widget이 될 수는 없지 않을까? 하는 고민에 빠지게 되더라구요.
마찬가지로 게시물 목록을 나타낼 때 posts와 user를 혼합한 데이터를 뿌리더라구요. posts와 user는 entities에 포함될 것이고, 혼합 데이터는 "게시물 목록 불러오기(혹은 보여주기)"라는 feature에 있어야 한다고 생각해요. 근데 "게시물 추가" 혹은 "게시물 수정" feature가 있을 때, 추가나 수정을 마치면 이 혼합 데이터를 업데이트해야 할 텐데 이 경우도 마찬가지로 같은 레이어인 "게시물 목록 불러오기" feature를 참조하게 되는 게 아닌가 싶더라구요. entities에서 혼합 엔티티를 관리해야 하는 건지,,, 그럼 entties에는 posts, user, posts+user가 있을 텐데 이에 맞는 건지,,, 아니면 따로 혼합 selector를 만들어야 하는 건지, 이 selector는 어디에 위치해야 하는 건지 너무 헷갈립니다.
FSD 너무 어렵습니다. 위 예시에 대한 해답도 궁금하지만, 이런 고민에 빠지지 않기 위해서 어떻게 코드를 작성해야 하는지도 궁금합니다.
과제 피드백
안녕하세요 홍준님! 클린코드 마지막 과제 잘 진행해주셨네요 ㅎㅎ
FSD 너무 어렵습니다. 위 예시에 대한 해답도 궁금하지만, 이런 고민에 빠지지 않기 위해서 어떻게 코드를 작성해야 하는지도 궁금합니다.
흠.. 말씀해주신 경우는 기본적으로 사용하는 디자인 시스템이 있다면 어느정도 해소되지 않을까!? 라는 생각이 들어요! 가령 게시물 수정 기능은 feature인데, 버튼은 UI 표현이라서 별도로 분리하지 않아도 무방한거죠 ㅎㅎ 이걸 디자인시스템을 통해 만든다면 고민을 하나 없애버릴 수 있겠죠!?
말씀해주시 혼합 엔티티의 경우 entities가 맞다고 생각해요. 혼합이 되더라도 어쨌든 entities 라서요! 다만 데이터의 구조가 혼합된것과 혼합해야 하는 로직을 만드는건 역할이 다를 수 있다고 생각해요. features 혹은 widgets에서 이 역할을 수행해야 할 수 있겠죠!?
이런 고민에 빠지지 않는건... 사실 어렵다고 생각해요 ㅋㅋ 하나의 해답은 팀에서 죽이되든 밥이되든 정해진 규칙이 있고 이 규칙을 지켜가는거죠.
모두가 납득하긴 어렵겠지만 어느정도 납득할 수 있는 공통 규칙이 이런 고민들을 해소해준다고 생각합니다.
고생하셨어요 홍준님!!