리팩토링을 어떤 식으로 하나?
리팩토링을 어떤 식으로 하나?
리팩토링(Refactoring)은 코드의 기능을 변경하지 않으면서 내부 구조를 개선하여 가독성, 유지보수성, 확장성을 향상시키는 작업입니다. 잘된 리팩토링은 코드의 품질을 높이고, 개발자가 더 효율적으로 작업할 수 있게 합니다. 아래는 리팩토링을 진행하는 방법과 주요 기법에 대한 자세한 설명입니다.
1. 리팩토링의 필요성
- 가독성 향상: 복잡하고 이해하기 어려운 코드를 쉽게 읽을 수 있도록 개선합니다.
- 유지보수성 증가: 코드를 쉽게 수정하고 확장할 수 있도록 합니다.
- 버그 감소: 코드 구조를 명확히 하여 버그를 줄입니다.
- 재사용성 향상: 중복 코드를 제거하고, 모듈화하여 재사용성을 높입니다.
2. 리팩토링의 원칙
- 작은 단계로 진행: 리팩토링은 작은 단계로 진행하여, 각 단계에서 기능이 유지되도록 합니다.
- 테스트 주도 개발(TDD): 리팩토링 전후에 테스트를 수행하여 코드가 올바르게 동작하는지 확인합니다.
- 단계적 개선: 전체 코드를 한 번에 리팩토링하지 말고, 부분적으로 개선해 나갑니다.
3. 리팩토링의 단계
3.1. 코드 분석
- 코드 이해: 리팩토링할 코드를 이해하고, 주요 기능과 흐름을 파악합니다.
- 코드 스멜(Code Smells): 코드 스멜을 식별하여 개선이 필요한 부분을 찾습니다.
3.2. 테스트 작성
- 단위 테스트: 리팩토링 전후의 코드가 동일하게 동작하는지 확인하기 위해 단위 테스트를 작성합니다.
- 테스트 커버리지: 코드의 주요 부분이 테스트로 커버되는지 확인합니다.
3.3. 리팩토링 수행
- 코드 스멜 제거: 식별된 코드 스멜을 제거하는 리팩토링 기법을 적용합니다.
- 단계적 리팩토링: 작은 단위로 리팩토링을 진행하고, 각 단계마다 테스트를 수행합니다.
3.4. 테스트 및 검증
- 테스트 실행: 모든 테스트를 실행하여 리팩토링 후 코드가 올바르게 동작하는지 확인합니다.
- 코드 리뷰: 다른 개발자와 코드 리뷰를 통해 리팩토링이 제대로 이루어졌는지 검토합니다.
4. 주요 리팩토링 기법
4.1. 코드 스멜 제거 기법
- 중복 코드 제거: 동일하거나 유사한 코드를 함수나 메서드로 추출하여 재사용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# Before def calculate_area(length, width): area = length * width print(f"Area: {area}") def calculate_perimeter(length, width): perimeter = 2 * (length + width) print(f"Perimeter: {perimeter}") # After def print_result(message, value): print(f"{message}: {value}") def calculate_area(length, width): area = length * width print_result("Area", area) def calculate_perimeter(length, width): perimeter = 2 * (length + width) print_result("Perimeter", perimeter)
- 긴 함수 나누기: 하나의 함수가 너무 많은 일을 하는 경우, 작은 함수로 나누어 가독성과 재사용성을 높입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# Before def process_data(data): # 데이터 정제 cleaned_data = clean_data(data) # 데이터 분석 results = analyze_data(cleaned_data) # 결과 출력 print_results(results) # After def process_data(data): cleaned_data = clean_data(data) results = analyze_data(cleaned_data) print_results(results) def clean_data(data): # 데이터 정제 로직 pass def analyze_data(cleaned_data): # 데이터 분석 로직 pass def print_results(results): # 결과 출력 로직 pass
- 매직 넘버 제거: 코드 내의 숫자 값을 상수로 치환하여 의미를 명확히 합니다.
1 2 3 4 5 6 7 8 9
# Before def calculate_circle_area(radius): return 3.14159 * radius * radius # After PI = 3.14159 def calculate_circle_area(radius): return PI * radius * radius
4.2. 구조 개선 기법
- 클래스 추출: 하나의 클래스가 너무 많은 책임을 지고 있는 경우, 새로운 클래스로 분리합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# Before class Employee: def __init__(self, name, age, salary): self.name = name self.age = age self.salary = salary def calculate_pay(self): # 급여 계산 로직 pass def save_to_database(self): # 데이터베이스 저장 로직 pass # After class Employee: def __init__(self, name, age, salary): self.name = name self.age = age self.salary = salary def calculate_pay(self): # 급여 계산 로직 pass class EmployeeRepository: def save_to_database(self, employee): # 데이터베이스 저장 로직 pass
- 메서드 이동: 메서드가 더 관련이 깊은 다른 클래스로 옮깁니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
# Before class Order: def __init__(self, order_id, customer): self.order_id = order_id self.customer = customer def get_customer_address(self): return self.customer.address class Customer: def __init__(self, customer_id, address): self.customer_id = customer_id self.address = address # After class Order: def __init__(self, order_id, customer): self.order_id = order_id self.customer = customer def get_customer_address(self): return self.customer.get_address() class Customer: def __init__(self, customer_id, address): self.customer_id = customer_id self.address = address def get_address(self): return self.address
결론
리팩토링은 소프트웨어 개발에서 지속적인 개선을 통해 코드 품질을 유지하고 향상시키는 중요한 과정입니다. 리팩토링의 원칙을 지키고, 다양한 기법을 적절히 활용하여 코드의 가독성, 유지보수성, 확장성을 높일 수 있습니다. 이를 통해 개발자는 더 효율적으로 작업할 수 있으며, 소프트웨어의 안정성과 성능을 향상시킬 수 있습니다.
다음시간에 계속…
This post is licensed under CC BY 4.0 by the author.