TECH 으로 돌아가기
TECH HACKER NEWS 오늘 8분 읽기 23 READS

구글의 러스트 스타일 가이드: 포매팅을 넘어 API 설계와 대규모 리팩터링까지

구글이 공개한 러스트 스타일 가이드는 단순한 코드 포매팅 규칙을 넘어선다. 이 문서가 말하는 '스타일'에는 들여쓰기나 줄바꿈 같은 표면적 규칙뿐 아니라 API 설계와 구현 방식에 대한 지침까지 포함된다. 러스트는 구글 내부 저장소인 google3를 비롯해 안드로이드, 크롬OS, 푸크시아(Fuchsia), 크롬 등 여러 곳에서 쓰이고 있고, 구글은 이 코드베이스들 안에서뿐 아니라 코드베이스를 가로질러서도 일관성을 유지하려 한다. 기존 C++ 스타일 가이드를 두는 것과 같은 이유에서 만들어진 문서인 셈이다.

규칙을 만든 목적

가이드가 밝히는 목적은 분명하다. 구글의 코드는 오랜 기간 유지되므로, 작성 시점에 약간의 노력을 더 들여서라도 가독성을 높이는 규칙이라면 장기적으로 그 비용이 아깝지 않다고 본다. 또 하나 눈에 띄는 것은 대규모 변경(LSC, Large-Scale Changes)을 수월하게 만드는 것을 명시적 목표로 삼았다는 점이다. 구글처럼 거대한 코드베이스에서는 도구의 도움을 받아 코드베이스 전체에 걸친 리팩터링을 수행해야 할 때가 있는데, 이때 도구가 다루기 쉬운 코드일수록 작업이 순조롭다. 일관성뿐 아니라 '리팩터링 친화적인 패턴'을 의도적으로 채택하는 이유가 여기에 있다. 동시에 가이드는 뚜렷한 이득이 없는 규칙은 최소화하고, 러스트 생태계가 이미 확보한 일관성에 최대한 기대어 학습 부담을 줄이려 한다. 공식 러스트 스타일 규칙은 이 가이드와 충돌하지 않는 한 그대로 따른다.

라이브러리와 애플리케이션을 구분하라

실무자가 특히 유념할 대목은 코드의 성격에 따라 규칙의 강제력이 달라진다는 점이다. 라이브러리 코드에서 API 설계 규칙은 '구속력'을 갖지만, 애플리케이션 코드에서는 '강한 권고'에 그친다. 애플리케이션 코드는 특정 문제를 풀기 위해 작성되는 만큼 넓은 재사용성보다 단순함과 직접성을 우선하고, 섣부른 일반화와 추상화를 피하라는 것이다. 당장 필요한 것에 집중하라는 조언은 과도한 설계를 경계하는 현실적 지침으로 읽힌다.

크레이트와 모듈 구성

크롬 생태계를 겨냥한 구체적 규칙도 많다. 가이드는 크레이트를 작게 유지하길 권하며, 가능하면 하나의 추상화에 집중하는 단일 파일을 이상으로 제시한다. 하나의 크레이트는 하나의 rust_static_library 규칙에 대응하고, 루트 모듈은 하위 모듈의 공개 API를 재노출(re-export)해 하위 모듈을 구현 세부사항으로 감출 수 있다. 크롬에서는 코드베이스의 방대한 규모, 의존성 추가가 빌드 그래프에 미치는 비국소적 영향, 병렬 컴파일과 빌드 캐싱 성능 때문에 세분화된 라이브러리 타깃을 권장한다. 한 크레이트에 속한 .rs 파일은 하위 디렉터리로 나누지 않고 단일 디렉터리에 두어야 하며, 디렉터리 분할이 필요하게 느껴진다면 크레이트가 지나치게 커졌다는 신호로 본다. 이는 오픈소스에서 흔한 전통적 Cargo 디렉터리 구조와 의도적으로 다르며, Cargo로도 빌드되는 third_party 코드만 예외다. 리프(leaf) 모듈이 Foo 같은 주요 항목을 담으면 그 이름을 따서 mod foo와 foo.rs로 명명하고, 비(非)리프 모듈에는 모듈 선언과 재노출만 둔다.

임포트 규칙도 명확하다. 글로브 임포트는 원칙적으로 금지되며, C++ 네임스페이스를 비공개로 병합하는 경우나 서드파티 크레이트의 프렐류드 정도가 예외다. 글로브 임포트는 LSC를 돌리는 코드 관리자의 수고를 늘리고, 상호참조 도구가 없는 환경에서 타입의 출처를 알기 어렵게 만들기 때문이다. 타입과 트레이트는 모듈 경로 없이 Regex처럼 쓰되 최상단에 use를 두고, 다른 모듈의 최상위 함수는 modulename::functionname() 형태로 호출한다. 이 규칙들 상당수는 리뷰 과정에서 반복되는 사소한 논쟁을 줄이기 위한 것이다. 포매팅은 git cl format 같은 도구에 맡기고 최대 100열, 소문자 16진 리터럴, 매크로 매처 포매팅 등을 적용하며, 개인 취향을 이유로 포매팅을 건너뛰어서는 안 된다.

소유권과 API 유연성

메모리 관리에서는 Rc와 Arc 같은 공유 소유권 스마트 포인터보다 고유 소유권과 빌림(borrowing)을 우선하라고 권한다. 다른 언어 출신 개발자가 이들을 너무 빨리 꺼내 드는 경향이 있으나, 러스트는 대개 공유 포인터 없이도 객체 그래프를 표현할 수 있고 이들 포인터는 런타임 비용과 고유한 복잡성을 더한다. .clone()은 진짜 깊은 복사가 필요할 때 쓰고 빌림의 대체물로 남용하지 말되, 빌림 관계가 지나치게 복잡해지면 실용적 선택으로 허용한다. 다만 Rc·Arc의 복제는 깊은 복사가 아니라 정상적인 사용 방식이라는 점을 구분한다. API 설계에서는 함수가 빌린 불변 데이터를 받을 때 스마트 포인터나 컨테이너가 아니라 데이터 자체에 대한 가장 유연한 참조를 받도록 하고(Clippy의 borrowed_box, ptr_arg 린트 참고), 재사용성이 높은 라이브러리라면 Vec 대신 이터레이터를 반환하거나 impl IntoIterator를 받아들여 호출자에게 소비 방식의 선택지를 주라고 권한다. 호출부 편의가 중요할 때는 impl Into를 고려하되 코드 비대화와 균형을 맞춰야 하며, 애플리케이션 코드에서는 이런 패턴을 거의 쓰지 말라는 단서가 붙는다.

정리하면 이 가이드는 러스트의 관용을 존중하면서도, 수십 년 단위로 유지되고 도구 기반 대규모 변경이 일상인 환경이라는 구글 특유의 제약을 규칙에 녹여냈다. 한국의 실무자에게도 라이브러리와 애플리케이션을 구분해 설계 강제력을 달리하는 사고, 그리고 리팩터링 용이성을 명시적 설계 목표로 삼는 관점은 자체 코드 규약을 다듬을 때 참고할 만하다. 다만 작은 크레이트와 단일 디렉터리 같은 규칙 상당수는 크롬 빌드 환경을 전제로 한 것이어서, 그대로 옮기기보다 각자의 빌드 시스템과 코드베이스 규모에 비추어 취사선택하는 편이 현실적이다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://google.github.io/styleguide/rustguide.html
SHARE
NEXT · CHOOSE

변화를 읽었다면,
내가 만들 수익 구조를 고릅니다.

정보를 더 모으는 데서 멈추지 않고, 광고·외주·판매·중개·구독 중 내 상황에 맞는 출발점을 정해보세요.

21가지 수익 구조 살펴보기 →
처리 중...