RicoCheesethe studio log · v2.0
Live · KRRead posts
목록으로
뉴스PUBLISHED · 2026년 6월 18일·18 MIN READ

리라이트 vs 리팩터: 레거시 앱을 안전하게 최신 프레임워크로 옮기는 법

JSNation 발표를 정리한 글. 레거시 마이그레이션을 미룰수록 비용이 커지는 이유와, Big Bang·Strangler 두 전략을 실제 사례로 풀어낸다.

#webdev#frontend#programming#javascript#react
Who Here Has Worked with Legacy? The Longer You Wait, the Worse It Gets

개요 #

레거시 애플리케이션은 건드리지 않아도 알아서 낡는다. 그리고 미룰수록 옮기기가 더 힘들고 비싸진다. JSNation에서 "Rewrite or Refactor?"라는 제목으로 발표한 Sylwia Laskowska는 Angular, ASP.NET MVC, React, Backbone 등 온갖 조합의 프론트엔드 앱을 옮겨온 경험을 바탕으로, 레거시 마이그레이션을 둘러싼 현실적인 판단 기준을 정리했다.

핵심은 단순하다. 마이그레이션을 미룰수록 더 어렵고 더 비싸진다. 그리고 가장 나쁜 선택은 아무것도 하지 않는 것이다.

애초에 왜 옮겨야 하나 #

비기술 직군 이해관계자에게서 가장 자주 듣는 질문이 있다. "잘 돌아가는데 왜 굳이 손대나? 개발자들이 이력서에 최신 기술 한 줄 적으려고 그러는 거 아니냐?"

저자의 대답은 솔직하다. 그는 특정 프레임워크의 광팬이 아니다. 프레임워크는 그저 망치 같은 도구일 뿐이다. 다만 무언가를 만들 때는 부품이 떨어져 나간 녹슨 망치보다 멀쩡한 망치를 쥐고 싶을 뿐이다.

하지만 마이그레이션은 개발자 경험만의 문제가 아니다. 결국은 제품의 생존이 걸린 문제다. 기술이 그 어느 때보다 빠르게 바뀌고, AI가 그 속도를 한 번 더 끌어올리는 지금은 더욱 그렇다.

대표적인 게 보안이다. 라이브러리가 더 이상 관리되지 않으면 보안 패치도 끊긴다. 취약점 리포트는 빨갛게 물들기 시작한다. "기능 몇 개 더 넣게 보안은 좀 포기하자"고 말하는 제품 책임자는 없다. 빌드 도구도 마찬가지다. Vite 빌드 하나만으로도 체감 차이가 크다. 빠른 애플리케이션이 곧 더 좋은 애플리케이션이다.

이유는 더 많지만, 기억할 건 하나다. 마이그레이션을 미룰수록 더 어렵고 더 비싸진다.

그래서 어떻게 옮기나 #

흥미롭게도 LLM의 등장이 마이그레이션 전략 자체를 바꾸지는 않았다. 작업이 빨라질 때도, 그렇지 않을 때도 있지만 근본 접근법은 AI 이전과 같다.

시니어 엔지니어 수만큼 전략이 있다지만, 실무에서는 결국 두 갈래로 나뉜다.

리라이트 (Big Bang 전략) #

애플리케이션 전체를 다시 쓴다. 프론트엔드에서 흔히 그렇듯, 오래된 스택을 한 번에 최신 버전으로 끌어올리는 경우도 여기 들어간다.

리팩터 (Strangler 패턴) #

기능을 계속 내놓으면서 애플리케이션을 조각조각 다시 쓴다.

어느 쪽이 더 나을까. 성전(holy war)을 벌일 필요는 없다. 대부분은 프로젝트의 현실이 알아서 답을 정해준다.

애플리케이션이 비교적 작고, 팀이 숙련됐고, 문서가 쓸 만하고, 몇 주에서 몇 달 정도 기능 개발을 멈출 여유가 있다면 리라이트도 충분히 합리적이다. 반대로 규모가 거대하고, 주니어가 많거나 해당 기술에 익숙지 않은 인원이 섞여 있고, 문서가 사실상 없다면 점진적 리팩터가 현실적으로 유일한 선택지다.

물론 고려할 요소는 더 많다. 정리하면 이렇다.

요소리라이트 (Big Bang)리팩터 (Strangler)
애플리케이션 규모작거나 중간
기능 개발잠시 멈출 수 있음계속해야 함
문서화 수준양호부실
팀 숙련도높음들쭉날쭉
리스크 감내높음낮음
첫 결과까지 시간짧음
마이그레이션 중 복잡도낮음높음
무한정 늘어질 위험낮음높음

Big Bang — 듣는 것만큼 무섭지 않다 #

먼저 Big Bang부터 보자. 저자는 이 전략을 꽤 좋아한다고 털어놓는다. 책이나 글에서는 위험하다, 심하면 안티패턴이라고까지 말하는데, 아무도 손대지 못하는 20년 된 자바 모놀리스 얘기라면 그 말이 맞다.

하지만 많은 프론트엔드 앱은 비교적 젊고 비교적 작다. 그런 상황이라면 Big Bang이 오히려 더 빠르고 더 싸게 먹힌다. 전체를 처음부터 다시 쓰는 경우는 요즘 드물지만, 대규모 업그레이드는 흔하다. Angular 7에서 Signals를 쓰는 최신 Angular로, 혹은 클래스 컴포넌트 시절 React에서 훅 기반 최신 React로 넘어가는 식이다.

이런 작업도 일은 많고 옛날 코드를 한참 파헤쳐야 하지만, Strangler 방식보다는 결승선에 훨씬 빨리 닿는다.

작업대 위의 도구를 다루는 모습 Photo by Andrea Piacquadio on Pexels

실제 사례: Angular 7 → 최신 Angular #

오래된 앱이 어쩌다 수년간 업그레이드 없이 방치되는지 의아할 때가 있다. 사실은 놀랄 만큼 쉽다. 제품이 유지보수 모드에 들어가 누구도 적극적으로 손대지 않으면 그냥 그렇게 된다. 이 사례가 딱 그랬다.

그러던 어느 날 이해관계자들이 앱을 크게 확장하고 기능을 여럿 추가하기로 했다. 저자는 보안을 이유로 최신 Angular 업그레이드를 설득했다. 시스템이 민감한 데이터를 저장하고 있었기 때문이다.

결과만 말하면, 개발자 네 명이 넉 달에 걸쳐 최신 버전으로 끌어올렸다. 그리고 예상보다 훨씬 고됐다.

우선 문제의 규모를 과소평가하기 쉽다. 밖에서 보면 "그냥 Angular 올리면 되잖아"처럼 단순해 보인다. 그런데 진짜 골칫거리는 프레임워크 자체가 아니라 그 주변 생태계다. 예컨대 주력 컴포넌트 라이브러리가 12와 13 버전 사이 어디쯤에서 문법을 크게 바꿔버렸다. 손볼 곳이 얼마나 많았을지 상상해 보라. AI가 거들 수는 있지만, 의욕 넘치는 UI 엔지니어가 CSS 클래스명을 갈아엎고 컴포넌트 구조까지 바꿔놨다면 AI도 구해주지 못한다. 결국 손으로 고치게 된다.

일부 서드파티 라이브러리는 이미 오래전 버려진 상태였다. 여기서 기억해 둘 게 있다.

수년째 업데이트가 없고, 만든 사람조차 그 존재를 잊은 듯하고, Node 18에서는 컴파일조차 안 되는 라이브러리는 "돌아가는 코드"가 아니다. 시한폭탄이다.

E2E 테스트도 넉넉히 갖춰뒀지만, 상당수가 컴포넌트 라이브러리 변경 탓에 줄줄이 터졌다. 자동화 테스트라고 늘 구해주는 건 아니라는 얘기다. 또 하나의 교훈은 핫픽스를 위한 탄탄한 브랜칭 전략을 항상 마련해 두라는 것이다. 무언가는 결국 잘못된다고 가정하는 편이 낫다.

다행히 마이그레이션은 성공했다. 빌드 시간이 극적으로 줄었고, 번들 크기도 크게 작아졌다. 새 레이아웃이 예전보다 훨씬 보기 좋아진 덕에 기술 변화를 가장 꺼리던 이해관계자들까지 흡족해했다. 무엇보다 앱이 앞으로의 업그레이드를 받아들일 준비를 갖췄다. 처음엔 우리를 미워하던 QA 팀조차 7년에 한 번 몰아서 올리느니 꾸준히 올리는 편이 낫다고 인정했다.

점진적 마이그레이션 — 두 마리 토끼 잡기 #

앱이 Big Bang을 감당하기엔 너무 크거나, 기능 출시를 멈출 수 없는 경우도 있다. 그럴 때는 점진적 마이그레이션이 유일한 현실적 선택이 된다.

이 단계별 리팩터는 보통 Strangler 패턴으로 구현한다. 다른 방법도 있지만 저자는 이 방식을 특히 좋아한다. 우아하고, 비교적 단순하며, 세계 최대급 기술 기업들이 실전에서 검증한 패턴이기 때문이다.

Strangler 패턴은 이렇게 동작한다. 레거시 앱에서 출발해, 그 옆에 새 앱을 세운다. 앞단에 리버스 프록시를 두고, 어떤 경로를 어느 앱으로 보낼지 결정하게 한다. 거기서부터 화면 단위, 경로 단위로 옮겨 나간다. 시간이 지나면 레거시 앱은 점점 작아지고, 결국 새 앱만 남으면 옛 앱과 리버스 프록시를 함께 걷어낼 수 있다.

이때 두 앱은 인증과 백엔드는 공유하되 프론트엔드 코드는 공유하지 않아야 한다. 그리고 두 앱이 꼭 통신해야 한다면, 이른바 "임시" 어댑터보다는 커스텀 DOM 이벤트처럼 단순한 방식을 강력히 추천한다. 소프트웨어 공학에서 "임시"가 무슨 뜻인지 우리 모두 안다. 영원히라는 뜻이다. 그 어댑터는 눈 깜짝할 새 또 하나의 레거시가 된다.

실제 사례: Backbone → Vue, Strangler 패턴 #

Backbone으로 짜인 오래된 앱이었다. 솔직히 코드는 정말 잘 쓰여 있었지만, 그래도 Backbone이었다. 규모가 크지 않아 이론상 Big Bang도 가능했다. 다만 우리는 스타트업이었고, 어느 날 그 유명한 말을 들었다. "여러분, 아직 존재하지도 않는 기능을 방금 팔았어요. 만들 시간은 석 달입니다. 즐겁게 작업하세요!"

저자의 첫 반응은 "하하, 웃기네요. Backbone으로는 절대 안 만듭니다"였다. 다행히 이해관계자들은 영리했고 Strangler 방식에 동의했다.

팀은 저자 본인과, "TypeScript"라는 단어를 난생처음 들어본 주니어 자바 개발자 둘로 구성됐다. 다행히 둘 다 야심차고 빨리 배웠다. 사실 선택의 여지도 없었다. 이게 이 전략의 또 다른 장점이다. 주니어가 일하면서 배워나갈 수 있다.

저자는 옆에 새 Vue 앱을 만들었다. 회사에 이미 Vue를 아는 사람이 많아 선택은 자연스러웠다. 먼저 로그인 화면을 개념 증명으로 옮겼고, 이어서 고객이 이미 값을 치른 그 반짝이는 새 기능으로 넘어갔다. 이후 1년 동안 화면 단위로 앱을 옮겼다.

결국 Backbone은 완전히 사라졌다. 그 모든 과정에서 다운타임은 0이었다. 고객들은 마이그레이션이 진행 중이라는 사실조차 알아채지 못했다. 앞선 사례처럼 번들은 눈에 띄게 작아졌고 빌드 시간도 크게 개선됐다.

다만 Strangler 방식이 마냥 좋기만 한 건 아니다. 우선 시간이 오래 걸린다. 비교적 작은 앱이었는데도 꼬박 1년이 걸렸다. 끝나지 않는 마이그레이션의 위험도 있다. 마감은 쌓이고 기능은 계속 들어오고, 어느 순간 제품 책임자에게 마이그레이션에 스토리 포인트 몇 개만 떼어 달라고 사정하는 자신을 발견하게 된다.

레거시 코드를 안 건드릴 방법도 없다. 그리고 개발자들은 그걸 싫어한다. "왜 이렇게 복잡하게 만들어요? 이제 기술 스택 두 개를 다 알아야 하잖아요!" 같은 소리를 듣게 된다. 그래서 어느 전략을 고르든, 마이그레이션이 진행되는 동안만큼은 팀의 희생양이 되기 쉽다. 하지만 끝나고 나면 번들은 반으로 줄고, 취약점 리포트의 빨간불은 꺼지고, 고객 불만도 멎는다. 그러면 어느새 회사의 영웅이 되어 있다.

마치며 #

레거시 앱 마이그레이션은 오래된 집을 사는 일과 비슷하다. 집이 낡은 건 당신 탓이 아니지만, 다시 멀쩡하게 되돌리는 건 당신 몫이다. 몇 주 휴가를 내 한 번에 전체를 고칠 수도 있고, 일단 입주한 뒤 방 하나씩 손볼 수도 있다.

진짜로 나쁜 전략은 아무것도 하지 않는 것뿐이다. 늦든 빠르든 결국 옮기게 된다. 다만 그때는 프로덕션 장애 때문에 떠밀려 옮기게 될 뿐이다.

저자가 덧붙인 한마디: 위 이야기들은 실제로 일어난 일이 아니다. 혹은 일어났을지도 모른다. NDA에 묶인 전문가로서, 어떤 회사나 프로젝트도 특정되지 않도록 여러 마이그레이션 경험을 의도적으로 섞었다. 어차피 시간이 좀 지나면 모든 마이그레이션은 신기할 만큼 서로 닮아간다고 한다.


이 글은 위 출처를 바탕으로 한국 독자를 위해 재작성한 기사입니다. 원문의 사실과 수치에 근거하며, 별도의 견해를 포함하지 않습니다.