배포링크 : 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~3보다 더 중요하게 생각하는 한 가지가... 나에 대해 알아가는 것 이라고 생각해요 ㅎㅎ
내가 무엇을 좋아하는지, 무엇을 하고싶은지, 어떤 조직에 어울리는지 등!
https://www.yes24.com/product/goods/51092531
표현적 글쓰기 라는 책인데요, 커리어를 위한 활동보다 나 자신에 대해 알아가는 활동이 더 중요하다는 것을 다루고 있답니다!