구글 엔지니어는 이렇게 일한다: 지속 가능한 코드를 위한 규칙과 지침
in BOOK on 구글 엔지니어는 이렇게 일한다, 코딩-규칙, Style-guide, 코드-품질, Sustainable-code, 코드-일관성, Engineering-culture, 자동화, Code-formatter, 가독성, Code-review, 확장성
대부분의 엔지니어링 조직에는 코드베이스를 관리하는 규칙이 있다. 코드 포맷팅, 명명 방식 등을 규정한다. 그리고 엔지니어 대부분은 조직에서 허용하는 정책 범위 안에서 코드를 작성한다. 여기서 규칙은 제안이나 권장사항이 아닌, 엄격하고 꼭 지켜야 하는 법과 같다.
반면, 지침은 권장사항이나 모범 사례이다. 따르는 편이 이득이라서 어지간하면 따르라고 권하지만, 규칙과 달리 다소 변형해 적용해도 괜찮다.
이러한 규칙과 지침을 모아놓은 것이 바로 프로그래밍 스타일 가이드이며, 그 궁극적인 목표는 코드의 지속 가능성을 높이는 것이다.
이 포스트에서는 구글이 어떻게 코드의 지속 가능성을 높이기 위해 규칙과 지침을 만들고 적용하는지, 그 원칙과 과정에 대해 이야기해본다.
1. 규칙이 필요한 이유
규칙을 관리하는 목표는 ‘좋은’ 행동을 장려하고 ‘나쁜’ 행동을 억제하기 위함이다. ‘좋음’과 ‘나쁨’의 해석은 조직마다 차이가 있는데, 이는 조직의 관심사가 다르기 때문이다. 어떤 조직은 메모리 사용량을 줄이거나 런타임 성능을 높여줄 가능성이 큰 사용 패턴을 장려하는 것을 ‘좋다’고 정의하고, 어떤 조직은 최신 언어 기능을 적극적으로 활용하는 쪽을 ‘좋다’고 정의하기도 한다.
따라서 가장 먼저 조직이 추구하는 가치를 파악해야 한다.
이렇게 확립된 규칙과 지침은 조직이 커지더라도 일관되게 통용되는 공통의 코딩 어휘가 된다. 어휘가 통일되면 엔지니어들은 코드를 표현하는 ‘형식’보다 코드에 담을 수 있는 ‘내용’에 집중할 수 있게 된다.
2. 규칙 만들기
규칙을 정의할 때 반드시 던져야 하는 질문은 ‘무슨 규칙이 필요한가?’가 아니라 ‘어떤 목표를 이루려 하는가?’이다. 목표에 집중하면 규칙은 자연스럽게 따라온다.
2.1. 기본 원칙 안내
구글의 규칙 목표는 개발 환경의 복잡도를 관리하고 엔지니어의 생산성을 희생하지 않는 선에서 코드베이스를 관리 가능하게끔 유지하는 것이다. 여기서 트레이드오프가 발생한다. 이 목적을 달성하는데 도움되는 규칙 중 상당수가 엔지니어들의 자유를 제한하기 때문이다. 하지만 권위 있는 표준은 일관성을 높여주고 의견 대립을 줄여주므로 그 혜택이 더 크다.
규칙을 만들 때 염두에 두어야 하는 원칙들은 다음과 같다.
1.규칙의 양을 최소화한다.
규칙이 너무 많으면 엔지니어들이 모두 기억하지도 못할 것이고, 새로 합류한 엔지니어가 적응하기도 어렵다.
여기서 ‘너무 많다’의 기준은 단순히 규칙의 수가 아니라 엔지니어가 기억해야 하는 수이다. 따라서 너무 자명한 규칙은 의도적으로 배제한다.
무언가를 불허한다고 명시하지 않았다고 해서 허용한다는 의미는 아니다. 예를 들어 C++ 스타일 가이드에는 goto 사용에 관한 규칙이 없다. 이미 커뮤니티에서 goto 를 금기시하기 때문이다. 한두 엔지니어의 잘못 때문에 새로운 규칙을 만들면 다른 모든 사람들에게 불필요한 정신적 부담을 주게 된다.
2.코드를 읽는 사람에게 맞춘다.
코드는 작성되는 횟수보다 읽히는 횟수가 훨씬 많으며, 시간이 지날수록 그 차이는 벌어진다. 따라서 읽기 난해한 것보다 타이핑하기 지루한 편이 낫다. 즉, ‘쓰기에 간편한’ 것보다 ‘읽기에 간단한’ 쪽에 가치를 두어야 한다. 변수와 타입 이름을 서술식으로 길게 짓고 반복해서 타이핑하는 것도 좋은 방법이다.
가장 좋은 것은 ‘현 위치에서 추론하기’가 가능하도록 만드는 것이다. 다른 코드를 찾아보거나 참조할 필요 없이, 함수의 구현부를 들여다보지 않고도 호출 지점에서 무슨 일이 벌어지는지를 명확히 이해할 수 있어야 한다.
코드 자체에 산재하는 구현 주석은 뻔하지 않은 선택을 한 이유를 설명하거나, 주의할 점을 알리고, 까다로운 부분의 로직을 설명하는 데 사용한다.
3.일관되어야 한다.
코드가 일관되게 작성되어 있다면 엔지니어는 익숙지 않은 부분을 보더라도 빠르게 작업을 이어갈 수 있다. 일관성은 때로는 구속처럼 느껴지기도 하지만, 더 많은 엔지니어가 더 많은 일을 적은 노력으로 수행할 수 있게 해준다.
코드베이스의 스타일과 기준이 일관되면 엔지니어와 코드 리뷰어는 ‘어떻게’ 표현하는지가 아닌 ‘무엇을’ 수행하는지에 집중할 수 있다.
일관성은 규모를 확장하기 쉽게 도와준다.
- 도구의 확장
- 조직 확장에는 도구 활용이 핵심이다. 코드가 일관되면 코드를 이해하고, 수정하고, 생성하는 도구를 만들기가 훨씬 쉬워진다.
- 예를 들어 모든 프로젝트가 같은 규칙으로 임포트문을 정렬한다면, 수많은 관리 작업을 자동화하는 강력한 도구를 제작할 수 있다.
- 인력의 확장
- 코드베이스가 일관되게 관리되면 엔지니어들이 새로운 팀으로 옮겨 적응하는 시간이 단축된다.
- 또한 사이트 신뢰성 엔지니어(SRE)나 라이브러리 엔지니어처럼 특정 프로젝트에 익숙하지 않은 전문가가 코드를 살피고 수정해야 할 때 업무 효율이 크게 높아진다.
C++ 스타일 가이드와 진화하는 일관성
_수년 전, 구글의 C++ 스타일 가이드는
“때로는 합리적인 근거를 들어 특정 스타일 규칙을 변경하자는 제안이 들어오지만, 그럼에도 우리는 기존의 일관성을 지키기 위해 현재의 규칙들을 견지할 것이다.”
라고 명시했다.
하지만 코드베이스가 거대해지면서 기존 코드와의 완벽한 일관성은 오히려 발목을 잡는 우선순위가 되었다.
현시점의 모범 사례에 맞게 낡은 규칙을 수정하고, 대규모 변경(LSC) 도구를 사용해 코드베이스 전체를 최신 스타일로 바꿀 수는 있지만, 그 비용이 얻는 것보다 커지는 단계에 도달했다.
이제 C++ 코드베이스 전체가 완벽히 일관되는 것을 목표로 삼지는 않는다._
일반적으로 규약은 바깥세상과 일관되게 잡는 편이 유리하다.
파이썬 들여쓰기 공백 개수
구글의 파이썬 스타일 가이드는 원래 C++ 코드와의 유사성 때문에 들여쓰기에 공백 두 개를 썼다.
하지만 외부 파이썬 커뮤니티의 표준은 공백 네 개였다.
시간이 지나 파이썬 자체 프로젝트가 많아지면서 이러한 차이는 외부 코드를 참고하거나 내부 코드를 오픈소스로 공개할 때마다 마찰을 일으켰다.
결국, 새로운 언어(Starlark)의 스타일 가이드를 만들 때는 바깥세상의 표준과 일치시켜 공백 네 개를 사용하도록 결정했다.
4.오류가 나기 쉽거나 예상치 못한 동작을 유발하는 구조는 피한다.
언어의 고급 기능들은 해당 기능을 잘 이해하고 활용하는 전문가에게는 이상적인 해법일 수 있다. 하지만 일반적으로 이해하기 더 어렵고 널리 쓰이지 않아 오류를 유발할 가능성이 크다.
코드베이스는 특정 전문가의 전유물이 아닌, 모든 엔지니어의 작업 공간이 되어야 한다.
5.꼭 필요하다면 실용성을 생각해 예외를 허용한다.
“어리석게 일관성만 고집한다면 편협한 홉고블린과 다를 바 없습니다.”
일관성은 매우 중요하지만 융통성이 없어서는 안된다. 성능 최적화나 외부 코드와의 상호운용성 같은 실용적인 이유가 있다면 규칙에 대한 예외를 허용해야 한다.
2.2. 스타일 가이드
스타일 가이드에는 주로 다음과 같은 내용이 들어간다.
1.모범사례 강제하기
스타일 가이드의 규칙 중 일부는 소스 코드의 가독성을 높이도록 설계된다. 한 줄의 최대 길이, 괄호 정렬 방식 등 포맷팅 규칙 상당수가 이 범주에 속하며, 언어에 따라서는 자동 포맷팅 도구를 사용하게끔 강제하기도 한다.
또한, 새롭거나 아직 널리 이해되지 못한 언어 기능을 제한하기도 한다. 이는 엔지니어 전반이 해당 기능을 제대로 습득할 때까지 선제적으로 방어선을 치는 것이다. 동시에 업계에서 해당 기능이 어떻게 활용되는지 관찰하며 모범 사례가 만들어지기를 기다리는 효과도 있다.
사례 연구: std::unique_ptr 도입
초기 대응 (사용 금지): C++11에 std::unique_ptr과 move 시맨틱이 도입되었을 때, 구글은 엔지니어 대부분에게 생소하고 복잡하다는 이유로 초기에 사용을 금지했다. 이는 잠재적인 오류를 막기 위한 안전한 선택이었다.
시간의 흐름과 재평가: 시간이 지나면서 엔지니어들은 새로운 개념에 적응했다. 그 결과, std::unique_ptr이 객체의 소유권을 명확히 하여 코드 가독성을 크게 향상시킨다는 장점이 부각되었다.
최종 결정 (도입): 초기 학습 비용이라는 단점보다 코드 품질 개선이라는 장기적인 이득이 더 크다고 판단하여, 최종적으로 std::unique_ptr을 스타일 가이드에 도입하기로 결정했다.
2.일관성 구축하기
스타일 가이드에는 사소한 문제를 다루는 규칙도 아주 많다. 이런 규칙들의 목적은 단순히 결정을 내리고 그 결정을 문서로 남기는 것이다.
예를 들어 명명 규칙, 들여쓰기 공백 수 등은 어떤 선택을 하든 명확하고 가시적인 차이가 없는 게 보통이다.
대신, 어느 쪽이든 하나를 선택하고 모두가 따르게 함으로써 끝없는 논쟁에서 벗어나 더 중요한 일로 시선을 돌리는 효과가 있다.
3. 규칙 수정하기
엔지니어들이 특정 규칙을 우회하는데 에너지를 쓰고 있다면, 이는 해당 규칙의 효용성이 다했거나 설계가 잘못 되었다는 증거이다. 규칙이 기대했던 트레이드오프를 다시 검토해야 할 시점인 것이다.
규칙은 한 번 만들고 잊히는 기념비가 아니라, 끊임없이 유용성과 최신 상태를 점검해야 한다. 이를 위해 가장 중요한 것은 각 규칙의 배경과 근거를 명확하게 문서화하는 것이다. 결정 과정에서 고려했던 장단점과 최종 결론에 도달한 핵심 요인을 기록해두어야 한다.
이렇게 결정의 이력을 남겨두면, 규칙의 진화를 관리하기 쉬워진다. 과거에 옳았던 결정이 현재는 최선이 아니게 되는 것은 자연스러운 일이다. 결정에 영향을 미쳤던 핵심 요인 중 하나라도 변했다면 그것이 바로 해당 규칙을 다시 평가해야 한다는 신호이다.
스타일 가이드 수정을 제안할 때 역시 가상의 예시가 아닌, 실존하는 코드에서 발견된 패턴으로 문제를 증명해야 한다. 실증적인 데이터만이 규칙 변경의 정당성을 부여한다.
마찬가지로, 규칙에 대한 예외 요청이 빈번해진다면 이는 개별 사례의 문제가 아니다. 규칙 자체가 현실과 맞지 않아 수정되거나 더 명확하게 가다듬어져야 한다는 신호로 해석해야 한다.
4. 코드 포맷터: 논쟁을 없애고 본질에 집중하는 기술
코드의 형식을 일관되게 관리하기 위한 가장 효과적인 방법은 자동화된 스타일 검사기와 포맷터를 적극 활용하는 것이 좋다.
이 도구들의 도입은 단순히 코드를 예쁘게 만드는 차원을 넘어선다. 한 줄의 최대 길이, 들여쓰기 방식 같은 소모적인 논쟁을 원천적으로 제거한다. 이러한 결정은 이제 엔지니어의 토론 대상이 아니라, 자동화된 도구가 처리하는 영역이 된다.
그 결과, 엔지니어는 가장 가치 있는 자원인 자신의 시간과 집중력을 코드의 스타일이 아닌 핵심 로직과 설계에 온전히 쏟아부을 수 있다. 또한 모든 코드가 일관된 형식으로 제출되므로 코드 리뷰 과정에서 스타일 문제를 지적하는데 드는 비용이 사라지고, 리뷰의 질이 자연스럽게 향상된다.
정리하며..
아래는 시간과 규모의 변화 속에서 코드의 가치를 지켜내는 몇 가지 핵심 원칙이다.
- 지향점
- 모든 규칙과 지침의 목표는 코드베이스의 장기적인 탄력성을 높이는 것이어야 한다.
- 유연성
- 규칙은 불변의 진리가 아니다. 규칙이 만들어진 근거와 데이터를 파악하고, 상황 변화에 맞춰 진화시켜야 한다.
- 최소주의
- 모든 것을 규칙으로 통제하려는 시도는 실패한다. 핵심적인 부분에만 규칙을 적용하고 나머지는 엔지니어의 판단에 맡기는 균형이 필요하다.
- 일관성
- 일관성은 대규모 협업과 도구 자동화를 가능하게 하는 확장성의 초석이다.
- 자동화
- 규칙은 가능한 한 사람의 노력 없이 자동으로 적용되어야 한다. 이는 실수를 방지하고 모든 이의 부담을 줄이는 가장 확실한 방법이다.
참고 사이트 & 함께 보면 좋은 사이트
본 포스트는 구글 엔지니어는 이렇게 일한다 를 읽으며 정리한 내용들입니다.