{"id":36,"date":"2025-07-16T13:44:54","date_gmt":"2025-07-16T04:44:54","guid":{"rendered":"https:\/\/34.64.61.65\/?p=36"},"modified":"2025-07-16T14:39:47","modified_gmt":"2025-07-16T05:39:47","slug":"%ec%8b%a4%eb%ac%b4%ec%97%90%ec%84%9c_%ec%9e%90%ec%a3%bc_%ec%93%b0%eb%8a%94_%eb%a6%ac%ed%8c%a9%ed%84%b0%eb%a7%81_%ed%8c%a8%ed%84%b4","status":"publish","type":"post","link":"https:\/\/hed-g.me\/?p=36","title":{"rendered":"\uc2e4\ubb34\uc5d0\uc11c \uc790\uc8fc \uc4f0\ub294 \ub9ac\ud329\ud130\ub9c1 \ud328\ud134: \ub808\uac70\uc2dc \ucf54\ub4dc\ub97c \ud604\ub300\uc801\uc73c\ub85c \uac1c\uc120\ud558\ub294 \uc2e4\uc804 \uac00\uc774\ub4dc"},"content":{"rendered":"\n<p>\uc548\ub155\ud558\uc138\uc694, \uc131\uc7a5\ud558\ub294 \uac1c\ubc1c\uc790 \uc5ec\ub7ec\ubd84!<\/p>\n\n\n\n<p>&#8220;\uc774 \ucf54\ub4dc \ub204\uac00 \uc9f0\uc5b4?&#8221; \ud83d\ude31<\/p>\n\n\n\n<p>\uc2e4\ubb34\uc5d0\uc11c \uac00\uc7a5 \ub9ce\uc774 \ub4e3\ub294 \ub9d0 \uc911 \ud558\ub098\uc785\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub180\ub78d\uac8c\ub3c4 <strong>6\uac1c\uc6d4 \uc804 \ub0b4\uac00 \uc9e0 \ucf54\ub4dc<\/strong>\uc77c \uac00\ub2a5\uc131\uc774 \ub192\uc8e0! \ucf54\ub4dc\ub294 \uc0b4\uc544\uc788\ub294 \uc0dd\ubb3c\ucc98\ub7fc \uacc4\uc18d \uc131\uc7a5\ud558\uace0 \ubcc0\ud654\ud574\uc57c \ud569\ub2c8\ub2e4. \uc624\ub298\uc740 \uc81c\uac00 \uc2e4\ubb34\uc5d0\uc11c \uacaa\uc740 \ub2e4\uc591\ud55c \uc0c1\ud669\ub4e4\uc744 \ud1b5\ud574 \ubc30\uc6b4 <strong>\ub9ac\ud329\ud130\ub9c1\uc758 \ubaa8\ub4e0 \uac83<\/strong>\uc744 \uc815\ub9ac\ud574 \ub4dc\ub9ac\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<p>&#8220;\ub9ac\ud329\ud130\ub9c1\uc740 \uc704\ud5d8\ud574&#8221;\ub77c\uace0 \uc0dd\uac01\ud558\uc168\ub2e4\uba74, \uc774 \uae00\uc744 \uc77d\uace0 \ub098\uba74 <strong>&#8220;\ub9ac\ud329\ud130\ub9c1\uc740 \ud544\uc218\uc57c&#8221;<\/strong>\ub85c \uc0dd\uac01\uc774 \ubc14\ub014 \uac70\uc608\uc694! \ud83d\ude80<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. \ub9ac\ud329\ud130\ub9c1\uc774\ub780? \ucf54\ub4dc\uc758 \uc131\ud615\uc218\uc220\uc774 \uc544\ub2cc \uac74\uac15\uac80\uc9c4<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ub9ac\ud329\ud130\ub9c1\uc758 \uc815\ud655\ud55c \uc815\uc758<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u274c \uc774\uac74 \ub9ac\ud329\ud130\ub9c1\uc774 \uc544\ub2d9\ub2c8\ub2e4\nfunction oldFunction() {\n  \/\/ \uae30\uc874 \uae30\ub2a5\uc744 \uc644\uc804\ud788 \ubc14\uafd4\ubc84\ub9bc\n  return \"completely different behavior\";\n}\n\nfunction newFunction() {\n  \/\/ \uc0c8\ub85c\uc6b4 \uae30\ub2a5 \ucd94\uac00\n  return \"new feature added\";\n}\n\n\/\/ \u2705 \uc774\uac83\uc774 \uc9c4\uc9dc \ub9ac\ud329\ud130\ub9c1\uc785\ub2c8\ub2e4\n\/\/ BEFORE: \ubcf5\uc7a1\ud558\uace0 \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\nfunction calculatePrice(items, userType, discount) {\n  let total = 0;\n  for (let i = 0; i &lt; items.length; i++) {\n    if (userType === \"premium\") {\n      total += items&#91;i].price * 0.9;\n    } else if (userType === \"vip\") {\n      total += items&#91;i].price * 0.8;\n    } else {\n      total += items&#91;i].price;\n    }\n  }\n  if (discount) {\n    total = total * (1 - discount);\n  }\n  return total;\n}\n\n\/\/ AFTER: \uac19\uc740 \ub3d9\uc791, \ub354 \uba85\ud655\ud55c \uad6c\uc870\nfunction calculatePrice(items, userType, discount = 0) {\n  const baseTotal = calculateBaseTotal(items);\n  const discountedTotal = applyUserDiscount(baseTotal, userType);\n  return applyAdditionalDiscount(discountedTotal, discount);\n}\n\nfunction calculateBaseTotal(items) {\n  return items.reduce((total, item) =&gt; total + item.price, 0);\n}\n\nfunction applyUserDiscount(total, userType) {\n  const discountRates = {\n    premium: 0.9,\n    vip: 0.8,\n    regular: 1.0,\n  };\n  return total * (discountRates&#91;userType] || 1.0);\n}\n\nfunction applyAdditionalDiscount(total, discount) {\n  return total * (1 - discount);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ub9ac\ud329\ud130\ub9c1\uc758 \ud575\uc2ec \uc6d0\uce59<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\uac89\ubcf4\uae30 \ub3d9\uc791\uc740 \uadf8\ub300\ub85c \uc720\uc9c0<\/strong>: \uc678\ubd80\uc5d0\uc11c \ubcf4\ub294 \uacb0\uacfc\ub294 \ub3d9\uc77c\ud574\uc57c \ud568<\/li>\n\n\n\n<li><strong>\ub0b4\ubd80 \uad6c\uc870\ub9cc \uac1c\uc120<\/strong>: \uac00\ub3c5\uc131, \uc720\uc9c0\ubcf4\uc218\uc131, \ud655\uc7a5\uc131 \ud5a5\uc0c1<\/li>\n\n\n\n<li><strong>\uc791\uc740 \ub2e8\uacc4\ub85c \uc9c4\ud589<\/strong>: \ud55c \ubc88\uc5d0 \ud558\ub098\uc529, \uc548\uc804\ud558\uac8c<\/li>\n\n\n\n<li><strong>\ud14c\uc2a4\ud2b8 \uc8fc\ub3c4<\/strong>: \ub9ac\ud329\ud130\ub9c1 \uc804\ud6c4 \ud14c\uc2a4\ud2b8\ub85c \uac80\uc99d<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">2. \uc65c \ub9ac\ud329\ud130\ub9c1\uc774 \ud544\uc694\ud560\uae4c? \ud604\uc2e4\uc801\uc778 \uc774\uc720\ub4e4<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ucf54\ub4dc \ubd80\ucc44(Technical Debt)\uc758 \ub204\uc801<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud83d\udcc8 \ucf54\ub4dc \ubd80\ucc44 \ub204\uc801 \uacfc\uc815\n\nWeek 1: \"\ube68\ub9ac \ub9cc\ub4e4\uc5b4\uc57c \ud574!\"\n        \u2192 \uae09\ud558\uac8c \uc791\uc131\ud55c \ucf54\ub4dc\n\nWeek 4: \"\ubc84\uadf8 \uc218\uc815\ub9cc \ube60\ub974\uac8c!\"\n        \u2192 \uc784\uc2dc\ubc29\ud3b8 \ucf54\ub4dc \ucd94\uac00\n\nWeek 8: \"\uc0c8 \uae30\ub2a5 \ucd94\uac00\ud574\uc57c \ud574!\"\n        \u2192 \uae30\uc874 \ucf54\ub4dc\uc5d0 \uc5b5\uc9c0\ub85c \ub07c\uc6cc \ub123\uae30\n\nWeek 12: \"\uc774 \ucf54\ub4dc\ub97c \uc544\ubb34\ub3c4 \uac74\ub4dc\ub9ac\uace0 \uc2f6\uc5b4\ud558\uc9c0 \uc54a\uc544\uc694\"\n         \u2192 \uac1c\ubc1c \uc18d\ub3c4 \uae09\uac10, \ubc84\uadf8 \uc99d\uac00\n\n# \uc774\ub54c \ud544\uc694\ud55c \uac83\uc774 \ub9ac\ud329\ud130\ub9c1!<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\uc2e4\ubb34\uc5d0\uc11c \uacaa\ub294 \ubb38\uc81c\ub4e4<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\ude31 \uc2e4\uc81c\ub85c \ubcf4\uac8c \ub418\ub294 \ucf54\ub4dc\ub4e4\n\n\/\/ 1. \ud558\ub098\uc758 \ud568\uc218\uac00 \ub108\ubb34 \ub9ce\uc740 \uc77c\uc744 \ud568\nfunction processUser(userData) {\n  \/\/ 100\uc904 \ub118\ub294 \ud568\uc218\n  \/\/ - \uc720\ud6a8\uc131 \uac80\uc0ac\n  \/\/ - \ub370\uc774\ud130 \ubcc0\ud658\n  \/\/ - DB \uc800\uc7a5\n  \/\/ - \uc774\uba54\uc77c \ubc1c\uc1a1\n  \/\/ - \ub85c\uadf8 \uae30\ub85d\n  \/\/ - \uce90\uc2dc \uc5c5\ub370\uc774\ud2b8\n  \/\/ - \uc54c\ub9bc \ubc1c\uc1a1\n}\n\n\/\/ 2. \ub9e4\uc9c1 \ub118\ubc84\uc640 \ud558\ub4dc\ucf54\ub529\uc758 \ub0a8\ubc1c\nif (user.age &gt; 18 &amp;&amp; user.score &gt; 750 &amp;&amp; user.level === 3) {\n  \/\/ \uc774 \uc22b\uc790\ub4e4\uc774 \ubb58 \uc758\ubbf8\ud558\ub294\uc9c0 \uc544\ubb34\ub3c4 \ubaa8\ub984\n}\n\n\/\/ 3. \uae4a\uac8c \uc911\ucca9\ub41c \uc870\uac74\ubb38\nif (user) {\n  if (user.isActive) {\n    if (user.hasPermission) {\n      if (user.subscription) {\n        if (user.subscription.isValid) {\n          \/\/ \uc2e4\uc81c \ub85c\uc9c1\uc740 \uc5ec\uae30 \ud55c \uc904\n        }\n      }\n    }\n  }\n}\n\n\/\/ 4. \uc758\ubbf8 \uc5c6\ub294 \ubcc0\uc218\uba85\nfunction calc(a, b, c) {\n  const x = a * b;\n  const y = x + c;\n  const z = y * 0.1;\n  return z;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. \ub9ac\ud329\ud130\ub9c1 \uc804 \uc900\ube44: \uc548\uc804\ub9dd \uad6c\ucd95\ud558\uae30<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1\ub2e8\uacc4: \ud14c\uc2a4\ud2b8 \ucf54\ub4dc \uc791\uc131<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ub9ac\ud329\ud130\ub9c1 \uc804 \ubc18\ub4dc\uc2dc \ud14c\uc2a4\ud2b8 \ucf54\ub4dc\ubd80\ud130!\ndescribe(\"calculatePrice \ud568\uc218\", () =&gt; {\n  test(\"\uc77c\ubc18 \uc0ac\uc6a9\uc790\uc758 \uac00\uaca9 \uacc4\uc0b0\", () =&gt; {\n    const items = &#91;{ price: 1000 }, { price: 2000 }];\n    const result = calculatePrice(items, \"regular\");\n    expect(result).toBe(3000);\n  });\n\n  test(\"\ud504\ub9ac\ubbf8\uc5c4 \uc0ac\uc6a9\uc790 10% \ud560\uc778\", () =&gt; {\n    const items = &#91;{ price: 1000 }];\n    const result = calculatePrice(items, \"premium\");\n    expect(result).toBe(900);\n  });\n\n  test(\"VIP \uc0ac\uc6a9\uc790 20% \ud560\uc778\", () =&gt; {\n    const items = &#91;{ price: 1000 }];\n    const result = calculatePrice(items, \"vip\");\n    expect(result).toBe(800);\n  });\n\n  test(\"\ucd94\uac00 \ud560\uc778 \uc801\uc6a9\", () =&gt; {\n    const items = &#91;{ price: 1000 }];\n    const result = calculatePrice(items, \"regular\", 0.1);\n    expect(result).toBe(900);\n  });\n\n  test(\"\ube48 \ubc30\uc5f4 \ucc98\ub9ac\", () =&gt; {\n    const result = calculatePrice(&#91;], \"regular\");\n    expect(result).toBe(0);\n  });\n});<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2\ub2e8\uacc4: \ubc84\uc804 \uad00\ub9ac \uccb4\uacc4 \uad6c\ucd95<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Git\uc744 \ud65c\uc6a9\ud55c \uc548\uc804\ud55c \ub9ac\ud329\ud130\ub9c1\ngit checkout -b refactor\/improve-price-calculation\n\n# \uc791\uc740 \ub2e8\uc704\ub85c \ucee4\ubc0b\ngit commit -m \"refactor: extract calculateBaseTotal function\"\ngit commit -m \"refactor: extract applyUserDiscount function\"\ngit commit -m \"refactor: extract applyAdditionalDiscount function\"\ngit commit -m \"refactor: improve variable naming in price calculation\"\n\n# \uac01 \ucee4\ubc0b\ub9c8\ub2e4 \ud14c\uc2a4\ud2b8 \uc2e4\ud589\nnpm test<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">4. \ud575\uc2ec \ub9ac\ud329\ud130\ub9c1 \ud328\ud134\ub4e4<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 1: \ud568\uc218 \ucd94\ucd9c\ud558\uae30 (Extract Function)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \uac00\uc7a5 \uc790\uc8fc \uc0ac\uc6a9\ud558\ub294 \ub9ac\ud329\ud130\ub9c1 \uae30\ubc95\n\n\/\/ BEFORE: \ud558\ub098\uc758 \ud568\uc218\uac00 \ub108\ubb34 \ub9ce\uc740 \uc77c\uc744 \ud568\nfunction processOrder(orderData) {\n  \/\/ \uc8fc\ubb38 \uac80\uc99d\n  if (!orderData.items || orderData.items.length === 0) {\n    throw new Error(\"\uc8fc\ubb38 \ud56d\ubaa9\uc774 \uc5c6\uc2b5\ub2c8\ub2e4\");\n  }\n  if (!orderData.customerId) {\n    throw new Error(\"\uace0\uac1d ID\uac00 \ud544\uc694\ud569\ub2c8\ub2e4\");\n  }\n\n  \/\/ \uac00\uaca9 \uacc4\uc0b0\n  let total = 0;\n  for (const item of orderData.items) {\n    total += item.price * item.quantity;\n  }\n\n  \/\/ \ud560\uc778 \uc801\uc6a9\n  if (orderData.coupon) {\n    if (orderData.coupon.type === \"percent\") {\n      total = total * (1 - orderData.coupon.value \/ 100);\n    } else if (orderData.coupon.type === \"fixed\") {\n      total = total - orderData.coupon.value;\n    }\n  }\n\n  \/\/ \uc138\uae08 \uacc4\uc0b0\n  const tax = total * 0.1;\n  const finalTotal = total + tax;\n\n  \/\/ DB \uc800\uc7a5\n  const order = {\n    id: generateOrderId(),\n    customerId: orderData.customerId,\n    items: orderData.items,\n    subtotal: total,\n    tax: tax,\n    total: finalTotal,\n    status: \"pending\",\n    createdAt: new Date(),\n  };\n\n  \/\/ \uc2e4\uc81c \uc800\uc7a5 \ub85c\uc9c1...\n  return order;\n}\n\n\/\/ AFTER: \ucc45\uc784\ubcc4\ub85c \ud568\uc218 \ubd84\ub9ac\nfunction processOrder(orderData) {\n  validateOrder(orderData);\n\n  const subtotal = calculateSubtotal(orderData.items);\n  const discountedTotal = applyCoupon(subtotal, orderData.coupon);\n  const tax = calculateTax(discountedTotal);\n  const finalTotal = discountedTotal + tax;\n\n  return createOrder({\n    customerId: orderData.customerId,\n    items: orderData.items,\n    subtotal: discountedTotal,\n    tax,\n    total: finalTotal,\n  });\n}\n\nfunction validateOrder(orderData) {\n  if (!orderData.items?.length) {\n    throw new Error(\"\uc8fc\ubb38 \ud56d\ubaa9\uc774 \uc5c6\uc2b5\ub2c8\ub2e4\");\n  }\n  if (!orderData.customerId) {\n    throw new Error(\"\uace0\uac1d ID\uac00 \ud544\uc694\ud569\ub2c8\ub2e4\");\n  }\n}\n\nfunction calculateSubtotal(items) {\n  return items.reduce((total, item) =&gt; {\n    return total + item.price * item.quantity;\n  }, 0);\n}\n\nfunction applyCoupon(total, coupon) {\n  if (!coupon) return total;\n\n  switch (coupon.type) {\n    case \"percent\":\n      return total * (1 - coupon.value \/ 100);\n    case \"fixed\":\n      return Math.max(0, total - coupon.value);\n    default:\n      return total;\n  }\n}\n\nfunction calculateTax(amount) {\n  return amount * 0.1;\n}\n\nfunction createOrder({ customerId, items, subtotal, tax, total }) {\n  return {\n    id: generateOrderId(),\n    customerId,\n    items,\n    subtotal,\n    tax,\n    total,\n    status: \"pending\",\n    createdAt: new Date(),\n  };\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 2: \ubcc0\uc218 \ucd94\ucd9c\ud558\uae30 (Extract Variable)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ubcf5\uc7a1\ud55c \ud45c\ud604\uc2dd\uc744 \uc758\ubbf8 \uc788\ub294 \ubcc0\uc218\ub85c \ubd84\ub9ac\n\n\/\/ BEFORE: \uc758\ubbf8\ub97c \ud30c\uc545\ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\nfunction calculateShippingCost(order) {\n  return order.weight &gt; 10 &amp;&amp; order.destination === \"international\" ? order.basePrice * 0.15 + 25 : order.basePrice * 0.05;\n}\n\n\/\/ AFTER: \uc758\ub3c4\uac00 \uba85\ud655\ud55c \ucf54\ub4dc\nfunction calculateShippingCost(order) {\n  const isHeavyPackage = order.weight &gt; 10;\n  const isInternationalShipping = order.destination === \"international\";\n  const requiresSpecialHandling = isHeavyPackage &amp;&amp; isInternationalShipping;\n\n  const internationalRate = 0.15;\n  const domesticRate = 0.05;\n  const specialHandlingFee = 25;\n\n  if (requiresSpecialHandling) {\n    return order.basePrice * internationalRate + specialHandlingFee;\n  } else {\n    return order.basePrice * domesticRate;\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 3: \uc870\uac74\ubd80 \ub85c\uc9c1 \uac1c\uc120<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ubcf5\uc7a1\ud55c \uc870\uac74\ubb38\uc744 \uac1d\uccb4\ub098 \ud568\uc218\ub85c \ub300\uccb4\n\n\/\/ BEFORE: \ub05d\uc5c6\uc774 \ub298\uc5b4\ub098\ub294 if-else\nfunction getDiscountRate(user) {\n  if (user.type === \"premium\" &amp;&amp; user.yearsActive &gt;= 5) {\n    return 0.2;\n  } else if (user.type === \"premium\" &amp;&amp; user.yearsActive &gt;= 2) {\n    return 0.15;\n  } else if (user.type === \"premium\") {\n    return 0.1;\n  } else if (user.type === \"regular\" &amp;&amp; user.yearsActive &gt;= 3) {\n    return 0.05;\n  } else {\n    return 0;\n  }\n}\n\n\/\/ AFTER: \uac1d\uccb4\ub97c \ud65c\uc6a9\ud55c \uae54\ub054\ud55c \ub85c\uc9c1\nconst DISCOUNT_RULES = {\n  premium: {\n    5: 0.2, \/\/ 5\ub144 \uc774\uc0c1\n    2: 0.15, \/\/ 2\ub144 \uc774\uc0c1\n    0: 0.1, \/\/ \uae30\ubcf8\n  },\n  regular: {\n    3: 0.05, \/\/ 3\ub144 \uc774\uc0c1\n    0: 0, \/\/ \uae30\ubcf8\n  },\n};\n\nfunction getDiscountRate(user) {\n  const userRules = DISCOUNT_RULES&#91;user.type] || DISCOUNT_RULES.regular;\n\n  \/\/ \uc870\uac74\uc744 \ub9cc\uc871\ud558\ub294 \uac00\uc7a5 \ub192\uc740 \ud560\uc778\uc728 \ucc3e\uae30\n  const eligibleDiscounts = Object.entries(userRules)\n    .filter((&#91;years]) =&gt; user.yearsActive &gt;= parseInt(years))\n    .map((&#91;_, rate]) =&gt; rate);\n\n  return Math.max(...eligibleDiscounts, 0);\n}\n\n\/\/ \ub610\ub294 \ub354 \uba85\ud655\ud55c \ud568\uc218\ud615 \uc811\uadfc\nfunction getDiscountRate(user) {\n  if (user.type === \"premium\") {\n    return getPremiumDiscount(user.yearsActive);\n  }\n  if (user.type === \"regular\") {\n    return getRegularDiscount(user.yearsActive);\n  }\n  return 0;\n}\n\nfunction getPremiumDiscount(yearsActive) {\n  if (yearsActive &gt;= 5) return 0.2;\n  if (yearsActive &gt;= 2) return 0.15;\n  return 0.1;\n}\n\nfunction getRegularDiscount(yearsActive) {\n  return yearsActive &gt;= 3 ? 0.05 : 0;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 4: \ub9e4\uc9c1 \ub118\ubc84\/\ubb38\uc790\uc5f4 \uc81c\uac70<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ud558\ub4dc\ucf54\ub529\ub41c \uac12\ub4e4\uc744 \uc0c1\uc218\ub85c \ubd84\ub9ac\n\n\/\/ BEFORE: \ub9e4\uc9c1 \ub118\ubc84\ub4e4\uc758 \ud5a5\uc5f0\nfunction validateUser(user) {\n  if (user.age &lt; 18) return false;\n  if (user.score &lt; 750) return false;\n  if (user.level !== 3 &amp;&amp; user.level !== 4 &amp;&amp; user.level !== 5) return false;\n  if (user.status !== \"active\" &amp;&amp; user.status !== \"premium\") return false;\n  return true;\n}\n\n\/\/ AFTER: \uc758\ubbf8\uac00 \uba85\ud655\ud55c \uc0c1\uc218\ub4e4\nconst USER_VALIDATION = {\n  MIN_AGE: 18,\n  MIN_SCORE: 750,\n  VALID_LEVELS: &#91;3, 4, 5],\n  VALID_STATUSES: &#91;\"active\", \"premium\"],\n};\n\nfunction validateUser(user) {\n  return isAgeValid(user.age) &amp;&amp; isScoreValid(user.score) &amp;&amp; isLevelValid(user.level) &amp;&amp; isStatusValid(user.status);\n}\n\nfunction isAgeValid(age) {\n  return age &gt;= USER_VALIDATION.MIN_AGE;\n}\n\nfunction isScoreValid(score) {\n  return score &gt;= USER_VALIDATION.MIN_SCORE;\n}\n\nfunction isLevelValid(level) {\n  return USER_VALIDATION.VALID_LEVELS.includes(level);\n}\n\nfunction isStatusValid(status) {\n  return USER_VALIDATION.VALID_STATUSES.includes(status);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 5: \uc911\ubcf5 \ucf54\ub4dc \uc81c\uac70 (DRY \uc6d0\uce59)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ubc18\ubcf5\ub418\ub294 \ucf54\ub4dc\ub97c \uacf5\ud1b5 \ud568\uc218\ub85c \ucd94\ucd9c\n\n\/\/ BEFORE: \ube44\uc2b7\ud55c \ucf54\ub4dc\uac00 \uc5ec\ub7ec \uacf3\uc5d0 \uc911\ubcf5\nfunction saveUser(userData) {\n  const timestamp = new Date().toISOString();\n  console.log(`&#91;${timestamp}] Saving user: ${userData.id}`);\n\n  if (!userData.email) {\n    throw new Error(\"Email is required\");\n  }\n\n  \/\/ DB \uc800\uc7a5 \ub85c\uc9c1\n  const result = database.save(\"users\", userData);\n\n  console.log(`&#91;${timestamp}] User saved successfully: ${userData.id}`);\n  return result;\n}\n\nfunction saveProduct(productData) {\n  const timestamp = new Date().toISOString();\n  console.log(`&#91;${timestamp}] Saving product: ${productData.id}`);\n\n  if (!productData.name) {\n    throw new Error(\"Name is required\");\n  }\n\n  \/\/ DB \uc800\uc7a5 \ub85c\uc9c1\n  const result = database.save(\"products\", productData);\n\n  console.log(`&#91;${timestamp}] Product saved successfully: ${productData.id}`);\n  return result;\n}\n\n\/\/ AFTER: \uacf5\ud1b5 \ub85c\uc9c1\uc744 \ucd94\ucd9c\nfunction saveEntity(entityType, data, requiredFields) {\n  logOperation(\"start\", entityType, data.id);\n\n  validateRequiredFields(data, requiredFields);\n\n  const result = database.save(entityType, data);\n\n  logOperation(\"success\", entityType, data.id);\n  return result;\n}\n\nfunction validateRequiredFields(data, requiredFields) {\n  for (const field of requiredFields) {\n    if (!data&#91;field]) {\n      throw new Error(`${field} is required`);\n    }\n  }\n}\n\nfunction logOperation(type, entityType, id) {\n  const timestamp = new Date().toISOString();\n  const messages = {\n    start: `&#91;${timestamp}] Saving ${entityType}: ${id}`,\n    success: `&#91;${timestamp}] ${entityType} saved successfully: ${id}`,\n  };\n  console.log(messages&#91;type]);\n}\n\n\/\/ \uc0ac\uc6a9\ubc95\nfunction saveUser(userData) {\n  return saveEntity(\"users\", userData, &#91;\"email\"]);\n}\n\nfunction saveProduct(productData) {\n  return saveEntity(\"products\", productData, &#91;\"name\"]);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5. \uac1d\uccb4\uc9c0\ud5a5 \ub9ac\ud329\ud130\ub9c1 \ud328\ud134<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 6: \ud074\ub798\uc2a4 \ucd94\ucd9c\ud558\uae30<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ud558\ub098\uc758 \ud074\ub798\uc2a4\uac00 \ub108\ubb34 \ub9ce\uc740 \ucc45\uc784\uc744 \uac00\uc9c8 \ub54c\n\n\/\/ BEFORE: \ubaa8\ub4e0 \uac83\uc744 \ub2e4 \ud558\ub294 \ud074\ub798\uc2a4\nclass User {\n  constructor(name, email) {\n    this.name = name;\n    this.email = email;\n    this.orders = &#91;];\n  }\n\n  \/\/ \uc0ac\uc6a9\uc790 \uc815\ubcf4 \uad00\ub9ac\n  updateProfile(name, email) {\n    this.name = name;\n    this.email = email;\n  }\n\n  \/\/ \uc8fc\ubb38 \uad00\ub9ac\n  addOrder(order) {\n    this.orders.push(order);\n  }\n\n  getTotalSpent() {\n    return this.orders.reduce((total, order) =&gt; total + order.amount, 0);\n  }\n\n  \/\/ \uc774\uba54\uc77c \ubc1c\uc1a1\n  sendWelcomeEmail() {\n    console.log(`Welcome email sent to ${this.email}`);\n  }\n\n  sendOrderConfirmation(order) {\n    console.log(`Order confirmation sent to ${this.email}`);\n  }\n\n  \/\/ \ud560\uc778 \uacc4\uc0b0\n  calculateDiscount() {\n    const totalSpent = this.getTotalSpent();\n    if (totalSpent &gt; 10000) return 0.1;\n    if (totalSpent &gt; 5000) return 0.05;\n    return 0;\n  }\n}\n\n\/\/ AFTER: \ucc45\uc784\ubcc4\ub85c \ud074\ub798\uc2a4 \ubd84\ub9ac\nclass User {\n  constructor(name, email) {\n    this.name = name;\n    this.email = email;\n    this.orderHistory = new OrderHistory();\n    this.emailService = new EmailService(email);\n    this.discountCalculator = new DiscountCalculator();\n  }\n\n  updateProfile(name, email) {\n    this.name = name;\n    this.email = email;\n    this.emailService.updateEmail(email);\n  }\n\n  addOrder(order) {\n    this.orderHistory.addOrder(order);\n    this.emailService.sendOrderConfirmation(order);\n  }\n\n  getTotalSpent() {\n    return this.orderHistory.getTotalAmount();\n  }\n\n  getDiscount() {\n    return this.discountCalculator.calculate(this.getTotalSpent());\n  }\n}\n\nclass OrderHistory {\n  constructor() {\n    this.orders = &#91;];\n  }\n\n  addOrder(order) {\n    this.orders.push(order);\n  }\n\n  getTotalAmount() {\n    return this.orders.reduce((total, order) =&gt; total + order.amount, 0);\n  }\n\n  getOrderCount() {\n    return this.orders.length;\n  }\n}\n\nclass EmailService {\n  constructor(email) {\n    this.email = email;\n  }\n\n  updateEmail(email) {\n    this.email = email;\n  }\n\n  sendWelcomeEmail() {\n    console.log(`Welcome email sent to ${this.email}`);\n  }\n\n  sendOrderConfirmation(order) {\n    console.log(`Order confirmation sent to ${this.email}`);\n  }\n}\n\nclass DiscountCalculator {\n  calculate(totalSpent) {\n    if (totalSpent &gt; 10000) return 0.1;\n    if (totalSpent &gt; 5000) return 0.05;\n    return 0;\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 7: \uc0c1\uc18d\uc744 \ucef4\ud3ec\uc9c0\uc158\uc73c\ub85c \ubc14\uafb8\uae30<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ubcf5\uc7a1\ud55c \uc0c1\uc18d \uad6c\uc870\ub97c \ucef4\ud3ec\uc9c0\uc158\uc73c\ub85c \uac1c\uc120\n\n\/\/ BEFORE: \uae4a\uc740 \uc0c1\uc18d \uacc4\uce35\nclass Animal {\n  eat() {\n    console.log(\"eating\");\n  }\n  sleep() {\n    console.log(\"sleeping\");\n  }\n}\n\nclass Mammal extends Animal {\n  giveBirth() {\n    console.log(\"giving birth\");\n  }\n}\n\nclass Bird extends Animal {\n  fly() {\n    console.log(\"flying\");\n  }\n  layEggs() {\n    console.log(\"laying eggs\");\n  }\n}\n\nclass FlyingMammal extends Mammal {\n  fly() {\n    console.log(\"flying\");\n  } \/\/ \uc911\ubcf5 \ucf54\ub4dc\n}\n\nclass Platypus extends Mammal {\n  layEggs() {\n    console.log(\"laying eggs\");\n  } \/\/ \uc911\ubcf5 \ucf54\ub4dc\n  swim() {\n    console.log(\"swimming\");\n  }\n}\n\n\/\/ AFTER: \ucef4\ud3ec\uc9c0\uc158\uacfc \ubbf9\uc2a4\uc778 \ud65c\uc6a9\nconst behaviors = {\n  eating: () =&gt; console.log(\"eating\"),\n  sleeping: () =&gt; console.log(\"sleeping\"),\n  flying: () =&gt; console.log(\"flying\"),\n  swimming: () =&gt; console.log(\"swimming\"),\n  givingBirth: () =&gt; console.log(\"giving birth\"),\n  layingEggs: () =&gt; console.log(\"laying eggs\"),\n};\n\nclass Animal {\n  constructor(name, behaviorList = &#91;]) {\n    this.name = name;\n    this.behaviors = new Set(behaviorList);\n\n    \/\/ \ud589\ub3d9\ub4e4\uc744 \uba54\uc11c\ub4dc\ub85c \ucd94\uac00\n    behaviorList.forEach((behavior) =&gt; {\n      if (behaviors&#91;behavior]) {\n        this&#91;behavior] = behaviors&#91;behavior];\n      }\n    });\n  }\n\n  can(behavior) {\n    return this.behaviors.has(behavior);\n  }\n}\n\n\/\/ \uc0ac\uc6a9\ubc95\nconst dog = new Animal(\"Dog\", &#91;\"eating\", \"sleeping\", \"givingBirth\"]);\nconst bird = new Animal(\"Bird\", &#91;\"eating\", \"sleeping\", \"flying\", \"layingEggs\"]);\nconst bat = new Animal(\"Bat\", &#91;\"eating\", \"sleeping\", \"flying\", \"givingBirth\"]);\nconst platypus = new Animal(\"Platypus\", &#91;\"eating\", \"sleeping\", \"swimming\", \"givingBirth\", \"layingEggs\"]);\n\n\/\/ \ub3d9\uc801\uc73c\ub85c \ud589\ub3d9 \ucd94\uac00\ub3c4 \uac00\ub2a5\nplatypus.addBehavior = function (behavior) {\n  if (behaviors&#91;behavior]) {\n    this.behaviors.add(behavior);\n    this&#91;behavior] = behaviors&#91;behavior];\n  }\n};<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6. \ud568\uc218\ud615 \ud504\ub85c\uadf8\ub798\ubc0d \uc2a4\ud0c0\uc77c \ub9ac\ud329\ud130\ub9c1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 8: \ubd88\ubcc0\uc131 \ub3c4\uc785\ud558\uae30<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \uac00\ubcc0 \uc0c1\ud0dc\ub97c \ubd88\ubcc0 \uc0c1\ud0dc\ub85c \uc804\ud658\n\n\/\/ BEFORE: \uac00\ubcc0 \uc0c1\ud0dc\ub85c \uc778\ud55c \ubd80\uc791\uc6a9\nclass ShoppingCart {\n  constructor() {\n    this.items = &#91;];\n    this.discounts = &#91;];\n  }\n\n  addItem(item) {\n    this.items.push(item); \/\/ \uc6d0\ubcf8 \ubc30\uc5f4 \uc218\uc815\n    return this;\n  }\n\n  applyDiscount(discount) {\n    this.discounts.push(discount); \/\/ \uc6d0\ubcf8 \ubc30\uc5f4 \uc218\uc815\n    return this;\n  }\n\n  removeItem(itemId) {\n    \/\/ \uc6d0\ubcf8 \ubc30\uc5f4\uc5d0\uc11c \uc9c1\uc811 \uc81c\uac70\n    this.items = this.items.filter((item) =&gt; item.id !== itemId);\n    return this;\n  }\n\n  calculateTotal() {\n    let total = this.items.reduce((sum, item) =&gt; sum + item.price, 0);\n    this.discounts.forEach((discount) =&gt; {\n      total -= discount.amount;\n    });\n    return total;\n  }\n}\n\n\/\/ AFTER: \ubd88\ubcc0\uc131\uc744 \uc720\uc9c0\ud558\ub294 \uc124\uacc4\nclass ImmutableShoppingCart {\n  constructor(items = &#91;], discounts = &#91;]) {\n    this._items = Object.freeze(&#91;...items]);\n    this._discounts = Object.freeze(&#91;...discounts]);\n  }\n\n  get items() {\n    return this._items;\n  }\n\n  get discounts() {\n    return this._discounts;\n  }\n\n  addItem(item) {\n    const newItems = &#91;...this._items, item];\n    return new ImmutableShoppingCart(newItems, this._discounts);\n  }\n\n  removeItem(itemId) {\n    const newItems = this._items.filter((item) =&gt; item.id !== itemId);\n    return new ImmutableShoppingCart(newItems, this._discounts);\n  }\n\n  applyDiscount(discount) {\n    const newDiscounts = &#91;...this._discounts, discount];\n    return new ImmutableShoppingCart(this._items, newDiscounts);\n  }\n\n  calculateTotal() {\n    const itemsTotal = this._items.reduce((sum, item) =&gt; sum + item.price, 0);\n    const discountTotal = this._discounts.reduce((sum, discount) =&gt; sum + discount.amount, 0);\n    return Math.max(0, itemsTotal - discountTotal);\n  }\n}\n\n\/\/ \uc0ac\uc6a9\ubc95\nlet cart = new ImmutableShoppingCart();\ncart = cart.addItem({ id: 1, name: \"Book\", price: 1000 });\ncart = cart.addItem({ id: 2, name: \"Pen\", price: 500 });\ncart = cart.applyDiscount({ amount: 100 });\n\nconsole.log(cart.calculateTotal()); \/\/ 1400<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 9: \uc21c\uc218 \ud568\uc218\ub85c \ubcc0\ud658\ud558\uae30<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \uc0ac\uc774\ub4dc \uc774\ud399\ud2b8\uac00 \uc788\ub294 \ud568\uc218\ub97c \uc21c\uc218 \ud568\uc218\ub85c \ubcc0\ud658\n\n\/\/ BEFORE: \uc0ac\uc774\ub4dc \uc774\ud399\ud2b8\uac00 \uc788\ub294 \ud568\uc218\ub4e4\nlet globalConfig = {\n  taxRate: 0.1,\n  currency: \"USD\",\n};\n\nfunction calculateTotalPrice(items) {\n  let total = 0;\n  for (let item of items) {\n    total += item.price;\n  }\n\n  \/\/ \uc804\uc5ed \uc0c1\ud0dc\uc5d0 \uc758\uc874\n  total += total * globalConfig.taxRate;\n\n  \/\/ \uc678\ubd80 \uc11c\ube44\uc2a4 \ud638\ucd9c (\uc0ac\uc774\ub4dc \uc774\ud399\ud2b8)\n  logToAnalytics(\"price_calculated\", total);\n\n  \/\/ \uc804\uc5ed \uc0c1\ud0dc \uc218\uc815\n  globalConfig.lastCalculation = new Date();\n\n  return total;\n}\n\nfunction logToAnalytics(event, data) {\n  \/\/ \uc678\ubd80 API \ud638\ucd9c\n  console.log(`Analytics: ${event} - ${data}`);\n}\n\n\/\/ AFTER: \uc21c\uc218 \ud568\uc218\ub4e4\ub85c \ubd84\ub9ac\nfunction calculateTotalPrice(items, config) {\n  const subtotal = calculateSubtotal(items);\n  const tax = calculateTax(subtotal, config.taxRate);\n  return subtotal + tax;\n}\n\nfunction calculateSubtotal(items) {\n  return items.reduce((total, item) =&gt; total + item.price, 0);\n}\n\nfunction calculateTax(amount, taxRate) {\n  return amount * taxRate;\n}\n\n\/\/ \uc0ac\uc774\ub4dc \uc774\ud399\ud2b8\ub294 \ubcc4\ub3c4 \ud568\uc218\ub85c \ubd84\ub9ac\nfunction logPriceCalculation(total) {\n  logToAnalytics(\"price_calculated\", total);\n}\n\nfunction updateLastCalculation(config) {\n  return {\n    ...config,\n    lastCalculation: new Date(),\n  };\n}\n\n\/\/ \uc0ac\uc6a9\ubc95 (\uc21c\uc218 \ud568\uc218 + \uc0ac\uc774\ub4dc \uc774\ud399\ud2b8 \ubd84\ub9ac)\nfunction processOrder(items, config) {\n  \/\/ \uc21c\uc218 \ud568\uc218\ub85c \uacc4\uc0b0\n  const total = calculateTotalPrice(items, config);\n\n  \/\/ \uc0ac\uc774\ub4dc \uc774\ud399\ud2b8\ub294 \uba85\uc2dc\uc801\uc73c\ub85c \uc2e4\ud589\n  logPriceCalculation(total);\n  const updatedConfig = updateLastCalculation(config);\n\n  return { total, updatedConfig };\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">7. \ube44\ub3d9\uae30 \ucf54\ub4dc \ub9ac\ud329\ud130\ub9c1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 10: \ucf5c\ubc31 \uc9c0\uc625 \ud574\uacb0\ud558\uae30<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \ucf5c\ubc31 \uc9c0\uc625\uc744 Promise\uc640 async\/await\ub85c \uac1c\uc120\n\n\/\/ BEFORE: \ucf5c\ubc31 \uc9c0\uc625\nfunction processUserOrder(userId, callback) {\n  getUser(userId, (err, user) =&gt; {\n    if (err) return callback(err);\n\n    validateUser(user, (err, isValid) =&gt; {\n      if (err) return callback(err);\n      if (!isValid) return callback(new Error(\"Invalid user\"));\n\n      getOrderHistory(userId, (err, orders) =&gt; {\n        if (err) return callback(err);\n\n        calculateDiscount(user, orders, (err, discount) =&gt; {\n          if (err) return callback(err);\n\n          createOrder(user, discount, (err, order) =&gt; {\n            if (err) return callback(err);\n\n            sendConfirmationEmail(user.email, order, (err) =&gt; {\n              if (err) return callback(err);\n              callback(null, order);\n            });\n          });\n        });\n      });\n    });\n  });\n}\n\n\/\/ AFTER: async\/await\ub85c \uae54\ub054\ud558\uac8c\nasync function processUserOrder(userId) {\n  try {\n    const user = await getUser(userId);\n\n    const isValid = await validateUser(user);\n    if (!isValid) {\n      throw new Error(\"Invalid user\");\n    }\n\n    const orders = await getOrderHistory(userId);\n    const discount = await calculateDiscount(user, orders);\n    const order = await createOrder(user, discount);\n\n    \/\/ \uc774\uba54\uc77c \ubc1c\uc1a1\uc740 \ubc31\uadf8\ub77c\uc6b4\ub4dc\uc5d0\uc11c (\ud544\uc694\uc2dc)\n    sendConfirmationEmail(user.email, order).catch(console.error);\n\n    return order;\n  } catch (error) {\n    console.error(\"Order processing failed:\", error);\n    throw error;\n  }\n}\n\n\/\/ Promise \uae30\ubc18 \ud5ec\ud37c \ud568\uc218\ub4e4\nfunction getUser(userId) {\n  return new Promise((resolve, reject) =&gt; {\n    \/\/ DB \uc870\ud68c \ub85c\uc9c1\n    setTimeout(() =&gt; resolve({ id: userId, email: \"user@example.com\" }), 100);\n  });\n}\n\nfunction validateUser(user) {\n  return new Promise((resolve) =&gt; {\n    \/\/ \uac80\uc99d \ub85c\uc9c1\n    setTimeout(() =&gt; resolve(!!user.email), 50);\n  });\n}\n\n\/\/ \ub354 \ub098\uc740 \ubc29\ubc95: \ubcd1\ub82c \ucc98\ub9ac\uac00 \uac00\ub2a5\ud55c \ubd80\ubd84 \ucd5c\uc801\ud654\nasync function processUserOrderOptimized(userId) {\n  try {\n    const user = await getUser(userId);\n\n    \/\/ \ubcd1\ub82c\ub85c \uc2e4\ud589 \uac00\ub2a5\ud55c \uc791\uc5c5\ub4e4\n    const &#91;isValid, orders] = await Promise.all(&#91;validateUser(user), getOrderHistory(userId)]);\n\n    if (!isValid) {\n      throw new Error(\"Invalid user\");\n    }\n\n    const discount = await calculateDiscount(user, orders);\n    const order = await createOrder(user, discount);\n\n    \/\/ \ubc31\uadf8\ub77c\uc6b4\ub4dc \uc791\uc5c5\n    sendConfirmationEmail(user.email, order).catch(console.error);\n\n    return order;\n  } catch (error) {\n    console.error(\"Order processing failed:\", error);\n    throw error;\n  }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">8. \uc5d0\ub7ec \ucc98\ub9ac \ub9ac\ud329\ud130\ub9c1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ud328\ud134 11: \uc5d0\ub7ec \ucc98\ub9ac \uac1c\uc120\ud558\uae30<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udd27 \uc911\ubcf5\ub418\ub294 \uc5d0\ub7ec \ucc98\ub9ac \ub85c\uc9c1\uc744 \uae54\ub054\ud558\uac8c \uc815\ub9ac\n\n\/\/ BEFORE: \uac01 \ud568\uc218\ub9c8\ub2e4 \ubc18\ubcf5\ub418\ub294 \uc5d0\ub7ec \ucc98\ub9ac\nasync function getUser(id) {\n  try {\n    const response = await fetch(`\/api\/users\/${id}`);\n    if (!response.ok) {\n      if (response.status === 404) {\n        throw new Error(\"User not found\");\n      } else if (response.status === 401) {\n        throw new Error(\"Unauthorized\");\n      } else {\n        throw new Error(\"Server error\");\n      }\n    }\n    return await response.json();\n  } catch (error) {\n    console.error(\"Error fetching user:\", error);\n    throw error;\n  }\n}\n\nasync function getOrders(userId) {\n  try {\n    const response = await fetch(`\/api\/users\/${userId}\/orders`);\n    if (!response.ok) {\n      if (response.status === 404) {\n        throw new Error(\"Orders not found\");\n      } else if (response.status === 401) {\n        throw new Error(\"Unauthorized\");\n      } else {\n        throw new Error(\"Server error\");\n      }\n    }\n    return await response.json();\n  } catch (error) {\n    console.error(\"Error fetching orders:\", error);\n    throw error;\n  }\n}\n\n\/\/ AFTER: \uacf5\ud1b5 \uc5d0\ub7ec \ucc98\ub9ac \ub85c\uc9c1 \ucd94\ucd9c\nclass APIError extends Error {\n  constructor(message, status, originalError) {\n    super(message);\n    this.name = \"APIError\";\n    this.status = status;\n    this.originalError = originalError;\n  }\n}\n\nclass APIClient {\n  async request(url, options = {}) {\n    try {\n      const response = await fetch(url, {\n        headers: {\n          \"Content-Type\": \"application\/json\",\n          ...options.headers,\n        },\n        ...options,\n      });\n\n      if (!response.ok) {\n        throw new APIError(this.getErrorMessage(response.status), response.status);\n      }\n\n      return await response.json();\n    } catch (error) {\n      if (error instanceof APIError) {\n        throw error;\n      }\n      throw new APIError(\"Network error\", 0, error);\n    }\n  }\n\n  getErrorMessage(status) {\n    const errorMessages = {\n      400: \"Bad Request\",\n      401: \"Unauthorized\",\n      403: \"Forbidden\",\n      404: \"Not Found\",\n      500: \"Internal Server Error\",\n    };\n    return errorMessages&#91;status] || \"Unknown Error\";\n  }\n\n  async get(endpoint) {\n    return this.request(endpoint);\n  }\n\n  async post(endpoint, data) {\n    return this.request(endpoint, {\n      method: \"POST\",\n      body: JSON.stringify(data),\n    });\n  }\n}\n\n\/\/ \uc0ac\uc6a9\ubc95\nconst apiClient = new APIClient();\n\nasync function getUser(id) {\n  try {\n    return await apiClient.get(`\/api\/users\/${id}`);\n  } catch (error) {\n    if (error.status === 404) {\n      return null; \/\/ \uc0ac\uc6a9\uc790 \uc5c6\uc74c\uc744 null\ub85c \ud45c\ud604\n    }\n    throw error; \/\/ \ub2e4\ub978 \uc5d0\ub7ec\ub294 \uc0c1\uc704\ub85c \uc804\ud30c\n  }\n}\n\nasync function getOrders(userId) {\n  try {\n    return await apiClient.get(`\/api\/users\/${userId}\/orders`);\n  } catch (error) {\n    if (error.status === 404) {\n      return &#91;]; \/\/ \uc8fc\ubb38 \uc5c6\uc74c\uc744 \ube48 \ubc30\uc5f4\ub85c \ud45c\ud604\n    }\n    throw error;\n  }\n}\n\n\/\/ \ub354 \uace0\uae09: Result \ud328\ud134 \uc801\uc6a9\nclass Result {\n  constructor(data, error) {\n    this.data = data;\n    this.error = error;\n  }\n\n  static success(data) {\n    return new Result(data, null);\n  }\n\n  static failure(error) {\n    return new Result(null, error);\n  }\n\n  isSuccess() {\n    return this.error === null;\n  }\n\n  isFailure() {\n    return this.error !== null;\n  }\n}\n\nasync function getUserSafe(id) {\n  try {\n    const user = await apiClient.get(`\/api\/users\/${id}`);\n    return Result.success(user);\n  } catch (error) {\n    return Result.failure(error);\n  }\n}\n\n\/\/ \uc0ac\uc6a9\ubc95\nconst userResult = await getUserSafe(123);\nif (userResult.isSuccess()) {\n  console.log(\"User:\", userResult.data);\n} else {\n  console.error(\"Error:\", userResult.error.message);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">9. \ub9ac\ud329\ud130\ub9c1 \uc2e4\uc804 \uc804\ub7b5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ub2e8\uacc4\ubcc4 \ub9ac\ud329\ud130\ub9c1 \uc811\uadfc\ubc95<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud83d\udccb \ub9ac\ud329\ud130\ub9c1 \ud504\ub85c\uc138\uc2a4\n\n1. \ud604\uc7ac \uc0c1\ud0dc \ud30c\uc545\n   \u251c\u2500\u2500 \ucf54\ub4dc \ub9ac\ubdf0 \ubc0f \ubb38\uc81c\uc810 \uc2dd\ubcc4\n   \u251c\u2500\u2500 \uae30\uc874 \ud14c\uc2a4\ud2b8 \ucf54\ub4dc \ud655\uc778\n   \u2514\u2500\u2500 \ube44\uc988\ub2c8\uc2a4 \ub85c\uc9c1 \uc774\ud574\n\n2. \ud14c\uc2a4\ud2b8 \ucee4\ubc84\ub9ac\uc9c0 \ud655\ubcf4\n   \u251c\u2500\u2500 \uae30\uc874 \uae30\ub2a5\uc5d0 \ub300\ud55c \ud14c\uc2a4\ud2b8 \uc791\uc131\n   \u251c\u2500\u2500 Edge case \ud14c\uc2a4\ud2b8 \ucd94\uac00\n   \u2514\u2500\u2500 \ub9ac\ud329\ud130\ub9c1 \uc804 \ubaa8\ub4e0 \ud14c\uc2a4\ud2b8 \ud1b5\uacfc \ud655\uc778\n\n3. \uc810\uc9c4\uc801 \uac1c\uc120\n   \u251c\u2500\u2500 \uc791\uc740 \ub2e8\uc704\ub85c \ub9ac\ud329\ud130\ub9c1\n   \u251c\u2500\u2500 \uac01 \ub2e8\uacc4\ub9c8\ub2e4 \ud14c\uc2a4\ud2b8 \uc2e4\ud589\n   \u2514\u2500\u2500 \ucee4\ubc0b \ub2e8\uc704\ub85c \uc9c4\ud589 \uc0c1\ud669 \uc800\uc7a5\n\n4. \uac80\uc99d \ubc0f \uc815\ub9ac\n   \u251c\u2500\u2500 \uc131\ub2a5 \ud14c\uc2a4\ud2b8 \uc2e4\ud589\n   \u251c\u2500\u2500 \ucf54\ub4dc \ub9ac\ubdf0 \uc694\uccad\n   \u2514\u2500\u2500 \ubb38\uc11c \uc5c5\ub370\uc774\ud2b8<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ub9ac\ud329\ud130\ub9c1 \uc6b0\uc120\uc21c\uc704 \uacb0\uc815<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83c\udfaf \uc5b4\ub5a4 \ucf54\ub4dc\ubd80\ud130 \ub9ac\ud329\ud130\ub9c1\ud560\uc9c0 \uacb0\uc815\ud558\uae30\n\nconst refactoringPriority = {\n  \/\/ \ub192\uc740 \uc6b0\uc120\uc21c\uc704 (\uc989\uc2dc \ub9ac\ud329\ud130\ub9c1)\n  high: &#91;\"\ubcf4\uc548 \ucde8\uc57d\uc810\uc774 \uc788\ub294 \ucf54\ub4dc\", \"\ubc84\uadf8\uac00 \uc790\uc8fc \ubc1c\uc0dd\ud558\ub294 \ucf54\ub4dc\", \"\uc131\ub2a5 \ubb38\uc81c\uac00 \uc788\ub294 \ucf54\ub4dc\", \"\uc0c8 \uae30\ub2a5 \ucd94\uac00\uac00 \ud544\uc694\ud55c \ubd80\ubd84\"],\n\n  \/\/ \uc911\uac04 \uc6b0\uc120\uc21c\uc704 (\uacc4\ud68d\uc801 \ub9ac\ud329\ud130\ub9c1)\n  medium: &#91;\"\ud14c\uc2a4\ud2b8\ud558\uae30 \uc5b4\ub824\uc6b4 \ucf54\ub4dc\", \"\uc911\ubcf5\uc774 \ub9ce\uc740 \ucf54\ub4dc\", \"\uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6b4 \ubcf5\uc7a1\ud55c \ucf54\ub4dc\", \"\ud655\uc7a5\uc131\uc774 \ubd80\uc871\ud55c \ucf54\ub4dc\"],\n\n  \/\/ \ub0ae\uc740 \uc6b0\uc120\uc21c\uc704 (\uc5ec\uc720\uac00 \uc788\uc744 \ub54c)\n  low: &#91;\"\ub124\uc774\ubc0d\uc774 \uba85\ud655\ud558\uc9c0 \uc54a\uc740 \ucf54\ub4dc\", \"\uc8fc\uc11d\uc774 \ubd80\uc871\ud55c \ucf54\ub4dc\", \"\uc2a4\ud0c0\uc77c \uac00\uc774\ub4dc\uc5d0 \ub9de\uc9c0 \uc54a\ub294 \ucf54\ub4dc\", \"\ub808\uac70\uc2dc \ud328\ud134\uc744 \uc0ac\uc6a9\ud558\ub294 \ucf54\ub4dc\"],\n};\n\n\/\/ \ucf54\ub4dc \ud488\uc9c8 \uce21\uc815 \uc9c0\ud45c\nfunction assessCodeQuality(file) {\n  return {\n    complexity: getCyclomaticComplexity(file),\n    testCoverage: getTestCoverage(file),\n    duplication: getDuplicationRate(file),\n    maintainabilityIndex: getMaintainabilityIndex(file),\n    bugDensity: getBugDensity(file),\n  };\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud300 \ub2e8\uc704 \ub9ac\ud329\ud130\ub9c1 \uc804\ub7b5<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>## \ud83e\udd1d \ud300 \ub9ac\ud329\ud130\ub9c1 \uac00\uc774\ub4dc\ub77c\uc778\n\n### \ub9ac\ud329\ud130\ub9c1 \uaddc\uce59\n\n1. **\ubcf4\uc774\uc2a4\uce74\uc6c3 \uaddc\uce59**: \ucf54\ub4dc\ub97c \uac74\ub4dc\ub9b4 \ub54c\ub9c8\ub2e4 \uc870\uae08\uc529 \uac1c\uc120\n2. **2\uc778 \uaddc\uce59**: \ud070 \ub9ac\ud329\ud130\ub9c1\uc740 \ucd5c\uc18c 2\uba85\uc774 \ud568\uaed8 \uc9c4\ud589\n3. **\uc2dc\uac04 \ubc15\uc2a4**: \ub9ac\ud329\ud130\ub9c1 \uc2dc\uac04\uc744 \ubbf8\ub9ac \uc815\ud574\ub450\uace0 \uc9c4\ud589\n4. **\ud53c\ucc98 \ud50c\ub798\uadf8**: \ud070 \ubcc0\uacbd\uc0ac\ud56d\uc740 \ud53c\ucc98 \ud50c\ub798\uadf8\ub85c \uc548\uc804\ud558\uac8c\n\n### \ucf54\ub4dc \ub9ac\ubdf0 \uccb4\ud06c\ub9ac\uc2a4\ud2b8\n\n- &#91; ] \uae30\uc874 \uae30\ub2a5\uc774 \uadf8\ub300\ub85c \ub3d9\uc791\ud558\ub294\uac00?\n- &#91; ] \ud14c\uc2a4\ud2b8 \ucee4\ubc84\ub9ac\uc9c0\uac00 \uc720\uc9c0\ub418\uac70\ub098 \uac1c\uc120\ub418\uc5c8\ub294\uac00?\n- &#91; ] \uc131\ub2a5\uc774 \uc800\ud558\ub418\uc9c0 \uc54a\uc558\ub294\uac00?\n- &#91; ] \ucf54\ub4dc\uac00 \ub354 \uc774\ud574\ud558\uae30 \uc26c\uc6cc\uc84c\ub294\uac00?\n- &#91; ] \uc0c8\ub85c\uc6b4 \ubc84\uadf8\ub97c \ub3c4\uc785\ud558\uc9c0 \uc54a\uc558\ub294\uac00?\n\n### \ucee4\ubba4\ub2c8\ucf00\uc774\uc158\n\n- \ub9ac\ud329\ud130\ub9c1 \uacc4\ud68d\uc744 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720\n- \uc9c4\ud589 \uc0c1\ud669\uc744 \uc8fc\uae30\uc801\uc73c\ub85c \uc5c5\ub370\uc774\ud2b8\n- \ubb38\uc81c \ubc1c\uc0dd \uc2dc \uc989\uc2dc \ud300\uc6d0\ub4e4\uc5d0\uac8c \uc54c\ub9bc\n- \uc644\ub8cc \ud6c4 \uac1c\uc120\ub41c \uc810\uc744 \ud300\uc6d0\ub4e4\uacfc \uacf5\uc720<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">10. \ub9ac\ud329\ud130\ub9c1 \ub3c4\uad6c\uc640 \uc790\ub3d9\ud654<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\uc815\uc801 \ubd84\uc11d \ub3c4\uad6c \ud65c\uc6a9<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udee0\ufe0f ESLint \uc124\uc815\uc73c\ub85c \ub9ac\ud329\ud130\ub9c1 \uac00\uc774\ub4dc\n\n\/\/ .eslintrc.js\nmodule.exports = {\n  extends: &#91;\"eslint:recommended\"],\n  rules: {\n    \/\/ \ubcf5\uc7a1\ub3c4 \uc81c\ud55c\n    complexity: &#91;\"error\", { max: 10 }],\n    \"max-depth\": &#91;\"error\", 4],\n    \"max-lines-per-function\": &#91;\"error\", { max: 50 }],\n\n    \/\/ \ub124\uc774\ubc0d \uaddc\uce59\n    camelcase: \"error\",\n    \"no-underscore-dangle\": \"error\",\n\n    \/\/ \ucf54\ub4dc \ud488\uc9c8\n    \"no-magic-numbers\": &#91;\"error\", { ignore: &#91;0, 1, -1] }],\n    \"prefer-const\": \"error\",\n    \"no-var\": \"error\",\n\n    \/\/ \ud568\uc218\ud615 \ud504\ub85c\uadf8\ub798\ubc0d \uad8c\uc7a5\n    \"prefer-arrow-callback\": \"error\",\n    \"no-loop-func\": \"error\",\n  },\n};\n\n\/\/ SonarQube \ud488\uc9c8 \uac8c\uc774\ud2b8 \uc124\uc815\nconst qualityGate = {\n  coverage: \"&gt; 80%\",\n  duplicatedLines: \"&lt; 3%\",\n  maintainabilityRating: \"A\",\n  reliabilityRating: \"A\",\n  securityRating: \"A\",\n};<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\uc790\ub3d9 \ub9ac\ud329\ud130\ub9c1 \ub3c4\uad6c<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud83e\udd16 \uc790\ub3d9 \ub9ac\ud329\ud130\ub9c1 \ub3c4\uad6c\ub4e4\n\n# 1. jscodeshift (JavaScript \ucf54\ub4dc \ubcc0\ud658)\nnpx jscodeshift -t transforms\/arrow-functions.js src\/\n\n# 2. Prettier (\ucf54\ub4dc \ud3ec\ub9e4\ud305)\nnpx prettier --write \"src\/**\/*.js\"\n\n# 3. TypeScript \ub9c8\uc774\uadf8\ub808\uc774\uc158\nnpx typescript-migrate --init\nnpx typescript-migrate --migrate\n\n# 4. \uc758\uc874\uc131 \uc5c5\ub370\uc774\ud2b8\nnpx npm-check-updates -u\nnpm install\n\n# 5. \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \ucf54\ub4dc \uc81c\uac70\nnpx unimported\nnpx depcheck<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">VS Code \ud655\uc7a5 \ub3c4\uad6c\ub4e4<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ settings.json - \ub9ac\ud329\ud130\ub9c1\uc5d0 \ub3c4\uc6c0\ub418\ub294 \uc124\uc815\n{\n    \"editor.codeActionsOnSave\": {\n        \"source.organizeImports\": true,\n        \"source.fixAll.eslint\": true\n    },\n    \"typescript.suggest.autoImports\": true,\n    \"javascript.suggest.autoImports\": true,\n    \"editor.formatOnSave\": true,\n    \"files.autoSave\": \"onFocusChange\"\n}\n\n\/\/ \ucd94\ucc9c \ud655\uc7a5 \ub3c4\uad6c\ub4e4\nconst recommendedExtensions = &#91;\n    'esbenp.prettier-vscode',      \/\/ \uc790\ub3d9 \ud3ec\ub9e4\ud305\n    'dbaeumer.vscode-eslint',      \/\/ \ub9b0\ud305\n    'formulahendry.auto-rename-tag', \/\/ HTML \ud0dc\uadf8 \uc790\ub3d9 \ub9ac\ub124\uc784\n    'bradlc.vscode-tailwindcss',   \/\/ CSS \ud074\ub798\uc2a4 \uc790\ub3d9\uc644\uc131\n    'ms-vscode.vscode-typescript-next' \/\/ \uace0\uae09 TypeScript \uc9c0\uc6d0\n];<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">11. \uc131\uacfc \uce21\uc815\uacfc \uc9c0\uc18d\uc801 \uac1c\uc120<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ub9ac\ud329\ud130\ub9c1 \ud6a8\uacfc \uce21\uc815<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud83d\udcca \ub9ac\ud329\ud130\ub9c1 \uc804\ud6c4 \ube44\uad50 \uc9c0\ud45c\n\nconst refactoringMetrics = {\n  before: {\n    cyclomaticComplexity: 15, \/\/ \ubcf5\uc7a1\ub3c4\n    linesOfCode: 1200, \/\/ \ucf54\ub4dc \ub77c\uc778 \uc218\n    testCoverage: 45, \/\/ \ud14c\uc2a4\ud2b8 \ucee4\ubc84\ub9ac\uc9c0 (%)\n    bugCount: 23, \/\/ \ubc84\uadf8 \uc218 (\uc6d4\ubcc4)\n    deploymentFrequency: 2, \/\/ \ubc30\ud3ec \ube48\ub3c4 (\uc6d4\ubcc4)\n    developmentVelocity: 18, \/\/ \uac1c\ubc1c \uc18d\ub3c4 (\uc2a4\ud1a0\ub9ac \ud3ec\uc778\ud2b8\/\uc2a4\ud504\ub9b0\ud2b8)\n  },\n\n  after: {\n    cyclomaticComplexity: 8, \/\/ 47% \uac10\uc18c\n    linesOfCode: 800, \/\/ 33% \uac10\uc18c\n    testCoverage: 82, \/\/ 82% \uc99d\uac00\n    bugCount: 7, \/\/ 70% \uac10\uc18c\n    deploymentFrequency: 8, \/\/ 300% \uc99d\uac00\n    developmentVelocity: 28, \/\/ 56% \uc99d\uac00\n  },\n};\n\n\/\/ ROI \uacc4\uc0b0\nfunction calculateRefactoringROI(metrics) {\n  const timeSaved = (metrics.before.bugCount - metrics.after.bugCount) * 2; \/\/ \ubc84\uadf8\ub2f9 2\uc2dc\uac04 \uc808\uc57d\n  const velocityGain = metrics.after.developmentVelocity - metrics.before.developmentVelocity;\n  const refactoringCost = 40; \/\/ \ub9ac\ud329\ud130\ub9c1\uc5d0 \ud22c\uc785\ub41c \uc2dc\uac04\n\n  const roi = ((timeSaved + velocityGain) \/ refactoringCost - 1) * 100;\n  return Math.round(roi);\n}\n\nconsole.log(`\ub9ac\ud329\ud130\ub9c1 ROI: ${calculateRefactoringROI(refactoringMetrics)}%`);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\uc9c0\uc18d\uc801\uc778 \uac1c\uc120 \ud504\ub85c\uc138\uc2a4<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud83d\udd04 \uc9c0\uc18d\uc801 \ub9ac\ud329\ud130\ub9c1 \uc6cc\ud06c\ud50c\ub85c\uc6b0\n\n# \uc8fc\uac04 \ucf54\ub4dc \ud488\uc9c8 \uccb4\ud06c\nnpm run lint\nnpm run test:coverage\nnpm run analyze:complexity\n\n# \uc6d4\uac04 \uae30\uc220 \ubd80\ucc44 \ub9ac\ubdf0\ngit log --since=\"1 month ago\" --grep=\"fix|hack|todo\"\nnpm audit\nnpx license-checker\n\n# \ubd84\uae30\ubcc4 \uc544\ud0a4\ud14d\ucc98 \ub9ac\ubdf0\nnpm run bundle-analyzer\nnpx madge --circular src\/\nnpx dependency-cruiser src<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\ub9c8\uce58\uba70: \ub9ac\ud329\ud130\ub9c1\uc740 \ub9c8\ub77c\ud1a4\uc774\ub2e4<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ub9ac\ud329\ud130\ub9c1 \uc131\uacf5\uc744 \uc704\ud55c \ud575\uc2ec \uc6d0\uce59<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>## \ud83c\udfaf \ub9ac\ud329\ud130\ub9c1 \uc131\uacf5\uc758 \ube44\ubc00\n\n### 1. \uc791\uac8c, \uc790\uc8fc, \uafb8\uc900\ud788\n\n- \ub9e4\uc77c \uc870\uae08\uc529 \uac1c\uc120\ud558\ub294 \uc2b5\uad00\n- \ud070 \ubcc0\uacbd\ubcf4\ub2e4\ub294 \uc791\uc740 \uac1c\uc120\uc758 \ub204\uc801\n- \uc644\ubcbd\ud568\ubcf4\ub2e4\ub294 \uc9c0\uc18d\uac00\ub2a5\uc131 \ucd94\uad6c\n\n### 2. \ud14c\uc2a4\ud2b8\ub294 \uc548\uc804\ub9dd\n\n- \ub9ac\ud329\ud130\ub9c1 \uc804 \ubc18\ub4dc\uc2dc \ud14c\uc2a4\ud2b8 \ucf54\ub4dc \uc791\uc131\n- \ud14c\uc2a4\ud2b8 \uc5c6\ub294 \ub9ac\ud329\ud130\ub9c1\uc740 \ub3c4\ubc15\n- \uc790\ub3d9\ud654\ub41c \ud14c\uc2a4\ud2b8\ub85c \uc2e0\ub8b0\uc131 \ud655\ubcf4\n\n### 3. \ud300\uacfc \ud568\uaed8\n\n- \ud63c\uc790\ub9cc\uc758 \ub9ac\ud329\ud130\ub9c1\uc740 \ub3c5\uc120\n- \ucf54\ub4dc \ub9ac\ubdf0\ub97c \ud1b5\ud55c \uc9c0\uc2dd \uacf5\uc720\n- \ud300 \uc804\uccb4\uc758 \ucf54\ub4dc \ud488\uc9c8 \uc758\uc2dd \ud5a5\uc0c1\n\n### 4. \ube44\uc988\ub2c8\uc2a4 \uac00\uce58 \uc6b0\uc120\n\n- \uae30\uc220\uc801 \uc644\ubcbd\ud568\ubcf4\ub2e4\ub294 \uc2e4\uc6a9\uc131\n- \uc0ac\uc6a9\uc790 \uac00\uce58\ub97c \ud574\uce58\uc9c0 \uc54a\ub294 \ubc94\uc704\uc5d0\uc11c\n- \uac1c\ubc1c \uc0dd\uc0b0\uc131 \ud5a5\uc0c1\uc774 \ucd5c\uc885 \ubaa9\ud45c<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ub2e8\uacc4\ubcc4 \uc131\uc7a5 \ub85c\ub4dc\ub9f5<\/h3>\n\n\n\n<p><strong>\ucd08\uae09 (1-3\uac1c\uc6d4)<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[x] \ud568\uc218 \ucd94\ucd9c\ud558\uae30, \ubcc0\uc218 \ucd94\ucd9c\ud558\uae30 \uc5f0\uc2b5<\/li>\n\n\n\n<li>[x] \ub9e4\uc9c1 \ub118\ubc84\/\ubb38\uc790\uc5f4 \uc0c1\uc218\ud654<\/li>\n\n\n\n<li>[x] \uac04\ub2e8\ud55c \uc870\uac74\ubb38 \uac1c\uc120<\/li>\n\n\n\n<li>[x] \uae30\ubcf8 \ud14c\uc2a4\ud2b8 \ucf54\ub4dc \uc791\uc131<\/li>\n<\/ul>\n\n\n\n<p><strong>\uc911\uae09 (3-6\uac1c\uc6d4)<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[x] \ud074\ub798\uc2a4\uc640 \ubaa8\ub4c8 \ub2e8\uc704 \ub9ac\ud329\ud130\ub9c1<\/li>\n\n\n\n<li>[x] \ub514\uc790\uc778 \ud328\ud134 \uc801\uc6a9<\/li>\n\n\n\n<li>[x] \ube44\ub3d9\uae30 \ucf54\ub4dc \uac1c\uc120<\/li>\n\n\n\n<li>[x] \uc131\ub2a5 \ucd5c\uc801\ud654<\/li>\n<\/ul>\n\n\n\n<p><strong>\uace0\uae09 (6\uac1c\uc6d4+)<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[x] \uc544\ud0a4\ud14d\ucc98 \uc218\uc900 \ub9ac\ud329\ud130\ub9c1<\/li>\n\n\n\n<li>[x] \ub808\uac70\uc2dc \uc2dc\uc2a4\ud15c \ud604\ub300\ud654<\/li>\n\n\n\n<li>[x] \ud300 \ub9ac\ud329\ud130\ub9c1 \ud504\ub85c\uc138\uc2a4 \uad6c\ucd95<\/li>\n\n\n\n<li>[x] \uc790\ub3d9\ud654 \ub3c4\uad6c \uad6c\ucd95<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\uc2e4\ubb34\uc5d0\uc11c \ubc14\ub85c \uc801\uc6a9\ud560 \uc218 \uc788\ub294 \uccb4\ud06c\ub9ac\uc2a4\ud2b8<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>## \ud83d\udccb \uc77c\uc77c \ub9ac\ud329\ud130\ub9c1 \uccb4\ud06c\ub9ac\uc2a4\ud2b8\n\n### \ucf54\ub4dc \uc791\uc131 \uc2dc\n\n- &#91; ] \ud568\uc218\uac00 \ud55c \uac00\uc9c0 \uc77c\ub9cc \ud558\ub294\uac00?\n- &#91; ] \ubcc0\uc218\uba85\uc774 \uc758\ub3c4\ub97c \uba85\ud655\ud558\uac8c \ud45c\ud604\ud558\ub294\uac00?\n- &#91; ] \uc911\ubcf5\ub41c \ucf54\ub4dc\uac00 \uc5c6\ub294\uac00?\n- &#91; ] \ubcf5\uc7a1\ud55c \uc870\uac74\ubb38\uc744 \uac04\uc18c\ud654\ud560 \uc218 \uc788\ub294\uac00?\n\n### \ucf54\ub4dc \ub9ac\ubdf0 \uc2dc\n\n- &#91; ] \uac00\ub3c5\uc131\uc774 \uc88b\uc740\uac00?\n- &#91; ] \ud14c\uc2a4\ud2b8\ud558\uae30 \uc26c\uc6b4 \uad6c\uc870\uc778\uac00?\n- &#91; ] \ud655\uc7a5\ud558\uae30 \uc26c\uc6b4 \uc124\uacc4\uc778\uac00?\n- &#91; ] \uc131\ub2a5\uc0c1 \ubb38\uc81c\ub294 \uc5c6\ub294\uac00?\n\n### \uc8fc\uac04 \uc810\uac80\n\n- &#91; ] \ucf54\ub4dc \ubcf5\uc7a1\ub3c4 \uc9c0\ud45c \ud655\uc778\n- &#91; ] \ud14c\uc2a4\ud2b8 \ucee4\ubc84\ub9ac\uc9c0 \uc810\uac80\n- &#91; ] \uae30\uc220 \ubd80\ucc44 \ubaa9\ub85d \uc5c5\ub370\uc774\ud2b8\n- &#91; ] \ub9ac\ud329\ud130\ub9c1 \uc6b0\uc120\uc21c\uc704 \uc7ac\uc815\ub82c<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ub9c8\uc9c0\ub9c9 \uc870\uc5b8<\/h3>\n\n\n\n<p><strong>\ub9ac\ud329\ud130\ub9c1\uc740 \ucf54\ub4dc\ub97c \uc608\uc058\uac8c \ub9cc\ub4dc\ub294 \uac83\uc774 \uc544\ub2d9\ub2c8\ub2e4.<\/strong> \ub354 \ub098\uc740 \uc18c\ud504\ud2b8\uc6e8\uc5b4\ub97c \ub354 \ube60\ub974\uac8c \ub9cc\ub4e4\uae30 \uc704\ud55c <strong>\uc804\ub7b5\uc801 \ud22c\uc790<\/strong>\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<p>&#8220;\uc644\ubcbd\ud55c \ucf54\ub4dc&#8221;\ub97c \ucd94\uad6c\ud558\uae30\ubcf4\ub2e4\ub294 <strong>&#8220;\uc9c0\uc18d\uc801\uc73c\ub85c \uac1c\uc120 \uac00\ub2a5\ud55c \ucf54\ub4dc&#8221;<\/strong>\ub97c \ub9cc\ub4dc\ub294 \uac83\uc774 \uc911\uc694\ud574\uc694. \ub9e4\uc77c \uc870\uae08\uc529, \uafb8\uc900\ud788, \ud300\uc6d0\ub4e4\uacfc \ud568\uaed8 \uac1c\uc120\ud574 \ub098\uac00\ub2e4 \ubcf4\uba74 \uc5b4\ub290\uc0c8 \ub180\ub77c\uc6b4 \ubcc0\ud654\ub97c \uacbd\ud5d8\ud558\uac8c \ub420 \uac70\uc608\uc694.<\/p>\n\n\n\n<p>\uac00\uc7a5 \uc911\uc694\ud55c \uac83\uc740 <strong>\uc2e4\ud589<\/strong>\uc785\ub2c8\ub2e4. \uc624\ub298 \ub2f9\uc7a5 \uc791\uc131\ud558\uace0 \uc788\ub294 \ucf54\ub4dc\uc5d0\uc11c \ud558\ub098\uc758 \ud568\uc218\ub77c\ub3c4 \ucd94\ucd9c\ud574\ubcf4\uc138\uc694. \ubcc0\uc218\uba85 \ud558\ub098\ub77c\ub3c4 \ub354 \uba85\ud655\ud558\uac8c \ubc14\uafd4\ubcf4\uc138\uc694. \uc791\uc740 \uc2dc\uc791\uc774 \ud070 \ubcc0\ud654\uc758 \ucd9c\ubc1c\uc810\uc774 \ub429\ub2c8\ub2e4! \ud83d\ude80<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><em>\ub2e4\uc74c\uc5d0\ub294 &#8220;Clean Code \uc2e4\uc804 \uac00\uc774\ub4dc: \uc77d\uae30 \uc26c\uc6b4 \ucf54\ub4dc \uc791\uc131\ubc95&#8221;\uc73c\ub85c \ub354 \uae4a\uc774 \uc788\ub294 \ucf54\ub4dc \ud488\uc9c8 \ud5a5\uc0c1 \ubc29\ubc95\uc744 \ub2e4\ub904\ubcf4\uaca0\uc2b5\ub2c8\ub2e4. \uae30\ub300\ud574 \uc8fc\uc138\uc694!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uc548\ub155\ud558\uc138\uc694, \uc131\uc7a5\ud558\ub294 \uac1c\ubc1c\uc790 \uc5ec\ub7ec\ubd84! &#8220;\uc774 \ucf54\ub4dc \ub204\uac00 \uc9f0\uc5b4?&#8221; \ud83d\ude31 \uc2e4\ubb34\uc5d0\uc11c \uac00\uc7a5 \ub9ce\uc774 \ub4e3\ub294 \ub9d0 \uc911 \ud558\ub098\uc785\ub2c8\ub2e4. \ud558\uc9c0\ub9cc \ub180\ub78d\uac8c\ub3c4 6\uac1c\uc6d4 \uc804 \ub0b4\uac00 \uc9e0 \ucf54\ub4dc\uc77c \uac00\ub2a5\uc131\uc774 \ub192\uc8e0! \ucf54\ub4dc\ub294 \uc0b4\uc544\uc788\ub294 \uc0dd\ubb3c\ucc98\ub7fc \uacc4\uc18d \uc131\uc7a5\ud558\uace0 \ubcc0\ud654\ud574\uc57c \ud569\ub2c8\ub2e4. \uc624\ub298\uc740 \uc81c\uac00 \uc2e4\ubb34\uc5d0\uc11c \uacaa\uc740 \ub2e4\uc591\ud55c \uc0c1\ud669\ub4e4\uc744 \ud1b5\ud574 \ubc30\uc6b4 \ub9ac\ud329\ud130\ub9c1\uc758 \ubaa8\ub4e0 \uac83\uc744 \uc815\ub9ac\ud574 \ub4dc\ub9ac\uaca0\uc2b5\ub2c8\ub2e4. &#8220;\ub9ac\ud329\ud130\ub9c1\uc740 \uc704\ud5d8\ud574&#8221;\ub77c\uace0 \uc0dd\uac01\ud558\uc168\ub2e4\uba74, \uc774 \uae00\uc744 \uc77d\uace0 \ub098\uba74 &#8220;\ub9ac\ud329\ud130\ub9c1\uc740 \ud544\uc218\uc57c&#8221;\ub85c \uc0dd\uac01\uc774 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[41],"tags":[93,92],"class_list":["post-36","post","type-post","status-publish","format-standard","hentry","category-computer-science","tag-refactoring","tag-92"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/36","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=36"}],"version-history":[{"count":3,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/36\/revisions"}],"predecessor-version":[{"id":73,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/36\/revisions\/73"}],"wp:attachment":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=36"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=36"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=36"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}