[Swift] Lint의 개념, homebrew로 swiftlint 설치 및 적용 (Sandbox 오류 해결)

팔랑이·2024년 6월 26일
1

iOS/Swift

목록 보기
39/71
post-thumbnail

서론

프로그래밍에서 lint 또는 linter는 코드의 잠재적인 문제를 자동으로 찾아주는 도구나 과정을 의미한다. 이 용어는 1978년에 C 프로그래밍 언어에서 코드의 결함을 찾아주는 프로그램을 개발한 스티븐 존슨(Stephen C. Johnson)에 의해 처음 사용되었다. 이 프로그램 이름이 Lint였고, 이후 다양한 프로그래밍 언어와 환경에서 비슷한 도구를 lint라고 부르게 되었다고 한다.

Swift에도 SwiftLint라는 패키지가 있다. 오늘은 이에 대해 알아볼 것.


본론

SwiftLint 사용의 이점

SwiftLint를 사용하여 코딩 컨벤션을 Rule로 정하면 다음과 같은 이점이 있다.

SwiftLint의 효능

  • 코드 품질 향상: 일관된 코딩 스타일을 유지할 수 있고, 잘못된 코드나 잠재적인 버그를 사전에 발견할 수 있다.
  • 자동화된 코드 검토: 코드 리뷰 과정에서 스타일 문제나 기본적인 오류를 자동으로 체크해줘서 리뷰어가 중요한 로직에 집중할 수 있다.
  • 생산성 향상: 반복적인 스타일 체크 작업을 줄여주며 IDE에서 실시간으로 경고를 확인할 수 있다.
    유지보수성 증가: 팀원 간의 코딩 스타일 차이를 줄여주며 코드가 일관되게 유지되어 추후 유지보수나 확장이 쉬워진다. 새로운 팀원이 프로젝트에 합류할 때 코드 스타일을 빠르게 익힐 수 있다.

사용법

1. homebrew로 설치

SPM으로 프로젝트 파일에 추가했다가 뭐가 잘 안돼서 (찾아보니 잘 안된다는 사람들이 많음... swift.packages인가? 그걸 못찾겠다)

spm으로 설치한 패키지 다 지우고 그냥 homebrew로 설치했다.

homebrew가 이미 설치되어 있다고 가정하고,

터미널에

brew install swiftlint

❗️ 설치 오류 해결
참고로 나는 Rosetta로 열기 설정이 되어있어서 처음에 오류가 났는데, finder에서 찾아서 해제해주면 설치가 잘 된다.

  • 터미널 아키텍처 확인:
arch

출력이 arm64이면 ARM 모드, i386이면 Rosetta 2 모드이다.
i386이라고 뜬다면 터미널 닫기 -> finder에서 터미널 찾기 -> 정보 가져오기 -> Rosetta를 사용하여 열기 체크 해제 -> 터미널 종료후 다시 열어 install 실행

하면 설치가 잘 될 것이다.

2. Run Script 입력

Targets -> Build Phases 가서 + 버튼 클릭 -> New Run Script phases -> 다음 코드 입력

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

빌드 단계에서 SwiftLint가 실행되게 해 주는 단계이다.

이 단계까지 마치면 코드에서 주의 표시를 볼 수 있다(고 하는데 난 오류가 계속 나서 해결하느라 이 단계 직후를 못봤다)

3. .swiftlint.yml 파일 추가

프로젝트 파일 단계(최상단) 에서 New File 클릭

맨 밑에 있는 Other -> Empty 생성해주고 이름은 .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


... # 문서의 끝

설정이 잘 되었다면 다음과 같이 주의창이 마구마구 뜬다.
주의창을 보고 이렇게 행복했던 적은 처음...
SPM설치 -> 실패
공식문서 조건으로 썼더니 -> 실패 (이게 이유인줄 모르고 계속 다른거 건드림..)
등등 해서 시간을 많이 버렸더니 실행됐을때 기분이 아주 좋았다.

❗️Sandbox deny(1) 어쩌고 오류가 뜬다면?

Sandbox: swiftlint(64002) deny(1) file-read-data

이런 오류가 떴다. 뭔가 파일에 접근을 못하고 있는 것 같은 오류...

Xcode 버전이 업그레이드 되면서 User Script Sandbox가 기본 Yes로 설정되었다고 하는 것 같은데, 이걸 No로 바꿔주면 실행이 잘 된다.

참고: 샌드박싱(Sandboxing) 이란?
샌드박싱은 애플리케이션이 보안상의 이유로 특정 시스템 자원에 접근하는 것을 제한하는 메커니즘이다. Xcode에서는 빌드 과정 중에 실행되는 사용자 스크립트에도 이러한 샌드박싱 정책을 적용할 수 있고, 이 경우 스크립트는 제한된 파일 시스템 접근 권한만 갖게 된다.

즉 샌드박싱이 활성화된 상태에서는 스크립트가 파일 시스템 접근 권한을 얻지 못해, 특정 파일을 읽으려고 할 때 접근이 거부될 수 있다는 것이다. 특히, SwiftLint 설정 파일인 .swiftlint.yml을 읽지 못해서 발생하는 문제가 있을 수 있다고 한다.

이렇게 설정해주면 (아마) 잘 보일것이다!!

profile
정체되지 않는 성장

0개의 댓글