yhun940731 님의 상세페이지[7팀 최용훈] Chapter 2-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과 라이브러리 훅과의 계층의 성격이 다르다는 것을 이해하고 적용했는가?

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

과제 셀프회고

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

  1. Entity와 View의 분리.

  2. custom hook으로 묶을 수 있는 state와 상태 변경 함수를 판단하기.

  3. 컴포넌트를 Atomic하게 쪼개기 vs 적당히 가독성 측면에서 쪼개기

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

  1. 기본과제를 진행하면서 처음 나눴던 Header, AdminPage, CartPage 단위에 공통으로 내려야하는 props들이 있다보니, 해당 상태로부터 파생되는 여러 props들이 drilling을 발생시켰다. props drilling자체를 막을 수는 없지만, 상태를 최대한 지역화해서 깔끔하게 다시 짜보고싶기는하다.

  2. 처음에는 Context API를 활용하여 심화과제를 진행하다가 원복하고 JoTai를 사용하여 심화과제를 진행했지만, 마지막에 시간에 쫓껴서 완성할 수 없었다. 다시 돌아가면 처음부터 하나만 제대로 해보고싶다. 그래도 전역상태 관리, Context를 사용하니 props drilling을 방지할 수 있었고 props를 내리는 과정에서 누락하는 실수를 줄일 수 있다는 것을 다시금 느꼈다.

  3. 이번 과제를 하면서 느끼는 나의 고질적인 문제는, 항상 정답이 있다고 가정하고 과제를 대하고 있다. 나의 코드를 작성하지 못하고, 계속 정답일것 같은 코드만 찾다보니, 개발도 못하고 나중에 시간에 쫓겨 대충대충 진행하게 된다. 코딩은 정답을 찾는 과정이 아니라, 문제를 해결하는 과정이라는 것을 여전히 받아드리지 못했나보다.

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

  1. 컴포넌트를 나누는 과정에서 Atomic에 너무 집중하다보면 너무 많이 쪼개진 컴포넌트들로 오히려 가독성이 떨어진다고 생각합니다. 컴포넌트를 나누는 기준이야 천차만별이지만 조금의 팁이 있을까요?

  2. 전역상태 관리 라이브러리를 단지 Props drilling 방지를 위해 사용하는 것에 대해 어떻게 생각하시나요?. 그렇다면 전역 상태로 보관해야할 상태와, 지역에 useState등으로 보관해야할 상태의 기준이 어떻게 될까요? "props로 몇 depth 이상 내리면 차라리 전역변수로 관리한다." 이런 기준들은 조금 모호하다고 생각해서 들었던 의문입니다.

  3. 전역상태 라이브러리와 Context Api를 사용하는 기준이 각각 어떻게 될까요?

  4. 규모가 작지 않은 프로젝트에서 기존 코드를 모두 리팩토링할 시간은 없는 경우, 새로 추가되는 코드들을 기존 코드와 맞는 패턴으로 추가해야할까요? 아니면 새로운 컨벤션으로 클린하게 짜보려 노력해야할까요?

그 외 기록

1. test에서의 실수

import { Provider } from 'jotai';
import React from 'react';
import ReactDOM from 'react-dom/client';

import App from './App.tsx';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Provider>
      <App />
    </Provider>
  </React.StrictMode>,
);

처음에 jotai Provider를 이렇게 묶었는데 테스트 실패 원인을 찾을 수가 없어서 고생했다.

원인은

beforeEach(() => {
  render(<App />);
  // 관리자 모드로 전환
  fireEvent.click(screen.getByText('관리자 페이지로'));
});

App부터 렌더링하기 때문에 main.tsx에서 Provider는 반영되지 않는다.

  • 기존 코드는 당연히 잘 돌아갈거라고 생각하고 수정한 부분에서만 원인을 찾는 안 좋은 버릇이 있다. 추가, 수정 후에는 기존 코드와의 연계도 생각을 하면서 이슈를 찾아야지.

2. GPT-5 사용기

  • 8월 8일 아침, gpt-5를 vscode copilot에서 사용할 수 있게 됐다. 딸깍 코딩의 맛을 보기 위해, 코드 리팩토링을 agent에게 부탁했는데, 체감상 sonnet 4 보다 전체 코드의 맥락을 잘 파악하고 내가 원하는 대로 척척 나눠줬다... 뭔가 의존하고 싶어지는 듬직한 녀석이지만 정신 차리고 도구로써 잘 쓰기를...

과제 피드백

안녕하세요 용훈님! 5주차 과제 잘 진행해주셨네요 ㅎㅎ 고생하셨습니다!!

심화과제가 미완성이라고 말씀해주셨는데, 일단 테스트도 통과하고 있고 어느정도 분리가 되어있어서 합격으로 남겨놓겠습니다!

컴포넌트를 나누는 과정에서 Atomic에 너무 집중하다보면 너무 많이 쪼개진 컴포넌트들로 오히려 가독성이 떨어진다고 생각합니다. 컴포넌트를 나누는 기준이야 천차만별이지만 조금의 팁이 있을까요?

처음부터 다 작게 작게 분리하기보단, 분리가 필요한 순간에 분리하는 방법이 있을 것 같아요 ㅎㅎ 반복적으로 보이는 컴포넌트를 분리한다거나?!

혹은 책임의 소재를 분리하기 위해 분리하는 등의 방법이 있을 것 같네요.

그리고 가독성이 떨어진다고 생각하시는 이유가 뭘까요!? 너무 Depth가 깊어져서 그런걸까요!?

전역상태 관리 라이브러리를 단지 Props drilling 방지를 위해 사용하는 것에 대해 어떻게 생각하시나요?. 그렇다면 전역 상태로 보관해야할 상태와, 지역에 useState등으로 보관해야할 상태의 기준이 어떻게 될까요? "props로 몇 depth 이상 내리면 차라리 전역변수로 관리한다." 이런 기준들은 조금 모호하다고 생각해서 들었던 의문입니다.

저는 상태관리 라이브러리에서 중요한건 "전역" 이라는 키워드가 아니라 "상태관리" 라는 키워드라고 생각해요. props drilling만 해결하고 싶다면 context를 쓰는게 맞다고 생각합니다.

상태관리 라이브러리는 복잡한 데이터의 변경과 흐름을 응집도 있게 관리하기 위함이라고 생각해요 ㅎㅎ "전역" 이라는 키워드는 이를 위한 장치라고 생각합니다.

전역상태 라이브러리와 Context Api를 사용하는 기준이 각각 어떻게 될까요?

Context API 는 보통 UI의 상태를 응집도 있게 관리하기 위해 사용하는 경우가 많습니다.

https://www.radix-ui.com/themes/docs/components/dialog

<Dialog.Root>
	<Dialog.Trigger>
		<Button>Edit profile</Button>
	</Dialog.Trigger>

	<Dialog.Content maxWidth="450px">
		<Dialog.Title>Edit profile</Dialog.Title>
		<Dialog.Description size="2" mb="4">
			Make changes to your profile.
		</Dialog.Description>

		<Flex direction="column" gap="3">
			<label>
				<Text as="div" size="2" mb="1" weight="bold">
					Name
				</Text>
				<TextField.Root
					defaultValue="Freja Johnsen"
					placeholder="Enter your full name"
				/>
			</label>
			<label>
				<Text as="div" size="2" mb="1" weight="bold">
					Email
				</Text>
				<TextField.Root
					defaultValue="freja@example.com"
					placeholder="Enter your email"
				/>
			</label>
		</Flex>

		<Flex gap="3" mt="4" justify="end">
			<Dialog.Close>
				<Button variant="soft" color="gray">
					Cancel
				</Button>
			</Dialog.Close>
			<Dialog.Close>
				<Button>Save</Button>
			</Dialog.Close>
		</Flex>
	</Dialog.Content>
</Dialog.Root>

잘 보면 state가 어디에도 없으나 정상적으로 동작해요. 이게 다 Context를 통해 추상화가 된거죠!

상태관리를 사용하는 이유는 앞선 질문에 답변 했으니 참고 부탁드려요!

규모가 작지 않은 프로젝트에서 기존 코드를 모두 리팩토링할 시간은 없는 경우, 새로 추가되는 코드들을 기존 코드와 맞는 패턴으로 추가해야할까요? 아니면 새로운 컨벤션으로 클린하게 짜보려 노력해야할까요?

시급도에 따라 다르다고 생각해요. 정말 시급한 경우에는 기존 구조를 쫓아가는게 생산성을 더 높일 수 있는 방법일 것이고, 그렇지 않은 경우에는 새로 추가하는 코드는 새로운 컨벤션으로 구성하고, 변경이 생길 때 마다 조금씩 조금씩 점진적인 개선을 하는 방법을 생각해볼 수 있을 것 같아요.

대신 이 때 중요한건 테스트가 있어야 한다는 것! 기존 코드가 정상적으로 동작하는지 보장해야 하기 때문에, 테스트 없이는 리팩토링을 하는게 위험할 수 있어요..!