정의
프로그램이 하는 일은 그대로 두고 코드의 짜임새만 다듬는 작업이에요. 화면에 나오는 결과가 달라진다면 그것은 리팩터링이 아니에요. 다음 사람이 읽기 쉽게, 그리고 새 기능을 붙이기 쉽게 만드는 것이 목적이에요.
부엌 서랍을 다시 정리하는 일
부엌 서랍을 떠올려 볼게요. 처음에는 국자와 가위를 아무 데나 넣어도 금방 찾을 수 있어요. 물건이 쌓이면 이야기가 달라져요. 숟가락 하나 꺼내는 데도 서랍을 다 뒤져야 해요.
코드도 비슷하게 쌓여요. 급한 마음에 붙여 둔 임시 처리와 비슷한 내용이 여러 곳에 흩어진 채 남아요. 나중에 온 사람은 어디를 고쳐야 할지 찾느라 시간을 다 써요.
그래서 개발자들은 가끔 하던 일을 멈추고 서랍을 다시 정리해요. 칸막이를 세우고 비슷한 물건을 한곳에 모으듯, 흩어진 코드를 이름 붙은 덩어리로 묶어요.
이때 서랍이 하던 역할은 하나도 잃지 않는다는 점이 중요해요. 국자로 국을 뜨는 일은 여전히 할 수 있어요. 똑같은 물건이 여러 개면 하나로 줄이고 안 쓰는 물건은 치울 수도 있지만, 놓인 자리와 정리 방식이 바뀌어도 할 수 있는 일은 그대로예요.
동작은 그대로, 속만 바꿔요
이 작업의 핵심 규칙은 하나예요. 겉으로 드러나는 동작을 바꾸지 않는 것이에요. 버튼을 눌렀을 때 나오는 화면과 값이 전과 같아야 해요.
그래서 손대기 전에 안전망부터 깔아요. 코드가 제대로 도는지 자동으로 확인해 주는 검사를 마련해 두는 것이죠. 정리하다 무언가 어긋나면 그 검사가 바로 빨간불을 켜 줘요.
작업은 잘게 나눠서 해요. 뜻이 흐릿한 변수 이름을 또렷하게 바꾸고, 길게 늘어진 코드 뭉치를 이름 붙은 함수로 떼어내고, 세 군데에 복사돼 있던 계산을 한곳으로 모아요. 하나하나는 사소해 보이지만 쌓이면 읽는 속도가 눈에 띄게 달라져요.
한 번에 하나씩 고치고 그때마다 검사를 돌리는 방식이 안전해요. 작게 바꾸고 바로 확인하기를 반복하면 문제가 생겨도 되돌리기 쉬워요.
조금 더 정확히 말하면: 기능 추가·버그 수정과 구분해요
정리하다 보면 버그가 눈에 띄기도 해요. 함께 고치고 싶은 마음이 들지만, 두 작업을 섞으면 나중에 곤란해져요. 오류가 났을 때 정리 탓인지 수정 탓인지 가려내기 어렵거든요.
조금 더 정확히 말하면 리팩터링은 기능 추가도 아니고 버그 수정도 아니에요. 셋을 다른 시간에 나누어 하고 기록도 따로 남기는 편이 좋아요. 그래야 나중에 문제가 생겼을 때 어느 지점으로 되돌릴지 고르기 쉬워져요.
이 일이 필요한 이유는 보기 좋게 만들려는 취향 때문이 아니에요. 읽기 어려운 코드에서는 새 기능 하나를 붙이는 데 드는 시간이 계속 늘어나요. 손대기 무서운 코드가 쌓이면 팀 전체가 느려져요.
그래서 많은 팀이 기능을 만들기 전에 그 주변부터 먼저 정돈해요. 고치기 쉬운 상태로 만든 다음에 고치는 것이 결국 빠른 길이에요.
흔한 오해
리팩터링은 프로그램을 더 빠르게 만드는 성능 개선 작업이다.
속도가 함께 좋아질 때도 있지만 목적은 아니에요. 동작을 그대로 둔 채 코드를 읽고 고치기 쉽게 만드는 것이 목적이에요.
코드를 처음부터 새로 짜는 것도 리팩터링이다.
밑바닥부터 다시 만드는 일은 재작성이라고 따로 불러요. 리팩터링은 기존 코드를 작은 단위로 조금씩 다듬어 가는 방식이에요.
일상에서 만나요
'a'나 'tmp' 같은 변수 이름을 '주문금액', '남은수량'처럼 뜻이 드러나는 이름으로 바꾸는 일이에요.
세 화면에 복사돼 있던 같은 계산식을 함수 하나로 모아, 앞으로는 한 곳만 고치면 되게 만드는 일이에요.
그러니까 한마디로
리팩터링은 프로그램의 동작은 그대로 둔 채 코드의 구조만 다듬어 다음 수정을 쉽게 만드는 일이에요.