annkimm 님의 상세페이지[8팀 김민지] Chapter 2-2. 디자인 패턴과 함수형 프로그래밍

링크

https://annkimm.github.io/front_6th_chapter2-2/

과제의 핵심취지

  • React의 hook 이해하기
  • 함수형 프로그래밍에 대한 이해
  • 액션과 순수함수의 분리

과제에서 꼭 알아가길 바라는 점

  • 엔티티를 다루는 상태와 그렇지 않은 상태 - cart, isCartFull vs isShowPopup
  • 엔티티를 다루는 컴포넌트와 훅 - CartItemView, useCart(), useProduct()
  • 엔티티를 다루지 않는 컴포넌트와 훅 - Button, useRoute, useEvent 등
  • 엔티티를 다루는 함수와 그렇지 않은 함수 - calculateCartTotal(cart) vs capaitalize(str)

기본과제

  • Component에서 비즈니스 로직을 분리하기

  • 비즈니스 로직에서 특정 엔티티만 다루는 계산을 분리하기

  • 뷰데이터와 엔티티데이터의 분리에 대한 이해

  • entities -> features -> UI 계층에 대한 이해

  • Component에서 사용되는 Data가 아닌 로직들은 hook으로 옮겨졌나요?

  • 주어진 hook의 책임에 맞도록 코드가 분리가 되었나요?

  • 계산함수는 순수함수로 작성이 되었나요?

  • Component에서 사용되는 Data가 아닌 로직들은 hook으로 옮겨졌나요?

  • 주어진 hook의 책임에 맞도록 코드가 분리가 되었나요?

  • 계산함수는 순수함수로 작성이 되었나요?

  • 특정 Entitiy만 다루는 함수는 분리되어 있나요?

  • 특정 Entitiy만 다루는 Component와 UI를 다루는 Component는 분리되어 있나요?

  • 데이터 흐름에 맞는 계층구조를 이루고 의존성이 맞게 작성이 되었나요?

심화과제

  • 이번 심화과제는 Context나 Jotai를 사용해서 Props drilling을 없애는 것입니다.

  • 어떤 props는 남겨야 하는지, 어떤 props는 제거해야 하는지에 대한 기준을 세워보세요.

  • Context나 Jotai를 사용하여 상태를 관리하는 방법을 익히고, 이를 통해 컴포넌트 간의 데이터 전달을 효율적으로 처리할 수 있습니다.

  • Context나 Jotai를 사용해서 전역상태관리를 구축했나요?

  • 전역상태관리를 통해 domain custom hook을 적절하게 리팩토링 했나요?

  • 도메인 컴포넌트에 도메인 props는 남기고 props drilling을 유발하는 불필요한 props는 잘 제거했나요?

  • 전체적으로 분리와 재조립이 더 수월해진 결합도가 낮아진 코드가 되었나요?

과제 셀프회고

  • 약간 뇌빼고 한 거 같긴 한데... 너무 욕심 부리지 않고 심화과제까지는 완성한 듯...
  • 큰 것부터 시작해서 작은 것으로 끝나는 흐름으로 완성한 듯 하다. (UI부터 시작하여 model 함수까지 다다르는...)

과제를 하면서 내가 알게된 점, 좋았던 점은 무엇인가요?

  • 저번 과제는 양이 너무 많아서 감당이 안됐는데, 이번 과제는 그래도 어느 정도 핸들링이 돼서 AI에게 부분적으로 물어보고, 잘 감이 안잡히는 부분은 AI에게 튜터로써 물어볼 수 있었던 점이 좋았습니다.
  • model → hooks → component로 흐르는 흐름을 이번에 처음 작성해봐서 좀 생소했던 점은 있었습니다만, 어떤 식으로 작성해야 하는지는 알 수 있어서 좋았습니다. 이게 FSD 방식인가라는 생각이 언뜻 들었습니다.

이번 과제에서 내가 제일 신경 쓴 부분은 무엇인가요?

  • 이번에는 Context API로 상태 관리를 구현했습니다. coupon, product, cart는 전역에서 사용해야 하기 때문에 Context에 두고, 나머지 상태는 props로 전달해도 충분하다고 판단했습니다. 따라서 Context API는 꼭 필요한 부분에만 적용하고, 그 외에는 props를 통해 값을 전달하도록 했습니다.
  • entities(models) → features(hooks) → UI(components) 구조로 각 계층이 명확한 역할을 가지고 있도록 하여, Models는 입력과 출력이 같은 비지니스 및 계산 로직만, Hooks는 상태 관리를 주로 다루며, Components는 렌더링만 담당하여 단일 책임 원칙에 따르게 하였습니다.
  • 또한 각 Hook이 하나의 도메인만 담당하도록 설계되어 있어서(useCart는 장바구니만, useProducts는 상품만), 기능을 확장하거나 수정할 때 다른 부분에 영향을 받지 않습니다.

이번 과제를 통해 앞으로 해보고 싶은게 있다면 알려주세요!

  • 고정적인 초기 데이터가 있는 것보다는 실제 API나 mock API로 데이터를 실제 끌어와서 작업을 해보면 실무에 도움이 되겠다 생각이 들었습니다.

리뷰 받고 싶은 내용이나 궁금한 것에 대한 질문 편하게 남겨주세요 :)

  • 아래 부분같은 경우에는 cart와 product가 혼재되어 있습니다. 이런 경우 모델의 어느쪽으로 가는게 맞는건지 아니면 새로운 모델 파일을 만들어서 혼재 되어 있는 경우에 그 파일에 넣어야할지... 헤깔린 부분 중에 하나기도 합니다. 어떤 기준으로 어떤 파일에 들어가야할까요? (뭔가 product와 cart 모델로 따로 넣기에는 코드 자체가 작아보이기도 하고 그래서 그런가 더 고민된달까요...흠...)
export const getRemainingStock = (
  product: Product,
  cart: CartItem[],
): number => {
  const cartItem = cart.find((item) => item.product.id === product.id)
  const remaining = product.stock - (cartItem?.quantity || 0)

  return remaining
}
  • 아직까지는 그래도 유틸에 들어가는 함수와 도메인에 들어가는 함수가 좀 헤깔리기도 합니다. 예를 들면 아래의 함수가 있다면 이건 어디든 써먹을 수 있는 함수갖기도 하고, 또 언뜻 보면 product와 관련된 함수로 보여서 비지니스 로직으로 봐야할지 잘 모르겠다는 생각이 듭니다. 저 함수가 도메인 함수로 봐야할까요? 아니면 유틸 함수로 봐야할까요.
export const calcRemainingStocks = (stock: number, min: number, max: number) => {
  return stock >= min && stock < max
}
  • 음... 이런 질문을 해도 되는지는 모르겠는데;; 이번 과제는 좀 익숙하기도 하고 양이 적당해서 코드를 갈아엎지 않고 한 것 같은데, 저번 과제인 '클린코드'는 저에게 양도 굉장히 많은 편이고, 썩 익숙한 편도 아니어서도 그런가 코드를 갈아 엎다 보니 완성하지 못했었습니다. 이렇게 많은 양이고 익숙하지 않은 코드인데 시간은 리밋이 있다 이럴 때 어떤 식으로 코드를 작성해야 코드를 갈아엎지 않고 할 수 있을까요?

과제 피드백

ㅋㅋㅋ민지님 고생하셨어요. 약간 뇌를 빼고 하신것 같다고 하셨지만 잘 마무리 하신것 같아요. 큰 것부터 시작해서 작은 흐름으로 진행을 한건 아마 익숙한 부분에서 시작해서 점점 중요한 로직들로 접근해나가셨던 것 같은데 이렇게 할 경우 영향 범위가 크니까 검증을 잘 하면서 조심해서 진행해야 했을 것 같네요! 다음에 이런 큰 개선이 있을때는 작은 단위부터 반복적이게 진행해보면 좋지 않을까 싶었습니다.

질문 주신 부분 답변 남겨보면요!

cart와 product가 혼재되어 있습니다

일단 코드와 상관 없이 이런 두 도메인 로직이 섞이는 경우에는 사실 명확한 기준을 만들기 어려운 부분이기도 한데요. 이럴때는 핵심 비즈니스 로직의 소유가 누구인지!를 기준으로 나누는 것 같아요. 지금의 경우에는 주된 사용 목적이 카트에 있는 것 같아서요. 근데 사실 명확하지는 않죠. 아무튼 이런 기준으로 모두가 합의할 수 있는 수준에 맞춰 작성하는게 가장 합리적이지 않을까 싶습니다.

다시 코드를 기반으로 살펴보면 지금의 코드는 사실 모델에 대한 순수한 로직이라고 보기보다는 비즈니스 로직이 합쳐진 것이라고 볼 수 있을 것 같아요. 이럴때는 service나 helpers같은 이름으로 분류를 해서 관리하고는 하는데요. 그런곳에 위치시키면 이런 코드들이 모여있구나라고 알 수 있어서 훨씬 합리적이고 쉽게 배치할 수 있지 않나 싶네요.

저 함수가 도메인 함수로 봐야할까요? 아니면 유틸 함수로 봐야할까요.

이 함수는 유틸함수로 봐야할 것 같은데요. 도메인 함수는 비즈니스 영역에 대한 규칙, 로직을 명확하게 담고 있어야하죠. 예를들어서 실제 도메인이 cart라면 cart에 담긴 내용을 제거한다라거나 하는 함수들이 비즈니스 로직이 될 것이고 지금처럼 특정 도메인에 종속되지 않고 다양한 상황에서 재사용 가능하다면 범용적인 헬퍼, 유틸리티 함수라고 볼 수 있을 것 같아요. 파라미터 이름을 stock으로 해서 그렇지 stock을 다른 이름으로 변경한다면 여러곳에서 사용할 수 있죠 사실 ㅎㅎ 이런 기준으로 보면 좋을것 같아요!

이렇게 많은 양이고 익숙하지 않은 코드인데 시간은 리밋이 있다 이럴 때 어떤 식으로 코드를 작성해야 코드를 갈아엎지 않고 할 수 있을까요?

사실 이런 상황이 일반적이지는 않고, 자주 경험해볼만한 상황은 아닌데요. 그럼에도 전체적인 코드를 개선해야 하는 상황이고 많은 양을 해야 한다면 작은 범위부터 명확한 검증을 수반해서 해야 한다고 생각해요. 만약 이 서비스를 운영중인 앱이라고 봤을 때 영향을 받을 수 있는 모듈, 기능 자체가 많기 때문에 굉장히 크고 꼼꼼한 검증이 함께 되어야 할 거에요. (하지만, 기능은 변하지 않았죠.) 그러니 굉장히 조심히 작은 범위부터 수정을 진행하고 점점 범위를 넓히면서 진행을 해야 하지 않을까 싶어요.

그럼에도 만약 시간 제한이 너무 강하게 있고..반드시 해내야 하는 개선이라면 명확한 목표만 두고 체크리스트를 만들어 둔 다음 빠르게 하고 검증에 시간을 훨씬 많이 쓰지 않았을까 싶네요. 어떤 상황이든 코드를 갈아엎는 리팩토링은 좋은 방식은 아닌것 같아요.

고생하셨고 다음주도 화이팅입니다!!