기술 리드 경험에서 제안하는 ‘오픈 소스 네이티브’ 설계 원칙을 소개하고, 가상의 패키지 관리자 사례로 동기를 설명하며 테스트 용이성, 릴리스 주기, 문서화, 인터페이스, 안정성, 오픈소스화 가능성 등 이점을 정리한다.
소프트웨어 설계를 위한 "오픈 소스 네이티브" 원칙
이 글은 내가 기술 리드로서 여러 번 적용해 온 “오픈 소스 네이티브”라는 소프트웨어 설계 원칙을 요약한 것이다. 나중에 쉽게 참조할 수 있도록 글로 남겨 두려 한다.
“오픈 소스 네이티브” 원칙은 간단히 말해 이렇다:
그 소프트웨어를 실제로 오픈 소스화할지와 무관하게, 마치 오픈 소스로 공개할 의도로 독점 소프트웨어를 설계하라
내가 이것을 “오픈 소스 네이티브” 원칙이라 부르는 이유는 소프트웨어를 오픈 소스 생태계의 “네이티브” 구성원처럼 설계하기 때문이다. 다시 말해, 비록 실제로 오픈 소스화하지 않더라도, 소프트웨어가 정신적으로는 오픈 소스로 “태어나” 처음부터 좋은 오픈 소스 시민이 되도록 지향하며 작성된다는 뜻이다.
항상 이 원칙을 지킬 수 있는 것은 아니지만, 나는 여전히 이를 일반적인 설계 가이드라인으로 삼는다.
이 원칙의 상세한 예시를 들기 어려운데, 내가 사용하고 싶은 대부분의 예시는 … 글쎄 … 독점적이어서 해당 조직 밖에서는 의미를 갖기 어렵기 때문이다. 그래도 많은 사람이 공감할 수 있기를 바라며 (실화를 바탕으로 한) 가상의 예시를 간략히 설명해 보겠다.
당신의 조직이 제품의 동작을 커스터마이즈하기 위한 도메인 특화 프로그래밍 언어를 제공한다고 가정하자. 그리고 그 프로그래밍 언어를 위한 패키지 관리자를 설계하고 구현하라는 과제를 받았다고 하자.
패키지를 보관할 수 있는 저장소는 여러 가지가 있을 수 있지만, 예시를 단순화하기 위해 두 가지만 있다고 하자:
아마도 제품이 다른 이유로 이미 데이터베이스를 사용하고 있을 것이고, 그 데이터베이스를 재사용해 패키지를 저장할 수 있다고 생각할 수 있다. 그러면 데이터베이스 팀이 이를 관리해 주기 때문에 새로운 인프라를 별도로 구축할 필요가 없다. 게다가 관계형 데이터베이스의 모든 강력함을 활용할 수 있으니 패키지 질의/수정에도 강력한 도구를 갖게 된다.
git에 패키지를 저장대신 패키지를 git 리포지토리 안의 평범한 파일들로 보관할 수도 있다.
이는 스펙트럼의 두 극단에 해당하며, 실제로는 그 사이에 다른 선택지들(예: 독립 실행형 sqlite 데이터베이스)도 있을 수 있지만, 여기서는 의도적으로 단순화한 예시다.
오픈 소스 네이티브 원칙에 따르면, 패키지는 git에 저장하는 것을 선호하게 된다. git은 이미 이 목적을 위해 전장에서 검증된 오픈 소스 생태계의 기초 빌딩 블록이기 때문이다. 이렇게 하면 일부 기능(관계형 데이터베이스의 모든 강력함)을 포기하게 되지만, 당신의 패키지 관리자는 보다 “오픈 소스 네이티브”해진다.
의문이 들 수 있다: 왜 스스로를 그렇게 일부러 제약해야 할까? 실제로 오픈 소스화하지 않을 수도 있는데 이런 방식으로 설계하면 무슨 이득이 있을까?
내가 이 설계 원칙을 지지하는 이유는 여러 가지다:
구성 요소를 제품 맥락 밖에서도 쉽게 사용할 수 있게 설계하면, 해당 구성 요소를 독립적으로 테스트하기도 쉬워진다. 이는 구성 요소의 올바른 동작을 검증하기 위해 무거운 통합 테스트나 엔드투엔드 테스트에 의존하지 않아도 됨을 의미한다.
예를 들어, 데이터베이스 기반 패키지 관리자보다 git 기반 패키지 관리자가 테스트하기 더 쉽다. git 리포지토리는 준비가 더 간단하기 때문이다.
구성 요소를 독립적으로 테스트할 수 있다면 조직의 나머지 부분과 지속적 통합(CI)을 공유할 필요조차 없다. 해당 구성 요소는 자체 CI를 갖고, 제품 전체의 릴리스 주기에 묶이지 않고 그 구성 요소에 적합한 빈도로 릴리스할 수 있다.
이는 곧 더 일찍, 더 자주 릴리스할 수 있음을 의미하며, 그것 자체로 미덕이다.
패키지 관리자 예시를 이어가면, 패키지 관리자 릴리스를 제품 전체의 릴리스 주기에 연동할 필요가 없어 개선이나 수정 사항을 더 신속히 배포할 수 있다.
독립적으로도 가치를 제공하는 소프트웨어는 따라 하기 위해 필요한 주변 인프라가 적기 때문에 튜토리얼을 작성하기가 훨씬 쉽다.
더 넓은 사용자층을 대상으로 설계하면 소프트웨어의 올바른 논리적 경계를 신중하게 고민하게 된다. 같은 이유로 더 강한 경계와 더 좁은 범위를 적용하기도 쉬워진다.
예를 들어, 우리 가상의 패키지 관리자는 제품과 독립적으로 작동하도록 설계되었기 때문에 패키지 메타데이터가 제품 특화 세부사항으로 오염될 가능성이 더 낮다.
오픈 소스 소프트웨어는 더 넓은 사용자층만을 겨냥하는 것이 아니라 더 긴 시간축도 겨냥한다. 오픈 소스 마인드는 분기 실적을 넘어서는 사고를 촉진한다.
말할 필요도 없이, 구성 요소를 오픈 소스 네이티브하게 설계하면 오픈 소스화가 더 쉬워진다. 야호! 🎉
이 설계 원칙은 최소 권능의 원칙과 유사하다고 볼 수 있다. 소프트웨어를 덜 강력하게(오픈 소스화 가능해야 한다는 제약을 추가함으로써) 만드는 대신, 이해 용이성, 유지보수성, 배포 용이성을 개선하는 것이다.
또, 이와 비슷한 예시가 있다면 댓글로 자유롭게 공유해 주시길 바란다.