GN⁺: 당신이 방금 물려받은 레거시 C++ 코드베이스, 이제 어떻게 할까?
(gaultier.github.io)기존 C++ 코드베이스를 상속받았다면 어떻게 해야 할까?
- 새로운 직장을 시작하거나 팀을 변경하거나 경험이 많은 동료가 떠난 후, 복잡하고 독특한 구조를 가진 큰 C++ 코드베이스를 담당하게 됨.
- 버그 수정과 새로운 기능 추가가 필요하지만, 코드베이스를 무시하거나 없애버릴 수는 없음. 이는 급여를 지불하는 이에게 중요하므로 당신에게도 중요함.
첫 단계: 코드를 로컬에서 작동시키기
- 코드와 빌드 시스템에 최소한의 변경만을 수행하여 로컬에서 작동시킴. 아직 대대적인 리팩토링은 하지 않음.
불필요한 것들 제거하기
- 회사나 오픈소스 프로젝트가 광고하고 판매하는 기능을 제공하는 데 절대적으로 필요하지 않은 모든 것을 제거함.
프로젝트를 21세기로 끌어올리기
- CI(지속적 통합), 린터, 퍼징, 자동 포맷팅 등을 추가함.
점진적인 코드 개선
- 코드에 작고 점진적인 변경을 수행함. 반복적으로 수행하여 애플리케이션의 보안, 개발자 경험, 정확성, 성능 측면에서 프로젝트를 수용 가능한 상태로 만듦.
메모리 안전한 언어로 일부 재작성 고려
- 가능하다면, 메모리 안전한 언어로 일부 코드를 재작성하는 것을 고려함.
지원하는 플랫폼 명시하기
- README에 공식적으로 지원하는 <아키텍처>-<운영체제> 쌍을 명시함. 예를 들어 x86_64-linux 또는 aarch64-darwin 등.
머신에서 빌드 작동시키기
- 모든 지원 플랫폼에서 신뢰할 수 있고 일관되게 빌드할 수 있도록 함.
머신에서 테스트 통과시키기
- 테스트가 없다면, 코드 변경 전에 테스트를 작성하고 통과시킨 후에 돌아옴.
README에 애플리케이션 빌드 및 테스트 방법 기술하기
- 빌드와 테스트를 위한 명령어를 간단하게 만들어서 비전문가도 쉽게 따라할 수 있도록 함.
빌드와 테스트 속도를 높이기 위한 저달과일 찾기
- 빌드 시스템 변경 없이 빌드와 테스트 속도를 높일 수 있는 간단한 방법을 찾음.
불필요한 코드 제거하기
- 컴파일러 경고와 린터를 사용하여 사용되지 않는 코드를 찾아 제거함.
린터
- 린터 규칙에 대해 과도하게 몰두하지 않고 기본적인 몇 가지를 추가하고, 개발 주기에 통합함.
코드 포매팅
- 적절한 시점에 전체 코드베이스에 대해 일괄적으로 코드 스타일을 적용하고, 설정을 커밋함.
산타이저
- 산타이저를 사용하여 실제 버그와 메모리 누수를 탐지하고 수정함.
CI 파이프라인 추가하기
- 모든 설정된 좋은 점들(린터, 코드 포매팅, 테스트 등)을 자동화하고, 모든 변경 사항에 대해 생산 환경에서 바이너리를 생성함.
점진적인 코드 개선
- 보안, 정확성, 성능과 같은 구체적인 목표에 집중하고, '깨끗한 코드'와 같은 주관적 기준에서 벗어남.
메모리 안전한 언어로 재작성?
- 현재 진행 중인 작업으로, 많은 주의사항이 있음. 명확한 이유가 있을 때만 수행함.
결론
- 복잡한 레거시 C++ 코드베이스에서 벗어나는 구체적이고 단계별 계획을 제공함.
부록: 의존성 관리
- C++에서는 의존성 관리가 없으며, 대부분 시스템 패키지 매니저를 사용함. 그러나 이는 좋지 않은 생각임.
- 의존성 관리에 대한 저자의 의견은 git 서브모듈과 소스 컴파일 방식을 사용하는 것임.
GN⁺의 의견
- 이 기사는 C++ 코드베이스를 상속받은 초급 소프트웨어 엔지니어에게 유용한 단계별 가이드를 제공함.
- 레거시 코드를 다루는 것은 많은 개발자에게 공통된 도전이며, 이 기사는 그러한 상황에서 실질적인 조언을 제공함.
- 코드베이스를 개선하는 과정에서 테스트의 중요성을 강조하는 것은 좋은 소프트웨어 개발 관행을 반영함.
- 의존성 관리에 대한 저자의 의견은 논란의 여지가 있으며, 실제 프로젝트에서는 Conan이나 vcpkg와 같은 현대적인 패키지 매니저를 성공적으로 사용하는 경우도 많음.
- 기술을 도입할 때는 프로젝트의 특성과 팀의 기술 수준을 고려해야 하며, 이 기사는 그러한 결정을 내리는 데 도움이 될 수 있는 좋은 출발점을 제공함.
Hacker News 의견
-
일부 해커뉴스 댓글에서는 C++ 프로젝트를 상속받았을 때의 조언이 제시됨:
- 재현 가능한 빌드: 도커 같은 도구를 사용하여 빌드 환경을 감싸서 도구와 의존성을 명확하고 재현 가능하게 만들 것을 권장함.
-
-Wall
옵션으로 깨끗하게 빌드하기: 경고를 해결하여 코드의 문제를 수정하고, 드물게는 이해한 후에 경고를 무시하는 것도 가능함. - Valgrind와 같은 도구로 초기 테스팅을 하여 읽기/쓰기 오류를 조사할 것을 제안함.
- 리팩토링은 초기에는 지역화된 범위에서 유지하고, 전체 구조를 이해하기 전에 대규모 재설계를 피할 것을 권장함.
-
다른 댓글에서는 CI, linting, auto-formatting 등을 먼저 도입하는 것이 중요하다고 주장함:
- 코드에서 불필요한 부분을 제거하기 전에 프로그램이 어떻게 작동하는지 이해하고, 정적 분석 도구를 통해 프로그램이 어디서 작업이 필요한지 통찰을 얻을 수 있음.
-
한 사용자는 새로운 팀이나 회사로 이동하는 것을 제안함.
-
코드 이해 도구와 기술의 중요성을 언급하는 댓글도 있음:
- 코드베이스를 색인화하는 도구 사용과 UML 시퀀스 다이어그램 작성, 마치 타인에게 가르치듯이 노트 작성하는 것이 중요함.
-
한 댓글은 프로젝트를 현대화하기 위해 CI, linters, fuzzing, auto-formatting 등을 추가하는 것에 대한 조언을 제시함:
- CI를 통해 다른 곳에서도 빌드가 가능하도록 하고, 컴파일러 경고 및 정적 분석기를 활용하여 코드 문제를 파악함.
- 중요한 코드 부분에 대한 단위 테스트를 설정하여 코드가 정확한 작업을 수행하는지 확인함.
- 자동 포매팅은 우선순위가 낮으며, 원래 유지자의 스타일을 따를 것을 권장함.
-
또 다른 댓글에서는 메모리 안전한 언어로 일부를 다시 작성하는 것에 대한 조언을 비판함:
- 추가 작업에 필요한 자원 확보가 어렵고, C++ 외에 추가 언어에 대한 지식이 필요하며, 테스팅이 더 복잡해질 수 있음.
-
git 서브모듈과 소스 컴파일 방식을 사용하는 것이 패키지 관리자보다 우수하다고 주장하는 댓글도 있음:
- vcpkg와 같은 도구를 사용해보기 전에 이러한 비판을 제기하는 것은 이상함을 지적함.
이러한 댓글들은 C++ 프로젝트를 상속받았을 때의 다양한 접근 방식과 조언을 제공하며, 프로젝트 관리, 코드 이해, 리팩토링, 현대화 전략 등에 대한 다양한 의견을 나타냄.