1.6경로 탐색하기
낯선 코드베이스에서 방향을 잃지 않기 위한 다양한 전략들
이미 존재하는 거대한 코드베이스에 적응하기란 어려운 일이다. 적응을 위해선 다음의 작업을 해야한다:
- 코드의 어느 부분부터 보아야 하는지 파악
- 코드의 부분별 기능을 알아내고, 그 기능을 어떻게 수행하는지 파악
- 코드의 품질 가늠
- 시스템 내부를 어떻게 탐색할 것인지 계획
- 코딩 관례를 이해하고, 본인의 수정 사항이 그것과 어울리도록 만들기
- 특정 기능이 있을 법한 위치를 파악하고, 그 기능에 의해 발생하는 버그 찾기
- 코드와 함께 그것의 중요 부속인 테스트 코드 및 문서 등의 관계를 이해
친구들의 작은 도움
코드에 정통한 누군가와 함께 일을 할 수 있다면, 질문하기를 주저하지 말고 할 수만 있다면 페어 프로그래밍을 하고 자신의 작업을 검토해줄 것을 요청하라.
주변 사람에게서 도움을 받을 수 없다면, 온라인 포럼이나 오픈소스 프로젝트 주변의 괜찮은 커뮤니티를 찾는것도 방법이다.
도움을 요청할 때는 언제나 공손해야하고 감사해야 한다. 합리적이고 적절한 질문을 해야한다. 질문하기에 앞서는 구글이나 GPT를 통해 검색해보자.
단서 찾기
도와주는 사람이 없다면, 코드 속에서 방향을 가늠할 수 있게 해주는 단서들을 찾아야 한다.
소스 획득의 용이성
버전 관리 시스템에서 한번의 체크아웃만으로 소스를 내려 받을 수 있는가? 아니면 여러 부분을 따로 체크아웃 한 뒤, 컴퓨터의 특정 위치에 설치해야 하는가?
소스 코드 자체의 획득 용이성 뿐 아니라, 코드의 건전성에 대한 정보를 어떻게 얻을수 있는지에 대해서도 고민해라. 지속적 통합(CI: Continuous Integration) 빌드 서버를 통해 코드의 모든 부분이 성공적으로 빌드되는지 지속해서 확인할 수 있는가? 자동화된 테스트들의 결과가 공개되어 있는가?
코드 빌드의 용이성
코드를 빌드하기 어렵다면 해당 코드를 이용해 일하기도 어렵다. 빌드 과정에서 익숙하지 않은 도구가 필요하다면 설치해야 하는가? 그 도구들을 어떻게 최신 버전으로 유지하는가?
소스 관리 시스템에서 코드를 받자마자 빌드할 수 있는가? 아니면 빌드 전에 수많은 자잘한 수작업이 필요한가?
건전한 빌드는 하나의 단계만으로 수행되며, 사용자의 개입을 필요로 하지 않는다.
테스트
테스트는 단위 테스트, 통합 테스트, 종단간 테스트 등으로 나뉜다. 테스트는 자동으로 수행되는가, 아니면 추가적인 빌드 단계가 필요한가? 얼마나 자주 테스트가 수행되는가? 테스트들은 적절하며 잘 구성되어 있는가?
좋은 테스트를 포함하는 코드는 일반적으로 적절히 분류되고, 심사숙고되며, 제대로 설계된다. 테스트들은 대상 코드에 대한 훌륭한 가이드를 제공해줄 수 있다.
파일 구조
디렉터리 구조를 살펴봤을 때, 코드 형태와 어울리는가? 여러 영역, 하부 시스템들, 또는 코드의 여러 계층을 명확하게 보여주는가? 간결한가?
문서
프로젝트 문서가 존재하는가? 잘 작성되었는가? 최신 정보를 반영하고 있는가?
정적 분석
코드의 건전도를 확인하고 코드 간의 관계 확인을 위해 도구를 써라. Doxygen은 훌륭한 다이어그램을 제공한다.
요구 사항
최초의 프로젝트 요구 사항 문서나 기능 명세서가 있는지? 이런 문서들은 최종 결과물과는 거리가 먼 경향이 있지만, 그래도 흥미로운 문서다.
프로젝트 의존성
코드에서 특정 프레임워크와 서드파티 라이브러리를 사용한다면, 그들에 대해 알기 위해 얼마나 많은 정보가 필요한가?
코드에서 언어의 표준 라이브러리를 충분히 사용하고 있는가, 아니면 많은 부분을 직접 만들었는가?
코드 품질
코드를 둘러보면 코드의 품질에 대한 느낌을 얻을 수 있다. 코드상의 주석 양이나 품질을 살펴보라. 죽은 코드가 많은지, 코드를 주석 처리해 썩혀두었는지, 코딩 스타일이 전반적으로 일관적인지.
구조
주요 계층들을 구분할 수 있는가? 계층들이 간결하게 나뉘어 있는가, 아니면 서로 엉켜 있는가? 데이터베이스 계층이 있는가? 스키마를 확인할 수 있는가? 앱은 외부세계와 어떤 방법으로 대화하는가? 어떤 네트워크 기술을 쓰는가?
시스템 구조는 코드를 심도 있게 확인하기 전에 알 수 있는 최상위 개념이다.
의문이 드는 코드에 대해선 버전 관리 도구의 로그를 확인하고, 이상한 코드의 원천과 진화 과정을 git blame
등의 명령으로 확인하라. 과거의 코드와 관련해 작업했던 사람들 중 누가 팀에 남아있는지 확인하라.
실행을 통해 배우기
자전거를 타려면 이론만으로 안되고 실제로 타봐야하는 것처럼, 코드도 올라타고, 운전해보고, 실수하며 떨어져봐야 한다. 나태함에 발이 묶여 앞으로 나아가지 못해서는 안된다.
그렇다면 무엇을 수정해야 할까?
코드에 대해 알아가면서, 즉시 이득을 취할 수 있고 무언가를 망가뜨릴 가능성이 적은 부분을 찾으라. 시스템에 가까이 데려가줄 무언가를 찾으라.
낮게 매달려 있는 과일
간단하고 사소한 일부터 도전한다. 바로 확인해볼 수 있고 코드와 직접 관련이 있는 작은 버그를 찾아내는것 등이다.
코드 조사하기
Lint, Fortify, Cppcheck, FxCop, ReSharper 같은 코드 검증 도구들로 코드베이스를 확인한다. 컴파일러 경고가 꺼져 있다면, 켜고 경고들을 수정한다.
확인한 뒤에 행동하라
코드의 작은 부분부터 확인하고, 취약한 부분이 있다면 가차 없이 리팩토링해야 한다. 변수명을 적절하게 변경하고, 들쭉날쭉 작성된 코드 부분을 더 작고 어울리는 이름의 함수들로 바꿔라.
신중하게 행동해야 한다. 코드를 작성하는게 읽는것보다 쉽기 때문에, 많은 프로그래머들은 코드를 읽고 이해하기보단 다시 만들어버리는걸 선호한다. 이를 통해 더 깊이 있게 코드를 이해할 수도 있지만, 수많은 불필요한 코드 변동, 시간 낭비, 새로운 버그가 초래된다.
테스트부터 하라
테스트를 찾아보라. 새로운 단위 테스트를 어떻게 추가하는지, 새 테스트 파일을 어떻게 추가하는지 확인하라. 테스트를 어떻게 실행하는가?
한 가지 훌륭한 방법으로, 하나로 된 한 줄짜리 실패 테스트를 추가해볼 수 있다. 이런 smoke test를 통해 테스트들이 실제로 무시되지 않는지 확인할 수 있다.
테스트를 통해 각 컴포넌트가 어떻게 작동하는지 확인할 수 있는가?
잡다한 일을 처리하라
사용자 인터페이스를 다듬어보라. UI 개선 작업을 함으로 핵심 기능을 변경하지 않고도 좀 더 즐겁게 사용할 수 있게 만들라.
소스 파일을 정리하고, 디렉터리 구조를 적절히 변경해 IDE나 프로젝트 파일 내에서의 구성에 어울리도록 만들라.
알아낸 것을 기록하라
코드에 최상위 수준의 README 파일이 있고, 그 문서는 어떻게 작업을 시작하면 되는지 알려주는가?
아니라면, 하나 만들어보고 지금까지 알아낸 것들을 기록하라. 경험 많은 프로그래머에게 README 문서 리뷰를 요청하고, 이를 통해 자신의 지식이 얼마나 정확한지 확인할 수 있다.
시스템에 대해 이해해나가면서, 코드의 주요 부분에 대한 계층 다이어그램(layer diagram)을 작성하라. 최신 정보에 맞게 시스템을 계속 보완하라.
🥸 생각해보기
1. 새로운 코드베이스에 자주 들어가보았는가? 익숙하지 않은 코드로 작업하기 수월했는가? 프로젝트 탐색에 사용되는 일반적 도구가 있는가? 이 무기고에 어떤 도구를 넣을 수 있겠는가?
자주 들어가봤다고는 말하지 못할것 같다. 회사에 들어갔을 때를 비롯해 몇몇 오픈 소스 프레임워크나 라이브러리를 사용할 때 들어가보았다.
익숙하지 않은 코드로 작업하기는 물론 수월하지 않았다. README 문서가 아주 체계적으로 되어 있어서 일부 세팅만으로 모든게 제대로 작동하는 라이브러리를 기억하는데, 바로 이 블로그를 만들때 처음에 사용하려고 고려했던 nextjs-notion-starter-kit이다. 다만 이 라이브러리를 커스터마이징하려면 이 라이브러리를 만든, 똑같은 개발자의 다른 라이브러리에 대한 이해가 꽤 필요했고 그 과정에서 어떤 것들은 커스터마이징이 아주 어렵다는 사실을 깨닫고 이 라이브러리를 결국엔 사용하지 않았던 기억이 있다. 공부를 조금 더 했으면 해당 라이브러리를 완전히 이해해서 원하는 커스터마이징을 했을지도 모르는 일이다.
git grep
은 특정 함수나 키워드의 위치를 전역적으로 찾게 도와준다. 브라우저 개발자 도구의 sourcemap은 렌더 흐름을 추적에 도움을 준다. 또, 브라우저 개발자 도구의 inspect로 볼 수 있는 요소들 또한 프로젝트 탐색에 큰 도움을 준다.2. 아직 완전히 이해하지 못한 시스템에 새 코드를 추가할 때 사용할 수 있는 몇 가지 전략을 기술하라. 기존 코드를 (그리고 자신도) 보호하기 위해 사용하는 방어책으로는 어떤 것이 있는가?
회사에서 첫 코드를 추가할 때가 기억나는데, 우선 로컬에 코드를 가져와서 로컬 서버로 웹 사이트를 띄운 후 UI를 변경하고 작동하는지 확인했다. 또, 테스트 서버와 라이브 서버를 분리해서 우선 테스트 서버에 디플로이 후, 모든 것이 문제가 없는 것을 확인하면 라이브 서버로 올렸다. 처음 코드를 추가할 때는 굉장히 많은 디버깅 로그를 임시적으로 넣어 어떻게 코드가 돌아가는지 확인하려고 노력했다.
3. 새 직원이 코드를 더 쉽게 이해할 수 있게 하려면 어떻게 해야 하는가? 현재 프로젝트의 상황을 더 향상시키려면 지금 무엇을 해야 하는가?
이번 장에서 설명된 것과 같은, 코드베이스의 구조나 특수성 등을 설명한 README 파일을 만드는 것은 큰 도움이 될 것이라고 생각한다. 또, 직접 사수가 붙어서 자신이 생각하기에 중요하다고 생각하는 지점들이나, 앱의 진입점 등을 설명해 주는 것도 좋다고 생각한다.
현재 진행하고 있는 블로그나 기타 사이드프로젝트에서도, 이렇게 README 파일을 아무도 읽지 않는다고 해도 작성해보면 프로젝트를 얼마나 잘 구성했는지 확인하고, 그간의 불필요한건 없었는지 확인하는데 도움이 될것 같다는 생각이 든다.
4. 이후의 코드 작업 기간에 따라 기존 코드를 알아가는 노력이나 태도가 달라지겠는가? 더 이상 유지 보수할 필요가 없으며 이후 다른 사람들이 작업해야 하는 코드에 대해, 빠르고 더럽게 수정 작업을 수행하는가? 이는 적절한가?
아무래도 단발성으로 종료되는, 간단한 UI 개선 같은 작업이 주어진다면 기존 코드를 알아가려는 노력이 크지 않을 것이다. 예전에 만든 브레멘 웹사이트는 내가 개발을 시작하고 가장 처음 만든 것 중 하나인데, 바닐라 자바스크립트로 작성한지라 한참 뒤에 간단한 문구를 고치려고 보니 간단한 웹사이트임에도 알아보기가 쉽지 않았다. 이때는 그냥 cmd + f로 문구만 찾아서 바꾸고 특별히 코드를 알아가려는 노력을 하지 않았다.
다른 사람들이 이후에 작업해야하는 코드라면 물론 수정 작업을 훨씬 깔끔하게 하려고 노력할 것이다. 더 이상 '나만의 비밀'이 아닌 이상 대충할 수는 없다. 물론 혼자만의 비밀일때도 변수명을 제대로 쓴다거나 들여쓰기를 잘한다거나 불필요한 코드를 최소화한다거나 함수 중복쓰기를 하지 않는다거나 하는 기본적인 원칙은 반드시 지키지만, 다른 사람들이 이후에 작업할 것이라면 훨씬 더 신경이 쓰일 것이다.