레거시를 옮기며 (1) 하나씩 바꾸려다 순서를 못 정했습니다

프레임워크, 데이터 접근 방식, 폴더 구조를 하나씩 바꾸려다 순서를 못 정했습니다. 결국 한꺼번에 바꿨고, 그 판단이 어디까지 맞았는지 적었습니다.

기반을 한꺼번에 바꿨습니다 — 오픈소프트랩 기술블로그
오래된 기반을 교체하면서 겪은 일을 다룹니다. 시리즈의 다른 글 보기

안녕하세요. 오픈소프트랩 개발팀입니다.

앞 시리즈 마지막 편에서 기존 코드를 복사해 따로 만들기 시작한 이야기를 했습니다. 그 새 갈래에서 실제로 무엇을 바꿨는지가 이번 시리즈입니다.

10년 가까이 이어온 제품을 다시 만들면서 기반을 통째로 바꿨습니다. 그때 무엇을 잘못 예상했는지 적었습니다.

하나씩 바꾸면 된다고 봤습니다

바꿔야 할 목록은 분명했습니다.

  • 프레임워크가 오래된 버전에 묶여 있음
  • 데이터 접근 코드가 한 방식으로 통일돼 있지 않음
  • 폴더 구조가 기능 추가를 거치며 흐트러짐
  • 빌드와 배포가 수작업 단계에 의존함

리스크를 줄이려면 하나씩 바꾸는 게 맞습니다. 한 번에 하나만 건드리면 문제가 생겨도 원인이 분명하니까요.

그래서 순서를 정하려고 했습니다. 여기서 막혔습니다.

무엇을 먼저 해도 다른 게 걸렸습니다

순서를 짜려고 의존 관계를 그려보니 이렇게 나왔습니다.

프레임워크를 올리려면
  → 데이터 접근 방식이 새 버전과 맞아야 함

데이터 접근 방식을 바꾸려면
  → 폴더 구조가 정리돼 있어야 함 (파일이 여기저기 있음)

폴더 구조를 정리하려면
  → 빌드 설정이 경로를 따라와야 함

빌드 설정을 바꾸려면
  → 프레임워크 버전에 맞는 설정이어야 함

한 바퀴 돌아서 제자리입니다.

물론 이걸 끊는 방법은 있습니다. 중간에 임시 계층을 하나 두고, 옛것과 새것을 동시에 지원하게 만들면 됩니다. 실제로 일부는 그렇게 해봤습니다.

그런데 그 임시 계층이 일이 되는 게 문제였습니다. 두 방식을 다 지원하는 코드를 쓰고, 그게 잘 도는지 확인하고, 나중에 걷어내야 합니다. 걷어낼 때까지 그 코드는 팀 전체가 읽고 지나가야 하는 짐이 됩니다.

임시 계층 세 개를 세울 바에는 한 번에 바꾸는 게 싸겠다는 계산이 나왔습니다.

한꺼번에 바꿨습니다

그래서 순차 교체를 포기했습니다. 다만 조건을 하나 붙였습니다.

동작을 바꾸지 않는다. 기반만 바꾼다.

기능을 개선하고 싶은 욕심이 생기는 지점이었는데, 그걸 섞으면 문제가 생겼을 때 기반 때문인지 기능 때문인지 가릴 수가 없습니다. 개선 항목은 전부 따로 적어두고 나중에 했습니다.

바꾼 것은 이렇습니다.

영역이전이후
프레임워크구버전 전자정부 표준프레임워크상위 버전
애플리케이션 기반레거시 설정 방식스프링 부트
데이터 접근혼재마이바티스로 통일
폴더 구조기능별로 흩어진 상태계층 기준으로 재배치

폴더 구조를 옮긴 것만으로 변경 줄 수가 20만 줄 규모로 잡혔습니다. 실제 로직이 바뀐 건 그중 일부고 대부분은 자리만 옮긴 것인데, 기록상으로는 구분이 안 됩니다. 이게 나중에 문제가 됩니다.

이력이 끊겼습니다

한꺼번에 바꿨을 때 가장 크게 치른 대가가 이거였습니다.

파일이 통째로 이동하면 그 파일의 과거를 따라가기 어려워집니다. 어떤 코드가 왜 그렇게 쓰였는지 알고 싶을 때 보통은 그 줄이 언제 왜 들어왔는지를 봅니다. 그 연결이 끊긴 겁니다.

한동안 이런 대화가 반복됐습니다.

"이 조건은 왜 있는 거예요?"
"모르겠는데요. 이력 보면 전부 '구조 이관'으로 나와요"

전환 전에 남겨둔 문서가 있긴 했지만 코드 옆에 붙어 있는 기록만 못했습니다. 지금은 옮긴 파일과 고친 파일을 나눠서 커밋하는 것을 규칙으로 두고 있습니다. 이동만 있는 커밋은 이동만, 로직 변경은 따로. 그때 알았으면 좋았을 것입니다.

얻은 것과 포기한 것

얻은 것 — 막혀 있던 것이 풀렸습니다. 새 라이브러리를 쓰려다 기반에 걸리는 일이 없어졌고, 빌드 시간도 줄었습니다. 그리고 "이건 기반 때문에 못 합니다"라는 말을 안 하게 됐습니다.

포기한 것 — 전환 기간 동안 새 기능이 거의 안 나갔습니다. 그리고 위에 쓴 대로 이력이 끊겼습니다. 이건 되돌릴 수 없는 손실입니다.

한 번에 바꾸는 방식이 항상 맞다고는 생각하지 않습니다. 저희 경우는 의존 관계가 한 바퀴 돌아서 순서를 못 정하는 상태였기 때문에 고른 겁니다. 그 고리가 없으면 하나씩 하는 게 낫습니다.

다음에 다시 이런 일이 오면

기반 교체는 한 번으로 끝나지 않습니다. 지금 올린 버전도 언젠가 옛것이 됩니다.

그래서 다음을 대비해 두 가지를 해두고 있습니다. 하나는 바깥 라이브러리에 직접 기대는 코드를 줄이는 것입니다. 업무 로직이 특정 라이브러리를 직접 부르면 그 라이브러리를 바꿀 때 업무 로직까지 열어야 합니다. 다른 하나는 버전 올리는 일을 미루지 않는 것입니다. 이번에 어려웠던 이유의 절반은 한 번에 여러 버전을 건너뛰어야 했기 때문입니다.

둘 다 지금은 규칙으로만 있고, 다음 전환 때 얼마나 도움이 될지는 그때 가봐야 알 것 같습니다. 한 가지는 확실합니다. 다음에도 이력은 남기면서 옮기겠습니다.


다음 편에서는 데이터 접근 쪽에서 있었던 일을 다룹니다. 자동으로 바꿀 수 있을 줄 알았던 부분입니다.

오픈소프트랩 개발팀이 작성합니다. 보안 운영 포탈과 생성형 AI 사용 통제를 만들고 있습니다.