惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LangChain Blog
云风的 BLOG
云风的 BLOG
M
MIT News - Artificial intelligence
A
About on SuperTechFans
J
Java Code Geeks
量子位
博客园 - 三生石上(FineUI控件)
博客园 - Franky
博客园_首页
H
Hackread – Cybersecurity News, Data Breaches, AI and More
IT之家
IT之家
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
3년만에 교내 IT동아리 웹파트 미션을 리팩토링 해보았다.
Chan · 2026-05-03 · via DEV Community

Chan

2023년에 교내 IT동아리 부원이 되었다. 최근에 다시 웹파트장을 하면서 부원들에게 과제로 나가는 코드를 검토해봤는데 3년 전이랑 다른 관점으로 리팩토링할만한 거리들이 생겨서 적어본다. 그 당시에는 SOLID 원칙을 최대한 지킨다는 이유로, 간결한 컴포넌트 이름을 유지한다는 이유, 컴포넌트 내부 동작이 너무 노출된다는 이유 등으로 내부를 최대한 숨기는 코드를 작성했는데, 지금은 숨길 건 숨기고 드러내야 된다는 관점을 가지게 되었다.

ProductRowList 컴포넌트의 제거

ProductRowList 컴포넌트는 products를 입력 받아서, map 함수를 통해 ProductRow를 렌더링하는 컴포넌트이다.

문제점

디테일을 숨기고 핵심만 드러내는 게 추상화의 이점인데 ProductRowList는 디테일이 없다. 단순히 map을 통해 컴포넌트의 배열을 랜더링하는 책임만 있어 RowList라는 이름으로 은닉하는 정보가 없다.

해결방안

ProductRowList 컴포넌트를 제거하고 사용처에서 map으로 직접 렌더링하는 로직을 노출시킨다.

AS-IS

<React.Fragment key={category}>
  <ProductCategoryRow category={category} />
    <ProductRowList
      products={products}
      onEdit={onProductEdit}
      onDelete={onProductDelete}
    />
</React.Fragment>

Enter fullscreen mode Exit fullscreen mode

export function ProductRowList({ products, ...props }) {
  return products.map((product) => (
    <ProductRow key={product.name} {...product} {...props} />
  ));
}

Enter fullscreen mode Exit fullscreen mode

TO-BE

<React.Fragment key={category}>
  <ProductCategoryRow category={category} />
  {products.map((product) => (
    <ProductRow 
      {...product}
      onEdit={onProductEdit}
      onDelete={onProductDelete}
    />
  ))}
</React.Fragment>

Enter fullscreen mode Exit fullscreen mode

ProductRow 컴포넌트 네이밍

문제점

ProductRow는 product를 렌더링하고, 해당 product에 대한 데이터를 수정할 수 있는 인라인 편집 기능까지 관리한다. 그런데 ProductRow라는 이름만 들었을 때 이 컴포넌트가 할 일은 제품을 row의 형태로 보여주는 것까지만 추측할 수 있다. 물론 onEdit, onDelete라는 이름을 통해 고유의 입력 상태가 있는 인터렉티브한 컴포넌트라는 것을 예측할 수 있지만, ProducRow의 prop 목록을 확인하면서 추측할 수 밖에 없기에 불분명하다고 생각한다.

해결방안

컴포넌트 이름을 ProductRow에서 EditableProductRow으로 변경한다.

EditableProductRow의 prop 이름 onEdit => onSave로 개선

문제점

EditableProductRow는 인라인 편집을 지원하는데, 편집이 끝날 경우 호출하는 함수라는 의미에서 onEdit으로 콜백 함수 이름을 지었다. 그런데 임시 상태가 있고, 이를 save action을 통해서 영구적인 상태로 변환할 때 실행되는 콜백 함수이기에 onEdit이라는 이름만으로는 save action시 호출되는 함수라는 것을 예측하기가 어려운 거 같다.

해결방안

onSave를 onEdit으로 변경한다. save action이 발생할 때 호출되는 함수라는 의미에서 onSave가 더 적합한 거 같다.

AS-IS

export default function ProductRow({ id, name, price, onEdit, onDelete }) {
  ...
}

Enter fullscreen mode Exit fullscreen mode

TO-BE

export default function EditableProductRow({ id, name, price, onSave, onDelete }) {
...
}

Enter fullscreen mode Exit fullscreen mode