Hwirin-Kim 님의 상세페이지[1팀 김휘린] Chapter 2-3. 관심사 분리와 폴더구조

과제 체크포인트

https://hwirin-kim.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기준으로 분리하면 코드 관리가 쉽다는 점을 느꼈다. 특히 기존에는 페이지나 컴포넌트를 위주로 분리했었는데, 그것과 더불어 데이터를 분리하여 관리하니 더욱 깔끔한 비즈니스 로직을 구성할 수 있게 되는것 같다.

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

엔티티에 최대한 도메인모델과 api만 넣으려고 했고, 피처엔 기능 단위만, 위젯엔 피처의 조합을 넣으려고 했다. 그런데 막상 하다보니 약간 안맞는 듯한 부분도 생기게 되었는데, 특히 엔티티가 겹치면서 애매한 부분들이 많았다.

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

데이터와 기능만 기준으로 보면 사실 그다지 어렵지 않았다. 하지만 UI가 포함될 때 부터 조금씩 막연하다. 뭔가 기준을 세울 때, 아토믹한 부분들은 shared에 넣고, 기능이 들어간 부분에서 조합하거나 만들어서 사용하려고 했는데, 테이블, 모달 등 여러가지 조합으로 이뤄진것을 하나의 기능으로 봐야하는지.. 위젯으로 봐야하는지.. 이러한 부분에서 많이 헷갈렸다.

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

이번주는 바쁜 일들이 많아서 수요일에 과제를 시작하게 되었다.. 사실 급한 마음에 UI분리가 더 안된것같다. 조만간 시작하려는 프로젝트가 있는데, 그 프로젝트를 통해서 한번 더 적용해서 만들어보고, 기존에 만들었던 사이드프로젝트 중 규모가 있는것을 골라 이렇게 저렇게 옮겨보는 연습을 해봐야겠다.

챕터 셀프회고

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

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

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

  • 더티 코드를 접했을 때, 처음엔 너무나도 당황스러웠지만 내 코드도 누군가에게 이렇게 보이진 않을까? 하는 생각도 들었다.

  • 6주차 과제를 진행하며 응집도가 왜 중요한지 알게 되었다. 이번 과제에 제출한 내 코드는 응집도가 높지 않다.. 그렇다고 분리가 세밀하게 되어있는것 같지도 않았다. 누가 보더라도 여기엔 이러한 코드들이 있겠구나 하는 코드, 그리고 누가 수정하더라도 사이드이펙트가 생기지 않게끔 만들어진 코드가 좋은 코드인것같다.

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

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

  • 일단 디자인패턴과 순수함수에 대해서 아예 모르지 않다고 생각했는데, 막상 나는 일관성있게 만들진 않았던것 같다. 그래서 더 헷갈리고 이해하기 어려운 코드가 되어버리는것 같았다.

  • 그리고 비즈니스로직과 UI의 철저한 분리가 가져오는 깔끔함이 너무 좋았다. 특히 비즈니스 로직에서도 순수함수들로 구성 후 조합해서 사용했을때, 하나의 커스텀훅이 마치 객체지향 코드를 보는것같이 깔끔할 수 있어서좋았다.

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

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

  • 일단 탄스택쿼리로 서버상태를 전역적으로 관리하게 되니 따로 프롭스 걱정을 할 필요가 없는것이 너무 쾌적하다.

  • 이번 과제에서 내가 철저하게 가져갔던 신념은 엔티티 폴더이다. 엔티티 폴더에서는 api와 도메인 모델만 넣었는데, 처음엔 여기에 Hook까지 넣어뒀다가 제외시켰다.

  • 그 이유는 훅 자체도 결국 상황마다 다른 파라미터를 필요로 하거나, 다른 엔티티에 관여하게 될 때도 있었기 때문이다.

  • feature 폴더에서는 hook을 작성할때까진 어렵지 않았다.

  • 하지만 UI를 만들기 시작하면서 사실 가독성이 많이 안좋아졌다.

  • 너무 많은 수정을 거치면서 아직까지도 명확한 분리 기준을 정하지 못한것이 큰 이유인것같다.

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

  • 저는 처음에 엔티티를 디비상 테이블처럼 생각하려고 했습니다.
  • 하지만 이번 과제를 보면 Comment가 User를 품고있는 데이터가 있었습니다.
// src/entities/comment/model.ts
import type { User } from "../user/model"
// TODO : 질문하기, 이렇게 다른 Entity의 타입을 가져다 써도 되나..?

export interface Comment {
  id: number
  body: string
  likes: number
  postId: number
  user: Pick<User, "id" | "username" | "fullName">
}

export interface CommentRequest {
  postId: number
  body: string
  userId: number
}
  • 그런데 저 유저를 코멘트에서 굳이 따로 정리할 필요가 없다고 생각이 들어서 User폴더에서 정의했던 유저 인터페이스를 가져다가 사용했습니다.
  • 지금은 이 한 가지 경우밖에 없지만 실무데이터에서는 이런 문제가 굉장히 많을것으로 생각이 듭니다.
  • 이렇게 도메인에 다른 도메인이 섞여있는 경우 다른 폴더와 공유하는 상태를 만들어도 괜찮을까요..?

과제 피드백

수고했습니다. 지난 3주간 클린코드를 비롯한 소프트웨어 공학적으로 결합도 낮추기 응집도 높이기를 위한 이론과 프론트엔드에서의 적용등을 통해서 좋은 코드와 구조에 대한 다각도의 시야가 생겼기를 기대합니다.

"프론트에서도 entity기준으로 분리하면 코드 관리가 쉽다는 점을 느꼈다." "하지만 UI가 포함될 때 부터 조금씩 막연하다."

좋아요. 데이터, 화면, 행동이라는 3가지의 큰 축에서 엔티티를 기준으로 볼 수 있는 관점은 확실히 생긴것 같아요. UI는 데이터와 행동이 모두 포함되어 있는 조립파트이기에 책임과 계층이 복잡해서 분리하기가 어렵다 느껴지죠.

이런 경우에는 최대한 데이터를 분리해내고 컴포넌트의 책임은 렌더링와 이벤트 핸들러에만 있다고 생각하고 나머지는 최대한 외부에 의존하려고 생각하면 좋습니다. (useEffect도 컴포넌트의 책임이죠.)

지금은 뭐가 정답일까 고민하고 있기에 어렵게 느껴질 수 있지만 이제 시야과 관점이 생겼으니 개발에 적용하면서 실제로 도움이 되는 것 취하고 되려 불편함을 야기하는 것들은 버리면 됩니다. 그렇게 자신의 철학을 정립해나가는 것이죠! 수고하셨습니다.

Q) 이렇게 도메인에 다른 도메인이 섞여있는 경우 다른 폴더와 공유하는 상태를 만들어도 괜찮을까요..?

-> 네 상관없어요. 엔티티에는 관계라는 개념이 있고 1:N , N:N 등 엔티티간의 상호작용을 하거나 복합적인 도구가 되는건 관계없습니다. 계층을 의존성을 가지고 나누는건 맞지만 같은 계층의 경우라도 의존성이 생길 수 있었요.

-> 의존성이 있더라도 결국 같은 계층이구나 라고 하는 미묘한 그 경계를 이애하보고 어쩄든 엔티티와 기능과 화면이 다른 경계에 속한다는 것을 기억하면서 자시만의 경계의 선명도를 잘 찾아가길 바래요 수고하셨습니다!