Rain Lag

빨간 펜 리팩터링: 작가처럼 코드를 다듬어 두려움 줄이기

작가가 초고를 고치듯, 작은 단위의 안전한 개선과 탄탄한 테스트, 그리고 (AI를 포함한) 도구들을 활용해 리팩터링을 덜 두렵고 더 지속 가능하게 만드는 방법을 알아봅니다.

빨간 펜 리팩터링: 작가처럼 코드를 다듬어 두려움 줄이기

리팩터링은 평판이 좋지 않습니다.

많은 개발자는 “리팩터링”이라는 말을 들으면 곧바로 위험한 변경, 깨진 기능, 그리고 기묘한 회귀 버그를 쫓아 새벽까지 붙들려 있는 상황을 떠올립니다. 하지만 제대로 된 리팩터링은 철거 작업이라기보다 초고를 고치는 편집 작업에 더 가깝습니다. 이야기를 처음부터 다시 쓰는 것이 아니라, 이미 있는 이야기를 더 명확하고 간결하게, 다루기 쉽게 만드는 일에 가깝죠.

이게 바로 **“빨간 펜 리팩터링(Red Pen Refactor)”**의 핵심 아이디어입니다. 코드베이스를 원고처럼, 자신을 편집자처럼 대하면서, 의미는 바꾸지 않은 채 텍스트를 꾸준히 개선해 나가는 것입니다.

이 글에서는 작가의 관점으로 리팩터링을 바라봅니다. 기능은 그대로 유지한 채 설계·구조·구현을 개선하는 방법, 그리고 코드 변경을 덜 두렵게 만들고 일상적인 개발의 자연스러운 일부로 만드는 방법을 살펴보겠습니다.


리팩터링이 진짜로 뜻하는 것 (그리고 아닌 것)

핵심부터 짚고 가면, 리팩터링은 외부 동작을 바꾸지 않고 내부 구조를 개선하는 과정입니다.

즉, 다음을 의미합니다.

  • 코드가 하는 일은 그대로입니다. (사용자 관점에서 동작은 유지됩니다.)
  • 코드가 그 일을 해내는 방식은 더 좋아집니다. (개발자 관점에서 구조가 개선됩니다.)

리팩터링의 초점은 다음과 같습니다.

  • 설계와 아키텍처
  • 읽기 쉬움과 명확성
  • 복잡도 감소
  • 관심사의 분리 강화
  • 테스트·확장 용이성 개선

반대로, 리팩터링이 아닌 것은 다음입니다.

  • 새로운 기능 추가
  • 버그 수정 자체 (다만 버그를 찾기와 고치기 쉽게 만들어 줍니다)
  • 아예 처음부터 다시 쓰는 풀 리라이트(rewrite)

정리하면, 리팩터링은 **다시 집필(re-authoring)이 아니라 편집(editing)**입니다. 이야기, 등장인물, 결말은 그대로 두되, 문장·단락·장(章)의 구성을 더 일관되고 이해하기 쉽게 바꾸는 일입니다.


왜 리팩터링이 중요한가: 그 보상

잘 편집된 글이 읽고 이해하기 쉬운 것처럼, 잘 리팩터링된 코드베이스는 유지·개선하기가 훨씬 수월합니다.

대표적인 이점은 다음과 같습니다.

  1. 가독성 향상
    깔끔하고 의도를 잘 드러내는 코드는, 나 자신은 물론 미래의 팀원들도 더 빨리 이해할 수 있습니다. 이로 인해 온보딩 시간, 오해, “도대체 이게 뭐지?” 같은 순간이 줄어듭니다.

  2. 복잡도 감소
    거대한 함수 쪼개기, 꼬여 있는 의존성 풀기, 복잡한 로직 단순화 등을 통해 코드의 동작을 추론하기가 쉬워지고, 엣지 케이스도 더 잘 눈에 들어옵니다.

  3. 유지보수성 향상
    요구사항이 바뀌었을 때, 리팩터링된 코드는 훨씬 수정하기 쉽습니다. “이거 건드리면 다 깨질 것 같은데…” 하는 두려움을 줄여 줍니다.

  4. 새 기능 추가 시 리스크 감소
    잘 구조화되고 잘 테스트된 코드베이스는 새로운 기능을 추가할 때 시스템 전체가 무너질까 걱정하지 않고 작업할 수 있는 자신감을 줍니다.

리팩터링은 코드베이스 건강에 대한 투자입니다. 좋은 편집이 이후의 모든 문장을 읽기 쉽게 만들 듯, 리팩터링의 효과는 앞으로 하게 될 모든 변경에서 체감됩니다.


편집자처럼 생각하기: 작고 선명한 여러 번의 패스

작가는 지저분한 초고를 단 한 번의 수정으로 완성된 글로 바꾸지 않습니다. 보통 이렇게 작업합니다.

  • 눈에 띄는 문제를 먼저 고치고
  • 표현을 다듬고
  • 단락 구조를 재배치하고
  • 그 다음에야 글 전체의 구조를 조정합니다.

각각의 패스(pass)는 명확한 초점을 갖습니다.

리팩터링도 같은 원칙을 적용할 수 있습니다.

1. 이번 “편집 패스”의 목표를 정하라

“이 파일을 좀 더 좋게 만들자” 같은 막연한 목표 대신, 구체적인 초점을 하나 정합니다. 예를 들어:

  • 너무 긴 메서드에서 작은 함수들을 추출하기
  • 헷갈리는 변수·메서드 이름을 더 명확하게 바꾸기
  • 사용되지 않는 코드와 도달 불가능한 분기 제거하기
  • 순환 의존성(circular dependency) 끊기
  • 복잡한 인라인 조건문을 명확한 가드 절(guard clause)로 바꾸기

이렇게 초점을 좁히면, 다음과 같은 장점이 있습니다.

  • 변경 범위를 작게 유지할 수 있고
  • 커밋 메시지에 리팩터링의 목적을 명확히 쓸 수 있으며
  • 문제가 생겼을 때 리뷰·롤백이 쉬워집니다.

2. “처음부터 다시 쓰기” 함정 피하기

리라이트(rewrite)는 원고를 통째로 버리고 처음부터 다시 쓰는 것과 같습니다. 가끔은 필요하지만, 대부분은 위험합니다.

리라이트는 다음과 같은 문제를 야기합니다.

  • 수많은 실전에서 검증된 동작(심지어 문서화되지 않은 엣지 케이스까지)을 한 번에 버리게 되고
  • 모든 것이 바뀌었기 때문에 검증이 더 어려워지며
  • 예상보다 훨씬 긴 시간이 걸리는 경우가 많습니다.

반면 리팩터링은 기존 이야기를 존중합니다. 이렇게 말하죠.

“지금도 돌아가긴 하지만, 읽기 어렵고 바꾸기 힘들다. 이걸 한 걸음씩 더 나아지게 만들자.”


점진적 리팩터링: 혼란 없이 바꾸기

한 번에 바꾸는 코드가 많을수록, 회귀 버그를 심을 가능성도 커집니다. 이에 대한 해답이 점진적(incremental) 리팩터링입니다. 작고 의도적인 단계를 밟으며, 이해·리뷰·배포가 쉬운 변경을 쌓아 가는 방식입니다.

실무에 쓸 수 있는 전략 몇 가지를 살펴보겠습니다.

1. 작고 리뷰하기 쉬운 커밋 만들기

각 커밋은 다음을 만족하는 것이 좋습니다.

  • 분명한 단일 목적을 가진다. (예: “이메일 검증 로직을 별도 함수로 추출”)
  • 필요할 경우 쉽게 되돌릴 수 있다.
  • 빠른 코드 리뷰로도 이해 가능한 범위다.

이것은 작가가 워드 프로세서의 “변경 내용 추적(track changes)” 기능을 사용하는 것과 비슷합니다. 각 수정이 눈에 잘 드러나고, 검토하기 좋습니다.

2. “보이스카우트 규칙(Boy Scout Rule)” 적용하기

코드를 건드릴 때마다, 처음 발견했을 때보다 조금이라도 더 나은 상태로 만들어 두자는 규칙입니다. 예를 들면:

  • 이름이 엉망인 변수를 더 의미 있는 이름으로 바꾸기
  • 빠져 있던 테스트 하나 추가하기
  • 헬퍼 메서드 하나로 추출해 가독성을 높이기

거창한 리팩터링이 아니라, 지속적인 마이크로 개선을 쌓아 가는 것입니다.

3. 가능하면 리팩터링과 기능 개발을 분리하기

리팩터링과 새로운 동작 추가를 한 번의 변경으로 섞으면 다음이 어려워집니다.

  • diff를 리뷰하기
  • 무엇 때문에 깨졌는지 원인을 찾기
  • 새 기능을 잃지 않고 롤백하기

둘을 동시에 해야만 하는 상황이라면, 이런 방식을 고려해 볼 수 있습니다.

  • 먼저 리팩터링만 담은 PR을 올리고
  • 그 다음에 새로운 기능을 추가하는 PR을 분리해서 올리기

테스트: 대담한 수정의 안전망

편집자가 대규모 수정을 한 원고를 아무 검수 없이 바로 출판하지는 않듯, 괜찮은 테스트 없이 큰 리팩터링에 덤비는 것은 매우 위험합니다.

리팩터링 전에는 다음을 수행하는 것이 좋습니다.

  1. 반드시 유지해야 할 동작을 파악하기
    이 코드가 보장해야 하는 핵심 플로우, 엣지 케이스, 외부 계약(contracts)은 무엇인가?

  2. 그 동작을 감싸는 테스트를 작성하거나 보강하기
    단위 테스트(unit test), 통합 테스트(integration test), E2E(end-to-end) 테스트 등 어떤 형태든 괜찮습니다.

리팩터링 중에는:

  • 자주 테스트를 실행합니다.
  • 테스트의 기대값(expectation)은, 잘못된 전제를 바로잡는 것이 아니라면, 가급적 바꾸지 않습니다.

리팩터링이 끝난 후에는:

  • 전체 테스트 스위트가 모두 통과하는지 확인합니다.
  • 리팩터링 과정에서 발견한 버그가 있다면, 그에 대한 회귀 테스트(regression test)를 추가로 작성하는 것도 좋습니다.

테스트는 빠른 피드백 루프를 제공합니다. 리팩터링 때문에 동작이 달라졌다면, 프로덕션 장애가 아니라 테스트 단계에서 바로 알게 되는 것이죠.


도구와 AI를 편집자의 빨간 펜처럼 사용하기

편집자는 눈으로만 원고를 보지 않습니다. 맞춤법 검사기나 문법 제안 도구처럼 각종 도구의 도움을 받습니다. 개발자에게도, 특히 AI 도우미까지 포함하면, 활용할 수 있는 도구가 점점 늘어나고 있습니다.

편집자–작가 워크플로에 빗대어 도구를 활용하는 방법을 살펴봅시다.

  1. 정적 분석기와 린터(linter)

    • 사용되지 않는 변수, 도달 불가능한 코드, 위험한 패턴 같은 명백한 코드 스멜을 잡아 줍니다.
    • 일관된 코딩 스타일을 강제해, diff가 의미 있는 변경에만 집중되도록 도와줍니다.
  2. IDE의 리팩터링 기능

    • 코드베이스 전체에서 심볼 이름을 안전하게 변경(rename)합니다.
    • 메서드, 클래스, 인터페이스를 추출(extract)합니다.
    • 파일을 옮기고(import 경로 수정 포함) 관련 참조를 자동으로 업데이트합니다.
  3. AI 코드 어시스턴트
    AI는 좋은 편집자 동료처럼 활용할 수 있습니다.

    • 특정 함수나 모듈에 대해 리뷰를 요청하고, 가독성·설계 측면의 개선 포인트를 물어볼 수 있습니다.
    • 오래된 레거시 코드 조각에 대해 구체적인 리팩터링 제안을 받습니다.
    • 리팩터링 전에 중요한 경로에 대한 테스트 코드 생성을 도와달라고 요청할 수 있습니다.
    • 피드백을 반영해 조금 리팩터링하고, 다시 AI에게 검토를 요청하는 식으로 반복 개선 루프를 돌릴 수 있습니다.

이 흐름은 작가–편집자 루프와 매우 닮아 있습니다.

내가 쓴다 → 편집자가 원고를 표시한다 → 내가 고친다 → 반복

여전히 저자는 개발자인 당신입니다. 도구는 문제를 더 잘 보이게 하고, 다양한 대안을 탐색하도록 돕는 증폭기 역할을 할 뿐입니다.


레거시 코드 리팩터링: 길지만 값지는 여정

레거시 코드는 여러 해에 걸쳐 여러 사람이 쓴, 너무 길고 엉킨 소설처럼 느껴질 때가 많습니다. “그냥 다 갈아엎자”는 유혹이 엄청나게 크죠. 하지만 가능하다면 그 충동을 조금만 참는 편이 낫습니다.

그 대신, 레거시 코드 리팩터링을 지속적인, 그러면서도 보람 있는 과정으로 바라보는 것이 좋습니다.

  1. 가장 아픈 곳부터 시작하기
    자주 손대는 모듈, 자주 버그를 일으키는 부분부터 개선합니다. 그곳이 개선 효과가 가장 크게 느껴지는 지점입니다.

  2. 먼저 테스트로 안정망 만들기
    구현이 아무리 지저분해도, 현재 동작을 기준으로 테스트를 작성해 의도된 동작을 역추적(reverse engineer) 합니다.

  3. 레이어를 나눠서 단계적으로 리팩터링하기

    • 먼저 외부 의존성(네트워크, 파일, DB 등)을 분리·격리합니다.
    • 그 다음, 작은 단계로 로직을 단순화합니다.
    • 이해도가 높아질수록 점진적으로 더 명확한 추상화(abstraction)를 도입합니다.
  4. 작은 진전을 눈에 보이게 축하하기

    • 길었던 함수가 짧아짐
    • 조건 분기의 수가 줄어듦
    • 이름이 더 명확해짐
    • 테스트가 추가됨

이 작은 변화들이 쌓이면, 전면 리라이트의 존재론적 위험을 감수하지 않고도, 코드베이스 전체의 건강 상태를 크게 끌어올릴 수 있습니다.


리팩터링을 덜 두렵게, 더 일상적으로 만들기

리팩터링은 특별하고 위험한 이벤트가 될 필요가 없습니다. 다음과 같은 방식으로 일상적인 개발 루틴 속에 녹여 넣을 수 있습니다.

  • 코드를 언제나 더 나아질 수 있는 초고(draft) 로 바라보기
  • 거대한 한 번의 작업 대신, 작고 초점이 분명한 패스들을 쌓아 가기
  • 탄탄한 테스트를 안전망으로 삼기
  • 도구와 AI를 편집 보조 도구로 적극 활용하기
  • 레거시 코드를 짐이 아니라, 조금씩 다듬어 가는 미완의 원고로 바라보기

빨간 펜 리팩터링 마인드를 가지면, 리팩터링은 다음과 같이 달라집니다.

  • 용기를 내야만 하는 일이 아니라, 장인정신(craft) 에 가까운 작업이 됩니다.
  • “뭔가를 깨뜨리는 것”이 아니라, 코드가 들려주는 이야기를 더 명확히 만드는 일이 됩니다.

모든 것을 한 번에 고칠 필요는 없습니다. 오늘 손대는 그 한 단락, 그 한 함수만 어제보다 조금 더 명확하게 만들면 됩니다. 이런 편집이 쌓이다 보면, 언젠가 그 코드베이스는 기꺼이 계속 손대고 싶은, 그리고 변경이 전혀 두렵지 않은 시스템으로 변해 있을 것입니다.

빨간 펜 리팩터링: 작가처럼 코드를 다듬어 두려움 줄이기 | Rain Lag