앱 개발의 레거시 — 개념, 위험 및 작업 전략

저자: IT Sectr 게시일: 2026-07-27 읽는 시간: 7 분

레거시 — 단순한 오래된 코드가 아닙니다. 비즈니스에 수익을 가져다주지만 개발을 지연시키는 작동 중인 시스템입니다. 모바일 개발에서 레거시는 Objective-C로 작성되었거나, 오래된 라이브러리나 아키텍처 패턴을 사용할 수 있습니다. CAST Software(2024)의 보고서에 따르면, 엔터프라이즈 프로젝트의 코드 한 줄 평균 수명은 14년을 초과합니다. 레거시 작업 전략에 따라 그것이 걸림돌이 될지, 관리 가능한 자산으로 남을지 결정됩니다.

핵심 내용

  • 레거시 — 프로덕션에서 실행되지만 오래된 기술이나 접근 방식을 사용하는 코드
  • 레거시 유지보수는 역사적 결정의 이해와 신중한 리팩토링이 필요합니다
  • 마이그레이션 전략 — Strangler Fig를 통한 제품 중단 없는 단계적 모듈 교체
  • 레거시 테스트 — characterization tests로 리팩토링 전 현재 동작 기록
  • 코드 수명 자체는 문제가 아닙니다 — 문제는 테스트와 아키텍처 비전의 부재입니다

앱 개발에서 레거시란

레거시 — 프로덕션에서 계속 실행되지만 더 이상 최신 품질 기준을 충족하지 않는 코드 또는 시스템입니다. 레거시는 오래된 언어(예: Objective-C, Swift 대신)로 작성되거나, 지원되지 않는 라이브러리 또는 오랫동안 안티패턴으로 간주된 아키텍처 패턴을 사용할 수 있습니다.

레거시의 주요 특징은 테스트의 부재입니다. Michael Feathers(2004)의 정의에 따르면, 레거시 코드는 테스트가 없는 코드입니다. 안전하게 동작을 변경할 수 없다면, 시스템은 수명에 관계없이 레거시 상태에 있습니다. 단위 테스트가 없는 새로운 코드는 첫날부터 레거시입니다.

레거시가 반드시 나쁜 것은 아닙니다. Java 8로 잘 설계된 시스템은 코루틴을 사용하는 Kotlin의 혼란스러운 코드보다 더 안정적이고 이해하기 쉬울 수 있습니다. 코드 수명은 품질의 지표가 아닙니다 — 중요한 것은 시스템을 얼마나 쉽게 변경하고 확장할 수 있는지입니다.

레거시 코드가 정상적인 이유

모든 성공적인 시스템은 시간이 지남에 따라 레거시가 됩니다. 이것은 자연스러운 과정입니다: 기술은 코드가 다시 작성되는 것보다 빠르게 발전합니다. 5년 전 Swift 2로 작성된 앱은 생성 당시에는 현대적이었지만, 오늘날에는 레거시입니다.

레거시의 비즈니스 가치는 종종 과소평가됩니다. 시스템은 안정적으로 작동하고, 트랜잭션을 처리하며, 데이터를 저장합니다 — 재작성에는 위험이 따릅니다. Standish Group(2024)에 따르면, 전체 재작성 프로젝트의 35%가 실패로 끝납니다. 경제적으로는 레거시를 제거하는 것이 아니라, 그것과 함께 작업하는 법을 배우는 것이 타당합니다.

최고의 전략은 점진적 마이그레이션, 새 인터페이스 뒤에 이전 코드 캡슐화, 그리고 자동화된 테스트입니다. 레거시는 예측 가능한 비용으로 변경할 수 없게 될 때만 문제가 됩니다.

레거시 시스템의 주요 징후

자동화된 테스트 부족 — 주요 지표입니다. 한 줄을 변경한 후 개발자가 테스트를 실행하고 아무것도 깨지지 않았음을 확인할 수 없다면, 그것은 레거시입니다. 추가 징후: 배포 프로세스에 몇 시간이 걸리고 수동 단계가 필요합니다.

문서화가 코드와 일치하지 않음 — 또 다른 표시입니다. 아키텍처 다이어그램은 구식이고, 주석은 이미 변경된 동작을 설명합니다. 새 개발자의 적응 시간이 한 달을 초과합니다 — 높은 복잡성과 낮은 유지보수성의 신호입니다.

추가 징후: 명확한 경계가 없는 모놀리식 아키텍처, 주요 검증 방법으로서의 수동 테스트, 긴 CI 파이프라인(30분 초과), 최신 버전이 아닌 라이브러리 사용, 관련 모듈을 깨뜨리지 않고 의존성을 업데이트할 수 없는 경우.

취약한 코드 현상 — 한 곳의 변경이 세 곳을 깨뜨립니다. 이것은 모듈이 서로에 대해 너무 많이 알 때 발생하는 강한 결합의 결과입니다. 결합도가 높을수록 시스템은 더 빨리 레거시 범주로 전환됩니다.

구식 코드 작업의 위험

속도 저하 — 주요 위험입니다. 간단한 기능 추가에 코드 연구에 몇 시간, 테스트에 며칠이 소요됩니다. Stripe(2024)에 따르면, 개발자는 시간의 33%를 기술 부채 해결에 사용하며, 이는 프로젝트 내 레거시 모듈 존재와 직접적으로 관련됩니다.

전문 지식 유출 — 원본 코드 작성자가 회사를 떠나고 문서화가 불완전합니다. 새 개발자는 낯선 모듈을 건드리는 것을 두려워하여 코드 동결 효과를 초래합니다: 모듈은 진화하지 않지만 계속 작동합니다. 이러한 시스템의 버스 팩터는 심각하게 낮습니다.

보안 — 오래된 라이브러리에는 알려진 취약점이 포함됩니다. Java 프로젝트에서 OpenSSL 1.0.2 또는 이전 버전의 Jackson을 사용하는 것은 비즈니스의 평판과 고객을 희생시킬 수 있는 보안 사고로 가는 직접적인 경로입니다.

팀 동기 저하 — 개선 전략 없이 레거시로 작업하면 개발자 만족도가 떨어집니다. 팀은 제품에 대한 자부심을 잃고, 직원 이직률이 증가하며, 이는 시스템 개발을 더욱 지연시킵니다.

레거시 리팩토링 전략

Characterization tests — 레거시 코드 변경 전 첫 번째 단계입니다. 알려진 입력 데이터로 코드를 실행하고 예상 출력을 기록합니다. 이 테스트는 현재 동작을 사양으로 캡처합니다. Golden master testing은 출력을 참조 파일과 비교하는 변형입니다.

Seam 분석 — 동작 변경 없이 결합을 끊을 수 있는 지점을 찾습니다. Michael Feathers는 여러 유형의 seam을 식별합니다: preprocessor seam, object seam, link seam. Object seam이 가장 일반적입니다: 인터페이스를 통해 실제 객체를 테스트 스텁으로 교체합니다.

Sprout method와 Sprout class — 기존 코드 내부가 아닌 옆에 새 코드를 추가하는 기술입니다. 기존 메서드를 수정하는 대신 원하는 로직으로 새 메서드를 만들고 기존 메서드에서 호출합니다. 이렇게 하면 작동 중인 코드를 손상시킬 위험이 최소화됩니다.

예제: 레거시에 로깅 추가

groovy
class LegacyPaymentProcessor {
    def process(payment) {
        // 건드리면 안 되는 레거시 코드 200줄
        logPayment(payment) // sprout 메서드
    }
    def logPayment(payment) {
        // 레거시 옆에 추가된 새 코드
    }
}

최신 기술 스택으로 마이그레이션

Strangler Fig 패턴 — 레거시 마이그레이션에 권장되는 접근 방식입니다. 새 모듈을 병렬로 생성하고 트래픽을 점차 이전에서 새로 전환합니다. 이전 모듈은 요청 수신을 중단하면 자연스럽게 소멸됩니다. 이 패턴은 위험을 최소화하고 문제 발생 시 롤백을 허용합니다.

Branch by Abstraction — 이전 구현과 새 구현 위에 추상화를 만드는 기술입니다. 클라이언트 코드는 추상화로 전환되고 이전 구현은 점차 교체됩니다. : 통합 NetworkService 프로토콜을 통해 네트워킹 레이어를 AFNetworking에서 Alamofire로 교체.

단계적 마이그레이션 — 전환을 작은 단계로 나눕니다: 이전 모듈 캡슐화 → 테스트 작성 → 새 모듈 생성 → 병렬 실행 → 이전 모듈 제거. 각 단계는 안정적인 시스템 상태로 종료되어 언제든지 배포가 가능합니다.

자주 묻는 질문

레거시를 완전히 다시 작성해야 합니까?

완전한 재작성은 가장 위험한 선택입니다. 프로젝트의 25%만 Big Rewrite가 기한 내에 성공합니다. Strangler Fig 패턴을 적용하는 것이 좋습니다: 제품을 중단하지 않고 모듈을 점진적으로 교체하세요. 각 반복은 비즈니스 가치를 제공하며 위험은 시간에 걸쳐 분산됩니다.

테스트 없이 레거시 리팩토링을 어떻게 시작합니까?

characterization tests로 시작하세요: 알려진 데이터로 모듈을 실행하고 결과를 기록합니다. Golden master testing은 동작을 캡처하는 간단한 방법입니다. 코드 한 줄을 건드릴 때마다 테스트를 추가하세요. 6개월 후에는 회귀를 방지하는 프레임워크가 갖춰질 것입니다.

레거시를 건드리지 않는 것이 나은 경우는?

시스템이 안정적이고, 빈번한 변경이 필요하지 않으며, 다른 모듈의 개발 속도에 영향을 미치지 않는다면 그대로 두십시오. 고장 나지 않았다면 고치지 마라 — 변경 빈도가 낮은 고립된 레거시 모듈에 합리적인 접근입니다. 비즈니스 변경이 필요할 때만 코드를 건드리세요.

레거시 프로젝트에서 의존성을 어떻게 업데이트합니까?

시맨틱 버저닝을 사용하고 patch → minor → major 순서로 단계적으로 업데이트합니다. 각 라이브러리에 대한 호환성 테스트를 작성합니다. Dependabot 또는 Renovate가 업데이트 PR 생성을 자동화합니다. 라이브러리가 더 이상 사용되지 않는 경우 추상화를 통해 교체를 계획합니다.

레거시와 기술 부채의 차이점은?

기술 부채는 연기된 개선의 비용을 추정하기 위한 은유입니다. 레거시는 이미 구식이 된 특정 시스템이나 코드입니다. 기술 부채는 한 달 안에 축적될 수 있지만, 레거시는 시간이 필요합니다. 모든 기술 부채가 레거시가 되는 것은 아니지만, 모든 레거시에는 기술 부채가 포함됩니다.

요약

  • 레거시 — 수명에 관계없이 테스트가 없는 코드. 커버리지 없는 새 코드는 첫날부터 레거시
  • 코드 수명 — 문제가 아닙니다. 문제는 높은 결합도, 테스트 및 문서화 부족
  • Characterization tests — 레거시 모듈 변경 전 동작 캡처를 위한 첫 번째 단계
  • Strangler Fig 패턴 — 단계적 모듈 교체를 통한 안전한 마이그레이션 전략
  • Sprout method — 손상 위험 없이 이전 코드 옆에 새 코드를 추가하는 기술
  • 전체 재작성의 35% 실패 — 단계적 마이그레이션이 Big Rewrite보다 신뢰성 높음
  • 고립된 레거시는 변경 빈도가 낮으면 건드리지 않는 것이 좋음

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기