Library

SwiftLint

GREEN.1229 2022. 5. 30. 08:27

안녕하세요. 그린입니다🟢

이번 포스팅에서는 SwiftLint에 대해 뿌셔보겠습니다!

 

코드 컨벤션을 체크해주는 툴이 필요한 이유

우선 다들 동료 개발자와 협업을 하면서 코드 컨벤션을 맞춰가는 과정들은 많이 겪으셨을거에요.

때로는 프로젝트를 처음부터 시작해서 팀원들과 킥오프 후 그라운드 룰을 수립하면서 코드 컨벤션을 같이 정의하기도하고

때로는 현업에서 프로젝트 도중에 조인하게 되었을때 이미 갖춰진 코드 컨벤션을 익히고 따르기도 합니다.

그런데 이렇게 같이 컨벤션을 정립하고 맞춰가고 문서화까지 시켜 매번 참고해도 너무 좋지만 이렇게 정해진 컨벤션들에 대해

Xcode에서 컴파일 시 어긋난 부분에 대해 알려주거나 더 나아가 강제로 컨벤션을 따르게 해준다면 너무 편하겠죠?

이럴때 SwiftLint, SwiftFormat 등의 라이브러리들이 존재합니다.

우리는 가장 흔히 쓰이고 커스텀한 기능이 많은 SwiftLint에 대해 알아보려합니다🙌

 

SwiftLint?

소개를 보면

https://github.com/github/swift-style-guide

 

GitHub - github/swift-style-guide: **Archived** Style guide & coding conventions for Swift projects

**Archived** Style guide & coding conventions for Swift projects - GitHub - github/swift-style-guide: **Archived** Style guide & coding conventions for Swift projects

github.com

해당 Swift 스타일 가이드를 기반으로 Swift 스타일 및 규칙을 적용해주는 라이브러리라고 나와있습니다.

물론 컨벤션들은 딱 이게 맞다 틀리다 정해진건 없습니다.

정말 개개인의 스타일, 즉 취향의 차이죠.

그럼에도 대중적으로 많이 쓰이는 스타일이 있고 우리는 그런 스타일을 따를때 다양한 개발자들과 많은 소통 없이도 편리하게 이해하고 협업을 해줄 수 있는것입니다.

그게 제가 생각하는 대중적인 컨벤션을 따를때의 이점이라고 생각합니다.

언제든 추후 내가 하고 있는 업무를 다른 사람이 할수도 있고 다른 사람이 하던 업무를 중간에 조인해서 할 수도 있으니까요!

 

SwiftLint 설치

대표적으로 homebrew 및 cocoaPod 혹은 Mint로 설치할 수 있습니다.

HomeBrew 설치 시 아래 명령어로 설치합니다.

brew install swiftlint

CocoaPod을 사용해서는 아래와 같이 pod을 추가해주면 됩니다.

pod 'SwiftLint'

마지막으로 Mint로 설치 시 아래 명령어를 입력하면 됩니다.

$ mint install realm/SwiftLint

그 외 SwiftLint.pkg로 사전 빌드된 패키지 설치를 통해 사용할 수도 있고 소스에서 설치할 수도 있습니다.

자유롭게~~🙌

 

Xcode에서 SwiftLint 적용하기

우선 가장 크게 프로젝트 타겟에서 해당 린트를 빌드 단계에서 적용해야하니 Bulid Phases에서 설정해줘야합니다.

그 다음에 린트 파일을 만들어 규칙을 정해주고 사용하면 됩니다.

만약 정할 규칙이 없으면 파일을 만들고 하는 과정은 스킵해도 됩니다.

우선 그럼 빌드 단계에서 설정부터 해보죠!

 

1. Build Phases 설정

프로젝트 타겟에서 Build Phases로 갑니다.

그런다음 스크립트를 하나 만들어 줍니다.

SwiftLint를 코코아팟으로 설치 했단 가정하에 스크립트 코드를 작성해줍니다.

${PODS_ROOT}/SwiftLint/swiftlint

만약 SwiftLint를 적용해 룰과 어긋난 부분의 warning만 띄워주는것이 아닌 강제로 수정시켜주고 싶으면 아래처럼 autocorrect 코드만 추가해주면 됩니다!

${PODS_ROOT}/SwiftLint/swiftlint autocorrect

중요한건 컴파일 전에 해당 린트 룰을 체크해야하니 Phases의 순서에서 SwiftLint를 Compile 전으로 해줍니다.

만약 홈브루로 설치했다면 스크립트의 코드가 아래와 같이 들어가야합니다.

export PATH="$PATH:/opt/homebrew/bin"
if which swiftlint > /dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

전체적으로는 요런 순서일거고 Compile전이면 됩니다!

그 다음으로 린트 파일을 만들어보시죠!

 

2. .swiftlint.yml 파일 생성

해당 파일은 꼭 아래와 같이 프로젝트 폴더 밖에서 해줘야합니다.

New file로 Empty 파일을 생성합니다.

자 그런다음 파일명을 ".swiftlint.yml"이라고 해줍시다!

그러면 요렇게 린트룰을 내마음대로 다룰 수 있도록 파일이 생성되요!

그러면 여기서 룰을 설정해주면 됩니다🙌

 

SwiftLint 룰 종류

SwiftLint에서는 크게 두가지의 룰 종류가 있습니다.

 

1. Default Rules

첫번째로는 기본적으로 default rules이라고 해서 말 그대로 기본룰입니다.

대략 90여가지가 있는걸로 알고 있고 이는 자주 사용되는 즉 위에서 말했던 대부분의 개발자들이 대중적으로 알고 있는 그런 컨벤션 룰을 기본 룰로 채택하고 있어요.

만약 기본 룰에서 제거하고 싶은 즉 적용시키지 싫은 룰이 있다면 disabled_rules로 yml 파일을 통해 정의해줘서 배제시킬 수도 있습니다.

또한 yml 파일을 통해 기본 룰에서 값들을 원하는대로 변경해줄 수 있습니다.

즉 커스텀하게 설정해줄 수도 있어요.

(어떻게 배제시키고 커스텀하게 설정 하는것은 최종적으로 아래 부분에서 코드로 보여드리겠습니다!)

 

2. Opt-In Rules

그 다음으로는 옵트인 룰 입니다.

기본적으로 채택되어 있진 않았지만 필요로 인해 하나씩 추가 되고 있으며 약간 조금 더 커스텀하다고 볼 수 있어요.

선택적으로 추가할 수 있도록 하는 룰입니다.

기본 룰과는 달리 옵트인 룰은 하나도 심어져 있지 않기에 원하는것들을 찾아 심어줘야합니다!

갯수로는 120여가지가 있으며 기본 룰보다 훨씬 많은 수치입니다😅

그만큼 정말 다양한 룰을 원한다면 왠만한 룰은 다 추가할 수 있다는 소리겠죠🤪

 

이 모든 기본/옵트인 룰에 대해 설명은 아래 링크를 통해 여러분들에 맞는 룰을 찾아 적용해보세요..!ㅎㅎ

https://realm.github.io/SwiftLint/rule-directory.html

 

Rule Directory Reference

 

realm.github.io

 

저만의 커스텀한 SwiftLint 룰

자 그럼 제가 생각할때 기본룰에서 배제되면 괜찮을 룰들 그리고 옵트인에서 쓸만한 룰등 또한 커스텀하게 꾸려준 그 모든 집합체의

SwiftLint yml 파일을 아래 코드에서 공유드려보려합니다!

--- # 문서의 시작


# 기본 적용되는 룰에서 사용하지 않는 룰
disabled_rules:
  - trailing_whitespace                    # 후행 공백 (선행 공백과 더불어 필요없다고 미적용이 불필요하다고 생각됨) - 선택 필요
  - nesting                                # 중첩
  - vertical_whitespace                    # 세로 공백
  - redundant_optional_initialization      # 옵셔널 타입을 nil로 초기화 중복
  - unused_closure_parameter               # 미사용 클로저 파라미터 _ 대체
  - syntactic_sugar                        # 간결한 표현 (Array 대신 [Int] 등의 표현)
  - cyclomatic_complexity                  # 순환 복잡성
  - type_body_length                       # 타입 본문의 행 길이 제한
  - file_length                            # 파일 줄 길이 제한
  - unused_optional_binding                # 사용되지 않는 옵셔널 바인딩 제한
  - function_parameter_count               # 파라미터 갯수 제한
  - function_body_length                   # 함수 본문의 행 길이 제한
  - large_tuple                            # 튜플 인자 수 제한
  - unused_control_flow_label              # 미사용 제어 플로우 제거
  - trailing_comma                         # 배열 및 딕셔너리에서 후행 쉼표 조건 (적용 혹은 미적용)
  - opening_brace                          # 중괄호 선언 조건 (중괄호 앞 단일 공백 및 선언과 같은 행)
  - closure_parameter_position             # 클로저 매개변수 위치 (중괄호와 같은 행)
  - for_where                              # for where 절 선호 (for 문 내 if 사용 대체)
  - inclusive_language                     # 포괄적 언어 사용 (인종, 성별, 사회경제적 지위를 나타내는 언어 사용금지)
  - statement_position                     # 구문 위치 제한 (else, catch 등이 선언 바로 뒤 한칸 공백 후 위치함) - 선택 필요
  - todo                                   # TODO, FIXME 주석 제한

# 옵트 인 룰
opt_in_rules:
  - indentation_width                      # 인덴트 룰 적용
  - closure_end_indentation                # 클로저의 끝 괄호를 시작한 행과의 들여쓰기 맞춤
  - empty_count                            # count보다 isEmpty 선호
  - empty_string                           # == ""보다 isEmpty 선호
  - sorted_imports                         # import 시 알파벳 순 정렬
  - used_import                            # 사용되지 않는 모듈 import 알림

# 인덴트 커스텀 정의
indentation_width:
  indentation_width: 2
  include_comments: false

# 타입 네이밍 커스텀 정의
type_name:
  min_length:
    warning: 1
  max_length:
    warning: 120
  allowed_symbols:
    - _

# 식별자 네이밍 커스텀 정의
identifier_name:
  min_length:
    warning: 0
    error: 0
  max_length:
    warning: 120
    error: 120
  allowed_symbols:
    - $
    - _

# 콜론 커스텀 정의
colon:
  apply_to_dictionaries: false             # 딕셔너리에서 콜론이 키 옆에 있어야 하는 룰 미적용

# 행 길이 커스텀 정의
line_length:
  ignores_urls: true                       # URL에 대해 행 길이 제한 미적용
  ignores_comments: true                   # 코멘트에 대해 행 길이 제한 미적용
  ignores_interpolated_strings: true       # 보간된 문자열 행 길이 제한 미적용

# 룰 적용 제외할 파일
excluded:
  - Pods
  - LintTest/AppDelegate.swift
  - LintTest/SceneDelegate.swift


... # 문서의 끝

하나씩 설명하면 너무 길어질것 같아 각각 필요한 부분에서 설명 주석을 달았습니다!

도움이 되면 좋겠네요🙌

 

린트가 적용되어 컨벤션에 맞지 않아 warning을 띄워주는 예시

아래와 같이 룰과 어긋나면 고치라고 경고를 띄워줍니다.

물론 경고일뿐 실행이 안되는건 아닙니다!

 

마무리

저는 잘 모를때 SwiftFormat과 SwiftLint 모두 사용했는데 SwifLint를 딥하게 몰랐고 어떠한 옵트인 룰들이 존재하는지 다 몰랐을때 어? 이거는 없는 룰같네? 근데 SwiftFormat에는 있네? 하던것들이 있어서 두개를 섞어 사용했던것 같아요. 근데 옵트인 룰을 하나씩 차근차근 보니 왠만하면 린트로 다 가능하더라구요?

그렇기에 둘다 채택하지 않고 이번에 린트로 갈아타서 다 꾸려보려합니다!

만약 필요한데 없다? 라이브러리에 기여하면 될것 같아요🙌

다들 SwiftLint로 컨벤션 맞추고 코드 리뷰에서 컨벤션에 대한 리뷰 부담을 덜어보세요!!ㅎㅎ

 

[참고자료]

https://github.com/realm/SwiftLint

 

GitHub - realm/SwiftLint: A tool to enforce Swift style and conventions.

A tool to enforce Swift style and conventions. Contribute to realm/SwiftLint development by creating an account on GitHub.

github.com