soyalattee 님의 상세페이지[2팀 박소연] Chapter 2-3. 관심사 분리와 폴더구조

배포링크: https://soyalattee.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 문서와 관련 영상을 시청했을 때는 '음, 뭔지 이해했어!' 하는 마음으로 시작했습니다. 실제 적용 과정에서는 이론과 현실의 괴리를 크게 느꼈습니다. 문서와 강의에서는 '데이터'면 entities, '동작, 동사'면 features라고 하던 것들이 실제 컴포넌트로 구현되어 있을 때 분류 기준이 애매했습니다.

하지만 이렇게 폴더 구조를 오랜시간동안 열심히 고민해본건 처음인것 같습니다. 항상 쓰던 구조에서 약간의 변형이 있었을뿐 이를 어떻게 개선하고, 어떤게 효율적일지에 대한 고민은 부족했는데 이번 과제를 통해 좋은 고민을 해볼 수 있었고 이를 실무에 잘 적용해 볼 수 있을것 같습니다.

본인이 과제를 하면서 가장 애쓰려고 노력했던 부분은 무엇인가요?

과제 진행 순서 잡기

제로초님의 유튜브 영상을 보고 우선은 크게 app, pages, entities, shared로 폴더를 나누어 시작했습니다.

대부분의 UI와 로직을 갖고 있는 PostsManagerPage.tsx 파일을 entities 폴더에 넣었고, 전역적으로 사용되는 설정들은 app으로, 공용으로 사용할 수 있는 util과 ui컴포넌트들은 shared로 분리했습니다. 그후 entities 폴더안에서 PostsManagerPage.tsx 파일을 쪼갠 후 쪼개진 파일들을 features 와 widget 폴더로 구분하고 전반적인 리팩토링을 마친후에 Tanstack-query 와 전역 상태관리를 적용하기로 계획을 세웠습니다.

레거시 제거와 폴더 분리

코드중에는 레거시한 코드들도 많았기에 이를 제거해가며 개발했습니다. 예를들면 React 19 부터는 forwardRef 없이 Props로 ref를 전달이 가능하며, 곧 사용중단될 예정인 레거시 Api 이기 때문에 제거하고 타입을 정의했습니다. props로 받은 className을 twMerge 와 clsx를 사용하여 합쳐지도록 util 함수를 만들어 사용했습니다.

그리고 shared 폴더에 utils 함수들과 ui 들을 정리하고, app 폴더에 provider와 router 설정을 분리하였습니다. FSD 원칙에 따라 index 파일을 만들어 내보내어 캡슐화되도록 하였습니다.

그 다음으로는 PostsManagerPage.tsx 파일을 중심으로 리팩토링을 시작했습니다. searchParams 관련 로직들을 커스텀 훅으로 분리하고 nuqs 를 사용하여 간단한 코드로 쿼리상태관리와 타입체킹을 할 수 있게 했습니다.
코드내에서도 재사용이 가능한 컴포넌트들은 shared 로 이동시켰습니다.

여기까지는 별 고민없이 진행할 수 있었습니다.

이 entities 폴더에 있는 수많은 UI 컴포넌트들과 customHook 등을 분리해야할때 가장 골머리를 앓았습니다.

문서와 강의에서는 '데이터'면 entities, '동작, 동사'면 features라고 하던 것들이 실제 컴포넌트로 구현되어 있을 때 분류 기준이 애매했습니다.

예를 들면:

  • 게시물을 추가할 수 있는 dialog 컴포넌트는 features인가?
  • 게시물을 자세히 볼 수 있는 detail dialog 컴포넌트는 데이터니까 entities인가?
  • comment를 add 하는 dialog는 features에 넣었는데, 이를 호출하는 컴포넌트도 features에 있어서 같은 레이어에서 다른 도메인을 호출해도 되는가?

또한 api 호출은 entities 에 두어야하는지, 쪼개어서 단순 get 요청은 entities에, 그 외 요청은 features 에 해야하는지에대한 고민도 있었습니다.
결국은 제 기준에서는 같은 data와 관련된 api는 모여있는게 응집도를 높히는 것이라 생각하여 api 폴더는 모두 entities 에 두기로 결정했습니다. 대신, 이런 데이터를 호출하여 가공하고, 액션을 취하는 custom hook은 features에 두었습니다.

이부분 역시 단순 조회하는 액션과 추가,삭제 등을 하는 액션을 분리해야 하나 고민이 되었으나 우선은 hooks 는 features 에서 모두 관리하고, entities 레이어의 ui는 별도의 api를 호출하지않고 props로 받아와 사용하지만, api 는 entities레이어에 있는 요상한 구조가 되었습니다.

영 찝찝하고 어떻게 놔도 예쁘게 '아 이구조야' 싶지 않아 이것저것 변경해보았지만.. 이렇게 고민하다간 완성을 못할것 같아 결국은 이러한 구조로 결정하게 되었습니다.

이부분이 과제에서 가장 많은 시간을 할애하고 머리를 싸매던 부분인것 같습니다.

원래 과제를 진행하기전 목표는 '나만의 궁극 폴더구조를 만들어보자'라는 큰 목표를 갖고 시작했는데 결국은 이도저도 아닌 아쉬운 폴더구조가 된거 같아 아쉬움이 많이 남습니다.

하지만 기존 2-1,2-2 챕터를 진행할때 개인적인 일정이 바빠 클린코드에 많은 시간을 할애하지 못했는데 이번에는 조금은 원하는 만큼 리팩토링이 된것같아(폴더 구조 제외하고) 만족스럽습니다.

전역 상태관리

기본 과제 조건에 전역상태관리가 있는데, Tanstack-query를 먼저 적용하다보니 서버에서 가져오는 데이터들은 모두 Tanstack-query로 가져오고 있었습니다.

그러다보니 어떤 데이터를 전역상태관리 해아할지가 애매해졌습니다. 이 프로젝트는 사용자인증이나, 전역적으로 UI 변화를 주는 일은 없었기 때문입니다. 그래서 이 프로젝트가 확장 되었을때, 어떤걸 전역으로 관리할 필요가 있을까를 고민했습니다. 결론적으로는 여러 Dialog들이 다른곳에서도 사용될 수 있을거라 생각 되었고 이것들을 store로 묶어 관리했습니다.

이번에 배운 내용 중을 통해 앞으로 개발에 어떻게 적용해보고 싶은지 적어주세요.

index 파일을 사용한 캡슐화가 생각보다 장점이 많은것 같아 실무에 적용해보려고합니다. 그리고 폴더 구조개선을 좀 해봐야겠다고 생각했습니다..!

챕터 셀프회고

클린코드와 아키테쳑 챕터 함께 하느라 고생 많으셨습니다! 지난 3주간의 여정을 돌이켜 볼 수 있도록 준비해보았습니다. 아래에 적힌 질문들은 추억(?)을 회상할 수 있도록 도와주려고 만든 질문이며, 꼭 질문에 대한 대답이 아니어도 좋으니 내가 느꼈던 인사이트들을 자유롭게 적어주세요.

클린코드: 읽기 좋고 유지보수하기 좋은 코드 만들기

  • 더티코드를 접했을 때 어떤 기분이었나요? ^^; 클린코드의 중요성, 읽기 좋은 코드란 무엇인지, 유지보수하기 쉬운 코드란 무엇인지에 대한 생각을 공유해주세요

정말 코드를 읽기가 너무 힘들어서 우선은 어떻게든 다 분해하고, 불필요한걸 제거하고싶다는 생각이 들었던 챕터였습니다.
그래서 코드를 제대로 읽지 않고 바로 변수타입을 변경하고 코드 쪼개기에 들어갔는데 이것이 큰 실수였음을 후반에 가서야 깨달았습니다.
제대로된 기능을 모르고, 변수명도 이해하기 어려운상태로 쪼개노니 더 헷갈려서 많이 삽질한 챕터였습니다.
그래서 코드를 리팩토링하며 이를 반면교사 삼아 어떤게 좋은 코드일지를 많이 배울 수 있었습니다.
제일 중요하게 느낀점은 읽기 좋은 변수명, 상태가 덜 변하게 할것, 순수 함수의 비중을 늘려 내가 봐야할 코드의 양을 줄이고 이러한 코드를 응집시켜 놓을것 이였습니다.

결합도 낮추기: 디자인 패턴, 순수함수, 컴포넌트 분리, 전역상태 관리

  • 거대한 단일 컴포넌트를 봤을때의 느낌! 처음엔 막막했던 상태관리, 디자인 패턴이라는 말이 어렵게만 느껴졌던 시절, 순수함수로 분리하면서 "아하!"했던 순간, 컴포넌트가 독립적이 되어가는 과정에서의 깨달음을 들려주세요

코드의 일부분이 급할때 제가 짜는 코드와 유사하다는 생각이들어 반성을 많이 하게되는 챕터였습니다.
아 정말 아무생각없이 짜면 이렇게까지 힘들어질 수 있겠구나를 체험 할 수 있었습니다 ㅎㅎ.
순수함수로 분리하여 컴포넌트가 독립적으로 되어갈때의 짜릿함이 있었습니다. 마치 어지럽혀진 집에서, 책상만큼은 정리했을때의 뿌듯함...?

응집도 높이기: 서버상태관리, 폴더 구조

  • "이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간, FSD를 적용해보면서의 느낌, 나만의 구조를 만들어가는 과정, TanStack Query로 서버 상태를 분리하면서 느낀 해방감(?)등을 공유해주세요

FSD는.. 너무 어려웠습니다.. 처음 이론만 봤을때는 그렇게 어려울게 있나? 싶었는데 정말 생각을 많이하게되고,,
폴더구조도 많이 뒤엎고.. 시간이 좀 더 있었으면 하는 챕터였어요.
응집도를 높인다는게 이제 어떤느낌인지 직접 느껴볼 수 있는 챕터였습니다만 제 코드가 필요한 코드들과 알맞게 응집도를 높혔는지에 대해서는 자신이 없네요 ㅠ

리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문

  • features 레이어는 '동작'을 담기 때문에 슬라이스의 폴더명도 동작으로 만들라는 내용을 봤는데요, 이럴경우 폴더가 엄청 많아지고 각 폴더에는 한두개의 파일밖에 없지 않나...? 라는 생각이드는데 아닐까요? 이경우 제가 생각한 폴더명은 add-comment, delete-comment 이런 느낌일꺼 같은데 맞을까요?

아직 FSD에 대한 이해가 부족하고, 이걸 적용할 만한 대규모 서비스를 경험해 보지 못해 묻는 질문일 수 있을것 같아요...!

과제 피드백

안녕하세요 소연님! 6주차 과제 잘 진행해주셨네요 ㅎㅎ 고생하셨습니다!!

features 레이어는 '동작'을 담기 때문에 슬라이스의 폴더명도 동작으로 만들라는 내용을 봤는데요, 이럴경우 폴더가 엄청 많아지고 각 폴더에는 한두개의 파일밖에 없지 않나...? 라는 생각이드는데 아닐까요? 이경우 제가 생각한 폴더명은 add-comment, delete-comment 이런 느낌일꺼 같은데 맞을까요?

안녕하세요 소연님! " features 레이어는 '동작'을 담기 때문에 슬라이스의 폴더명도 동작으로 만들라는 내용을 봤는데요" 라는건 결국 소연님의 의견보단 그 글을 작성한 사람의 의견이라고 생각해요 ㅎㅎ 정답은 아닌거죠. 그 규칙이 마음에 들지 않는다면 소연님이 생각하는 규칙대로 만들어가면 된답니다!

저의 경우 폴더 대신에 command 라는 이름으로 묶어서 사용할 것 같아요! 파일 하나에 개별 훅들을 정의해서 사용한다거나!?

다만 어떤식으로 정의하든 일관성이 제일 중요하다고 생각해요! 어딘가에서는 폴더 + 개별 파일로 나누고, 어딘가에서는 하나의 파일로 선언하는 경우 일관성이 깨지고 불필요한 생각에 에너지를 사용하게 되는거죠.

여튼 결론은, 소연님의 의견이 제일 중요하다는점! 누군가가 "왜 이렇게 만들었어요?" 라고 할 때 술술 나와야해요!