RFC: Discourse를 위한 새로운 버전 관리 전략

라이브러리든 더 큰 애플리케이션이든 사실 큰 차이는 없습니다. 시맨틱 버전 관리(such as semver) 방식은 대형 애플리케이션에도 완벽하게 잘 작동합니다. 플랫폼으로 번들링된 애플리케이션 모음에도 사용할 수 있지만, 이 경우 적용하기가 꽤 어려워집니다.

주된 질문은 특정 릴리스에서 지원되는 비추천(deprecation) 기능을 도입하고, 다음 메이저 버전에서만 이를 제거하는 경로를 선택하는 것이냐는 것입니다. 비추천되었지만 여전히 지원되는 기능을 유지하는 것은 상당한 노력이 필요합니다. 영속 데이터 모델(persisted data model)을 변경할 때는 비추천 처리가 아예 불가능한 경우가 많습니다. 그런 일이 발생하면 비추천 기능이 포함된 마이너 버전 릴리스조차 할 수 없으며, 즉시 다음 메이저 버전으로 넘어가야 합니다. 대형 애플리케이션이 보통 문제를 겪는 부분이 바로 여기입니다. 후방 호환성을 제공할 수 없어 3.0.0에서 3.0.1을 거쳐 4.0.0으로 건너뛰게 됩니다. 깨지는 변경(breaking changes)이 잦다면 semver을 고수하는 것이 거의 가치를 주지 못합니다.

그럼에도 불구하고, 저는 이 구성을 훨씬 더 선호합니다. 개발자에게 깨지는 변경이 있을 것이라는 점을 더 명확하게 전달할 수 있기 때문입니다. YYYY.N 방식은 개발자로서도, 관리자로서도 아무런 정보를 주지 못합니다.

그러면 질문은, 버전으로 무엇을 전달하고 싶은가에 달려 있습니다. 6개의 기능 릴리스(깨지는 변경이 있을 수도, 없을 수도 있음)를 수행하고, 6번째 릴리스마다 패치를 통해 더 긴 기간 동안 지원하며, 패치 릴리스에는 버전을 매기지 않으려면 X.Y 방식이 적합합니다. 여기서 Y=0이 더 긴 기간 동안 지원되는 버전입니다. X는 단순히 숫자입니다. 문제는 X가 연도일 경우, Y가 빠르게 월과 연관 지어지다는 것입니다. 그러면 더 긴 기간 동안 지원되는 새로운 릴리스가 항상 1월에 출시되는 걸까요? 저는 항상 어떤 Ubuntu 버전이 LTS인지 찾아봐야 해서 번거롭습니다.

그렇다면 Discourse가 단순히 현재 메이저 버전을 계속 이어가는 것은 어떨까요. 다음 장기 지원(LTS) 버전은 4.0이라고 부르고, 그 후 4.1부터 4.5까지 기능 릴리스를 진행하며, 그 다음에는 최신 장기 지원 버전인 5.0이 나온다고 가정해 보겠습니다.

이렇게 하면 메이저 이슈로 인해 릴리스가 지연되는 그 어색한 순간도 사라집니다.

롤링 패치 릴리스를 하는 대신 명시적으로 패치를 릴리스할 계획이 있다면 선택적으로 “패치” 번호를 추가할 수 있습니다. "그럼 x.y.z인데, 이건 semver 아냐?"라고 할 수 있지만, 아닙니다. semver처럼 보일 뿐, 실제로는 아닙니다. 모든 새로운 “마이너” 릴리스가 깨지는 변경을 포함할 수 있기 때문입니다. 그래서 저는 Y=0 → LTS인 X.Y 버전 방식을 유지할 것을 제안합니다.

버전 문자열 문제는 일단 제쳐두겠습니다. 저는 새로운 릴리스 계획 자체는 마음에 듭니다.