← 목록으로
SW공학·관리
#3R#역공학#재공학#재구조화#레거시#133회
최종 업데이트 · 2026-09-30

소프트웨어 유지보수 3R (Reverse Engineering · Restructuring · Reengineering)

1. 개요

가. 정의

노후·복잡해진 소프트웨어의 유지보수성(maintainability)을 높이고 총소유비용(TCO)을 절감하기 위해, 기존 시스템을 분석(역공학)·개선(재구조화)·재구축(재공학)하는 세 가지 대표 기법을 통칭하는 개념(3R).

3R은 서로 독립된 별개의 기법이라기보다 "분석 → 개선 → 재구축"으로 이어지는 하나의 연속선(spectrum) 위에 놓인 활동들이다. 역공학이 "이 시스템이 무엇을, 어떻게 만들어졌는지 이해"하는 단계라면, 재구조화는 "이해한 것을 기능은 그대로 둔 채 더 낫게 정리"하는 단계이고, 재공학은 앞의 둘을 포함해 "다시 만들어내는" 단계다. 따라서 세 기법 중 재공학이 가장 포괄적이며, 역공학과 재구조화를 자신의 부분 공정(sub-process)으로 품는 관계라는 점을 먼저 이해해야 개념의 층위가 흐트러지지 않는다.

이 개념이 하나로 묶여 다뤄지는 이유는, 실무에서 레거시를 손볼 때 이 세 활동이 거의 항상 함께 등장하기 때문이다. 문서가 없는 시스템은 먼저 역공학으로 구조를 복원해야 하고, 복원된 구조는 대개 손볼 곳이 많아 재구조화가 뒤따르며, 플랫폼까지 바꿔야 한다면 재공학으로 확장된다. 즉 3R은 레거시 현대화라는 하나의 목표를 향한 강도(intensity)의 스펙트럼으로 볼 수 있다 — 가장 가벼운 개입이 역공학, 중간이 재구조화, 가장 무거운 개입이 재공학이다.

나. 등장 배경 및 필요성

오래 운영된 레거시(legacy) 시스템은 담당 인력이 여러 차례 교체되고 설계 문서가 유실되면서 시스템의 구조를 온전히 아는 사람이 조직에서 사라지는 상황에 이른다. 여기에 기능 추가·긴급 수정이 오랜 기간 누적되면 코드의 결합도(coupling)가 높아지고 응집도(cohesion)가 낮아지며, 이른바 기술부채(technical debt) 가 복리처럼 불어난다. 이 상태에서는 한 줄의 수정조차 예상치 못한 부작용(ripple effect)을 일으켜, 변경 한 건당 회귀 오류를 검증하는 비용이 기하급수적으로 증가한다. 실제로 소프트웨어 생애주기 총비용의 상당 부분(통상 절반 이상으로 인용된다)이 개발 이후의 유지보수 단계에서 발생한다는 점은 이 문제의 무게를 잘 보여준다.

그렇다고 시스템 전체를 걷어내고 신규 개발(rewrite)로 가면, 수년간 코드 속에만 암묵적으로 축적된 업무 규칙(도메인 지식)이 소실되고, 신·구 시스템 병행 운영에 따르는 위험과 비용이 매우 커진다. 대규모 재작성 프로젝트가 자주 실패하거나 일정을 크게 넘기는 이유가 여기에 있다. 3R은 이 두 극단(방치 vs 전면 재작성) 사이에서, 기존 자산을 최대한 재활용하면서 위험과 비용을 통제 가능한 수준으로 낮추는 절충안을 제공한다. 오늘날 온프레미스 레거시를 클라우드·마이크로서비스(MSA)로 옮기는 레거시 현대화(Legacy Modernization) 흐름 속에서 3R은 그 핵심 실행 수단으로 다시 주목받고 있다.

다. 특징

3R의 첫 번째 특징은 자산 재활용성이다. 세 기법 모두 처음부터 다시 만들지 않고 기존 코드·데이터·업무 규칙을 최대한 살려 쓰므로, 검증된 도메인 지식을 보존하면서 개선을 이룬다. 두 번째 특징은 기능 동등성 보존을 전제로 한다는 점으로, 역공학·재구조화는 겉보기 기능을 전혀 바꾸지 않고 재공학도 기존 기능의 보존을 검증한 뒤에만 향상을 더한다. 세 번째 특징은 연속적 스펙트럼이라는 점이다 — 역공학·재구조화·재공학은 개입 강도가 점점 커지는 단계로, 문제의 성격에 맞춰 필요한 강도만 선택하거나 조합해 적용한다.

2. 3R의 전체 구조와 구분 기준

3R을 정확히 쓰려면 세 기법이 추상화 수준(level of abstraction) 위에서 어떻게 이동하는가로 구분하는 것이 가장 명료하다. 소프트웨어는 요구사항 → 설계·명세 → 구현(코드)이라는 추상화 계단을 갖는데, 각 기법은 이 계단 위에서 서로 다른 방향으로 움직인다.

flowchart LR
  L["레거시 SW(코드·산출물)"] --> RE["Reverse Engineering(역공학)"]
  RE --> RS["Restructuring(재구조화)"]
  RS --> RN["Reengineering(재공학)"]
  RN --> N["현대화된 SW"]
  RE -. "상위 명세 복원" .-> SPEC["설계·명세"]
  SPEC -. "순공학으로 재구현" .-> RN

역공학은 구현(코드)에서 설계·명세라는 상위 개념으로 거슬러 올라가는 상향(bottom-up) 활동이다. 코드를 읽어 그 안에 담긴 자료구조·제어 흐름·업무 규칙을 도표나 명세로 되살리는 것이 목적이며, 시스템의 겉으로 드러나는 동작은 전혀 바꾸지 않는다. 문서가 없는 레거시를 다룰 때 반드시 거쳐야 하는 "이해의 출발점"이며, 뒤따르는 모든 개선의 정확도를 결정한다.

재구조화는 추상화 수준을 옮기지 않고 같은 층위 안에서 표현(representation)만 개선하는 활동이다. 예컨대 코드 계층에 머무르며 스파게티 코드를 모듈로 나누거나, 데이터 계층에 머무르며 정규화가 깨진 스키마를 정리하는 식이다. 겉으로 보이는 기능은 동일하게 유지한 채 내부 품질만 끌어올리는 것이 핵심이므로, 그 효과는 즉각적 기능이 아니라 이후 변경 비용의 절감으로 나타난다.

재공학은 역공학으로 상위 명세를 복원한 뒤, 그 명세를 개선하고 다시 순공학(forward engineering)으로 구현까지 내려오는 "상향 → 하향"의 왕복 활동이다. 세 기법 중 유일하게 겉으로 드러나는 기능·품질·플랫폼까지 바꿀 수 있으며, 그만큼 범위와 위험이 크다. 따라서 재공학은 "왜 지금 재구축해야 하는가"에 대한 비즈니스 정당화가 선행되어야 하는 가장 무거운 개입이다.

기법 주 목적 겉보기 기능 변화 추상화 이동 방향 대표 산출물
역공학 설계·명세 추출(이해) 없음 상향(코드→설계) 복원된 설계도·데이터 모델
재구조화 구조·가독성·복잡도 개선 없음 동일 수준 개선된 코드·스키마
재공학 재구축·품질·플랫폼 향상 있을 수 있음 상향→하향(왕복) 재구축된 시스템

표에서 보듯 세 기법을 가르는 두 축은 "겉보기 기능을 바꾸는가" 와 "추상화 계단 위에서 어디로 이동하는가" 이다. 이 두 질문에 답하면 어떤 상황에서 어느 기법을 써야 하는지가 자연스럽게 결정된다.

3. 각 기법의 심층 이해

가. 역공학(Reverse Engineering)

역공학은 소스코드·실행 바이너리·데이터베이스·화면 등 이미 만들어진 산출물로부터 설계와 명세를 추출·복원하는 활동이다. 본래 제조업에서 완제품을 분해해 설계를 알아내던 개념을 소프트웨어에 가져온 것으로, 핵심은 "만들기"가 아니라 "이해하기"에 있다. 따라서 역공학은 시스템의 동작을 절대 바꾸지 않으며, 오직 지식을 되살리는 데 집중한다.

역공학의 대상은 크게 코드 관점과 데이터 관점으로 나뉜다. 코드 관점에서는 제어 흐름 그래프·호출 관계·클래스 다이어그램을 복원하고, 데이터 관점에서는 물리 스키마로부터 논리 데이터 모델(ERD)을 되살린다. 실무에서는 정적 분석(코드를 실행하지 않고 구조를 분석)과 동적 분석(실행 로그·프로파일링으로 실제 흐름을 관찰)을 병행해 정확도를 높인다. 예를 들어 20년 된 코볼(COBOL) 기간계 시스템을 다룰 때, 정적 분석만으로는 실제로 어떤 분기가 살아 있는지 알기 어려워 운영 로그 기반 동적 분석으로 "죽은 코드(dead code)"를 식별한다.

역공학이 중요한 이유는, 레거시 현대화의 성패가 "얼마나 정확히 이해했는가"에 좌우되기 때문이다. 이해가 부실하면 뒤따르는 재구조화·재공학이 잘못된 전제 위에 세워져 원래 기능을 훼손한다. 최근에는 대형 언어모델(LLM) 기반 코드 요약·설명 도구가 역공학의 이해 속도를 크게 끌어올리고 있으나, 자동 복원 결과에는 오류가 섞일 수 있어 반드시 사람의 검증이 뒤따라야 한다.

나. 재구조화(Restructuring)

재구조화는 외부에서 보이는 기능·동작을 그대로 유지한 채 내부의 코드·구조·표현만 개선하는 활동이다. 목적은 가독성·모듈성을 높이고 순환 복잡도(cyclomatic complexity)와 중복을 낮춰, 이후의 변경을 더 쉽고 안전하게 만드는 데 있다. "지금 당장 새 기능을 주는 것"이 아니라 "앞으로의 변경 비용을 낮추는 것"이 재구조화의 가치이므로, 그 효과는 즉각적 매출이 아니라 유지보수 생산성으로 나타난다.

재구조화의 전형적 작업으로는 긴 함수를 의미 단위로 분할하기, 중복 로직을 공통 모듈로 추출하기, 깊게 중첩된 조건문을 평탄화하기, 매직 넘버를 상수화하기 등이 있다. 데이터 측면에서는 반정규화로 얽힌 테이블을 정규화하거나 참조 무결성 제약을 복원하는 작업이 여기에 해당한다. 중요한 전제는 재구조화 전후로 겉보기 동작이 완전히 같아야 한다는 점이며, 이를 보장하는 안전장치가 회귀 테스트다. 테스트가 부족한 레거시에서는 재구조화에 앞서 특성화 테스트(characterization test)를 먼저 확보해 현재 동작을 "고정"한 뒤 손대는 것이 정석이다.

재구조화가 자주 리팩터링과 혼동되지만, 둘은 층위가 다르다. 재구조화는 코드·데이터·아키텍처를 아우르는 넓은 개념이고, 리팩터링은 그중 소스코드 수준에서 작은 단위로 반복 적용하는 실천 기법이다. 예컨대 대형 은행 시스템에서 "결제 모듈을 계층 구조로 재편"하는 것은 재구조화이며, 그 과정에서 개별 함수를 쪼개고 이름을 바꾸는 것은 리팩터링이다.

다. 재공학(Reengineering)

재공학은 역공학 + 개선 + 순공학을 하나로 결합해 시스템을 재구축하는 가장 포괄적인 활동이다. 먼저 역공학으로 기존 시스템의 설계와 업무 규칙을 복원하고, 복원된 명세에서 결함·중복·낡은 설계를 제거해 개선한 뒤, 개선된 명세를 바탕으로 새 플랫폼·언어·아키텍처에 맞게 순공학으로 재구현한다. 이 과정에서 겉보기 기능이 향상되거나 플랫폼이 통째로 바뀔 수 있다는 점이 재구조화와 결정적으로 다르다.

재공학의 강점은 축적된 도메인 지식을 보존하면서도 시스템을 근본적으로 개선할 수 있다는 데 있다. 예를 들어 메인프레임의 코볼 기간계를 자바 기반 웹 시스템으로 옮기는 프로젝트는, 화면과 데이터를 처음부터 다시 상상하는 것이 아니라 기존 업무 규칙을 역공학으로 확보한 뒤 그 규칙을 새 플랫폼에 재구현하는 재공학의 전형이다. 이렇게 하면 "무엇을 계산해야 하는가"라는 검증된 지식을 유지하면서 기술 스택만 현대화할 수 있다.

다만 재공학은 세 기법 중 범위와 위험이 가장 크므로, 무엇을 어디까지 바꿀지에 대한 명확한 목표 설정과 단계적 이행 전략이 필수다. 흔히 쓰는 방식은 시스템을 한 번에 교체하는 빅뱅(big-bang)이 아니라, 기능 단위로 신규 시스템에 점진 이관하면서 구 시스템 앞단에 중계 계층을 두는 스트랭글러 무화과(Strangler Fig) 패턴이다. 이 방식은 이관 중에도 서비스를 멈추지 않고, 문제가 생기면 해당 기능만 롤백할 수 있어 위험을 크게 낮춘다.

4. 재공학 프로세스와 관련 개념

재공학이 세 기법을 어떻게 하나의 흐름으로 엮는지는 다음 프로세스 다이어그램으로 볼 수 있다.

flowchart TD
  A["분석·역공학(현행 구조·업무규칙 복원)"] --> B["개선·재구조화(설계 결함·중복 제거)"]
  B --> C["변환·순공학(신 플랫폼 재구현)"]
  C --> D["테스트·이행(회귀검증·병행운영)"]
  D --> E["운영 반영·안정화"]
  D -. "기능 불일치 발견" .-> A

재공학은 먼저 분석·역공학으로 기존 시스템의 구조와 업무 규칙을 복원하고, 개선·재구조화로 설계 결함과 중복을 제거하며, 변환·순공학으로 새 플랫폼·구조에 맞게 재구현한 뒤, 테스트·이행으로 기존 기능이 보존되었는지 검증하고 운영에 반영한다. 이 흐름에서 가장 중요한 통제점은 마지막 테스트 단계다. 재구축 이후에도 원래 기능이 동일하게 동작함을 회귀 테스트(regression test) 로 반드시 확인해야 하며, 기능 불일치가 발견되면 분석 단계로 되돌아가는 반복 구조를 갖는다. 실무에서는 신·구 시스템에 같은 입력을 넣어 출력을 비교하는 병행 운영(parallel run) 으로 이 검증을 대규모로 수행하며, 계산 결과가 최소 단위까지 일치할 때 비로소 구 시스템을 폐기한다.

3R은 인접 개념과 자주 혼동되므로 관계를 정리해 둘 필요가 있다. 특히 순공학·마이그레이션·리팩터링이 3R의 어디에 위치하는지를 알면 개념이 명료해진다.

개념 설명 3R과의 관계
Forward Engineering(순공학) 명세 → 설계 → 구현의 정방향 개발 재공학의 마지막 공정
Migration(이식) 플랫폼·언어·DB를 다른 환경으로 옮김 재공학의 한 형태·부분
Refactoring(리팩터링) 외부 동작을 유지하며 내부 구조 개선 재구조화를 코드 단위로 실천

리팩터링은 재구조화의 개념을 소스코드 수준에서 작은 단위로 반복 적용하는 실천 기법이고, 마이그레이션은 재공학 과정에서 대상 환경(플랫폼·언어·DB)을 바꾸는 특수 사례로 볼 수 있다. 따라서 "마이그레이션했다"는 말은 대개 재공학의 일부를 수행했다는 뜻이며, "리팩터링했다"는 말은 재구조화를 국소적으로 실천했다는 뜻이 된다.

이처럼 인접 개념을 3R의 좌표 위에 위치시키면 실무 대화의 혼선을 줄일 수 있다. 현장에서 "리엔지니어링"과 "리라이트(rewrite)"가 뒤섞여 쓰이는 경우가 많은데, 리라이트는 기존 자산을 버리고 처음부터 만드는 것이므로 자산 재활용을 전제로 하는 3R과는 지향이 다르다. 기술사는 제안·설계 문서에서 이 용어들을 정확히 구분해 사용함으로써, 프로젝트의 범위·위험·비용에 대한 이해관계자의 기대를 처음부터 정렬시켜야 한다.

5. 기법 선택 기준과 적용 사례

세 기법 중 무엇을 적용할지는 유행이 아니라 문제의 성격과 목표로 판단해야 한다. "구조를 아무도 모른다"가 문제라면 역공학이 먼저이고, "구조는 알지만 손대기 두렵다"가 문제라면 재구조화이며, "플랫폼 자체가 수명을 다했다"가 문제라면 재공학이 답이 된다. 즉 진단 없이 곧바로 재공학으로 뛰어드는 것은, 병의 원인을 모른 채 대수술을 감행하는 것과 같다.

판단을 도우려면 세 가지 신호를 본다. 첫째는 변경 빈도로, 자주 바뀌는 모듈일수록 재구조화·재공학의 투자 회수가 빠르다. 둘째는 결함 밀도로, 특정 모듈에 장애가 집중된다면 그 부분이 우선 개선 대상이다. 셋째는 인력 이해도로, 아무도 이해하지 못하는 영역은 역공학으로 지식을 먼저 복원해야 한다. 이 세 신호가 모두 높은 모듈이 3R 투자 우선순위의 맨 앞에 놓인다.

구체적 예로, 어느 유통사의 정산 배치가 매월 마감 때마다 수 시간씩 지연되고 담당자가 퇴사해 아무도 로직을 설명하지 못하는 상황을 가정하자. 이때 곧바로 재작성에 착수하면 검증되지 않은 정산 규칙이 유실될 위험이 크다. 올바른 순서는 먼저 역공학으로 배치의 계산 규칙과 데이터 흐름을 복원해 명세로 남기고, 특성화 테스트로 현재 산출값을 고정한 뒤, 병목이 되는 반복 조회 로직을 재구조화하고, 필요하면 배치 엔진 자체를 재공학으로 교체하는 것이다. 이렇게 단계를 밟으면 "월 마감 지연 수 시간"이라는 겉으로 드러난 증상 뒤의 근본 원인을 안전하게 제거할 수 있다.

또 다른 사례로, 특정 언어·런타임의 지원 종료(End of Support)가 임박한 시스템은 보안 패치가 끊기므로 재공학이 사실상 강제된다. 이 경우에는 기능 개선보다 "동등 기능을 지원되는 플랫폼에서 재현"하는 것이 1차 목표가 되며, 여기서도 역공학으로 확보한 명세와 회귀 테스트가 이행의 안전판 역할을 한다. 결국 세 기법은 상황에 따라 단독으로도, 조합으로도 쓰이지만, 공통적으로 "이해 → 검증 → 개선"의 순서를 지켜야 실패하지 않는다.

6. 심화: 클라우드 현대화 전략과의 연계 및 최신 동향

3R은 근래 클라우드 전환 담론과 만나며 더 넓은 실행 전략으로 확장되었다. 클라우드 마이그레이션에서 널리 인용되는 6R/7R 프레임워크(Rehost·Replatform·Refactor·Rearchitect·Rebuild·Replace, 그리고 Retain·Retire를 더한 확장)는 사실상 "레거시를 얼마나 깊이 손댈 것인가"의 스펙트럼이며, 이 중 Refactor·Rearchitect·Rebuild가 3R의 재구조화·재공학과 직접 맞닿는다. 예를 들어 서버만 클라우드로 옮기는 Rehost(lift-and-shift)는 3R을 거의 쓰지 않지만, 애플리케이션 구조를 컨테이너·MSA에 맞게 재편하는 Rearchitect는 역공학·재구조화·재공학을 모두 동원한다.

실무 적용 사례로, 국내외 금융·공공 기관의 차세대 시스템 구축은 대부분 메인프레임 기간계의 재공학 프로젝트다. 수백만 라인 규모의 코볼 자산을 자바·클라우드로 옮기면서, 자동 변환 도구로 1차 코드를 생성한 뒤 사람이 업무 규칙을 검증·정정하는 방식이 표준화되어 있다. 이때 병행 운영 기간에 신·구 시스템의 계산 결과가 원(₩) 단위까지 일치하는지를 대사(reconciliation)하는 것이 이행 성공의 관문이 된다.

가장 주목할 최신 동향은 AI 기반 코드 분석·자동 변환의 확산이다. LLM 기반 도구는 역공학 단계에서 낯선 코드의 의도를 요약하고, 재구조화 단계에서 리팩터링 후보를 제안하며, 변환 단계에서 레거시 언어를 현대 언어로 옮기는 초안을 만들어 준다. 이로써 사람이 코드를 읽고 이해하는 데 드는 시간이 크게 줄어드는 것은 분명한 이점이다. 다만 자동 변환 결과에는 미묘한 의미 오류나 환각(hallucination)이 섞일 수 있으므로, 테스트 기반 검증과 사람의 최종 확인을 반드시 거쳐야 품질을 담보할 수 있다. 기술사 관점에서는 AI를 "이해·초안 생성의 가속기"로 위치시키되, 정확성의 최종 책임은 여전히 검증 체계에 두는 균형이 요구된다.

7. 고려사항 및 시사점

기술사 관점에서 3R의 성패는 결국 "무엇을, 왜, 어디까지 손댈지"의 판단에 달려 있다. 다음 네 가지를 전략적으로 고려해야 한다.

  • 대상 우선순위화(트레이드오프): 모든 레거시를 재공학할 수는 없다. 유지보수 비용·비즈니스 중요도·기술부채 수준·변경 빈도를 축으로 포트폴리오를 평가해, 비용 대비 효과가 큰 시스템부터 손대야 한다. 변경이 거의 없고 안정적인 시스템은 오히려 Retain(유지)이 합리적일 수 있다.
  • 기능 보존의 보장 체계: 3R의 최대 위험은 재구축 과정에서 검증되지 않은 업무 규칙이 유실되는 것이다. 따라서 특성화 테스트로 현행 동작을 고정하고, 회귀 테스트·병행 운영·결과 대사로 기능 동등성을 입증하는 안전망을 사전에 구축해야 한다.
  • 점진적 이행 전략: 빅뱅 전환은 위험이 크므로, 스트랭글러 무화과 패턴처럼 기능 단위로 점진 이관하고 문제 시 롤백 가능한 구조를 택하는 것이 바람직하다. 이는 서비스 연속성과 위험 통제를 동시에 달성한다.
  • 현대화 전략 및 AI 활용과의 연계: 3R은 클라우드·MSA 전환(6R/7R)의 실행 엔진이며, AI 기반 분석·변환 도구로 역공학·변환의 효율을 크게 높일 수 있다. 다만 자동화 결과는 반드시 검증을 전제로 하고, 도메인 지식을 아는 인력의 참여를 유지해야 현대화의 품질과 지속가능성이 확보된다.

한 줄 요약: 3R은 역공학(설계 추출)·재구조화(구조 개선)·재공학(재구축) 으로 이어지는 레거시 개선 스펙트럼으로, 추상화 이동 방향과 기능 변화 여부로 구분되며, 대상 우선순위화·회귀 테스트 기반 기능 보존·점진적 이행을 전제로 클라우드·MSA 현대화(6R/7R)와 AI 자동화의 핵심 실행 수단이 된다.