Dart 튜토리얼 16편: Effective Dart 요약(Style·Documentation·Usage·Design)
요약
핵심 요지
- 문제 정의: 코드가 돌아가기만 해도, 이름/주석/import/API 설계가 제각각이면 협업과 유지보수가 빠르게 어려워진다.
- 핵심 주장: Effective Dart는 “읽히는 코드”를 만들기 위한 기준을 Style/Documentation/Usage/Design 네 축으로 제시하며, 특히 이름 규칙과 공개 API 문서화, import 규칙은 초기에 고정할수록 비용이 낮다.
- 주요 근거: 타입/확장 이름의
UpperCamelCase1, 문장 형태의 주석과///2 문서 주석,lib/src3 내부 import 금지, 용어 일관성/약어 지양 등의 예시가 제시된다. - 실무 기준: “이름(Style) → 문서(Documentation) → import/의존(Usage) → API 표면(Design)” 순서로 최소 규칙을 고정하면, 이후 리팩터링이 쉬워진다.
문서가 설명하는 범위
- Style: 타입/확장/파일 이름 규칙과 기본 네이밍 기준
- Documentation: 주석/문서 주석 작성 규칙과
dart doc4 기반 문서화 흐름 - Usage: import 경로/패키지 경계 규칙과
src디렉터리 import 금지 같은 사용 규칙 - Design: 용어 일관성, 약어 지양, 문장처럼 읽히는 API 등 설계 기준
읽는 시간: 15분 | 난이도: 초급
참고 자료
문제 상황
같은 기능을 하는 코드라도, 이름과 표현이 제각각이면 읽는 시간이 늘어납니다.
또한 “공개 API”5가 커질수록, import 규칙을 깨거나 문서 주석이 비어 있는 상태가 빠르게 누적됩니다.
이때 가장 큰 비용은 “코드를 고치는 비용”이 아니라 “코드를 이해하는 비용”입니다.
그래서 최소한의 규칙을 초기에 고정하는 것이 중요합니다.
해결 방법
단계 1: 이름은 UpperCamelCase와 일관된 규칙으로 시작하기(Style)
Why
NOTE타입 이름이 들쑥날쑥하면, 코드를 읽는 사람이 “이게 클래스인지/함수인지”부터 추측해야 합니다.
그래서 타입과 확장은 형태를 통일해두는 편이 좋습니다.
What
NOTE클래스/enum/typedef/타입 파라미터는
UpperCamelCase로 이름을 짓는 규칙이 제시됩니다.
확장(extension)도 같은 규칙을 따릅니다.
How
TIP타입 이름과 확장 이름 예시는 다음과 같이 제시됩니다.
class SliderMenu {// ...}class HttpRequest {// ...}typedef Predicate<T> = bool Function(T value);extension MyFancyList<T> on List<T> {// ...}extension SmartIterable<T> on Iterable<T> {// ...}
Watch out
WARNING이름이 바뀌면 사용처도 함께 바뀌므로, 공개 API에서는 네이밍을 특히 안정적으로 유지해야 합니다.
즉, “일단 대충 짓고 나중에 바꾸기”가 반복되면, 코드와 문서의 비용이 함께 커집니다.
결론: 타입/확장은 UpperCamelCase로 시작해, 형태부터 통일합니다.
단계 2: 주석은 문장처럼, 공개 API는 /// 문서 주석으로 남기기(Documentation)
Why
NOTE주석이 “문장 같지 않거나” 형식이 제각각이면, 읽는 사람이 내용을 신뢰하기 어려워집니다.
또한 공개 API가 문서화되지 않으면, 사용자가 올바르게 쓰기 어렵습니다.
What
NOTE일반 주석은 문장처럼 작성하는 팁이 제시됩니다.
그리고 공개 API를 문서화하려면///형태의 문서 주석을 쓰는 규칙이 제시됩니다.
dart doc는 이 문서 주석을 읽어 API 문서를 생성합니다.
How
TIP문장 형태의 주석 예시는 다음과 같습니다.
// 이 위치 이전에 무언가가 오면 안 된다.if (_chunks.isNotEmpty) return false;문서 주석은
///로 작성합니다./// 이 청크가 분리되지 않았을 때의 문자 개수.int get length => ...;
Watch out
WARNING문서로 남길 목적의 설명을 블록 주석(
/* ... */)로 쓰지 않는 규칙이 제시됩니다.
블록 주석은 “일시적으로 코드 조각을 주석 처리”할 때 사용하고, 그 외에는//를 사용합니다.
결론: 주석은 문장처럼 쓰고, 공개 API는 /// 문서 주석으로 dart doc 흐름에 태웁니다.
단계 3: lib/src 내부 import를 피하고, import 경계를 명확히 유지하기(Usage)
Why
NOTE패키지의 내부 구현(
lib/src)은 유지보수자가 “자유롭게 바꿀 수 있는 영역”으로 취급됩니다.
외부가 그 영역을 직접 import하면, 작은 버전 변화에도 코드가 깨질 수 있습니다.
What
NOTE다른 패키지의
lib/src아래 라이브러리를 import하지 않는 규칙이 제시됩니다.
또한package:import를 사용하면 디스크 경로에 덜 의존하게 되며,lib경계를 넘나드는 상대 경로 import를 피하는 규칙이 제시됩니다.
How
TIP
src내부 import를 피하고, 공개된 경로(package:)로 import하는 습관을 들입니다.
또한 “같은 파일을 두 경로로 import”하는 상황을 만들지 않습니다.import 'package:my_package/api.dart';import '../lib/api.dart';
Watch out
WARNING서로 다른 import 경로는 Dart가 “서로 다른 라이브러리”로 인식할 수 있습니다.
그러면 타입이 같아 보여도 서로 다른 것으로 취급되는 등, 이해하기 어려운 오류로 이어질 수 있습니다.
결론: import는 package:를 기준으로 정리하고, src 구현 내부를 직접 import하지 않습니다.
단계 4: API 설계는 “용어 일관성”과 “문장처럼 읽히기”로 확인하기(Design)
Why
NOTEAPI를 쓰는 사람은 “내가 알고 있는 개념”에 기대어 코드를 이해합니다.
이때 용어가 흔들리거나 약어가 과하면, 학습 비용이 커집니다.
What
NOTE같은 개념에는 같은 이름을 쓰는(일관성) 기준이 제시되고, 불필요한 약어를 피하는 기준이 제시됩니다.
또한 사용 코드를 문장처럼 읽어보는 방식으로 이름을 점검하는 기준이 제시됩니다.
How
TIP일관성/문장처럼 읽히는 예시는 다음과 같이 제시됩니다.
pageCount // 필드updatePageCount() // pageCount와 일관됨toSomething() // Iterable의 toList() 관례와 일관됨asSomething() // List의 asMap() 관례와 일관됨// "errors가 비어 있으면..."if (errors.isEmpty) {// ...}// "구독(subscription)이여, 취소해."subscription.cancel();
Watch out
WARNING용어를 바꾸는 리팩터링은 단순한 변수명 변경이 아니라, 사용자의 학습 모델을 바꾸는 작업이 됩니다.
그래서 공개 API는 초기에 용어를 안정적으로 정하고, 바꾸려면 근거와 마이그레이션 경로를 함께 준비해야 합니다.
결론: API는 “용어 일관성 + 문장처럼 읽히기”로 점검하면, 사용자가 더 빨리 이해할 수 있습니다.
Footnotes
공유
이 글이 도움이 되었다면 다른 사람과 공유해주세요!