taeyeong0814 님의 상세페이지[6팀 이태영] Chapter 2-3. 관심사 분리와 폴더구조

배포 링크

https://taeyeong0814.github.io/front_6th_chapter2-3/

과제 체크포인트

기본과제

목표 : 전역상태관리를 이용한 적절한 분리와 계층에 대한 이해를 통한 FSD 폴더 구조 적용하기

  • 전역상태관리를 사용해서 상태를 분리하고 관리하는 방법에 대한 이해
  • Context API, Jotai, Zustand 등 상태관리 라이브러리 사용하기
  • FSD(Feature-Sliced Design)에 대한 이해
  • FSD를 통한 관심사의 분리에 대한 이해
  • 단일책임과 역할이란 무엇인가?
  • 관심사를 하나만 가지고 있는가?
  • 어디에 무엇을 넣어야 하는가?

체크포인트

  • 전역상태관리를 사용해서 상태를 분리하고 관리했나요?
    • Zustand를 사용하여 클라이언트 상태 관리
    • TanStack Query를 사용하여 서버 상태 관리
  • Props Drilling을 최소화했나요?
    • 전역 상태 관리를 통해 컴포넌트 간 데이터 전달 복잡성 해결
  • shared 공통 컴포넌트를 분리했나요?
    • src/shared/ui/ - Button, Input, Card, Dialog, Table 등 재사용 가능한 UI 컴포넌트
  • shared 공통 로직을 분리했나요?
    • src/shared/lib/ - 유틸리티 함수들
    • src/shared/api/ - API 클라이언트 및 인터셉터
    • src/shared/stores/ - Zustand 스토어들
  • entities를 중심으로 type을 정의하고 model을 분리했나요?
    • src/entities/{post,user,comment}/model/ - 비즈니스 로직 및 타입 정의
  • entities를 중심으로 ui를 분리했나요?
    • src/entities/{post,user,comment}/ui/ - 엔티티별 UI 컴포넌트
  • entities를 중심으로 api를 분리했나요?
    • src/shared/api/ - 엔티티별 API 함수들
  • feature를 중심으로 사용자행동(이벤트 처리)를 분리했나요?
  • feature를 중심으로 ui를 분리했나요?
  • feature를 중심으로 api를 분리했나요?
  • widget을 중심으로 데이터를 재사용가능한 형태로 분리했나요?
    • src/widgets/ - post-table, post-form, comment-list, search-filter 등

아무리 생각해도 feature 계층을 만드는 것보다 제가 이해 할 수 있는 계층에 담아 처리하는게 맞다고 생각했습니다.

심화과제

목표: 서버상태관리 도구인 TanstackQuery를 이용하여 비동기코드를 선언적인 함수형 프로그래밍으로 작성하기

  • TanstackQuery의 사용법에 대한 이해
  • TanstackQuery를 이용한 비동기 코드 작성에 대한 이해
  • 비동기 코드를 선언적인 함수형 프로그래밍으로 작성하는 방법에 대한 이해

체크포인트

  • 모든 API 호출이 TanStack Query의 useQuery와 useMutation으로 대체되었는가?
  • 쿼리 키가 적절히 설정되었는가?
  • fetch와 useState가 아닌 선언적인 함수형 프로그래밍이 적절히 적용되었는가?
  • 캐싱과 리프레시 전략이 올바르게 구현되었는가?
  • 낙관적인 업데이트가 적용되었는가?
  • 에러 핸들링이 적절히 구현되었는가?
  • 서버 상태와 클라이언트 상태가 명확히 분리되었는가?
  • 코드가 간결하고 유지보수가 용이한 구조로 작성되었는가?
  • TanStack Query의 Devtools가 정상적으로 작동하는가?

최종과제

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

과제 셀프회고

프로젝트 구조

src/
├── app/                    # 앱 레벨 설정
│   ├── layouts/           # 레이아웃 컴포넌트
│   └── providers/         # 전역 프로바이더
├── entities/              # 비즈니스 엔티티
│   ├── post/             # 게시글 엔티티
│   ├── user/             # 사용자 엔티티
│   └── comment/          # 댓글 엔티티
├── widgets/               # 재사용 가능한 위젯
│   ├── post-table/       # 게시글 테이블
│   ├── post-form/        # 게시글 폼
│   ├── comment-list/     # 댓글 목록
│   └── search-filter/    # 검색 및 필터
├── pages/                 # 페이지 컴포넌트
└── shared/               # 공통 리소스
    ├── api/              # API 클라이언트
    ├── ui/               # 공통 UI 컴포넌트
    ├── stores/           # 상태 관리 스토어
    ├── lib/              # 유틸리티 함수
    └── types/            # 공통 타입 정의

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

새롭게 알게 된 점들

  • FSD 아키텍처의 실제 적용: 이론으로도 몰랐던 FSD 아키텍처를 공부하고 실제 과제(프로젝트)에 적용해보면서 레이어별 분리와 의존성 방향의 중요성을 체감했습니다. 하지만 시간 내에 FSD 아키텍처가 원하는 방향과 각 레이어 계층별 관계에 대해 정확히 알고 진행 했다 생각은 들지 않아서 많은 아쉬움이 남았습니다.

  • React Query 적용: 기존의 useState와 useEffect로 복잡하게 관리하던 서버 상태를 React Query로 선언적으로 관리하면서 코드가 훨씬 간결해지고 캐싱, 에러 처리, 로딩 상태 관리가 자동화되는 것을 경험했습니다.

  • Zustand 적용: Redux의 복잡함 대신 Zustand의 간단한 API로 클라이언트 상태를 효율적으로 관리할 수 있다는 것을 알게 되었습니다.

  • Props Drilling 문제 해결: 전역 상태 관리를 통해 컴포넌트 간 데이터 전달의 복잡성을 크게 줄일 수 있다는 것을 실감했습니다.

React Query, Zustand, Props Drilling 문제 내용은 이번 과제 뿐 아니라 2챕터 전반적인 과제 모두에 해당되는 내용이며 이번 주차 과제에서도 다시 한번 깨닫는 과정이 있었습니다.

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

가장 애쓰려고 노력한 것은 테오가 발제한 이 과제를 기준에 맞게 어떻게든 통과를 시키려고 애썼습니다. 처음에 과제를 진행함에 있어서 FSD 구조가 막연했기 때문에 앞서 진행한 5주차 과제처럼 components, hooks, types 부터 분리한 후 react-query, zustand를 도입 후 FSD 구조로 구조화 하는 방향으로 과제를 진행 하였습니다. 모르니 못 할 것 같고 안 하게 될 것 같은 상황이라 이렇게 진행 해보았는데 이 과정에서 AI의 도움을 받으면서도 직접 손코딩으로 진행하여 개념을 확실히 이해하려고 노력했습니다. 저와 같은 사람이 있다면 이렇게 진행하는 것을 추천 할 것 같습니다.

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

  • 아직 고민이 필요한 부분 FSD 레이어 구분의 정확성: entities와 widgets의 구분, shared와 entities의 경계 등에서 여전히 막연함이 있습니다. 특히 기존 코드를 분리하는 과정에서 AI의 도움을 받다 보니 의도하지 않은 변경이 발생한 부분들이 있어, 이에 대한 이해가 부족하다고 느꼈습니다.

  • 막연하고 개선이 필요한 부분 FSD 구조로 바꾸는 부분에 있어서 막연함 이전에 기존 코드를 분리하는 부분부터 다시 학습을 해야겠다 느꼈습니다. 리팩토링 전 코드를 관심사로 분리를 정확하게 나의 기준을 통해 하지 못 하니까 FSD 아키텍처를 적용함에 있어서도 계속적으로 생각이 많아졌습니다.

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

앞으로의 적용 계획: 아직 FSD 아키텍처를 직접적으로 다른 프로젝트나 현업에 적용하기에는 부족함이 있지만 FSD 와 같은 아키텍처, 혹은 도메인 주도 설계(DDD) 등과 같은 아키텍처를 현업이나 개인 프로젝트에 직접 적용해보면서 아키텍처에 대해 확실하게 이해하는 시간을 갖을 예정입니다.

상태 관리 전략: 서버 상태는 React Query, 클라이언트 상태는 Zustand를 조합하여 효율적인 상태 관리 시스템을 현업에서 이미 적용 중이지만 막상 이번 과제를 통해 직접 구축 단계부터 진행을 해보니 유지보수와는 다른 느낌으로 다가왔습니다. 그렇기 때문에 직접 구축을 해보는 과정을 회사 사내 프로젝트에 적용 해보고 싶다고 느꼈습니다.

팀 프로젝트에서: 사내 같은 팀원 중 FSD 원칙에 대해 관심이 있고 적용해보고 싶어 하는 팀원이 있는데 이번 기회를 시작으로 팀원과 함께 FSD 원칙을 공유하고, 추후에는 직접 사내 솔루션 혹은 프로젝트에 적용하며 리뷰도 하고 협업하는 자리를 만들고 싶습니다.

점진적 개선: 지금 이 과제를 여기서 마무리하면 아쉬워서 단계적으로 FSD 구조로 마이그레이션하여 나만의 FSD를 완성시키는게 계획입니다.

챕터 셀프회고

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

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

  • 더티코드를 접했을 때의 기분과 클린코드의 중요성: 처음에 기존 코드를 보면서 "이 코드가 정말 동작하는 건가?"라는 의문이 들었습니다. 하나의 컴포넌트에 모든 로직이 섞여있어서 수정할 때마다 다른 부분에 영향을 주지 않을까 걱정이 되었습니다. FSD 구조로 리팩토링하면서 "아, 이렇게 분리하면 각 부분의 책임이 명확해지고 수정이 쉬워지구나!"라는 깨달음을 얻었습니다. 특히 관심사 분리의 중요성을 실감했고, 읽기 좋은 코드는 유지보수하기도 쉽다는 것을 체감했습니다.

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

  • 거대한 단일 컴포넌트를 봤을 때의 느낌과 깨달음: 처음에는 모든 상태와 로직이 하나의 컴포넌트에 몰려있어서 "이걸 어떻게 분리해야 하지?"라는 막막함이 있었습니다. 하지만 단계적으로 컴포넌트를 분리하고, 순수함수로 로직을 추출하면서 "아하! 이렇게 하면 테스트하기도 쉽고 재사용도 가능하구나!"라는 깨달음을 얻었습니다. 특히 전역 상태 관리를 도입하면서 Props Drilling 문제가 해결되고, 컴포넌트들이 독립적으로 동작하게 되면서 "이제 이 컴포넌트는 이 기능만 신경 쓰면 되구나!"라는 해방감을 느꼈습니다.

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

  • "이 코드는 대체 어디에 둬야 하지?" 고민과 FSD 적용 과정: FSD를 처음 접했을 때는 "이 코드를 어느 레이어에 넣어야 할까?"라는 고민이 많았습니다. 특히 entities와 widgets의 구분, shared와 entities의 경계 등이 막연했습니다. 하지만 실제로 적용해보면서 "아, 이건 비즈니스 로직이니까 entities에, 이건 UI 조합이니까 widgets에"라는 기준이 명확해졌습니다. TanStack Query로 서버 상태를 분리하면서 "이제 서버 데이터는 React Query가 알아서 관리해주니까, 나는 UI 로직에만 집중하면 되구나!"라는 해방감을 느꼈습니다. 캐싱, 에러 처리, 로딩 상태가 자동으로 관리되어 개발 효율성이 크게 향상되었습니다.

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

레이어를 구성하면서 많은 정보와 나만의 레이어를 만들어보자 하면서 어쩌면 코치님들이 말하는 남들과 비슷한 편안한 구조가 아닐 수 있다고 생각은 들었습니다. 하지만 제 생각에는 이번 과제에서 굳이 Features 레이어까지 나누어서 처리를 해야 할까? 싶은 생각이 들어 레이어를 나누지 않았습니다.

Features vs Widgets 구분

Features 레이어가 필요한 경우:

// 복잡한 비즈니스 로직이 있는 경우
src/features/post-management/
├── ui/
│   ├── PostManagementPage.tsx
│   ├── PostBulkActions.tsx
│   └── PostAnalytics.tsx
├── model/
│   ├── usePostManagement.ts
│   └── postManagementStore.ts
└── api/
    └── postManagementApi.ts

현재 프로젝트의 경우:

// 단순한 CRUD 기능들
src/widgets/post-table/
└── ui/
    └── PostTable.tsx  // 단순한 테이블 표시

src/entities/post/
└── model/
    └── hooks.ts       // 기본 CRUD 훅

복잡하지 않은 로직이기 때문에 그냥 Widgets에 두면 문제 없을 것 같다고 생각하며 발제자료 속 FSD 원칙 및 조사 결과를 통해 아래와 같이 조건을 생각 했습니다.

Features 레이어가 필요한 조건:

  1. 복잡한 비즈니스 로직
  2. 여러 엔티티를 조합한 기능
  3. 사용자 시나리오 중심의 기능
  4. 독립적으로 배포 가능한 기능

그래서 이번 과제는 아래와 같이 단순하고 복잡하지 않은 화면이라 Widgets으로 두고 해보았습니다.

이번 과제는:

  1. 단순한 CRUD: 기본적인 데이터 조작만
  2. 단일 엔티티 중심: 각 기능이 하나의 엔티티에 집중
  3. 표준적인 관리 화면: 일반적인 관리자 페이지
  4. 모놀리식 구조: 독립 배포 불필요

만약 이 과제 기준으로 규모가 확장되어 음.. 뭐 게시물을 등록 할 때 관리자 승인이 있어야 한다 는 요구사항이 생기면 이 부분을 Features로 구성하면 되지 않을까.. 요? 이 부분에 대해 코치님께서는 어떤 생각이 드시나요?

과제 피드백

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

만약 이 과제 기준으로 규모가 확장되어 음.. 뭐 게시물을 등록 할 때 관리자 승인이 있어야 한다 는 요구사항이 생기면 이 부분을 Features로 구성하면 되지 않을까요? 이 부분에 대해 코치님께서는 어떤 생각이 드시나요?

말씀해주신 것 처럼 feature로 구성해주면 될 것 같아요! 지금은 모든 계층에 대해 테스트 하기에는 페이지가 하나라서 조금 아쉽긴 하네요 ㅎㅎ ㅠㅠ

다만 "게시물을 등록 할 때 관리자 승인" 이라는게 여러가지 비즈니스가 섞여있다보니 features로 만들어보고 안 되면 widgets 로 옮기면 좋지 않을까?! 라는 생각이 들어요 ㅎㅎ