유동적 소프트웨어
이 장에서 배우는 것 코드가 파생물이 되면 레거시가 무엇이 되는지, 그리고 무엇을 대신 지켜야 하는지.
레거시란 무엇이었나
지금까지 레거시는 이런 것이었습니다.
아무도 손대기 무서운 오래된 코드.
왜 무서웠습니까? 이해하는 데 드는 비용 때문입니다.
고치는 비용이 방치하는 비용보다 커서 그대로 두는 것이 레거시였습니다.
계산이 무너집니다
코드가 파생물이면 이 계산이 달라집니다.
이해 비용이 재생성 비용보다 크면, 이해하지 않고 다시 만드는 게 합리적입니다.
graph TD
A["낡은 부분 발견"] --> B{"의도와 테스트가 있나?"}
B -->|"있다"| C["같은 의도로 재생성"]
B -->|"없다"| D["기존 방식대로 읽고 고침"]
C --> E["테스트로 동작 동일함 확인"]분기점이 "의도와 테스트가 있나"입니다. 이게 없으면 유동적 소프트웨어는 성립하지 않습니다.
지켜야 할 것이 이동합니다
| 기존 | 유동적 소프트웨어 | |
|---|---|---|
| 자산 | 코드 | 명세 + 테스트 |
| 백업해야 할 것 | 저장소 | 저장소 (의도가 거기 있음) |
| 리뷰 대상 | 코드 변경 | 의도 변경 |
| 기술 부채 | 나쁜 코드 | 부실한 테스트 |
마지막 줄이 중요합니다. 기술 부채의 정의가 바뀝니다.
테스트가 얇으면 그 영역은 재생성할 수 없습니다. 재생성해도 맞는지 확인할 방법이 없기 때문입니다. 그러면 그 영역만 예전처럼 굳어갑니다.
실제로는 어디까지 가능한가
솔직하게 말하면 전부 재생성하는 조직은 드뭅니다. 현실적인 모습은 이렇습니다.
| 영역 | 실제 |
|---|---|
| 새로 만드는 기능 | 의도 + 테스트로 시작. 재생성 가능 |
| 최근 1~2년 코드 | 테스트가 있으면 부분 재생성 |
| 오래된 핵심 로직 | 그대로 유지. 건드리지 않음 |
| 외부 연동 | 계약이 고정되어 있어 재생성 여지 적음 |
새로 만드는 것부터 이 방식으로 하는 게 현실적인 시작입니다. 기존 코드를 전부 전환하려 하면 시작을 못 합니다.
무엇이 좋아지나
1. 스택 이동이 쉬워집니다
언어나 프레임워크를 바꿔야 할 때, 의도와 테스트가 있으면 다시 만들 수 있습니다. 기존에는 이게 몇 달짜리 프로젝트였습니다.
2. 최적화가 쉬워집니다
"동작은 그대로, 성능만 개선"이 명확해집니다. 테스트가 동작을 고정하니까 그 안에서 자유롭게 바꿀 수 있습니다.
3. 코드 리뷰가 짧아집니다
리뷰 대상이 의도로 옮겨갑니다. 구현 세부를 줄 단위로 보는 대신 "이 의도가 맞나, 테스트가 충분한가"를 봅니다.
무엇을 조심해야 하나
테스트가 곧 명세라는 뜻입니다
테스트에 안 적힌 동작은 보장되지 않습니다. 재생성하면 사라질 수 있습니다.
이런 암묵적 계약이 재생성 후 깨집니다. 그래서 실무에서는 재생성 전에 "이 영역에 대해 다른 곳이 무엇을 가정하고 있나"를 확인합니다.
재생성이 항상 답은 아닙니다
작은 수정이면 그냥 고치는 게 빠릅니다. 재생성은 낡아서 이해가 어려운 영역에 쓰는 도구입니다.
확인
1. 레거시의 기존 정의는 무엇이고 왜 그렇게 됐습니까?
답
아무도 손대기 무서운 오래된 코드입니다. 이해하는 비용(읽고, 왜 그런지 추측하고, 깨지는지 확인하는)이 방치하는 비용보다 커서 그대로 두게 된 것입니다.
2. 유동적 소프트웨어에서 기술 부채의 정의는 무엇으로 바뀝니까?
답
테스트가 얇은 영역입니다. 테스트가 없으면 재생성해도 맞는지 확인할 방법이 없어 그 영역만 예전처럼 굳어갑니다.
3. 재생성할 때 가장 조심해야 할 것은?
답
테스트에 안 적힌 암묵적 계약입니다. 응답 필드 존재, 정렬 순서, 오류 문구처럼 다른 곳이 의존하지만 테스트에는 없는 동작이 재생성 후 깨질 수 있습니다.
개념 셋을 봤습니다. 이제 실제 프로세스로 들어갑니다 → 프로세스 4단계 지도