코드 리팩토링 이해하기

in #krsuccess3 days ago

리팩토링, 코드를 ‘다시 예쁘게’ 만드는 마법

6장에서 작은 프로그램을 완성하면서 “어? 돌아가네?” 했을 거야. 나도 그랬어. 근데 솔직히 말하면, 프로그램이 돌아간 순간부터 슬슬 보이는 게 있어.
바로 코드가 좀 지저분해 보이기 시작하는 느낌… 음… 나름 열심히 짰는데, 나중에 내가 읽기에도 헷갈리는 거 있잖아. 😅

그래서 이번 7-1에서는 리팩토링이 뭔지, 그리고 “그냥 조금만” 손대도 코드가 얼마나 편해지는지 배워볼게.

refactoring


리팩토링이 뭐냐고? “기능은 그대로, 모양은 더 좋게”

리팩토링은 한 줄로 요약하면 이거야:

  • 기능은 바꾸지 않고
  • 코드를 더 읽기 쉽게 바꾸는 작업

어? 그럼 그냥 코드 정리랑 뭐가 달라?
내 경험상, 정리는 “대충 보기 좋게” 할 때가 많은데, 리팩토링은 “기능이 절대 안 바뀌게” 더 신경 써. 그래서 바꾸기 전에 테스트/실행 결과 확인도 같이 가는 편이야.

“에이, 기능이 같으면 되지 뭐.”
라고 생각할 수 있는데… 솔직히 나는 한 번씩 그걸 모르고 바꿨다가, 어느 순간 입력 하나에만 예외가 터진 적이 있어. 그때는… 그냥 웃고 넘기기엔 좀 울었지. (유머로 승화함)


리팩토링을 해야 하는 대표적인 이유 3가지

리팩토링은 “귀찮은 작업”처럼 느껴질 수 있는데, 이유가 분명해.

  1. 가독성이 올라가서 내가 다음에 덜 헤맴
  2. 유지보수가 쉬워져서 나중에 수정이 편해짐
  3. 실수할 확률이 줄어듦
    같은 기능을 여러 군데 복붙해두면, 바꿔야 할 때 한 군데만 고치게 되거든… 아! 그건 나다.

szmiki95


리팩토링은 보통 이런 순서로 한다 (겁먹지 말기)

리팩토링은 “한 방에 완벽하게”가 목표가 아니야. 보통 이런 흐름으로 가.

  1. 현재 코드가 잘 동작하는지 확인
  2. 작게 바꾼 뒤 결과가 같은지 다시 확인
  3. 안전하게 계속 개선

이게 핵심이야.
즉, “리팩토링은 도박이 아니라 점검”이야.

jothamsutharson


자주 하는 리팩토링 예시 (초보도 바로 써먹기 좋게)

여기서부터가 진짜 꿀팁 파트야. 내가 실제로 많이 하는 것들만 뽑아볼게.


1) 변수 이름 바꾸기: a, temp를 줄여라

예를 들어 이런 코드:

a = 0
for x in nums:
    a = a + x
print(a)

리팩토링하면:

total = 0
for x in nums:
    total += x
print(total)

처음엔 차이 없어 보여도, 나중에 읽으면 확 달라져.
변수 이름이 친절하면, 코드가 스스로 설명해주거든.


2) 반복되는 코드 묶기: “복붙 금지”

예를 들어 메뉴 출력에서 이런 식으로 반복되면:

if choice == "1":
    print("추가합니다")
elif choice == "2":
    print("삭제합니다")
elif choice == "3":
    print("조회합니다")

이게 커지기 시작하면 지옥이야…
리팩토링 포인트는 “패턴이 있으면 구조로 만들기”야.

messages = {
    "1": "추가합니다",
    "2": "삭제합니다",
    "3": "조회합니다",
}

print(messages.get(choice, "알 수 없습니다"))

기능은 그대로, 코드 길이는 줄고, 수정도 쉬워져.


3) 긴 if-else를 함수로 쪼개기

한 파일에서 모든 처리를 한 번에 해버리면, 나중에 “뭐가 무슨 역할인지”가 흐려져.

예를 들면:

  • 입력 받기
  • 검증하기
  • 계산하기
  • 출력하기

이런 걸 한 덩어리로 짜놓으면… 음… 나도 손이 떨리더라.
그래서 리팩토링으로 “역할별”로 함수를 나눠.

def validate_choice(choice):
    return choice in ["1", "2", "3"]

def print_message(choice):
    messages = {"1": "추가합니다", "2": "삭제합니다", "3": "조회합니다"}
    print(messages.get(choice, "알 수 없습니다"))

choice = input("메뉴 선택: ")
if validate_choice(choice):
    print_message(choice)
else:
    print("잘못된 입력이야!")

이렇게 나누면 코드 읽는 사람이 편해져. 미래의 나도 편해지고.

Simon


4) 중복된 조건 정리: if를 덜 쓰기

조건이 여러 겹이면, 가독성이 뚝 떨어져.

  • if, else를 줄이고
  • 공통 부분을 먼저 처리하고
  • 조기 반환(early return) 같은 방식으로 단순화해

이건 언어/스타일에 따라 다르지만, 방향성은 같아:
복잡도를 낮추기.


내가 리팩토링하다가 한 번 크게 말아먹은 썰 (짧게)

15년 전쯤…? 아니 정확하진 않아. 어쨌든 예전 프로젝트에서 “코드 보기 좋게” 하려고 변수명 바꾸고 조건 묶고 막 정리했거든.

그런데 결과가 미묘하게 달라졌어.
원인은 뭐였냐면:

  • “기능은 그대로겠지” 하고
  • 테스트를 제대로 안 돌렸고
  • 한 줄에 들어있는 조건 순서를 바꿔버린 거야

그날 이후로 내가 얻은 교훈은 딱 하나야.

리팩토링은 수정이 아니라 ‘검증을 동반한 개선’이다.

솔직히 말하면 지금도 실수해. 근데 예전보단 덜 하게 됐지. (덕분에 내가 안 무너짐)


이번 글에서 가져갈 핵심 한 줄

리팩토링은 코드를 바꾸는 게 아니라, 코드를 ‘다시 쓰기 쉽게’ 만드는 거야.
그리고 제일 중요한 건 작게 바꾸고, 계속 확인하기.

Boskampi


다음 글(7-2)로 자연스럽게 이어지는 포인트

다음 7-2에서는 모듈과 라이브러리 활용을 배울 거야.

리팩토링을 하다 보면 결국 이런 생각이 들거든:

  • “아 이 기능, 이제 또 쓰고 싶은데…”
  • “이 로직은 매번 다시 만들기엔 귀찮은데…”
  • “그럼 어디에 정리해두면 편하지?”

그 답이 보통 모듈/라이브러리 쪽으로 이어져.
그러니까 이번 리팩토링은 준비운동이고, 다음은 본운동 느낌! 😄


원하면 내가 질문 하나 던져볼게.
너 지금까지 만든 코드 중에서 “나중에 다시 보기가 좀 싫은 부분” 있어?
그 부분을 기준으로, 리팩토링 방식(이름 바꾸기/함수 쪼개기/중복 제거) 어떤 걸 먼저 해볼지 같이 정해줄 수도 있어.