ํจ๊ณผ์ ์ธ ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฒ์ ํตํด ํ์ด์ฌ ์ฝ๋์ ์ ์ง๋ณด์์ฑ, ๊ฐ๋ ์ฑ, ์ฑ๋ฅ์ ํฅ์์ํค์ธ์. ์ฝ๋ ํ์ง์ ๊ฐ์ ํ๊ธฐ ์ํ ์ค์ฉ์ ์ธ ์ ๋ต๊ณผ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐฐ์๋๋ค.
ํ์ด์ฌ ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฒ: ์ฝ๋ ํ์ง ๊ฐ์ ์ ์ํ ์ข ํฉ ๊ฐ์ด๋
๋์์์ด ์งํํ๋ ์ํํธ์จ์ด ๊ฐ๋ฐ ํ๊ฒฝ์์ ๊น๋ํ๊ณ ํจ์จ์ ์ด๋ฉฐ ์ดํดํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ์ ์งํ๋ ๊ฒ์ ๋งค์ฐ ์ค์ํฉ๋๋ค. ๊ฐ๋ ์ฑ์ผ๋ก ์ ์๋ ค์ง ํ์ด์ฌ๋ ์ ์คํ๊ฒ ๊ด๋ฆฌํ์ง ์์ผ๋ฉด ์ฝ๋ ์ค๋ฉ๊ณผ ๊ธฐ์ ๋ถ์ฑ์ ๋น ์ง ์ ์์ต๋๋ค. ๋ฆฌํฉํ ๋ง์ ๊ธฐ์กด ์ปดํจํฐ ์ฝ๋๋ฅผ ์ธ๋ถ ๋์์ ๋ณ๊ฒฝํ์ง ์๊ณ ์ฌ๊ตฌ์ฑํ๋ ๊ณผ์ ์ ๋๋ค. ๋ณธ์ง์ ์ผ๋ก ์ฝ๋๋ฅผ ์์์ํค์ง ์๊ณ ์ ๋ฆฌํ๋ ๊ฒ์ ๋๋ค. ์ด ๊ฐ์ด๋๋ ๋ค์ํ ํ์ด์ฌ ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฒ์ ํ์ํ๋ฉฐ, ์ฝ๋ ํ์ง์ ํฅ์์ํค๊ธฐ ์ํ ์ค์ฉ์ ์ธ ์์์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํ์ด์ฌ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํด์ผ ํ๋ ์ด์ ?
๋ฆฌํฉํ ๋ง์ ๋ค์๊ณผ ๊ฐ์ ๋ค์ํ ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ๊ฐ๋ ์ฑ ํฅ์: ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ๊ณ ์ ์ง๋ณด์ํ ์ ์๊ฒ ํฉ๋๋ค.
- ๋ณต์ก์ฑ ๊ฐ์: ๋ณต์กํ ๋ก์ง์ ๋จ์ํํ์ฌ ์ค๋ฅ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ ์ค์ ๋๋ค.
- ์ ์ง๋ณด์์ฑ ๊ฐํ: ์ฝ๋ ์์ ๋ฐ ํ์ฅ์ ์ฉ์ดํ๊ฒ ํฉ๋๋ค.
- ์ฑ๋ฅ ํฅ์: ์ฝ๋ ์คํ ์๋๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค.
- ๊ธฐ์ ๋ถ์ฑ ๊ฐ์: ์ ์ง๋ณด์ํ๊ฑฐ๋ ํ์ฅํ๊ธฐ ์ด๋ ค์ด ์ฝ๋์ ์ถ์ ์ ๋ฐฉ์งํฉ๋๋ค.
- ๋ ๋์ ์ค๊ณ: ๋ ๊ฒฌ๊ณ ํ๊ณ ์ ์ฐํ ์ฝ๋ ์ํคํ ์ฒ๋ก ์ด์ด์ง๋๋ค.
๋ฆฌํฉํ ๋ง์ ๋ฌด์ํ๋ฉด ์ดํดํ๊ธฐ ์ด๋ ต๊ณ , ์์ ํ๊ธฐ ์ด๋ ค์ฐ๋ฉฐ, ํ ์คํธํ๊ธฐ ์ด๋ ค์ด ์ฝ๋๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ ๊ฐ๋ฐ ์๊ฐ์ ํฌ๊ฒ ๋๋ฆฌ๊ณ ๋ฒ๊ทธ ๋ฐ์ ์ํ์ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค.
์ธ์ ๋ฆฌํฉํ ๋งํด์ผ ํ๋๊ฐ?
์ธ์ ๋ฆฌํฉํ ๋งํด์ผ ํ๋์ง ์๋ ๊ฒ์ ์ค์ํฉ๋๋ค. ๋ค์์ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ์๋๋ฆฌ์ค์ ๋๋ค:
- ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ์ : ๊ธฐ์กด ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ๋ฉด ์๋ก์ด ๊ธฐ๋ฅ์ ๋ ์ฝ๊ฒ ํตํฉํ ์ ์์ต๋๋ค.
- ๋ฒ๊ทธ ์์ ํ: ์ฃผ๋ณ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ๋ฉด ์ ์ฌํ ๋ฒ๊ทธ๊ฐ ์ฌ๋ฐํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
- ์ฝ๋ ๊ฒํ ์ค: ๊ฐ์ ํ ์ ์๋ ์์ญ์ ์๋ณํ๊ณ ๋ฆฌํฉํ ๋งํฉ๋๋ค.
- "์ฝ๋ ์ค๋ฉ"์ ๋ฐ๊ฒฌํ์ ๋: ์ฝ๋ ์ค๋ฉ์ ์ฝ๋์ ์ ์ฌ์ ์ธ ๋ฌธ์ ์ ์ ๋ํ๋ด๋ ์งํ์ ๋๋ค.
- ์ ๊ธฐ์ ์ธ ๋ฆฌํฉํ ๋ง ์ผ์ : ๋ฆฌํฉํ ๋ง์ ๊ฐ๋ฐ ํ๋ก์ธ์ค์ ์ ๊ธฐ์ ์ธ ํ๋์ผ๋ก ํตํฉํฉ๋๋ค.
์ฝ๋ ์ค๋ฉ ์๋ณํ๊ธฐ
์ฝ๋ ์ค๋ฉ์ ์ผ๋ฐ์ ์ผ๋ก ์์คํ ์ ๋ ๊น์ ๋ฌธ์ ์ ํด๋นํ๋ ํ๋ฉด์ ์ธ ์งํ์ ๋๋ค. ํญ์ ๋ฌธ์ ์ ์ ๋ํ๋ด๋ ๊ฒ์ ์๋์ง๋ง, ์ข ์ข ์ถ๊ฐ ์กฐ์ฌ๊ฐ ํ์ํฉ๋๋ค.
์ผ๋ฐ์ ์ธ ํ์ด์ฌ ์ฝ๋ ์ค๋ฉ:
- ์ค๋ณต ์ฝ๋ (Duplicated Code): ์ฌ๋ฌ ๊ณณ์ ๋์ผํ๊ฑฐ๋ ๋งค์ฐ ์ ์ฌํ ์ฝ๋๊ฐ ๋ํ๋๋ ๊ฒฝ์ฐ.
- ๊ธด ๋ฉ์๋/ํจ์ (Long Method/Function): ์ง๋์น๊ฒ ๊ธธ๊ณ ๋ณต์กํ ๋ฉ์๋ ๋๋ ํจ์.
- ํฐ ํด๋์ค (Large Class): ๋๋ฌด ๋ง์ ์ฑ ์์ ๊ฐ์ง ํด๋์ค.
- ๊ธด ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก (Long Parameter List): ๋๋ฌด ๋ง์ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ง ๋ฉ์๋ ๋๋ ํจ์.
- ๋ฐ์ดํฐ ๋ฉ์ด๋ฆฌ (Data Clumps): ์์ฃผ ํจ๊ป ๋ํ๋๋ ๋ฐ์ดํฐ ๊ทธ๋ฃน.
- ์์ ํ์ ์ง์ฐฉ (Primitive Obsession): ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋์ ์์ ๋ฐ์ดํฐ ํ์ ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ.
- ์ค์์น ๋ฌธ (Switch Statements): ๊ธธ๊ฒ ์ฐ๊ฒฐ๋ if/elif/else ๋ฌธ ๋๋ switch ๋ฌธ.
- ์ฐํ์ด ์์ (Shotgun Surgery): ํ๋์ ๋ณ๊ฒฝ ์ฌํญ์ด ์ฌ๋ฌ ๋ค๋ฅธ ํด๋์ค์ ๋ง์ ์์ ๋ณ๊ฒฝ ์ฌํญ์ ์๊ตฌํ๋ ๊ฒฝ์ฐ.
- ๋ถ๊ธฐ ๋ณ๊ฒฝ (Divergent Change): ํด๋์ค๊ฐ ๋ค๋ฅธ ์ด์ ๋ก ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ๊ณตํต์ ์ผ๋ก ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ.
- ๊ธฐ๋ฅ ํธ์ (Feature Envy): ๋ฉ์๋๊ฐ ์์ ์ ๋ฐ์ดํฐ๋ณด๋ค ๋ค๋ฅธ ๊ฐ์ฒด์ ๋ฐ์ดํฐ์ ๋ ๋ง์ด ์ ๊ทผํ๋ ๊ฒฝ์ฐ.
- ๋ฉ์์ง ์ฒด์ธ (Message Chains): ํด๋ผ์ด์ธํธ๊ฐ ํ ๊ฐ์ฒด์๊ฒ ๋ค๋ฅธ ๊ฐ์ฒด์๊ฒ ๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์์ฒญํ๋๋ก ํ๋ ๊ฒฝ์ฐ...
ํ์ด์ฌ ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฒ: ์ค์ฉ ๊ฐ์ด๋
์ด ์น์ ์์๋ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ํ์ด์ฌ ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฒ์ ์ค์ฉ์ ์ธ ์์์ ํจ๊ป ์์ธํ ์ค๋ช ํฉ๋๋ค.
1. ๋ฉ์๋/ํจ์ ์ถ์ถ (Extract Method/Function)
์ด ๊ธฐ๋ฒ์ ๋ฉ์๋ ๋๋ ํจ์ ๋ด์ ์ฝ๋ ๋ธ๋ก์ ์๋กญ๊ณ ๋ณ๊ฐ์ ๋ฉ์๋ ๋๋ ํจ์๋ก ์ฎ๊ธฐ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ด๋ ์๋ ๋ฉ์๋์ ๋ณต์ก์ฑ์ ์ค์ด๊ณ ์ถ์ถ๋ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค.
์์:
def print_invoice(customer, details):
print("***********************")
print(f"Customer: {customer}")
print("***********************")
total_amount = 0
for order in details["orders"]:
total_amount += order["amount"]
print(f"Amount is : {total_amount}")
if total_amount > 1000:
print("You earned a discount!")
๋ฆฌํฉํ ๋ง ํ:
def print_header(customer):
print("***********************")
print(f"Customer: {customer}")
print("***********************")
def calculate_total(details):
total_amount = 0
for order in details["orders"]:
total_amount += order["amount"]
return total_amount
def print_invoice(customer, details):
print_header(customer)
total_amount = calculate_total(details)
print(f"Amount is : {total_amount}")
if total_amount > 1000:
print("You earned a discount!")
2. ํด๋์ค ์ถ์ถ (Extract Class)
ํด๋์ค๊ฐ ๋๋ฌด ๋ง์ ์ฑ ์์ ๊ฐ์ง ๋, ๊ทธ ์ค ์ผ๋ถ๋ฅผ ์๋ก์ด ํด๋์ค๋ก ์ถ์ถํฉ๋๋ค. ์ด๋ ๋จ์ผ ์ฑ ์ ์์น(Single Responsibility Principle)์ ์ด์งํฉ๋๋ค.
์์:
class Person:
def __init__(self, name, phone_number, office_area_code, office_number):
self.name = name
self.phone_number = phone_number
self.office_area_code = office_area_code
self.office_number = office_number
def get_name(self):
return self.name
def get_phone_number(self):
return f"({self.office_area_code}) {self.office_number}"
๋ฆฌํฉํ ๋ง ํ:
class PhoneNumber:
def __init__(self, area_code, number):
self.area_code = area_code
self.number = number
def get_phone_number(self):
return f"({self.area_code}) {self.number}"
class Person:
def __init__(self, name, phone_number):
self.name = name
self.phone_number = phone_number
def get_name(self):
return self.name
3. ๋ฉ์๋/ํจ์ ์ธ๋ผ์ธํ (Inline Method/Function)
์ด๋ ๋ฉ์๋ ์ถ์ถ(Extract Method)์ ๋ฐ๋์ ๋๋ค. ๋ฉ์๋์ ๋ณธ๋ฌธ์ด ์ด๋ฆ๋งํผ ๋ช ํํ๋ค๋ฉด, ํด๋น ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋ถ๋ถ์ ๋ฉ์๋ ๋ด์ฉ์ผ๋ก ๋์ฒดํ์ฌ ์ธ๋ผ์ธํํ ์ ์์ต๋๋ค.
์์:
def get_rating(driver):
return more_than_five_late_deliveries(driver) ? 2 : 1
def more_than_five_late_deliveries(driver):
return driver.number_of_late_deliveries > 5
๋ฆฌํฉํ ๋ง ํ:
def get_rating(driver):
return driver.number_of_late_deliveries > 5 ? 2 : 1
4. ์์ ๋ณ์๋ฅผ ์ง์๋ก ๋์ฒด (Replace Temp with Query)
ํํ์์ ๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ๋ ์์ ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๋์ , ํํ์์ ๋ฉ์๋๋ก ์ถ์ถํฉ๋๋ค. ์ด๋ ์ฝ๋ ์ค๋ณต์ ํผํ๊ณ ๊ฐ๋ ์ฑ์ ํฅ์์ํต๋๋ค.
์์:
def get_price(order):
base_price = order.quantity * order.item_price
discount_factor = 0.98 if base_price > 1000 else 0.95
return base_price * discount_factor
๋ฆฌํฉํ ๋ง ํ:
def get_price(order):
return base_price(order) * discount_factor(order)
def base_price(order):
return order.quantity * order.item_price
def discount_factor(order):
return 0.98 if base_price(order) > 1000 else 0.95
5. ๋งค๊ฐ๋ณ์ ๊ฐ์ฒด ๋์ (Introduce Parameter Object)
์์ฃผ ํจ๊ป ๋ํ๋๋ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก์ด ๊ธธ๋ค๋ฉด, ์ด๋ค์ ์บก์ํํ๋ ๋งค๊ฐ๋ณ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค. ์ด๋ ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก์ ๊ธธ์ด๋ฅผ ์ค์ด๊ณ ์ฝ๋ ๊ตฌ์ฑ์ ๊ฐ์ ํฉ๋๋ค.
์์:
def calculate_total(width, height, depth, weight, shipping_method):
# Calculation logic
pass
๋ฆฌํฉํ ๋ง ํ:
class ShippingDetails:
def __init__(self, width, height, depth, weight, shipping_method):
self.width = width
self.height = height
self.depth = depth
self.weight = weight
self.shipping_method = shipping_method
def calculate_total(shipping_details):
# Calculation logic using shipping_details attributes
pass
6. ์กฐ๊ฑด๋ฌธ์ ๋คํ์ฑ์ผ๋ก ๋์ฒด (Replace Conditional with Polymorphism)
๊ฐ์ฒด ์ ํ์ ๋ฐ๋ผ ๋์์ ์ ํํ๋ ๋ณต์กํ ์กฐ๊ฑด๋ฌธ์ด ์์ ๋, ๋คํ์ฑ(polymorphism)์ ์ฌ์ฉํ์ฌ ๋์์ ํ์ ํด๋์ค์ ์์ํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค. ์ด๋ ์ฝ๋ ๊ตฌ์ฑ์ ๊ฐ์ ํ๊ณ ์๋ก์ด ์ ํ์ ์ถ๊ฐํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
์์:
def calculate_bonus(employee):
if employee.employee_type == "SALES":
return employee.sales * 0.1
elif employee.employee_type == "ENGINEER":
return employee.projects_completed * 100
elif employee.employee_type == "MANAGER":
return 1000
else:
return 0
๋ฆฌํฉํ ๋ง ํ:
class Employee:
def calculate_bonus(self):
return 0
class SalesEmployee(Employee):
def __init__(self, sales):
self.sales = sales
def calculate_bonus(self):
return self.sales * 0.1
class EngineerEmployee(Employee):
def __init__(self, projects_completed):
self.projects_completed = projects_completed
def calculate_bonus(self):
return self.projects_completed * 100
class ManagerEmployee(Employee):
def calculate_bonus(self):
return 1000
7. ์กฐ๊ฑด๋ฌธ ๋ถํด (Decompose Conditional)
๋ฉ์๋ ์ถ์ถ(Extract Method)๊ณผ ์ ์ฌํ๊ฒ, ์ด๋ ๋ณต์กํ ์กฐ๊ฑด๋ฌธ์ ๋ ์๊ณ ๊ด๋ฆฌํ๊ธฐ ์ฌ์ด ๋ฉ์๋๋ก ๋ถํดํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์ด๋ ๊ฐ๋ ์ฑ์ ํฅ์์ํค๊ณ ์กฐ๊ฑด๋ฌธ์ ๋ ผ๋ฆฌ๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ๊ฒ ํฉ๋๋ค.
์์:
if (platform.upper().index("MAC") > -1) and (browser.upper().index("IE") > -1) and was_initialized() and resize > MAX_RESIZE:
# Do something
pass
๋ฆฌํฉํ ๋ง ํ:
def is_mac_os():
return platform.upper().index("MAC") > -1
def is_ie_browser():
return browser.upper().index("IE") > -1
if is_mac_os() and is_ie_browser() and was_initialized() and resize > MAX_RESIZE:
# Do something
pass
8. ๋งค์ง ๋๋ฒ๋ฅผ ์ฌ๋ณผ๋ฆญ ์์๋ก ๋์ฒด (Replace Magic Number with Symbolic Constant)
๋ฆฌํฐ๋ด ์ซ์ ๊ฐ์ ๋ช ๋ช ๋ ์์๋ก ๋์ฒดํฉ๋๋ค. ์ด๋ ๊ฐ๋ ์ฑ์ ํฅ์์ํค๊ณ ๋์ค์ ๊ฐ์ ๋ณ๊ฒฝํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. ์ด๋ ๋ฌธ์์ด๊ณผ ๊ฐ์ ๋ค๋ฅธ ๋ฆฌํฐ๋ด ๊ฐ์๋ ์ ์ฉ๋ฉ๋๋ค. ์ ์ญ์ ์ธ ๊ด์ ์์ ํตํ ์ฝ๋(์: 'USD', 'EUR', 'JPY') ๋๋ ์ํ ์ฝ๋(์: 'ACTIVE', 'INACTIVE', 'PENDING')๋ฅผ ๊ณ ๋ คํ์ญ์์ค.
์์:
def calculate_area(radius):
return 3.14159 * radius * radius
๋ฆฌํฉํ ๋ง ํ:
PI = 3.14159
def calculate_area(radius):
return PI * radius * radius
9. ์ค๊ฐ์ ์ ๊ฑฐ (Remove Middle Man)
ํด๋์ค๊ฐ ๋จ์ํ ๋ค๋ฅธ ํด๋์ค๋ก ํธ์ถ์ ์์ํ๋ ๊ฒฝ์ฐ, ์ค๊ฐ์๋ฅผ ์ ๊ฑฐํ๊ณ ํด๋ผ์ด์ธํธ๊ฐ ๋์ ํด๋์ค์ ์ง์ ์ ๊ทผํ๋๋ก ํ๋ ๊ฒ์ ๊ณ ๋ คํ์ญ์์ค.
์์:
class Person:
def __init__(self, department):
self.department = department
def get_manager(self):
return self.department.get_manager()
class Department:
def __init__(self, manager):
self.manager = manager
def get_manager(self):
return self.manager
๋ฆฌํฉํ ๋ง ํ:
class Person:
def __init__(self, manager):
self.manager = manager
def get_manager(self):
return self.manager
10. ๋จ์ธ ๋์ (Introduce Assertion)
ํ๋ก๊ทธ๋จ ์ํ์ ๋ํ ๊ฐ์ ์ ๋ฌธ์ํํ๊ธฐ ์ํด ๋จ์ธ(assertion)์ ์ฌ์ฉํ์ญ์์ค. ์ด๋ ์ค๋ฅ๋ฅผ ์กฐ๊ธฐ์ ํฌ์ฐฉํ๊ณ ์ฝ๋๋ฅผ ๋ ๊ฒฌ๊ณ ํ๊ฒ ๋ง๋๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์์:
def calculate_discount(price, discount_percentage):
if discount_percentage < 0 or discount_percentage > 100:
raise ValueError("Discount percentage must be between 0 and 100")
return price * (1 - discount_percentage / 100)
๋ฆฌํฉํ ๋ง ํ:
def calculate_discount(price, discount_percentage):
assert 0 <= discount_percentage <= 100, "Discount percentage must be between 0 and 100"
return price * (1 - discount_percentage / 100)
ํ์ด์ฌ ๋ฆฌํฉํ ๋ง ๋๊ตฌ
์ฌ๋ฌ ๋๊ตฌ๊ฐ ํ์ด์ฌ ๋ฆฌํฉํ ๋ง์ ๋์์ ์ค ์ ์์ต๋๋ค:
- Rope: ํ์ด์ฌ์ฉ ๋ฆฌํฉํ ๋ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ.
- PyCharm: ๋ฆฌํฉํ ๋ง ์ง์ ๊ธฐ๋ฅ์ด ๋ด์ฅ๋ ์ธ๊ธฐ ์๋ ํ์ด์ฌ IDE.
- VS Code with Python Extension: ํ์ฅ ํ๋ก๊ทธ๋จ์ ํตํด ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ค์ฌ๋ค๋ฅํ ํธ์ง๊ธฐ.
- Sourcery: ์๋ํ๋ ๋ฆฌํฉํ ๋ง ๋๊ตฌ.
- Bowler: ๋๊ท๋ชจ ์ฝ๋ ์์ ์ฉ Facebook ๋ฆฌํฉํ ๋ง ๋๊ตฌ.
ํ์ด์ฌ ๋ฆฌํฉํ ๋ง ๋ชจ๋ฒ ์ฌ๋ก
- ๋จ์ ํ ์คํธ ์์ฑ: ๋ฆฌํฉํ ๋ง ์ ์ ์ฝ๋๊ฐ ์ ํ ์คํธ๋์๋์ง ํ์ธํฉ๋๋ค.
- ์์ ๋จ๊ณ๋ก ๋ฆฌํฉํ ๋ง: ์ค๋ฅ ๋ฐ์ ์ํ์ ์ต์ํํ๊ธฐ ์ํด ์๊ณ ์ ์ง์ ์ธ ๋ณ๊ฒฝ์ ์ํํฉ๋๋ค.
- ๊ฐ ๋ฆฌํฉํ ๋ง ๋จ๊ณ ํ ํ ์คํธ: ๋ณ๊ฒฝ ์ฌํญ์ผ๋ก ์ธํด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์๋์ง ํ์ธํฉ๋๋ค.
- ๋ฒ์ ๊ด๋ฆฌ ์ฌ์ฉ: ํ์ํ ๊ฒฝ์ฐ ์ฝ๊ฒ ๋๋๋ฆด ์ ์๋๋ก ๋ณ๊ฒฝ ์ฌํญ์ ์์ฃผ ์ปค๋ฐํฉ๋๋ค.
- ํ๊ณผ์ ์ํต: ๋ฆฌํฉํ ๋ง ๊ณํ์ ๋ํด ํ์ ์๋ฆฝ๋๋ค.
- ๊ฐ๋ ์ฑ์ ์ง์ค: ์ฝ๋๋ฅผ ๋ ์ฝ๊ฒ ์ดํดํ ์ ์๋๋ก ์ฐ์ ์์๋ฅผ ๋ก๋๋ค.
- ๋ถํ์ํ ๋ฆฌํฉํ ๋ง ๊ธ์ง: ํน์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋๋ง ๋ฆฌํฉํ ๋งํฉ๋๋ค.
- ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๋ฆฌํฉํ ๋ง ์๋ํ: ๋ฐ๋ณต์ ์ธ ๋ฆฌํฉํ ๋ง ์์ ์ ์๋ํํ๊ธฐ ์ํด ๋๊ตฌ๋ฅผ ํ์ฉํฉ๋๋ค.
๋ฆฌํฉํ ๋ง์ ์ํ ์ ์ญ์ ๊ณ ๋ ค ์ฌํญ
๊ตญ์ ํ๋ก์ ํธ๋ฅผ ์งํํ๊ฑฐ๋ ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ๋์์ผ๋ก ํ ๋, ๋ฆฌํฉํ ๋ง ์ค ๋ค์ ์์๋ค์ ๊ณ ๋ คํ์ญ์์ค:
- ์ง์ญํ (L10n) ๋ฐ ๊ตญ์ ํ (I18n): ์ฝ๋๊ฐ ๋ค์ํ ์ธ์ด, ํตํ ๋ฐ ๋ ์ง ํ์์ ์ฌ๋ฐ๋ฅด๊ฒ ์ง์ํ๋์ง ํ์ธํฉ๋๋ค. ๋ก์ผ์ผ๋ณ ๋ก์ง์ ๋ถ๋ฆฌํ๋๋ก ๋ฆฌํฉํ ๋งํฉ๋๋ค.
- ๋ฌธ์ ์ธ์ฝ๋ฉ: ๊ด๋ฒ์ํ ๋ฌธ์๋ฅผ ์ง์ํ๊ธฐ ์ํด UTF-8 ์ธ์ฝ๋ฉ์ ์ฌ์ฉํฉ๋๋ค. ํน์ ์ธ์ฝ๋ฉ์ ๊ฐ์ ํ๋ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํฉ๋๋ค.
- ๋ฌธํ์ ๋ฏผ๊ฐ์ฑ: ๋ฌธํ์ ๊ท๋ฒ์ ์ผ๋์ ๋๊ณ ๋ถ์พ๊ฐ์ ์ค ์ ์๋ ์ธ์ด๋ ์ด๋ฏธ์ง๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ํฉ๋๋ค. ๋ฆฌํฉํ ๋ง ์ค์ ๋ฌธ์์ด ๋ฆฌํฐ๋ด ๋ฐ ์ฌ์ฉ์ ์ธํฐํ์ด์ค ์์๋ฅผ ๊ฒํ ํฉ๋๋ค.
- ์๊ฐ๋: ์๊ฐ๋ ๋ณํ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํฉ๋๋ค. ์ฌ์ฉ์ ์๊ฐ๋์ ๋ํ ๊ฐ์ ์ ํ๋ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํฉ๋๋ค. `pytz`์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ญ์์ค.
- ํตํ ์ฒ๋ฆฌ: ํตํ ๊ฐ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ ์ ํ ๋ฐ์ดํฐ ์ ํ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋ ํตํ ๋ณํ์ ์ํํ๋ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํฉ๋๋ค. `babel`๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ์ฉํฉ๋๋ค.
์์: ๋ ์ง ํ์ ์ง์ญํ
import datetime
def format_date(date):
return date.strftime("%m/%d/%Y") # US date format
๋ฆฌํฉํ ๋ง ํ:
import datetime
import locale
def format_date(date, locale_code):
locale.setlocale(locale.LC_TIME, locale_code)
return date.strftime("%x") # Locale-specific date format
# Example usage:
# format_date(datetime.date(2024, 1, 1), 'en_US.UTF-8') # Output: '01/01/2024'
# format_date(datetime.date(2024, 1, 1), 'de_DE.UTF-8') # Output: '01.01.2024'
๊ฒฐ๋ก
๋ฆฌํฉํ ๋ง์ ๊ณ ํ์ง ํ์ด์ฌ ์ฝ๋๋ฅผ ์ ์งํ๋ ๋ฐ ํ์์ ์ธ ๊ดํ์ ๋๋ค. ์ฝ๋ ์ค๋ฉ์ ์๋ณํ๊ณ ํด๊ฒฐํ๋ฉฐ, ์ ์ ํ ๋ฆฌํฉํ ๋ง ๊ธฐ๋ฒ์ ์ ์ฉํ๊ณ , ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ์ฝ๋์ ๊ฐ๋ ์ฑ, ์ ์ง๋ณด์์ฑ, ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค. ๋ฆฌํฉํ ๋ง ๊ณผ์ ์ ๋ฐ์ ๊ฑธ์ณ ํ ์คํธ์ ์ปค๋ฎค๋์ผ์ด์ ์ ์ฐ์ ์ํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค. ๋ฆฌํฉํ ๋ง์ ์ง์์ ์ธ ํ๋ก์ธ์ค๋ก ๋ฐ์๋ค์ด๋ ๊ฒ์ ํนํ ์ ์ธ๊ณ์ ๋ค์ํ ์ฌ์ฉ์๋ฅผ ์ํด ๊ฐ๋ฐํ ๋ ๋์ฑ ๊ฒฌ๊ณ ํ๊ณ ์ง์ ๊ฐ๋ฅํ ์ํํธ์จ์ด ๊ฐ๋ฐ ์ํฌํ๋ก์ฐ๋ก ์ด์ด์ง ๊ฒ์ ๋๋ค.