realstone2 님의 상세페이지[3팀 여진석] Chapter 2-3. 관심사 🦍분리와 폴더구조 🦍

https://realstone2.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가 정상적으로 작동하는가?

최종과제

  • 폴더구조와 나의 멘탈모델이 일치하나요?
  • 다른 사람이 봐도 이해하기 쉬운 구조인가요?

과제 셀프회고

이번 과제를 통해 이전에 비해 새롭게 알게 된 점이 있다면 적어주세요.

  1. FSD 아키텍처 이해

    • FSD에서 entities, features, widgets 레이어 구분이 항상 헷갈렸는데 흐름을 명확히 이해하게 되었습니다.
    • entities: data 모델에 대한 레이어
      • api는 entities를 가져오기 위한 로직들을 분리
      • ui는 entities만을 보여주기 위한 UI
      • model은 entities를 가져오기 위한 query나 모델 자체 데이터
    • features: 사용자의 Action 기능
      • api는 사용자의 액션들을 분리
      • ui는 액션하게 되는 UI(ex: add button 등)
    • widget: 여러 개의 feature들을 조합한 비즈니스 로직 컴포넌트
      • ui: 비즈니스 로직 컴포넌트
  2. FSD의 강제성과 명확성 평소에는 리액트에서 제안해놓은 features 정도만 더 들어가도록 사용하고 있었고, 이 정도면 충분하다고 생각했습니다. 불편함을 느낀 적은 있지만 이것에 대해서 크게 생각하지는 않았습니다.

    FSD로 전부 나눠가며 작업을 해보니까 FSD가 어떤 방향성을 추구하는지 느꼈습니다.

    강제로 레이어를 나눠놓지 않은 기존 구조에서는 features로만 나눠졌을 때 여러 개의 features가 합쳐지는 경우에 대해서는 domain이 섞이는 일도 다반사였습니다. 업무하면서도 "여기 features는 짬뽕이 되어가는 것 같다"라고 느낀 경우가 많았습니다.

    FSD에서는 레이어 간, 도메인 간 침범할 수 없는 강제성을 띄다 보니까 이런 일이 발생하지 않았습니다.

    전에는 이런 폴더구조가 과하지 않나? 라는 생각도 했지만, 강제적으로 나눠져 있다 보니 팀프로젝트 할 때 명확하게 어디에 어떤 내용이 들어가야 될지 제시가 되어준다는 점에서 훌륭하다는 생각을 했습니다.

  3. AI와 함께하는 리팩토링의 효과 평소에 AI를 많이 사용하지 않았었는데, 이번에 리팩토링 챕터하면서 AI 활용법에 대해서 많이 익히려고 노력했습니다. 어떻게 하면 내가 학습도 하면서 AI를 효율적으로 사용할 수 있을지를 많이 고민했습니다.

    준형님이 공유해주신 bmad methods를 활용하여 이번 챕터 과제하면서는 목적에 맞춰서 페르소나를 사용하였고, 내가 작업하려는 내용을 AI와 함께 md파일을 만들어 소통했습니다.

    정리해보면 아래 네 가지 작업을 AI와 함께 진행한 것 같습니다:

    1. 구조 분석: 현재 코드베이스의 문제점과 개선 방향 분석

    2. 반복 작업 업무: Dialog 분리, API 분리 등 체계적인 리팩토링

    3. 내가 생각하고 있는 내용 전달 및 검증: FSD 구조 설계와 최적화 방안 검토

    4. 누락된 테스크 탐색: 리팩토링 진행한 내용중 누락된 내용 없는지 검토

      내가 하고자 하는 걸 명확히 전달하고, 분석한 내용을 전달받고, 내가 분석한 내용을 전달하며 검증했습니다. 결과물은 AI가 이상한 코드를 내놓는 경우는 거의 없어졌고, 내가 원하는 코드가 그대로 나왔습니다. 다음에도 리팩토링하는 과정만큼은 AI를 적극적으로 사용하면서 원하는 결과물을 빠르게 얻을 수 있을 것 같습니다.

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

  1. 리스트, 단건 Query Data 효율적으로 관리하기 현재 구조에서는 게시글 단건 Query가 없긴 하지만 단건 쿼리를 따로 구성해서 작업했습니다. update 시에 list query data를 순회하면서 수정하는 방식으로 접근하고 싶지 않았습니다. 지금은 mock API의 한계였던 부분도 있긴 하지만, 낙관적 업데이트를 만약 해준다고 했을 때도 마찬가지입니다. 향후에 단건 쿼리가 생겼을 때 리스트 데이터와 단건 데이터의 싱크 단건 데이터가 변경되었을 때, 단건 query만 invalidate가 되면 밖에 리스트와 싱크가 맞지 않을 것입니다. 이 때 그렇다고 지금까지 쌓아놓은 pagination 리스트들을 전부 invalidate하는 것은 비효율적입니다.
/**
 * 리스트에서는 ID 리스트만 제공 - UI에서는 ID를 이용해 detail 쿼리만 사용 - `setQueriesData`는 detail만 시켜주기 - `queryFn` 내부에서 모든 데이터를 조합해서 캐시에 저장
 * */
const prevData = queryClient.getQueryData<Post>(postQueryKeys.detail(request.id))
if (prevData) {
  queryClient.setQueryData(postQueryKeys.detail(request.id), {
    ...prevData,
    ...request.data,
  })
}
  1. searchParams를 zod로 safe하게 사용하기 searchParams데이터를 safe하게 사용하기 위해서 zod를 도입하였습니다.

아직은 막연하다거나 더 고민이 필요한 부분을 적어주세요.

  1. 모달을 띄워주는 방식

지금은 모달을 list item마다 띄워주고 있어서 불필요하게 여러 개의 모달을 선언하게 되는 것 같습니다. 모달을 하나로 두고 searchParams에 postID를 두는식으로 했으면 어땠을까 라는 생각이 듭니다.

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

  1. 명확한 레이어 기반의 폴더 구조 적용하기 앞으로 팀프로젝트에서는 FSD가 아니더라도 명확한 레이어 기반 구조를 적용하고 싶습니다. 레이어를 명확히 나누면 코드리뷰시에도 pr을 나누는 기준이 될 수 있을 것 같습니다.

  2. AI와의 협업 구조 분석 단계: AI와 함께 현재 코드베이스 분석 및 개선 방향 도출 계획 수립 단계: md 파일을 통한 명확한 계획 수립 및 검증 구현 단계: AI의 도움을 받아 효율적인 코드 작성 검증 단계: AI와 함께 코드 품질 검토 및 개선점 도출

  3. AI와의 개발 프로세스 설계 우선: 구현 전에 구조 설계와 계획 수립 점진적 개선: 큰 변경보다는 작은 개선을 지속적으로 적용 문서화: AI와의 협업 내용을 md 파일로 기록하여 지식 축적

챕터 셀프회고

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

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

더티코드를 접했을 때의 기분과 클린코드의 중요성

처음에 src/pages/post/index.tsx의 787줄짜리 모놀리식 컴포넌트를 봤을 때는 정말 막막했습니다. 하나의 파일에 모든 로직이 들어있어서 어디서부터 시작해야 할지 몰랐습니다. FSD로 하나씩 도메인을 분리하니까 짜릿하고, 해당 페이지에는 view 호출 컴포넌트만 남았을 때는 짜릿했습니다.

읽기 좋은 코드란 무엇인지

단일 책임 원칙: 하나의 컴포넌트나 함수가 하나의 역할만 가지도록 하는 것 명확한 네이밍: 변수명, 함수명, 컴포넌트명이 그 역할을 명확히 표현하는 것 적절한 추상화: 복잡한 로직을 이해하기 쉬운 단위로 나누는 것

유지보수하기 쉬운 코드란 무엇인지

관심사의 분리: UI 로직, 비즈니스 로직, API 로직이 명확히 분리된 것 재사용 가능한 구조: 공통 컴포넌트와 로직을 적절히 분리한 것 확장 가능한 아키텍처: 새로운 기능을 추가할 때 기존 코드를 크게 수정하지 않아도 되는 것

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

거대한 단일 컴포넌트를 봤을 때의 느낌

처음에는 모든 것이 하나의 컴포넌트에 있어서 "이걸 어떻게 나누지?"라는 생각이 들었습니다. 하지만 AI로 단계별로 점진적으로 분석시키고 분석된 내용을 확인한다음에 코드를 다시 보니까 구조가 보였습니다.

FSD 구조에 맞춰서 도메인을 하나씩 분리하니까 어느새 거대한 컴포넌트가 page로직만 남는 것을 경험하였습니다.

순수함수로 분리하면서 "아하!"했던 순간

API 호출 로직을 순수함수로 분리하고, React Query 훅으로 감싸면서 비동기 로직이 훨씬 깔끔해진 것을 느꼈습니다. 특히 에러 처리와 로딩 상태 관리가 자동으로 되는 것을 보면서 "이게 바로 선언적 프로그래밍이구나!"라는 깨달음을 얻었습니다.

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

"이 코드는 대체 어디에 둬야 하지?"라고 고민했던 시간

FSD를 처음 적용할 때는 entities, features, widgets의 구분이 헷갈렸습니다. 왔다갔다 하다가 이렇게 두니까 편하네? 라고 생각을 멈춘 지점에서 해당 폴더 구조들이 이해될 것 같습니다.

FSD를 적용해보면서의 느낌

강제로 레이어를 나눠놓지 않은 기존 구조에서는 features로만 나눠졌을 때 여러 개의 features가 합쳐지는 경우에 domain이 섞이는 일이 많았습니다. 하지만 FSD에서는 레이어 간, 도메인 간 침범할 수 없는 강제성이 있어서 이런 문제가 발생하지 않았습니다. 처음에는 FSD 구조가 과하다고 생각했지만, 실제로 적용해보니 팀 프로젝트에서 명확하게 어디에 어떤 내용이 들어가야 될지 제시가 되어준다는 점에서 훌륭하다는 생각을 했습니다.

TanStack Query로 서버 상태를 분리하면서 느낀 해방감

기존의 useState와 useEffect로 복잡하게 관리하던 서버 상태가 TanStack Query로 선언적 코딩이 되었고, 도메인별로 전역 상태자체가 분리되니까 속이 뻥 뚫렸습니다.

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

  1. list query detail query 엮는 방식

저는 detail query로만 쿼리를 관리하는 방식을 선택했는데, 코치님은 실무에서 어떤 방식으로 detail과 list 쿼리를 관리하시나요?

  1. FSD 위젯

지금도 post dashboard 약간 크다고 느껴지지만 위젯이 그냥 거대한 컴포넌트가 될 수도 있을 것 같다고 느꼈습니다. 위젯의 올바른 단위가 아직 정확히 가늠이 안되는것 같습니다. 지금 post dashboard 정도는 올바르게 분리된 위젯일까요?

  1. AI와의 협업 패턴

현재 사용한 AI 협업 방식이 효율적이었는지, 더 나은 방법이 있는지 피드백을 받고 싶습니다.

과제 피드백

(다른 분들이 진짜 리얼스톤 리얼스톤 해서 장난인줄 알았는데 깃헙 계정이 정말 realstone이었군요..) 진석님 고생하셨습니다. 저도 준형님 영업으로 BMAD METHOD활용해서 코딩을 이리저리 해보고 있었는데, 이번에 큰 도움을 받으셨군요.ㅎㅎㅎ 엔티티에 대한 구조도 잘 분리하셨고 전반적으로 위배되는 것들은 많이 없으셨던 것 같아요. 타입이지만 entity에서 entity를 improt하는 경우는 있는 것 같아서 이 부분에 대해서는 수정이 필요해보이네요.

list query detail query 엮는 방식

지금의 작성 방식 처럼 detail과 list를 분리하고 공통으로 관리하는 키들을 가져와서 각각 조합해서 쓰는 방식을 사용하고 있어요 ㅎㅎ

FSD 위젯

위젯의 역할이 사실 모호하긴하죠. 레이어에 대해 feature나 app에서 조합하기 애매하다고 느껴질 때 주로 위젯에 몰아넣는 경우들이 왕왕 있는것 같은데, 일단 앱에 두고 컴포넌트를 분리하는 것이 좋을 것 같아요. 그리고 그 컴포넌트가 재사용성이 생긴다면 위젯에 두는것도 좋은 분리 방법일것 같아요.

AI와의 협업 패턴

지금의 작업방식은 좋은 것 같아요! 구체적인 작업 지침과 파일명, 수정 방향까지 주고 작업을 맡기는거죠. 저는 이 부분에 있어서 중요한 건 인간의 피드백이 언제 들어가냐 인거 같은데요. 인간은 AI보다 작업의 단위가 적으니까 인위적이라도 단위를 내가 이해할 수 있는 범위로 나누고 검증 후 작업 루프를 만드는게 그나마 유지보수 성을 높이고 빠르게 개발하는 방법이 아닐까 싶습니다 ㅎㅎ 하지만, bmad의 방식은 그런것들을 전부 해주려고 하는 패턴이다 보니 결론이 나온 경우에 내가 이 코드를 이해하기 너무 힘든것 같아요 ㅎㅎ 애매하면 마지막에 작업한 것들을 내가 이해하기 명확하게 정리해서 문서로 줘 하고 파악하는것도 나쁘지 않은 방법일 것 같구요.

고생하셨고 다음주는 AI 디톡스를 해야 하는데, 화이팅입니다!