오늘은 작성된 코드의 가독성을 높이는 방법인 코드 리팩토링(Code Refactoring)에 대해 정리해 보겠습니다.
리팩토링은 소프트웨어의 겉으로 드러나는 기능(동작)은 바꾸지 않으면서, 내부적인 코드 구조를 개선하여 가독성을 높이고 복잡도를 낮추는 행위를 말합니다.
즉, 똑같이 동작하는 코드를 더 보기 쉽게 다듬는 작업을 의미합니다.
리팩토링의 가장 큰 목적은 유지보수성 향상입니다.
코드가 복잡하고 지저분하면 새로운 기능을 추가할 때 버그가 생길 확률이 높고 분석하는 데 시간이 오래 걸립니다.
이를 기술 부채(Technical Debt)라고 부르는데, 리팩토링은 이 부채를 갚아나가는 과정입니다.
중복을 제거하고 로직을 명확하게 함으로써 팀원과의 협업을 원활하게 하고, 나아가 시스템의 확장성을 확보하기 위해 반드시 필요합니다.
좋은 코드를 만들기 위한 대표적인 기법들은 다음과 같습니다.
메소드 추출 (Extract Method)
메소드 내부에 많은 로직이 담겨 있을 때, 이를 기능 단위로 쪼개어 별도의 함수로 분리하는 기법입니다.
코드가 짧아지고 함수의 이름만으로도 어떤 일을 하는지 명확히 알 수 있게 됩니다.
피처 이동 (Feature Move)
특정 로직이 자신이 속한 클래스보다 다른 클래스의 데이터를 더 많이 참조하거나 그곳에 있는 것이 더 자연스러울 때, 해당 로직을 적절한 위치로 옮기는 작업입니다.
객체 간의 결합도를 낮추는 데 효과적입니다.
추상화 - Pull up & Push down
부모 클래스와 자식 클래스 간의 계층 구조를 정리하는 기법입니다.
간소화 (Simplification)
복잡한 조건문(if-else), 의미 불명인 변수명 등을 수정합니다.(State Machine을 통한 상태 관리)
레드-그린-리팩토링 (Red-Green-Refactoring)
테스트 주도 개발(TDD)에서 파생된 주기로, 리팩토링을 안전하게 진행하는 방법입니다.
<style>
using UnityEngine;
// 리팩토링 전: Update에 모든 로직이 섞여 있음
public class PlayerLegacy : MonoBehaviour
{
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 dir = new Vector3(h, v, 0);
transform.Translate(dir * 5f * Time.deltaTime);
if (transform.position.x > 10) transform.position = new Vector3(10, transform.position.y, 0);
}
}
// 리팩토링 후: 메소드 추출을 통해 역할 분리
public class PlayerRefactored : MonoBehaviour
{
public float speed = 5f;
public float xLimit = 10f;
void Update()
{
Move();
ClampPosition();
}
private void Move()
{
Vector3 dir = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
transform.Translate(dir * speed * Time.deltaTime);
}
private void ClampPosition()
{
if (transform.position.x > xLimit)
{
transform.position = new Vector3(xLimit, transform.position.y, 0);
}
}
}
</style>
오늘은 리팩토링에 대하여 학습해보았습니다.
함수의 분리, 명확한 변수, 비대해지는 조건문의 간결화가 얼마나 중요한지 다시 깨달을 수 있었습니다.