Amelia-Shin 님의 상세페이지[1팀 신희원] Chapter 2-2. 디자인 패턴과 함수형 프로그래밍

배포링크 : https://amelia-shin.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는 분리되어 있나요?

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

심화과제

  • 재사용 가능한 Custom UI 컴포넌트를 만들어 보기

  • 재사용 가능한 Custom 라이브러리 Hook을 만들어 보기

  • 재사용 가능한 Custom 유틸 함수를 만들어 보기

  • 그래서 엔티티와는 어떤 다른 계층적 특징을 가지는지 이해하기

  • UI 컴포넌트 계층과 엔티티 컴포넌트의 계층의 성격이 다르다는 것을 이해하고 적용했는가?

  • 엔티티 Hook과 라이브러리 훅과의 계층의 성격이 다르다는 것을 이해하고 적용했는가?

  • 엔티티 순수함수와 유틸리티 함수의 계층의 성격이 다르다는 것을 이해하고 적용했는가?

과제 셀프회고

4주차 때 바이브코딩을 하다보니 엄청 현타가 왔었다. 내 생각대로 되지 않는 AI... 코드를 짜줘도 맘에 들지 않아...과제 제출하고 테스트 통과하기 위해 맘에 안들지만 계속 진행시켜... 이런식으로 과제를 진행하다 보니 스스로 이번 교육의 목적을 잊은채로 나 뭐하고 있는거지?? 했다. 테스트 통과가 목적이 아니라 스스로 배워가는게 크다는 것을 왜 잊었을까!! (근데 또 막상 테스트 실패하면 과제 fail나서 이것도 이거 나름대로 현타가 옴 ㅜㅜ -> 1주차때 과제를 다 못끝내 엄청 아쉬움이 많았지만 배워가는데에 의의를 두자 ! 라고 맘 편히 먹자 했지만 과제 결과로 2fail 뜬 것을 보니 아쉬움 x 99999 와 마음이 편안하지 못했다.)

4주차 때 엄청난 현타로 인해 5주차 때는 다시 초심으로 돌아가서 내가 배워가는데 의의를 두고, AI한테 짜달라하지 말고 간단한 작업만 도움을 받자! 라는 마음으로 진행했다. 처음에 과제를 진행하면서 막히는 부분도 꽤 많았지만 같은 팀원분들과 같이 코드 리뷰도 하고 서로의 코드를 공유하며 스스로 생각했을 때 상대방 코드가 더 좋은거 같다 생각이 들면 직접 내 코드에 적용해보는 등 하나하나 부딪혀가고 배워갔다. 내가 이렇게 물어보는게 어떻게 보면 상대방의 시간을 뻇는 것이라 생각이 들었지만, 오히려 나한테 개념이랑 코드를 설명해주면서 그 사람도 알고 있던 지식응 공유해주면서 실수를 바로 잡거나 새로 배워가지 않았을까? 서로 win-win관계이지 않았을까? 라고 생각하며 그냥 열심히 물어보면서 이번 과제를 진행했다. 4주차보단 이번 주차 과제에서는 흥미와 재미를 좀 느끼며 진행했다.

다음 주차도 페어코딩(?) 을 하면서 더 많은 것을 배우고 싶다!

과제를 하면서 내가 제일 신경 쓴 부분은 무엇인가요?

  • 컴포넌트 분리 ( UI 와 Hooks ) -> 더 세세하게 나누는게 좋았을까(ProductImg , ProductDiscount, ProductPrice 등등) ? 큼직큼직하게 나누는게 (ProductCard < ProductList ) 좋았을까?

  • 도메인별로 컴포넌트를 나눌때, 낮은 결합도, 높은 응집도 를 지키기 -> Product, Cart, Coupon 에 대해서 응집도를 높이기 위해서 어떻게 하면 더 잘 분리할 수 있을까? 고민이 들었던거 같다.

  • 배워가는 과정 (Custom Hook, 전역상태 (localStorage 와 상태 연동) 등등)

🔍 Custom Hooks 상태 공유 실수 Props drilling을 피하기 위해 하위 컴포넌트에서 같은 커스텀 훅을 다시 선언해서 사용했었다.

// 예시 코드 
function ParentComponent() {
  const { addNotification } = useNotification();
  
  addNotification('성공');
  return (
    <div>
      <ChildComponent />  {/* props로 전달하지 않음 */}
    </div>
  );
}

function ChildComponent() {
  const { addNotification } = useNotification(); // 같은 훅을 다시 선언
  
}

발생한 문제점 : 각 컴포넌트마다 독립적인 상태가 생성 Parent에서 addNotification 값이 변경되었음에도 불구하고, Child에서 addNotification은 값이 변하지 않았다. (같은 훅을 사용하는데도 완전히 분리된 두 개의 상태가 존재)

이 부분을 2번이나 실수했고... 1팀에 휘린님에게 문제 해결을 도와달라고 부탁하여 같이 진행해보았다. 그러면서 배우게 된 점!!! (2번이나 실수하니 확실히 배우게 되었다 :) ) -> 리액트 훅의 기본 원칙!

커스텀 훅을 호출할 때마다 새로운 상태가 생성된다!

useState는 호출될 때마다 새로운 독립적인 상태를 만듦 커스텀 훅은 단순히 로직을 재사용하는 것이지, 상태를 공유하는 것이 아님 ( = 커스텀 훅은 로직 재사용을 위한 도구) 각 컴포넌트는 자신만의 상태 인스턴스를 가지게 됨

🔍 localStorage와 React State 동기화 딜레마 핵심 문제: 두 개의 독립적인 상태 저장소

React state: 컴포넌트 마운트/언마운트 시 생성/소멸 localStorage: 브라우저 세션을 넘어 영구 지속

이 둘을 동기화하는 과정에서 다음과 같은 질문들이 떠올랐다. "상태 변경 시점에 즉시 localStorage에 저장해야 하는가?" "초기 로드 시 localStorage 값이 React state를 덮어써야 하는가?"

처음에 내가 접근한 방식

const [value, setValue] = useState(() => {
  const saved = localStorage.getItem(key);
  return saved ? JSON.parse(saved) : initialValue;
});

React state → localStorage 동기화  
useEffect(() => {
  localStorage.setItem(key, JSON.stringify(value));
}, [value, key]);

이 방법을 썼더니, 상태 업데이트 시 일관성이 보장되지 않았다.

그래서 같이 페어코딩을 하던 1팀(휘린, 아름)과 코드 공유를 하면서 어떻게 해결하면 되는지 알게 되었다. (Single Source of Truth 사용)

const setValue = (value: T | ((val: T) => T)) => {
    setStoredValue((prev) => {
      // value는 T 타입이거나, (prev: T) => T 형태
      // 함수면 이전 상태 prev를 넣어 새 상태를 계산
      const newValue =
        typeof value === "function" ? (value as (val: T) => T)(prev) : value;

      if (
        // 빈 배열이나 undefined면 localStorage에서 제거
        newValue === undefined ||
        (Array.isArray(newValue) && newValue.length === 0)
      ) {
        localStorage.removeItem(key);
      } else {
        // 그 외엔 JSON으로 직렬화해서 localStorage에 저장
        localStorage.setItem(key, JSON.stringify(newValue));
      }

      return newValue;
    });
  };

내가 생각한 위 두 코드의 차이점을 작성해본다. 첫번째 코드는 useEffect로 상태값(key, value)이 변할 때 localStorage에 값을 바꿔주기만 하고 (변한 상태값 반환 X), 두번째 코드는 상태값이 변했을 때 localStorage를 업뎃해준뒤 변한 상태값을 반환해준다.

좀 더 찾아보니 실행 시점에도 차이가 있었다. 첫번째 : React state 업데이트 → 렌더링 → useEffect 실행 두번째 : localStorage 저장 → React state 업데이트 요청 (동기)

과제를 다시 해보면 더 잘 할 수 있었겠다 아쉬운 점이 있다면 무엇인가요?

원래의 목표는 과제를 진행하면서 몰랐던 부분들을 열심히 배워가면서 과제를 하는 것이었다. 하지만 배워가면서 진행하다 보니 진도가 너무 뒤쳐지고 있었다. 결국엔 과제 제출일에 가까워 질 수록 테스트 통과가 목표가 되어 결국엔 다른 사람의 PR을 보거나 AI를 활용하여 스스로 생각하는 기회가 적어졌다. 내가 더 과제에 시간을 투자하고 진행했다면, 더 많이 배워가고 스스로 생각하는 힘이 길러졌을 텐데... 내 노력과 배움이 잘 녹아든 과제가 될 수 있었을텐데.. 이런 부분에서 좀 아쉬워서 꼭 다음에는 스스로 생각하면서 과제를 오로지 내 힘으로만 진행해보고 싶다. ( 꼭!!! ) -> 왜 클린코드 주차 과제에서는 아쉬움만 크게 남는걸까...ㅠㅠ

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

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

Q1. 제가 위에 배워가는 과정에 작성한 내용이 맞는 내용인지 궁금합니다! (혹시나 틀린 개념이 있거나 더 추가보완해서 설명해주실 것이 있다면 말씀 부탁드립니다.) Q2. 과제 관련한 질문은 아니지만, 현재 항해를 5주차 진행했는데요. 남은 기간동안 취업을 위해 무엇을 하면 좋고, 남은 항해과정을 어떻게 나아가면 좋을지... (교육을 더 잘 흡수하기 위한 꿀팁같은게 있을지..) 궁금합니다!

과제 피드백

안녕하세요 희원님! 5주차 과제 잘 진행해주셨네요 ㅎㅎ 고생하셨습니다. 희원님의 1주일이 세세하게 느껴지는 것 같아요 ㅋㅋ

🔍 localStorage와 React State 동기화 딜레마

이건 3주차 과제의 useStorage도 한 번 참고해주시면 좋겠어요! storage의 변경을 storage를 사용하고 있는 컴포넌트에게 전파하는 과정이 필요하답니다 ㅎㅎ

Q1. 제가 위에 배워가는 과정에 작성한 내용이 맞는 내용인지 궁금합니다! (혹시나 틀린 개념이 있거나 더 추가보완해서 설명해주실 것이 있다면 말씀 부탁드립니다.)

작성해주신 내용은 정확하다고 생각해요! 제가 위에 언급한 것 처럼, setState와 useEffect 말고도 useSyncExternalStore 같은걸 활용하는 방법이 있답니다 ㅎㅎ

https://github.com/hanghae-plus/front_6th_chapter1-3/pull/13

특히 영서님의 PR에 자세하게 나와있답니다!

Q2. 과제 관련한 질문은 아니지만, 현재 항해를 5주차 진행했는데요. 남은 기간동안 취업을 위해 무엇을 하면 좋고, 남은 항해과정을 어떻게 나아가면 좋을지... (교육을 더 잘 흡수하기 위한 꿀팁같은게 있을지..) 궁금합니다!

일단 10주차까지 학습을 꾸준히 하는게 제일 중요하겠죠!? 끝난 후에는 여태까지 했던 과제를 한 번 더 풀이해보세요 ㅎㅎ 그리고 이전보다 더 깊게 여유를 가지고 고민을 해보는 과정이 필요합니다.

특히 다른 사람이 작성한 코드에 대해 많이 살펴봐주시면 좋겠어요. 솔루션에 있는 코드도, 과제가 제공하는 환경도, 하나하나 다 소개해드리진 못했지만 알아가면 좋겠다고 생각한 내용을 최대한 꾹꾹 눌러서 담았답니다!

어쨌든, 취업까지 도달하기 위해 가장 중요한건

  1. 꾸준히 하는 것.
  2. 꾸준히 하는 모습을 알아봐줄 사람을 곁에 두는 것.
  3. 이력서를 작성하는 것.

그리고 1~3보다 더 중요하게 생각하는 한 가지가... 나에 대해 알아가는 것 이라고 생각해요 ㅎㅎ

내가 무엇을 좋아하는지, 무엇을 하고싶은지, 어떤 조직에 어울리는지 등!

https://www.yes24.com/product/goods/51092531

표현적 글쓰기 라는 책인데요, 커리어를 위한 활동보다 나 자신에 대해 알아가는 활동이 더 중요하다는 것을 다루고 있답니다!