관련 없는 정보를 함께 두지 않기
관련 없는 정보를 함께 두면 코드의 의도가 모호해집니다. 관련 없는 정보는 적절히 분리하여 코드의 의도를 명확하게 합니다.
좋지 않은 예시
tsx
// hook
export const useProductSaleSection = (productId: number, userId: number) => {
const { data: product } = useQuery(productQuery.detail(productId));
const { data: enrollment } = useQuery(enrollmentQuery.enrollment(userId));
const isOnSale = getIsOnSale(product);
const isEnrolled = getIsEnrolled(product, enrollment);
const salePrice = getSalePrice(product);
return { product, isOnSale, salePrice, isEnrolled };
};
// component
interface SaleSectionProps {
productId: number;
userId: number;
}
export const SaleSection = ({ productId, userId }: SaleSectionProps) => {
const { product, isOnSale, salePrice, isEnrolled } = useProductSaleSection(
productId,
userId,
);
return (
<div>
<p>product: {product.name}</p>
<p>isOnSale: {isOnSale}</p>
<p>salePrice: {salePrice}</p>
{isEnrolled && <p>이미 수강중인 상품입니다</p>}
</div>
);
};문제
useProductSaleSection은 SaleSection에서 사용할 정보들을 모아서 반환해주고 있습니다. 즉, useProductSaleSection 목적은 UI에 의존적입니다. UI가 빠르게 변하는 프론트엔드 환경에서는 이 함수 또한 자주 변경이 필요해질 것이고 이 함수를 호출하는 모든 곳이 동시에 변경되어야 합니다. 따라서 유지보수가 어렵고 재사용이 어려워집니다.
또한, product와 enrollment 데이터를 동시에 관리하고 있기 때문에 각 데이터에 변경이
있을 때 모두 하나의 훅을 수정하게 됩니다. 이는 서로 관계없는 데이터가 한 곳에 모여 있다는
뜻으로, enrollment 로직을 수정할 때 product 관련 코드에 의도치 않은 영향을 줄 수 있습니다.
좋은 예시
tsx
// hook
const useProductSaleInfo = (productId: number) => {
const { data: product } = useQuery(productQuery.detail(productId));
const isOnSale = getIsOnSale(product);
const salePrice = getSalePrice(product);
return { isOnSale, salePrice };
};
const useIsEnrolled = (userId: number) => {
const { data: enrollment } = useQuery(enrollmentQuery.enrollment(userId));
const isEnrolled = getIsEnrolled(product, enrollment);
return isEnrolled;
};
// component
interface SaleSectionProps {
productId: number;
userId: number;
}
export const SaleSection = ({ productId, userId }: SaleSectionProps) => {
const { data: product } = useQuery(productQuery.detail(productId));
const { isOnSale, salePrice } = useProductSaleInfo(productId);
const isEnrolled = useIsEnrolled(userId);
return (
<div>
<p>product: {product.name}</p>
<p>isOnSale: {isOnSale}</p>
<p>salePrice: {salePrice}</p>
{isEnrolled && <p>이미 수강중인 상품입니다</p>}
</div>
);
};상품의 판매 정보와 관련 있는 데이터와 수강권과 관련 있는 데이터를 분리해서 관리합니다.
이제 product 데이터 구조에 변경이 생겼을 때 어느 곳을 수정해야 할 지 명확해집니다. 그 변화에 enrollment는 더 이상 영향 받지 않습니다.
UI가 아닌 데이터의 성격을 기준으로 함수를 구성했기 때문에 함수의 책임과 의도가 더 명확해졌습니다.
