아날로그 리팩터 스토리보드: Git을 건드리기 전에 레거시 코드 변경을 4컷 만화처럼 설계하기
레거시 리팩터를 만화식 스토리보드처럼 다루면, 복잡한 변경의 리스크를 줄이고 팀을 정렬시키며, 한 줄의 코드도 쓰기 전에 계획을 테스트 주도 마이그레이션 경로로 바꿀 수 있다.
소개: 레거시 리팩터는 왜 ‘수술’처럼 느껴질까
레거시 코드를 리팩터링하는 일은 종종 달리는 기차에서 수술하는 것처럼 느껴집니다. 시스템은 이미 프로덕션에서 돌아가고 있고, 사용자는 거기에 의존하고 있으며, 한 번 잘못 건드리면 Git 히스토리는 곧 공포 단편집이 되어 버립니다.
많은 리팩터 실패는 코드를 한 줄도 쓰기 전에 시작됩니다. 문제는 실력이 아니라 공유된, 구체적인 계획의 부재입니다. 목표는 흐릿하고, 단계는 모호하며, 팀은 곧장 코드와 Git 브랜치부터 파기 시작한 뒤 “가면서 맞춰 가면 되겠지”라고 생각합니다.
더 나은 방법이 있습니다. Git을 건드리기 전에, 리팩터를 만화 스토리보드처럼 패널(장면)로 쪼개는 것입니다.
이 글에서는 다음 내용을 다룹니다.
- 복잡한 레거시 변경을 작은 시각적 장면(패널) 으로 바꾸는 법
- 카드, 포스트잇, 화이트보드 같은 아날로그 도구로 리팩터를 설계하는 법
- 각 패널을 테스트와 연결해, 테스트 주도 마이그레이션 경로로 만드는 법
- 스토리보드를 협업·문서화 산출물로 활용하는 법 – AI 도구와 함께 쓰는 경우까지 포함해
왜 리팩터를 스토리보드로 만드는가
스토리보드는 영화와 애니메이션 업계에서는 표준입니다. 감독은 촬영에 들어가기 전에, 주요 장면을 패널로 그려서 흐름, 리스크, 내러티브를 미리 탐색합니다.
리팩터 스토리보드는 이 아이디어를 코드에 적용한 것입니다.
- 각 패널은 하나의 작고 안전한 변경을 나타냅니다.
- 패널은 순서대로 배치되어, 시스템이 어떻게 변화하는지 보여 줍니다.
- 패널을 재배치·삭제·삽입하는 데 몇 분이면 충분합니다. 리베이스는 필요 없습니다.
이 접근이 유용한 이유는 리팩터링의 본질이 시간에 따른 변화이기 때문입니다. Git은 “무엇이 바뀌었는지”를 보여 주고, 스토리보드는 “어떻게, 왜 그렇게 바꿀 것인지”를 보여 줍니다.
스토리보드는 리팩터 실패의 세 가지 전형적인 패턴을 막아 줍니다.
- 모호한 목표 – “좀 깨끗하게 만들자”가 아니라, “X 동작은 유지, Y는 개선, Z는 이후 작업을 위해 노출”처럼 분명해집니다.
- 덩치 큰 변경 – 하나의 괴물 같은 PR 대신, 작고 되돌리기 쉬운 단계 여러 개로 쪼개집니다.
- 팀 내 불일치 – 각자 머릿속에 있던 침묵의 가정이, 토론하고 다듬을 수 있는 명시적 패널로 바뀝니다.
Git에 아무것도 올라가기 전에 이미 리스크가 줄어든 상태가 됩니다.
1단계: 리팩터를 ‘할 일’이 아닌 ‘이야기’로 만들기
“결제 파이프라인 리팩터링” 같은 식으로 작업을 정의하는 대신, 등장인물과 긴장이 있는 이야기로 바꿔 봅니다.
- 등장인물: 사용자, 업스트림 시스템, 다운스트림 서비스, 백그라운드 잡
- 배경: 현재 아키텍처와 그로 인한 고통 지점
- 갈등: 지금 코드에서 망가지거나, 느리거나, 아예 불가능한 것들
- 해결: 리팩터 이후에 반드시 참이 되어야 할 것들
이제 이것을 세 가지 명시적인 목표로 옮깁니다.
- 반드시 동일하게 유지되어야 하는 동작
- 예: “결제 승인 규칙은 달라지지 않는다.”
- 개선되어야 하는 동작
- 예: “재시도 로직을 세 서비스에 복붙하지 않고, 하나로 중앙집중화한다.”
- 사용자 및 다른 시스템에 미치는 영향
- 예: “API 응답은 하위 호환을 유지한다. 로그는 더 구조화된다.”
이 내용을 큰 카드에 적고 보드 맨 위에 붙입니다: 리팩터 의도(Refactor Intent). 이후에 그리는 모든 패널은 이 의도를 뒷받침해야 합니다.
2단계: 마찰이 적은 시각적 도구를 선택하기
시작부터 거대한 다이어그램 툴을 열 필요는 없습니다. 속도를 늦추기만 한다면 오히려 해롭습니다. 필요한 것은 빠르고 버리기 쉬운 산출물입니다.
- 책상 위에 인덱스 카드
- 벽이나 화이트보드에 붙이는 포스트잇
- 간단한 드래그 앤 드롭 다이어그램 도구(Miro, Excalidraw, FigJam 등)
도구가 가져야 할 핵심 속성은 다음과 같습니다.
- 낮은 마찰: 패널을 만들고, 복제하고, 지우는 데 몇 초도 안 걸려야 합니다.
- 재배치 가능: 순서를 바꾸는 데 도구와 싸울 필요가 없어야 합니다.
- 협업 친화적: 여러 사람이 같이 서서 보고, 가리키고, 메모를 남길 수 있어야 합니다.
각 카드나 포스트잇은 하나의 리팩터 단계를 나타냅니다. 예를 들어 이렇게 적습니다.
패널 3:
PaymentGateway인터페이스 도입, 기존 구현은 그 뒤에 유지
텍스트는 만화의 말풍선처럼 짧게 유지하세요. 목적은 스펙 문서를 쓰는 게 아니라, 한눈에 이해되는 명료함입니다.
3단계: 리팩터를 만화 패널로 쪼개기
이제 크고 무서운 리팩터를 작고 순서 있는 패널들의 시퀀스로 바꿉니다.
-
현재 상태를 그려 본다
요청이 지금은 어떻게 흐르는지, 어떤 모듈이 무엇을 호출하는지, 어디가 핵심 꼼수나 핫스팟인지 몇 개의 패널로 스케치합니다. -
최종 상태를 표시한다
리팩터가 끝났을 때 아키텍처가 어떤 모습이어야 하는지, 몇 개의 패널로 보여 줍니다. -
그 사이를 점진적인 변경들로 메운다.
각 패널은 다음을 만족해야 합니다.
- 자급자족(self-contained) – 이 단계만 구현해서 배포해도 안전해야 합니다.
- 목적이 분명 – “대충 정리”보다는 “검증 로직 추출”처럼 구체적이어야 합니다.
- 안전한 롤백 지점 – 이 커밋만 되돌려도 앱이 망가지지 않아야 합니다.
예시 시퀀스:
- 패널 1: 기능 플래그
new_payment_flow추가(기본값 off). - 패널 2: 검증 로직을
PaymentValidator로 추출, 아직은 기존 플로우에서만 사용. - 패널 3:
PaymentGateway인터페이스 도입, 기존 게이트웨이를 여기에 맞게 어댑트. - 패널 4: 동일 인터페이스 뒤에 새로운 게이트웨이 구현, 기능 플래그로 가린다.
- 패널 5: 트래픽의 일부만 점진적으로 새 게이트웨이로 라우팅.
- 패널 6: 안정화 기간 후 레거시 게이트웨이 제거.
- 패널 7: 완전히 마이그레이션되면 기능 플래그 삭제.
보면 각 패널이 작은 커밋처럼 보입니다. 의도된 것입니다. 좋은 리팩터는 점진적입니다. 스토리보드는 코드를 쓰기 전에 그 구조를 눈에 보이게 만듭니다.
4단계: 각 패널에 테스트를 연결하기
스토리보드는 예쁜 순서도로 끝나면 안 됩니다. 실제로는 테스트 주도 마이그레이션 경로가 되어야 합니다.
각 패널마다 두 가지 질문에 답해 봅니다.
- 이 패널이 ‘완료’되었다고 말하려면 어떤 테스트가 새로 필요하거나 업데이트되어야 하는가?
- 이 단계 이후에도 반드시 그대로 유지되어야 하는 동작은 무엇인가? (회귀 방지 가드레일)
이 내용을 카드 위에 직접 쓰거나, 카드 아래 체크리스트로 붙여도 좋습니다.
테스트가 달린 예시 패널:
패널 3:
PaymentGateway인터페이스 도입
- 추가/수정할 테스트:
PaymentGateway계약을 검증하는 새로운 단위 테스트- 기존 결제 플로우가 모두 통과하는 통합 테스트 유지
- 동작 보장:
- 결제 성공/실패 비율이 변하지 않는다
- 로그와 메트릭은 이전과 동일하게 남는다
이 작업은 세 가지 효과를 가져옵니다.
- 각 단계의 스코프를 정직하게 바라보게 해 줍니다.
- “테스트는 나중에…”라는 미루기를 줄여 줍니다.
- 스토리보드를 구현 단계에서 사용할 수 있는 살아 있는 TDD 가이드로 만들어 줍니다.
이제 실제 코딩에 들어가면 “이제 뭘 하지?”라고 묻지 않아도 됩니다. 패널을 따라가면서, 단계별로 테스트를 추가·수정하면 됩니다.
5단계: 코드가 아닌 아날로그 보드를 중심으로 협업하기
코드 리뷰가 문제를 일으키는 경우 중 상당수는, 리뷰가 팀이 처음으로 계획을 보는 순간이기 때문입니다. 이미 방향을 바꾸기 비싼 시점에 이름, 패턴, 아키텍처를 두고 논쟁이 벌어집니다.
아날로그 스토리보드는 그 논의를 더 이르고 더 싼 시점으로 옮겨 줍니다.
- 엔지니어들은 순서에 대해 토론할 수 있습니다.
(“새 게이트웨이를 추가하기 전에 인터페이스부터 도입해야 하지 않을까?”) - 사람들은 대체 경로를 제안할 수 있습니다.
(“여기서는 스트랭글러 패턴을 쓰는 게 더 낫지 않을까?”) - PO와 QA는 사용자 영향과 코너 케이스를 옆에 적어 넣을 수 있습니다.
카드와 포스트잇으로 작업하면, 구현 세부사항에 너무 일찍 매달리는 ‘바이크셰딩’을 피할 수 있습니다. “이걸 PaymentOrchestrator라고 부를까, PaymentManager라고 부를까?” 대신, 무엇을 어떤 순서로 바꿔야 하는지에 집중하게 됩니다.
실용적인 패턴 몇 가지:
- 벽 앞 스탠드업: 5–10분 동안 현재 스토리보드와 오늘 처리할 패널을 같이 훑어봅니다.
- 리팩터 계획 회의: 맨 위의 리팩터 의도 카드부터 시작해, 각 패널을 마치 이야기를 들려주듯 순서대로 설명합니다.
- 주석 추가: 리스크, 의존성, 열린 질문은 펜 색을 다르게 해서 표시합니다.
에디터를 열 때쯤이면, 팀은 이미 “좋은 결과”가 무엇인지에 대해 상당히 합의를 이룬 상태가 됩니다.
6단계: 스토리보드에서 Git 히스토리로, 그리고 다시 돌아오기
코딩을 시작하면, 스토리보드를 미래의 자신과 맺은 계약처럼 다뤄 보세요.
- 패널 하나당 한두 개 정도의 커밋을 목표로 합니다.
- 커밋 메시지에 패널 ID를 넣습니다. 예:
feat: Panel 3 – Introduce PaymentGateway interface - 작업하는 동안 스토리보드를 항상 눈에 보이는 곳에 둡니다.
리팩터를 배포한 뒤에는 강력한 피드백 루프가 생깁니다.
-
스토리보드와 Git 히스토리를 비교합니다.
- 어떤 패널은 계획과 정확히 일치했나요?
- 어디서 벗어났고, 그 이유는 무엇이었나요?
-
그 교훈을 스토리보드에 바로 적어 둡니다.
- “패널 4는 예기치 않은 결합 때문에 두 커밋으로 나뉨.”
- “패널 6은 불필요, 레거시 게이트웨이를 더 일찍 제거함.”
-
이것을 문서화·온보딩 자료로 활용합니다.
- 새 팀원은 무엇이 바뀌었는지만이 아니라, 왜, 어떤 순서로 바뀌었는지를 한눈에 볼 수 있습니다.
AI 도구로 리팩터 제안을 생성하고 있다면, 스토리보드는 훌륭한 기준점이 됩니다.
- AI가 제안한 변경 시퀀스를 여러분의 패널 시퀀스와 비교합니다.
- 괜찮은 아이디어는 코드를 건드리기 전에 스토리보드에 먼저 흡수합니다.
- 리팩터 의도와 충돌하는 AI 변경을 무비판적으로 수용하는 일을 피합니다.
이렇게 하면 스토리보드는 개별 PR을 넘어서는 설계 의도의 살아 있는 아티팩트가 됩니다.
마무리: 전부 합쳐 보기
아날로그 리팩터 스토리보드는 겉으로 보기에는 단순합니다.
- 의도를 명확히 한다: 무엇을 유지하고, 무엇을 개선하며, 누구에게 영향이 있는지 정의합니다.
- 마찰이 낮은 도구를 쓴다: 카드, 포스트잇, 간단한 다이어그램 등 몇 초 만에 재배치 가능한 도구를 사용합니다.
- 패널로 쪼갠다: 각 패널은 목적이 분명하고, 되돌릴 수 있는 작은 단계입니다.
- 테스트와 짝지운다: 각 패널마다 필요한 테스트와 반드시 지켜야 할 보장을 정의합니다.
- 일찍 협업한다: 디프가 아니라 스토리보드를 두고 토론하면서 팀을 정렬시킵니다.
- 루프를 닫는다: 스토리보드와 실제 Git 히스토리를 비교해 접근 방식을 계속 다듬습니다.
얻을 수 있는 이득은 큽니다. 예기치 않은 실패는 줄고, Git 히스토리는 더 깨끗해지며, 의도는 더 분명해지고, 팀은 리팩터가 왜 그런 모습이 되었는지를 이해하게 됩니다.
다음에 끔찍한 레거시 코드 덩어리를 마주하게 되면, 에디터부터 여는 유혹을 참아 보세요. 인덱스 카드를 집어 들고, 리팩터를 만화처럼 스케치한 뒤, 코드를 이끄는 것은 스토리보드가 되게 하고, 그 반대가 되지 않도록 해 보세요.