팀에서 Flutter 프로젝트를 진행하고 있는데 코딩 컨벤션을 비롯하여 스타일을 통일하기 위해 Lint를 알아보았다.
Flutter 프로젝트를 생성하면 프로젝트 루트에 analysis_options.yaml
파일이 생성된다.
$ ll
total 88
-rw-r--r-- 1 johnnyuhm staff 566B Jun 25 2022 README.md
-rw-r--r-- 1 johnnyuhm staff 1.4K Jun 25 2022 analysis_options.yaml # <- 요놈
drwxr-xr-x 13 johnnyuhm staff 416B Jun 25 2022 android
drwxr-xr-x 9 johnnyuhm staff 288B Jul 24 2022 build
drwxr-xr-x 4 johnnyuhm staff 128B Jun 26 2022 images
drwxr-xr-x 7 johnnyuhm staff 224B Jun 25 2022 ios
drwxr-xr-x 5 johnnyuhm staff 160B Jun 25 2022 lib
-rw-r--r--@ 1 johnnyuhm staff 5.9K Jan 18 16:12 pubspec.lock
-rw-r--r-- 1 johnnyuhm staff 3.6K Jun 26 2022 pubspec.yaml
drwxr-xr-x 3 johnnyuhm staff 96B Jun 25 2022 test
-rw-r--r-- 1 johnnyuhm staff 23K Dec 23 2022 youtube_clone.iml
이 파일은 다음과 같이 작성되어 있다. 기본적으로 flutter팀에서 정의하고 있는 Lint 스타일을 include
명령어를 통해 따르도록 구성되어 있다.
대표적인 예시로 코드 끝에 콤마 찍으면 개행되는게 이것 때문이다.
$ cat analysis_options.yaml
include: package:flutter_lints/flutter.yaml # 기본적으로 flutter_lints 패키지의 룰을 따른다.
linter:
rules: # 위 룰을 기반으로, 추가적으로 사용하고 싶은 Lint 룰이 있다면 여기에 작성하기만 하면 된다.
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
Dart 언어에 적용할 수 있는 Lint 룰들은 다음의 링크를 통해 확인할 수 있다. 필요한 룰 항목이 있다면 위에서 언급한 analysis_options.yaml
파일에 추가하기만 하면 된다.
위의 과정을 통해 Lint 구성을 완료했다면 다음과 같은 명령어를 통해 소스코드가 Lint를 잘 지키고 있는지 검토해볼 수 있다.
$ flutter analyze
Analyzing youtube_clone...
info • Use 'const' with the constructor to improve performance • lib/main.dart:14:12 • prefer_const_constructors
info • Use 'const' with the constructor to improve performance • lib/pages/home.dart:23:13 • prefer_const_constructors
info • Constructors for public widgets should have a named 'key' parameter • lib/widgets/bottom_navigation_bar.dart:3:7 • use_key_in_widget_constructors
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:10:18 • prefer_const_constructors
info • Use 'const' literals as arguments to constructors of '@immutable' classes • lib/widgets/bottom_navigation_bar.dart:12:23 • prefer_const_literals_to_create_immutables
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:13:15 • prefer_const_constructors
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:22:18 • prefer_const_constructors
info • Use 'const' literals as arguments to constructors of '@immutable' classes • lib/widgets/bottom_navigation_bar.dart:24:23 • prefer_const_literals_to_create_immutables
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:25:15 • prefer_const_constructors
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:34:18 • prefer_const_constructors
info • Use 'const' literals as arguments to constructors of '@immutable' classes • lib/widgets/bottom_navigation_bar.dart:36:23 • prefer_const_literals_to_create_immutables
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:37:15 • prefer_const_constructors
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:46:18 • prefer_const_constructors
info • Use 'const' literals as arguments to constructors of '@immutable' classes • lib/widgets/bottom_navigation_bar.dart:48:23 • prefer_const_literals_to_create_immutables
info • Use 'const' with the constructor to improve performance • lib/widgets/bottom_navigation_bar.dart:49:15 • prefer_const_constructors
15 issues found. (ran in 1.5s)
룰에 위배되는 사항이 있는 경우 소스 파일 정보들과 어떠한 Lint 룰을 위배했는지 나타내준다.
이 과정으로 Flutter Lint 환경 구성을 완료했고, 이제 이를 Git hook을 통해 자동화 및 강제화를 팀에 적용했다.
합의한 Flutter Lint 룰을 모든 팀원에게 강제화하기 위해 Git hook을 통해 pre-commit 단계에 적용하여 커밋 과정에서 Lint를 강제화하였고, 룰에 위배되는 코드 사항이 생길 경우 이를 보고하여 반드시 수정하도록 환경을 구성했다.
Git hook 디렉토리는 다음과 같은 위치에 있다.
$ cd <프로젝트 루트>/.git/hook
$ ll
total 120
-rwxr-xr-x 1 johnnyuhm staff 478B Aug 18 04:18 applypatch-msg.sample
-rwxr-xr-x 1 johnnyuhm staff 896B Aug 18 04:18 commit-msg.sample
-rwxr-xr-x 1 johnnyuhm staff 4.6K Aug 18 04:18 fsmonitor-watchman.sample
-rwxr-xr-x 1 johnnyuhm staff 189B Aug 18 04:18 post-update.sample
-rwxr-xr-x 1 johnnyuhm staff 424B Aug 18 04:18 pre-applypatch.sample
-rwxr-xr-x 1 johnnyuhm staff 1.6K Aug 18 04:18 pre-commit.sample # <- 이 녀석이 git commit 명령 수행 전 동작하는 hook 파일이다.
-rwxr-xr-x 1 johnnyuhm staff 416B Aug 18 04:18 pre-merge-commit.sample
-rwxr-xr-x 1 johnnyuhm staff 1.3K Aug 18 04:18 pre-push.sample
-rwxr-xr-x 1 johnnyuhm staff 4.8K Aug 18 04:18 pre-rebase.sample
-rwxr-xr-x 1 johnnyuhm staff 544B Aug 18 04:18 pre-receive.sample
-rwxr-xr-x 1 johnnyuhm staff 1.5K Aug 18 04:18 prepare-commit-msg.sample
-rwxr-xr-x 1 johnnyuhm staff 2.7K Aug 18 04:18 push-to-checkout.sample
-rwxr-xr-x 1 johnnyuhm staff 3.6K Aug 18 04:18 update.sample
pre-commit.sample 파일을 수정하여 Flutter Lint가 동작하는 스크립트를 작성해보자
$ cp ./pre-commit.sample ./pre-commit # pre-commit 쉘 스크립트를 만들기 위해 pre-commit.sample 을 복사한다. 이 때 확장자는 제거한다.
$ chmod +x ./pre-commit # 실행 권한을 부여하고
$ vi ./pre-commit # 편집기로 파일을 연다.
pre-commit 파일을 열고 아래의 스크립트를 작성해주자.
#!/bin/bash
#### dart fix와 dart format 명령어를 통해 스타일과 개행을 프로젝트 전역적으로 한번 수행한다.
echo "dart fix --apply 명령어 수행 중..."
dart fix --apply
dart format .
#### 이후 flutter analyze를 수행하여 Lint를 위배하는 사항이 없는지 조사하고, 결과 레포트에서 Lint 룰에 위배된 사항이 나오는 문자열 항목들만 grep 명령어를 통해 변수로 저장한다.
echo "flutter analyze 명령어 수행 중..."
analyze_result=$(flutter analyze | grep -Ei "info • |warning • |error • ")
#### Lint 룰에 위배되는 사항이 있으면 결과를 출력하고 커밋을 중지한다.
if [ -n "$analyze_result" ]; then
echo "⚠️ Lint 룰에 위배되는 사항이 있습니다. 결과를 확인하여 코드를 수정해주세요. ⚠️"
echo "$analyze_result"
exit 1
fi
이렇게 팀에 Flutter Lint 강제하는 환경을 구성했다. v
더 나아가서 https://pub.dev/packages/custom_lint 패키지를 이용하면 제공하는 룰 외에 추가적을 커스텀 룰을 생성할 수 있어보인다.
이에 대한 후기는 https://techblog.lycorp.co.jp/ko/using-custom-lint-in-flutter 라인 플러스 테크 블로그에서 확인할 수 있다.